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