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, struct nameidata *nd)
  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                struct nameidata *nd)
  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        if (inode->i_nlink >= UFS_LINK_MAX) {
 170                unlock_ufs(dir->i_sb);
 171                return -EMLINK;
 172        }
 173
 174        inode->i_ctime = CURRENT_TIME_SEC;
 175        inode_inc_link_count(inode);
 176        ihold(inode);
 177
 178        error = ufs_add_nondir(dentry, inode);
 179        unlock_ufs(dir->i_sb);
 180        return error;
 181}
 182
 183static int ufs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
 184{
 185        struct inode * inode;
 186        int err = -EMLINK;
 187
 188        if (dir->i_nlink >= UFS_LINK_MAX)
 189                goto out;
 190
 191        lock_ufs(dir->i_sb);
 192        inode_inc_link_count(dir);
 193
 194        inode = ufs_new_inode(dir, S_IFDIR|mode);
 195        err = PTR_ERR(inode);
 196        if (IS_ERR(inode))
 197                goto out_dir;
 198
 199        inode->i_op = &ufs_dir_inode_operations;
 200        inode->i_fop = &ufs_dir_operations;
 201        inode->i_mapping->a_ops = &ufs_aops;
 202
 203        inode_inc_link_count(inode);
 204
 205        err = ufs_make_empty(inode, dir);
 206        if (err)
 207                goto out_fail;
 208
 209        err = ufs_add_link(dentry, inode);
 210        if (err)
 211                goto out_fail;
 212        unlock_ufs(dir->i_sb);
 213
 214        d_instantiate(dentry, inode);
 215out:
 216        return err;
 217
 218out_fail:
 219        inode_dec_link_count(inode);
 220        inode_dec_link_count(inode);
 221        iput (inode);
 222out_dir:
 223        inode_dec_link_count(dir);
 224        unlock_ufs(dir->i_sb);
 225        goto out;
 226}
 227
 228static int ufs_unlink(struct inode *dir, struct dentry *dentry)
 229{
 230        struct inode * inode = dentry->d_inode;
 231        struct ufs_dir_entry *de;
 232        struct page *page;
 233        int err = -ENOENT;
 234
 235        de = ufs_find_entry(dir, &dentry->d_name, &page);
 236        if (!de)
 237                goto out;
 238
 239        err = ufs_delete_entry(dir, de, page);
 240        if (err)
 241                goto out;
 242
 243        inode->i_ctime = dir->i_ctime;
 244        inode_dec_link_count(inode);
 245        err = 0;
 246out:
 247        return err;
 248}
 249
 250static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
 251{
 252        struct inode * inode = dentry->d_inode;
 253        int err= -ENOTEMPTY;
 254
 255        lock_ufs(dir->i_sb);
 256        if (ufs_empty_dir (inode)) {
 257                err = ufs_unlink(dir, dentry);
 258                if (!err) {
 259                        inode->i_size = 0;
 260                        inode_dec_link_count(inode);
 261                        inode_dec_link_count(dir);
 262                }
 263        }
 264        unlock_ufs(dir->i_sb);
 265        return err;
 266}
 267
 268static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
 269                      struct inode *new_dir, struct dentry *new_dentry)
 270{
 271        struct inode *old_inode = old_dentry->d_inode;
 272        struct inode *new_inode = new_dentry->d_inode;
 273        struct page *dir_page = NULL;
 274        struct ufs_dir_entry * dir_de = NULL;
 275        struct page *old_page;
 276        struct ufs_dir_entry *old_de;
 277        int err = -ENOENT;
 278
 279        old_de = ufs_find_entry(old_dir, &old_dentry->d_name, &old_page);
 280        if (!old_de)
 281                goto out;
 282
 283        if (S_ISDIR(old_inode->i_mode)) {
 284                err = -EIO;
 285                dir_de = ufs_dotdot(old_inode, &dir_page);
 286                if (!dir_de)
 287                        goto out_old;
 288        }
 289
 290        if (new_inode) {
 291                struct page *new_page;
 292                struct ufs_dir_entry *new_de;
 293
 294                err = -ENOTEMPTY;
 295                if (dir_de && !ufs_empty_dir(new_inode))
 296                        goto out_dir;
 297
 298                err = -ENOENT;
 299                new_de = ufs_find_entry(new_dir, &new_dentry->d_name, &new_page);
 300                if (!new_de)
 301                        goto out_dir;
 302                ufs_set_link(new_dir, new_de, new_page, old_inode);
 303                new_inode->i_ctime = CURRENT_TIME_SEC;
 304                if (dir_de)
 305                        drop_nlink(new_inode);
 306                inode_dec_link_count(new_inode);
 307        } else {
 308                if (dir_de) {
 309                        err = -EMLINK;
 310                        if (new_dir->i_nlink >= UFS_LINK_MAX)
 311                                goto out_dir;
 312                }
 313                err = ufs_add_link(new_dentry, old_inode);
 314                if (err)
 315                        goto out_dir;
 316                if (dir_de)
 317                        inode_inc_link_count(new_dir);
 318        }
 319
 320        /*
 321         * Like most other Unix systems, set the ctime for inodes on a
 322         * rename.
 323         */
 324        old_inode->i_ctime = CURRENT_TIME_SEC;
 325
 326        ufs_delete_entry(old_dir, old_de, old_page);
 327        mark_inode_dirty(old_inode);
 328
 329        if (dir_de) {
 330                ufs_set_link(old_inode, dir_de, dir_page, new_dir);
 331                inode_dec_link_count(old_dir);
 332        }
 333        return 0;
 334
 335
 336out_dir:
 337        if (dir_de) {
 338                kunmap(dir_page);
 339                page_cache_release(dir_page);
 340        }
 341out_old:
 342        kunmap(old_page);
 343        page_cache_release(old_page);
 344out:
 345        return err;
 346}
 347
 348const struct inode_operations ufs_dir_inode_operations = {
 349        .create         = ufs_create,
 350        .lookup         = ufs_lookup,
 351        .link           = ufs_link,
 352        .unlink         = ufs_unlink,
 353        .symlink        = ufs_symlink,
 354        .mkdir          = ufs_mkdir,
 355        .rmdir          = ufs_rmdir,
 356        .mknod          = ufs_mknod,
 357        .rename         = ufs_rename,
 358};
 359
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.