The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/ufs/namei.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 3052aa3cdbe207148f36c76ee7320ee6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.