Merge branch 'master' of git://git.infradead.org/users/eparis/selinux into next
[linux-2.6.git] / fs / reiserfs / namei.c
index 2715791..82f4554 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/time.h>
 #include <linux/bitops.h>
+#include <linux/slab.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/reiserfs_acl.h>
 #include <linux/reiserfs_xattr.h>
@@ -324,6 +325,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
                                      struct nameidata *nd)
 {
        int retval;
+       int lock_depth;
        struct inode *inode = NULL;
        struct reiserfs_dir_entry de;
        INITIALIZE_PATH(path_to_entry);
@@ -331,7 +333,13 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
        if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len)
                return ERR_PTR(-ENAMETOOLONG);
 
-       reiserfs_write_lock(dir->i_sb);
+       /*
+        * Might be called with or without the write lock, must be careful
+        * to not recursively hold it in case we want to release the lock
+        * before rescheduling.
+        */
+       lock_depth = reiserfs_write_lock_once(dir->i_sb);
+
        de.de_gen_number_bit_string = NULL;
        retval =
            reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
@@ -341,7 +349,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
                inode = reiserfs_iget(dir->i_sb,
                                      (struct cpu_key *)&(de.de_dir_id));
                if (!inode || IS_ERR(inode)) {
-                       reiserfs_write_unlock(dir->i_sb);
+                       reiserfs_write_unlock_once(dir->i_sb, lock_depth);
                        return ERR_PTR(-EACCES);
                }
 
@@ -350,7 +358,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
                if (IS_PRIVATE(dir))
                        inode->i_flags |= S_PRIVATE;
        }
-       reiserfs_write_unlock(dir->i_sb);
+       reiserfs_write_unlock_once(dir->i_sb, lock_depth);
        if (retval == IO_ERROR) {
                return ERR_PTR(-EIO);
        }
@@ -539,7 +547,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th,
 */
 static int drop_new_inode(struct inode *inode)
 {
-       vfs_dq_drop(inode);
+       dquot_drop(inode);
        make_bad_inode(inode);
        inode->i_flags |= S_NOQUOTA;
        iput(inode);
@@ -547,30 +555,20 @@ static int drop_new_inode(struct inode *inode)
 }
 
 /* utility function that does setup for reiserfs_new_inode.
-** vfs_dq_init needs lots of credits so it's better to have it
+** dquot_initialize needs lots of credits so it's better to have it
 ** outside of a transaction, so we had to pull some bits of
 ** reiserfs_new_inode out into this func.
 */
 static int new_inode_init(struct inode *inode, struct inode *dir, int mode)
 {
-
-       /* the quota init calls have to know who to charge the quota to, so
-        ** we have to set uid and gid here
-        */
-       inode->i_uid = current_fsuid();
-       inode->i_mode = mode;
        /* Make inode invalid - just in case we are going to drop it before
         * the initialization happens */
        INODE_PKEY(inode)->k_objectid = 0;
-
-       if (dir->i_mode & S_ISGID) {
-               inode->i_gid = dir->i_gid;
-               if (S_ISDIR(mode))
-                       inode->i_mode |= S_ISGID;
-       } else {
-               inode->i_gid = current_fsgid();
-       }
-       vfs_dq_init(inode);
+       /* the quota init calls have to know who to charge the quota to, so
+        ** we have to set uid and gid here
+        */
+       inode_init_owner(inode, dir, mode);
+       dquot_initialize(inode);
        return 0;
 }
 
@@ -587,13 +585,15 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode,
        struct reiserfs_transaction_handle th;
        struct reiserfs_security_handle security;
 
+       dquot_initialize(dir);
+
        if (!(inode = new_inode(dir->i_sb))) {
                return -ENOMEM;
        }
        new_inode_init(inode, dir, mode);
 
        jbegin_count += reiserfs_cache_default_acl(dir);
-       retval = reiserfs_security_init(dir, inode, &security);
+       retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
        if (retval < 0) {
                drop_new_inode(inode);
                return retval;
@@ -659,13 +659,15 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
        if (!new_valid_dev(rdev))
                return -EINVAL;
 
+       dquot_initialize(dir);
+
        if (!(inode = new_inode(dir->i_sb))) {
                return -ENOMEM;
        }
        new_inode_init(inode, dir, mode);
 
        jbegin_count += reiserfs_cache_default_acl(dir);
-       retval = reiserfs_security_init(dir, inode, &security);
+       retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
        if (retval < 0) {
                drop_new_inode(inode);
                return retval;
@@ -725,12 +727,15 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        struct inode *inode;
        struct reiserfs_transaction_handle th;
        struct reiserfs_security_handle security;
+       int lock_depth;
        /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
        int jbegin_count =
            JOURNAL_PER_BALANCE_CNT * 3 +
            2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
                 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
 
+       dquot_initialize(dir);
+
 #ifdef DISPLACE_NEW_PACKING_LOCALITIES
        /* set flag that new packing locality created and new blocks for the content     * of that directory are not displaced yet */
        REISERFS_I(dir)->new_packing_locality = 1;
@@ -742,13 +747,13 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        new_inode_init(inode, dir, mode);
 
        jbegin_count += reiserfs_cache_default_acl(dir);
-       retval = reiserfs_security_init(dir, inode, &security);
+       retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
        if (retval < 0) {
                drop_new_inode(inode);
                return retval;
        }
        jbegin_count += retval;
-       reiserfs_write_lock(dir->i_sb);
+       lock_depth = reiserfs_write_lock_once(dir->i_sb);
 
        retval = journal_begin(&th, dir->i_sb, jbegin_count);
        if (retval) {
@@ -766,7 +771,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
                                        EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE,
                                        dentry, inode, &security);
        if (retval) {
-               dir->i_nlink--;
+               DEC_DIR_INODE_NLINK(dir)
                goto out_failed;
        }
 
@@ -798,8 +803,8 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        d_instantiate(dentry, inode);
        unlock_new_inode(inode);
        retval = journal_end(&th, dir->i_sb, jbegin_count);
-      out_failed:
-       reiserfs_write_unlock(dir->i_sb);
+out_failed:
+       reiserfs_write_unlock_once(dir->i_sb, lock_depth);
        return retval;
 }
 
@@ -834,6 +839,8 @@ static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry)
            JOURNAL_PER_BALANCE_CNT * 2 + 2 +
            4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
 
+       dquot_initialize(dir);
+
        reiserfs_write_lock(dir->i_sb);
        retval = journal_begin(&th, dir->i_sb, jbegin_count);
        if (retval)
@@ -913,6 +920,9 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
        struct reiserfs_transaction_handle th;
        int jbegin_count;
        unsigned long savelink;
+       int depth;
+
+       dquot_initialize(dir);
 
        inode = dentry->d_inode;
 
@@ -924,7 +934,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
            JOURNAL_PER_BALANCE_CNT * 2 + 2 +
            4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
 
-       reiserfs_write_lock(dir->i_sb);
+       depth = reiserfs_write_lock_once(dir->i_sb);
        retval = journal_begin(&th, dir->i_sb, jbegin_count);
        if (retval)
                goto out_unlink;
@@ -985,7 +995,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
 
        retval = journal_end(&th, dir->i_sb, jbegin_count);
        reiserfs_check_path(&path);
-       reiserfs_write_unlock(dir->i_sb);
+       reiserfs_write_unlock_once(dir->i_sb, depth);
        return retval;
 
       end_unlink:
@@ -995,7 +1005,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
        if (err)
                retval = err;
       out_unlink:
-       reiserfs_write_unlock(dir->i_sb);
+       reiserfs_write_unlock_once(dir->i_sb, depth);
        return retval;
 }
 
@@ -1015,12 +1025,15 @@ static int reiserfs_symlink(struct inode *parent_dir,
            2 * (REISERFS_QUOTA_INIT_BLOCKS(parent_dir->i_sb) +
                 REISERFS_QUOTA_TRANS_BLOCKS(parent_dir->i_sb));
 
+       dquot_initialize(parent_dir);
+
        if (!(inode = new_inode(parent_dir->i_sb))) {
                return -ENOMEM;
        }
        new_inode_init(inode, parent_dir, mode);
 
-       retval = reiserfs_security_init(parent_dir, inode, &security);
+       retval = reiserfs_security_init(parent_dir, inode, &dentry->d_name,
+                                       &security);
        if (retval < 0) {
                drop_new_inode(inode);
                return retval;
@@ -1102,6 +1115,8 @@ static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
            JOURNAL_PER_BALANCE_CNT * 3 +
            2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
 
+       dquot_initialize(dir);
+
        reiserfs_write_lock(dir->i_sb);
        if (inode->i_nlink >= REISERFS_LINK_MAX) {
                //FIXME: sd_nlink is 32 bit for new files
@@ -1142,7 +1157,7 @@ static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
        inode->i_ctime = CURRENT_TIME_SEC;
        reiserfs_update_sd(&th, inode);
 
-       atomic_inc(&inode->i_count);
+       ihold(inode);
        d_instantiate(dentry, inode);
        retval = journal_end(&th, dir->i_sb, jbegin_count);
        reiserfs_write_unlock(dir->i_sb);
@@ -1226,6 +1241,9 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
            JOURNAL_PER_BALANCE_CNT * 3 + 5 +
            4 * REISERFS_QUOTA_TRANS_BLOCKS(old_dir->i_sb);
 
+       dquot_initialize(old_dir);
+       dquot_initialize(new_dir);
+
        old_inode = old_dentry->d_inode;
        new_dentry_inode = new_dentry->d_inode;