linux/fs/ext2/namei.c
<<
>>
Prefs
   1/*
   2 * linux/fs/ext2/namei.c
   3 *
   4 * Rewrite to pagecache. Almost all code had been changed, so blame me
   5 * if the things go wrong. Please, send bug reports to
   6 * viro@parcelfarce.linux.theplanet.co.uk
   7 *
   8 * Stuff here is basically a glue between the VFS and generic UNIXish
   9 * filesystem that keeps everything in pagecache. All knowledge of the
  10 * directory layout is in fs/ext2/dir.c - it turned out to be easily separatable
  11 * and it's easier to debug that way. In principle we might want to
  12 * generalize that a bit and turn it into a library. Or not.
  13 *
  14 * The only non-static object here is ext2_dir_inode_operations.
  15 *
  16 * TODO: get rid of kmap() use, add readahead.
  17 *
  18 * Copyright (C) 1992, 1993, 1994, 1995
  19 * Remy Card (card@masi.ibp.fr)
  20 * Laboratoire MASI - Institut Blaise Pascal
  21 * Universite Pierre et Marie Curie (Paris VI)
  22 *
  23 *  from
  24 *
  25 *  linux/fs/minix/namei.c
  26 *
  27 *  Copyright (C) 1991, 1992  Linus Torvalds
  28 *
  29 *  Big-endian to little-endian byte-swapping/bitmaps by
  30 *        David S. Miller (davem@caip.rutgers.edu), 1995
  31 */
  32
  33#include <linux/pagemap.h>
  34#include <linux/quotaops.h>
  35#include "ext2.h"
  36#include "xattr.h"
  37#include "acl.h"
  38#include "xip.h"
  39
  40static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
  41{
  42        int err = ext2_add_link(dentry, inode);
  43        if (!err) {
  44                d_instantiate(dentry, inode);
  45                unlock_new_inode(inode);
  46                return 0;
  47        }
  48        inode_dec_link_count(inode);
  49        unlock_new_inode(inode);
  50        iput(inode);
  51        return err;
  52}
  53
  54/*
  55 * Methods themselves.
  56 */
  57
  58static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
  59{
  60        struct inode * inode;
  61        ino_t ino;
  62        
  63        if (dentry->d_name.len > EXT2_NAME_LEN)
  64                return ERR_PTR(-ENAMETOOLONG);
  65
  66        ino = ext2_inode_by_name(dir, &dentry->d_name);
  67        inode = NULL;
  68        if (ino) {
  69                inode = ext2_iget(dir->i_sb, ino);
  70                if (IS_ERR(inode)) {
  71                        if (PTR_ERR(inode) == -ESTALE) {
  72                                ext2_error(dir->i_sb, __func__,
  73                                                "deleted inode referenced: %lu",
  74                                                (unsigned long) ino);
  75                                return ERR_PTR(-EIO);
  76                        } else {
  77                                return ERR_CAST(inode);
  78                        }
  79                }
  80        }
  81        return d_splice_alias(inode, dentry);
  82}
  83
  84struct dentry *ext2_get_parent(struct dentry *child)
  85{
  86        struct qstr dotdot = {.name = "..", .len = 2};
  87        unsigned long ino = ext2_inode_by_name(child->d_inode, &dotdot);
  88        if (!ino)
  89                return ERR_PTR(-ENOENT);
  90        return d_obtain_alias(ext2_iget(child->d_inode->i_sb, ino));
  91} 
  92
  93/*
  94 * By the time this is called, we already have created
  95 * the directory cache entry for the new file, but it
  96 * is so far negative - it has no inode.
  97 *
  98 * If the create succeeds, we fill in the inode information
  99 * with d_instantiate(). 
 100 */
 101static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd)
 102{
 103        struct inode *inode;
 104
 105        dquot_initialize(dir);
 106
 107        inode = ext2_new_inode(dir, mode);
 108        if (IS_ERR(inode))
 109                return PTR_ERR(inode);
 110
 111        inode->i_op = &ext2_file_inode_operations;
 112        if (ext2_use_xip(inode->i_sb)) {
 113                inode->i_mapping->a_ops = &ext2_aops_xip;
 114                inode->i_fop = &ext2_xip_file_operations;
 115        } else if (test_opt(inode->i_sb, NOBH)) {
 116                inode->i_mapping->a_ops = &ext2_nobh_aops;
 117                inode->i_fop = &ext2_file_operations;
 118        } else {
 119                inode->i_mapping->a_ops = &ext2_aops;
 120                inode->i_fop = &ext2_file_operations;
 121        }
 122        mark_inode_dirty(inode);
 123        return ext2_add_nondir(dentry, inode);
 124}
 125
 126static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev)
 127{
 128        struct inode * inode;
 129        int err;
 130
 131        if (!new_valid_dev(rdev))
 132                return -EINVAL;
 133
 134        dquot_initialize(dir);
 135
 136        inode = ext2_new_inode (dir, mode);
 137        err = PTR_ERR(inode);
 138        if (!IS_ERR(inode)) {
 139                init_special_inode(inode, inode->i_mode, rdev);
 140#ifdef CONFIG_EXT2_FS_XATTR
 141                inode->i_op = &ext2_special_inode_operations;
 142#endif
 143                mark_inode_dirty(inode);
 144                err = ext2_add_nondir(dentry, inode);
 145        }
 146        return err;
 147}
 148
 149static int ext2_symlink (struct inode * dir, struct dentry * dentry,
 150        const char * symname)
 151{
 152        struct super_block * sb = dir->i_sb;
 153        int err = -ENAMETOOLONG;
 154        unsigned l = strlen(symname)+1;
 155        struct inode * inode;
 156
 157        if (l > sb->s_blocksize)
 158                goto out;
 159
 160        dquot_initialize(dir);
 161
 162        inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO);
 163        err = PTR_ERR(inode);
 164        if (IS_ERR(inode))
 165                goto out;
 166
 167        if (l > sizeof (EXT2_I(inode)->i_data)) {
 168                /* slow symlink */
 169                inode->i_op = &ext2_symlink_inode_operations;
 170                if (test_opt(inode->i_sb, NOBH))
 171                        inode->i_mapping->a_ops = &ext2_nobh_aops;
 172                else
 173                        inode->i_mapping->a_ops = &ext2_aops;
 174                err = page_symlink(inode, symname, l);
 175                if (err)
 176                        goto out_fail;
 177        } else {
 178                /* fast symlink */
 179                inode->i_op = &ext2_fast_symlink_inode_operations;
 180                memcpy((char*)(EXT2_I(inode)->i_data),symname,l);
 181                inode->i_size = l-1;
 182        }
 183        mark_inode_dirty(inode);
 184
 185        err = ext2_add_nondir(dentry, inode);
 186out:
 187        return err;
 188
 189out_fail:
 190        inode_dec_link_count(inode);
 191        unlock_new_inode(inode);
 192        iput (inode);
 193        goto out;
 194}
 195
 196static int ext2_link (struct dentry * old_dentry, struct inode * dir,
 197        struct dentry *dentry)
 198{
 199        struct inode *inode = old_dentry->d_inode;
 200        int err;
 201
 202        if (inode->i_nlink >= EXT2_LINK_MAX)
 203                return -EMLINK;
 204
 205        dquot_initialize(dir);
 206
 207        inode->i_ctime = CURRENT_TIME_SEC;
 208        inode_inc_link_count(inode);
 209        ihold(inode);
 210
 211        err = ext2_add_link(dentry, inode);
 212        if (!err) {
 213                d_instantiate(dentry, inode);
 214                return 0;
 215        }
 216        inode_dec_link_count(inode);
 217        iput(inode);
 218        return err;
 219}
 220
 221static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 222{
 223        struct inode * inode;
 224        int err = -EMLINK;
 225
 226        if (dir->i_nlink >= EXT2_LINK_MAX)
 227                goto out;
 228
 229        dquot_initialize(dir);
 230
 231        inode_inc_link_count(dir);
 232
 233        inode = ext2_new_inode (dir, S_IFDIR | mode);
 234        err = PTR_ERR(inode);
 235        if (IS_ERR(inode))
 236                goto out_dir;
 237
 238        inode->i_op = &ext2_dir_inode_operations;
 239        inode->i_fop = &ext2_dir_operations;
 240        if (test_opt(inode->i_sb, NOBH))
 241                inode->i_mapping->a_ops = &ext2_nobh_aops;
 242        else
 243                inode->i_mapping->a_ops = &ext2_aops;
 244
 245        inode_inc_link_count(inode);
 246
 247        err = ext2_make_empty(inode, dir);
 248        if (err)
 249                goto out_fail;
 250
 251        err = ext2_add_link(dentry, inode);
 252        if (err)
 253                goto out_fail;
 254
 255        d_instantiate(dentry, inode);
 256        unlock_new_inode(inode);
 257out:
 258        return err;
 259
 260out_fail:
 261        inode_dec_link_count(inode);
 262        inode_dec_link_count(inode);
 263        unlock_new_inode(inode);
 264        iput(inode);
 265out_dir:
 266        inode_dec_link_count(dir);
 267        goto out;
 268}
 269
 270static int ext2_unlink(struct inode * dir, struct dentry *dentry)
 271{
 272        struct inode * inode = dentry->d_inode;
 273        struct ext2_dir_entry_2 * de;
 274        struct page * page;
 275        int err = -ENOENT;
 276
 277        dquot_initialize(dir);
 278
 279        de = ext2_find_entry (dir, &dentry->d_name, &page);
 280        if (!de)
 281                goto out;
 282
 283        err = ext2_delete_entry (de, page);
 284        if (err)
 285                goto out;
 286
 287        inode->i_ctime = dir->i_ctime;
 288        inode_dec_link_count(inode);
 289        err = 0;
 290out:
 291        return err;
 292}
 293
 294static int ext2_rmdir (struct inode * dir, struct dentry *dentry)
 295{
 296        struct inode * inode = dentry->d_inode;
 297        int err = -ENOTEMPTY;
 298
 299        if (ext2_empty_dir(inode)) {
 300                err = ext2_unlink(dir, dentry);
 301                if (!err) {
 302                        inode->i_size = 0;
 303                        inode_dec_link_count(inode);
 304                        inode_dec_link_count(dir);
 305                }
 306        }
 307        return err;
 308}
 309
 310static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
 311        struct inode * new_dir, struct dentry * new_dentry )
 312{
 313        struct inode * old_inode = old_dentry->d_inode;
 314        struct inode * new_inode = new_dentry->d_inode;
 315        struct page * dir_page = NULL;
 316        struct ext2_dir_entry_2 * dir_de = NULL;
 317        struct page * old_page;
 318        struct ext2_dir_entry_2 * old_de;
 319        int err = -ENOENT;
 320
 321        dquot_initialize(old_dir);
 322        dquot_initialize(new_dir);
 323
 324        old_de = ext2_find_entry (old_dir, &old_dentry->d_name, &old_page);
 325        if (!old_de)
 326                goto out;
 327
 328        if (S_ISDIR(old_inode->i_mode)) {
 329                err = -EIO;
 330                dir_de = ext2_dotdot(old_inode, &dir_page);
 331                if (!dir_de)
 332                        goto out_old;
 333        }
 334
 335        if (new_inode) {
 336                struct page *new_page;
 337                struct ext2_dir_entry_2 *new_de;
 338
 339                err = -ENOTEMPTY;
 340                if (dir_de && !ext2_empty_dir (new_inode))
 341                        goto out_dir;
 342
 343                err = -ENOENT;
 344                new_de = ext2_find_entry (new_dir, &new_dentry->d_name, &new_page);
 345                if (!new_de)
 346                        goto out_dir;
 347                ext2_set_link(new_dir, new_de, new_page, old_inode, 1);
 348                new_inode->i_ctime = CURRENT_TIME_SEC;
 349                if (dir_de)
 350                        drop_nlink(new_inode);
 351                inode_dec_link_count(new_inode);
 352        } else {
 353                if (dir_de) {
 354                        err = -EMLINK;
 355                        if (new_dir->i_nlink >= EXT2_LINK_MAX)
 356                                goto out_dir;
 357                }
 358                err = ext2_add_link(new_dentry, old_inode);
 359                if (err)
 360                        goto out_dir;
 361                if (dir_de)
 362                        inode_inc_link_count(new_dir);
 363        }
 364
 365        /*
 366         * Like most other Unix systems, set the ctime for inodes on a
 367         * rename.
 368         */
 369        old_inode->i_ctime = CURRENT_TIME_SEC;
 370        mark_inode_dirty(old_inode);
 371
 372        ext2_delete_entry (old_de, old_page);
 373
 374        if (dir_de) {
 375                if (old_dir != new_dir)
 376                        ext2_set_link(old_inode, dir_de, dir_page, new_dir, 0);
 377                else {
 378                        kunmap(dir_page);
 379                        page_cache_release(dir_page);
 380                }
 381                inode_dec_link_count(old_dir);
 382        }
 383        return 0;
 384
 385
 386out_dir:
 387        if (dir_de) {
 388                kunmap(dir_page);
 389                page_cache_release(dir_page);
 390        }
 391out_old:
 392        kunmap(old_page);
 393        page_cache_release(old_page);
 394out:
 395        return err;
 396}
 397
 398const struct inode_operations ext2_dir_inode_operations = {
 399        .create         = ext2_create,
 400        .lookup         = ext2_lookup,
 401        .link           = ext2_link,
 402        .unlink         = ext2_unlink,
 403        .symlink        = ext2_symlink,
 404        .mkdir          = ext2_mkdir,
 405        .rmdir          = ext2_rmdir,
 406        .mknod          = ext2_mknod,
 407        .rename         = ext2_rename,
 408#ifdef CONFIG_EXT2_FS_XATTR
 409        .setxattr       = generic_setxattr,
 410        .getxattr       = generic_getxattr,
 411        .listxattr      = ext2_listxattr,
 412        .removexattr    = generic_removexattr,
 413#endif
 414        .setattr        = ext2_setattr,
 415        .check_acl      = ext2_check_acl,
 416};
 417
 418const struct inode_operations ext2_special_inode_operations = {
 419#ifdef CONFIG_EXT2_FS_XATTR
 420        .setxattr       = generic_setxattr,
 421        .getxattr       = generic_getxattr,
 422        .listxattr      = ext2_listxattr,
 423        .removexattr    = generic_removexattr,
 424#endif
 425        .setattr        = ext2_setattr,
 426        .check_acl      = ext2_check_acl,
 427};
 428