linux/fs/ufs/namei.c
<<
>>
Prefs
   1/*
   2 * linux/fs/ufs/namei.c
   3 *
   4 * Migration to usage of "page cache" on May 2006 by
   5 * Evgeniy Dushistov <dushistov@mail.ru> based on ext2 code base.
   6 *
   7 * Copyright (C) 1998
   8 * Daniel Pirkl <daniel.pirkl@email.cz>
   9 * Charles University, Faculty of Mathematics and Physics
  10 *
  11 *  from
  12 *
  13 *  linux/fs/ext2/namei.c
  14 *
  15 * Copyright (C) 1992, 1993, 1994, 1995
  16 * Remy Card (card@masi.ibp.fr)
  17 * Laboratoire MASI - Institut Blaise Pascal
  18 * Universite Pierre et Marie Curie (Paris VI)
  19 *
  20 *  from
  21 *
  22 *  linux/fs/minix/namei.c
  23 *
  24 *  Copyright (C) 1991, 1992  Linus Torvalds
  25 *
  26 *  Big-endian to little-endian byte-swapping/bitmaps by
  27 *        David S. Miller (davem@caip.rutgers.edu), 1995
  28 */
  29
  30#include <linux/time.h>
  31#include <linux/fs.h>
  32
  33#include "ufs_fs.h"
  34#include "ufs.h"
  35#include "util.h"
  36
  37static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode)
  38{
  39        int err = ufs_add_link(dentry, inode);
  40        if (!err) {
  41                d_instantiate(dentry, inode);
  42                return 0;
  43        }
  44        inode_dec_link_count(inode);
  45        iput(inode);
  46        return err;
  47}
  48
  49static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
  50{
  51        struct inode * inode = NULL;
  52        ino_t ino;
  53        
  54        if (dentry->d_name.len > UFS_MAXNAMLEN)
  55                return ERR_PTR(-ENAMETOOLONG);
  56
  57        lock_ufs(dir->i_sb);
  58        ino = ufs_inode_by_name(dir, &dentry->d_name);
  59        if (ino)
  60                inode = ufs_iget(dir->i_sb, ino);
  61        unlock_ufs(dir->i_sb);
  62        return d_splice_alias(inode, dentry);
  63}
  64
  65/*
  66 * By the time this is called, we already have created
  67 * the directory cache entry for the new file, but it
  68 * is so far negative - it has no inode.
  69 *
  70 * If the create succeeds, we fill in the inode information
  71 * with d_instantiate(). 
  72 */
  73static int ufs_create (struct inode * dir, struct dentry * dentry, umode_t mode,
  74                bool excl)
  75{
  76        struct inode *inode;
  77        int err;
  78
  79        UFSD("BEGIN\n");
  80
  81        inode = ufs_new_inode(dir, mode);
  82        err = PTR_ERR(inode);
  83
  84        if (!IS_ERR(inode)) {
  85                inode->i_op = &ufs_file_inode_operations;
  86                inode->i_fop = &ufs_file_operations;
  87                inode->i_mapping->a_ops = &ufs_aops;
  88                mark_inode_dirty(inode);
  89                lock_ufs(dir->i_sb);
  90                err = ufs_add_nondir(dentry, inode);
  91                unlock_ufs(dir->i_sb);
  92        }
  93        UFSD("END: err=%d\n", err);
  94        return err;
  95}
  96
  97static int ufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
  98{
  99        struct inode *inode;
 100        int err;
 101
 102        if (!old_valid_dev(rdev))
 103                return -EINVAL;
 104
 105        inode = ufs_new_inode(dir, mode);
 106        err = PTR_ERR(inode);
 107        if (!IS_ERR(inode)) {
 108                init_special_inode(inode, mode, rdev);
 109                ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev);
 110                mark_inode_dirty(inode);
 111                lock_ufs(dir->i_sb);
 112                err = ufs_add_nondir(dentry, inode);
 113                unlock_ufs(dir->i_sb);
 114        }
 115        return err;
 116}
 117
 118static int ufs_symlink (struct inode * dir, struct dentry * dentry,
 119        const char * symname)
 120{
 121        struct super_block * sb = dir->i_sb;
 122        int err = -ENAMETOOLONG;
 123        unsigned l = strlen(symname)+1;
 124        struct inode * inode;
 125
 126        if (l > sb->s_blocksize)
 127                goto out_notlocked;
 128
 129        lock_ufs(dir->i_sb);
 130        inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO);
 131        err = PTR_ERR(inode);
 132        if (IS_ERR(inode))
 133                goto out;
 134
 135        if (l > UFS_SB(sb)->s_uspi->s_maxsymlinklen) {
 136                /* slow symlink */
 137                inode->i_op = &ufs_symlink_inode_operations;
 138                inode->i_mapping->a_ops = &ufs_aops;
 139                err = page_symlink(inode, symname, l);
 140                if (err)
 141                        goto out_fail;
 142        } else {
 143                /* fast symlink */
 144                inode->i_op = &ufs_fast_symlink_inode_operations;
 145                memcpy(UFS_I(inode)->i_u1.i_symlink, symname, l);
 146                inode->i_size = l-1;
 147        }
 148        mark_inode_dirty(inode);
 149
 150        err = ufs_add_nondir(dentry, inode);
 151out:
 152        unlock_ufs(dir->i_sb);
 153out_notlocked:
 154        return err;
 155
 156out_fail:
 157        inode_dec_link_count(inode);
 158        iput(inode);
 159        goto out;
 160}
 161
 162static int ufs_link (struct dentry * old_dentry, struct inode * dir,
 163        struct dentry *dentry)
 164{
 165        struct inode *inode = old_dentry->d_inode;
 166        int error;
 167
 168        lock_ufs(dir->i_sb);
 169
 170        inode->i_ctime = CURRENT_TIME_SEC;
 171        inode_inc_link_count(inode);
 172        ihold(inode);
 173
 174        error = ufs_add_nondir(dentry, inode);
 175        unlock_ufs(dir->i_sb);
 176        return error;
 177}
 178
 179static int ufs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
 180{
 181        struct inode * inode;
 182        int err;
 183
 184        lock_ufs(dir->i_sb);
 185        inode_inc_link_count(dir);
 186
 187        inode = ufs_new_inode(dir, S_IFDIR|mode);
 188        err = PTR_ERR(inode);
 189        if (IS_ERR(inode))
 190                goto out_dir;
 191
 192        inode->i_op = &ufs_dir_inode_operations;
 193        inode->i_fop = &ufs_dir_operations;
 194        inode->i_mapping->a_ops = &ufs_aops;
 195
 196        inode_inc_link_count(inode);
 197
 198        err = ufs_make_empty(inode, dir);
 199        if (err)
 200                goto out_fail;
 201
 202        err = ufs_add_link(dentry, inode);
 203        if (err)
 204                goto out_fail;
 205        unlock_ufs(dir->i_sb);
 206
 207        d_instantiate(dentry, inode);
 208out:
 209        return err;
 210
 211out_fail:
 212        inode_dec_link_count(inode);
 213        inode_dec_link_count(inode);
 214        iput (inode);
 215out_dir:
 216        inode_dec_link_count(dir);
 217        unlock_ufs(dir->i_sb);
 218        goto out;
 219}
 220
 221static int ufs_unlink(struct inode *dir, struct dentry *dentry)
 222{
 223        struct inode * inode = dentry->d_inode;
 224        struct ufs_dir_entry *de;
 225        struct page *page;
 226        int err = -ENOENT;
 227
 228        de = ufs_find_entry(dir, &dentry->d_name, &page);
 229        if (!de)
 230                goto out;
 231
 232        err = ufs_delete_entry(dir, de, page);
 233        if (err)
 234                goto out;
 235
 236        inode->i_ctime = dir->i_ctime;
 237        inode_dec_link_count(inode);
 238        err = 0;
 239out:
 240        return err;
 241}
 242
 243static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
 244{
 245        struct inode * inode = dentry->d_inode;
 246        int err= -ENOTEMPTY;
 247
 248        lock_ufs(dir->i_sb);
 249        if (ufs_empty_dir (inode)) {
 250                err = ufs_unlink(dir, dentry);
 251                if (!err) {
 252                        inode->i_size = 0;
 253                        inode_dec_link_count(inode);
 254                        inode_dec_link_count(dir);
 255                }
 256        }
 257        unlock_ufs(dir->i_sb);
 258        return err;
 259}
 260
 261static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
 262                      struct inode *new_dir, struct dentry *new_dentry)
 263{
 264        struct inode *old_inode = old_dentry->d_inode;
 265        struct inode *new_inode = new_dentry->d_inode;
 266        struct page *dir_page = NULL;
 267        struct ufs_dir_entry * dir_de = NULL;
 268        struct page *old_page;
 269        struct ufs_dir_entry *old_de;
 270        int err = -ENOENT;
 271
 272        old_de = ufs_find_entry(old_dir, &old_dentry->d_name, &old_page);
 273        if (!old_de)
 274                goto out;
 275
 276        if (S_ISDIR(old_inode->i_mode)) {
 277                err = -EIO;
 278                dir_de = ufs_dotdot(old_inode, &dir_page);
 279                if (!dir_de)
 280                        goto out_old;
 281        }
 282
 283        if (new_inode) {
 284                struct page *new_page;
 285                struct ufs_dir_entry *new_de;
 286
 287                err = -ENOTEMPTY;
 288                if (dir_de && !ufs_empty_dir(new_inode))
 289                        goto out_dir;
 290
 291                err = -ENOENT;
 292                new_de = ufs_find_entry(new_dir, &new_dentry->d_name, &new_page);
 293                if (!new_de)
 294                        goto out_dir;
 295                ufs_set_link(new_dir, new_de, new_page, old_inode);
 296                new_inode->i_ctime = CURRENT_TIME_SEC;
 297                if (dir_de)
 298                        drop_nlink(new_inode);
 299                inode_dec_link_count(new_inode);
 300        } else {
 301                err = ufs_add_link(new_dentry, old_inode);
 302                if (err)
 303                        goto out_dir;
 304                if (dir_de)
 305                        inode_inc_link_count(new_dir);
 306        }
 307
 308        /*
 309         * Like most other Unix systems, set the ctime for inodes on a
 310         * rename.
 311         */
 312        old_inode->i_ctime = CURRENT_TIME_SEC;
 313
 314        ufs_delete_entry(old_dir, old_de, old_page);
 315        mark_inode_dirty(old_inode);
 316
 317        if (dir_de) {
 318                ufs_set_link(old_inode, dir_de, dir_page, new_dir);
 319                inode_dec_link_count(old_dir);
 320        }
 321        return 0;
 322
 323
 324out_dir:
 325        if (dir_de) {
 326                kunmap(dir_page);
 327                page_cache_release(dir_page);
 328        }
 329out_old:
 330        kunmap(old_page);
 331        page_cache_release(old_page);
 332out:
 333        return err;
 334}
 335
 336const struct inode_operations ufs_dir_inode_operations = {
 337        .create         = ufs_create,
 338        .lookup         = ufs_lookup,
 339        .link           = ufs_link,
 340        .unlink         = ufs_unlink,
 341        .symlink        = ufs_symlink,
 342        .mkdir          = ufs_mkdir,
 343        .rmdir          = ufs_rmdir,
 344        .mknod          = ufs_mknod,
 345        .rename         = ufs_rename,
 346};
 347
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.