Merge branch 'topic/core-cleanup' into for-linus
[safe/jmp/linux-2.6] / fs / ocfs2 / namei.c
index f010b22..4cbb18f 100644 (file)
@@ -84,7 +84,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
 static int ocfs2_orphan_add(struct ocfs2_super *osb,
                            handle_t *handle,
                            struct inode *inode,
-                           struct ocfs2_dinode *fe,
+                           struct buffer_head *fe_bh,
                            char *name,
                            struct ocfs2_dir_lookup_result *lookup,
                            struct inode *orphan_dir_inode);
@@ -212,7 +212,7 @@ static struct inode *ocfs2_get_init_inode(struct inode *dir, int mode)
        } else
                inode->i_gid = current_fsgid();
        inode->i_mode = mode;
-       vfs_dq_init(inode);
+       dquot_initialize(inode);
        return inode;
 }
 
@@ -244,6 +244,8 @@ static int ocfs2_mknod(struct inode *dir,
                   (unsigned long)dev, dentry->d_name.len,
                   dentry->d_name.name);
 
+       dquot_initialize(dir);
+
        /* get our super block */
        osb = OCFS2_SB(dir->i_sb);
 
@@ -348,13 +350,9 @@ static int ocfs2_mknod(struct inode *dir,
                goto leave;
        }
 
-       /* We don't use standard VFS wrapper because we don't want vfs_dq_init
-        * to be called. */
-       if (sb_any_quota_active(osb->sb) &&
-           osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
-               status = -EDQUOT;
+       status = dquot_alloc_inode(inode);
+       if (status)
                goto leave;
-       }
        did_quota_inode = 1;
 
        mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry,
@@ -410,28 +408,33 @@ static int ocfs2_mknod(struct inode *dir,
                }
        }
 
-       status = ocfs2_add_entry(handle, dentry, inode,
-                                OCFS2_I(inode)->ip_blkno, parent_fe_bh,
-                                &lookup);
-       if (status < 0) {
+       /*
+        * Do this before adding the entry to the directory. We add
+        * also set d_op after success so that ->d_iput() will cleanup
+        * the dentry lock even if ocfs2_add_entry() fails below.
+        */
+       status = ocfs2_dentry_attach_lock(dentry, inode,
+                                         OCFS2_I(dir)->ip_blkno);
+       if (status) {
                mlog_errno(status);
                goto leave;
        }
+       dentry->d_op = &ocfs2_dentry_ops;
 
-       status = ocfs2_dentry_attach_lock(dentry, inode,
-                                         OCFS2_I(dir)->ip_blkno);
-       if (status) {
+       status = ocfs2_add_entry(handle, dentry, inode,
+                                OCFS2_I(inode)->ip_blkno, parent_fe_bh,
+                                &lookup);
+       if (status < 0) {
                mlog_errno(status);
                goto leave;
        }
 
        insert_inode_hash(inode);
-       dentry->d_op = &ocfs2_dentry_ops;
        d_instantiate(dentry, inode);
        status = 0;
 leave:
        if (status < 0 && did_quota_inode)
-               vfs_dq_free_inode(inode);
+               dquot_free_inode(inode);
        if (handle)
                ocfs2_commit_trans(osb, handle);
 
@@ -447,11 +450,6 @@ leave:
 
        ocfs2_free_dir_lookup_result(&lookup);
 
-       if ((status < 0) && inode) {
-               clear_nlink(inode);
-               iput(inode);
-       }
-
        if (inode_ac)
                ocfs2_free_alloc_context(inode_ac);
 
@@ -461,6 +459,17 @@ leave:
        if (meta_ac)
                ocfs2_free_alloc_context(meta_ac);
 
+       /*
+        * We should call iput after the i_mutex of the bitmap been
+        * unlocked in ocfs2_free_alloc_context, or the
+        * ocfs2_delete_inode will mutex_lock again.
+        */
+       if ((status < 0) && inode) {
+               OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SKIP_ORPHAN_DIR;
+               clear_nlink(inode);
+               iput(inode);
+       }
+
        mlog_exit(status);
 
        return status;
@@ -636,6 +645,8 @@ static int ocfs2_link(struct dentry *old_dentry,
        if (S_ISDIR(inode->i_mode))
                return -EPERM;
 
+       dquot_initialize(dir);
+
        err = ocfs2_inode_lock_nested(dir, &parent_fe_bh, 1, OI_LS_PARENT);
        if (err < 0) {
                if (err != -ENOENT)
@@ -791,6 +802,8 @@ static int ocfs2_unlink(struct inode *dir,
        mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry,
                   dentry->d_name.len, dentry->d_name.name);
 
+       dquot_initialize(dir);
+
        BUG_ON(dentry->d_parent->d_inode != dir);
 
        mlog(0, "ino = %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno);
@@ -877,7 +890,7 @@ static int ocfs2_unlink(struct inode *dir,
        fe = (struct ocfs2_dinode *) fe_bh->b_data;
 
        if (inode_is_unlinkable(inode)) {
-               status = ocfs2_orphan_add(osb, handle, inode, fe, orphan_name,
+               status = ocfs2_orphan_add(osb, handle, inode, fe_bh, orphan_name,
                                          &orphan_insert, orphan_dir);
                if (status < 0) {
                        mlog_errno(status);
@@ -1051,6 +1064,9 @@ static int ocfs2_rename(struct inode *old_dir,
                   old_dentry->d_name.len, old_dentry->d_name.name,
                   new_dentry->d_name.len, new_dentry->d_name.name);
 
+       dquot_initialize(old_dir);
+       dquot_initialize(new_dir);
+
        osb = OCFS2_SB(old_dir->i_sb);
 
        if (new_inode) {
@@ -1295,7 +1311,7 @@ static int ocfs2_rename(struct inode *old_dir,
                if (S_ISDIR(new_inode->i_mode) ||
                    (ocfs2_read_links_count(newfe) == 1)) {
                        status = ocfs2_orphan_add(osb, handle, new_inode,
-                                                 newfe, orphan_name,
+                                                 newfe_bh, orphan_name,
                                                  &orphan_insert, orphan_dir);
                        if (status < 0) {
                                mlog_errno(status);
@@ -1599,6 +1615,8 @@ static int ocfs2_symlink(struct inode *dir,
        mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir,
                   dentry, symname, dentry->d_name.len, dentry->d_name.name);
 
+       dquot_initialize(dir);
+
        sb = dir->i_sb;
        osb = OCFS2_SB(sb);
 
@@ -1688,13 +1706,9 @@ static int ocfs2_symlink(struct inode *dir,
                goto bail;
        }
 
-       /* We don't use standard VFS wrapper because we don't want vfs_dq_init
-        * to be called. */
-       if (sb_any_quota_active(osb->sb) &&
-           osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
-               status = -EDQUOT;
+       status = dquot_alloc_inode(inode);
+       if (status)
                goto bail;
-       }
        did_quota_inode = 1;
 
        mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry,
@@ -1716,11 +1730,10 @@ static int ocfs2_symlink(struct inode *dir,
                u32 offset = 0;
 
                inode->i_op = &ocfs2_symlink_inode_operations;
-               if (vfs_dq_alloc_space_nodirty(inode,
-                   ocfs2_clusters_to_bytes(osb->sb, 1))) {
-                       status = -EDQUOT;
+               status = dquot_alloc_space_nodirty(inode,
+                   ocfs2_clusters_to_bytes(osb->sb, 1));
+               if (status)
                        goto bail;
-               }
                did_quota = 1;
                status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0,
                                              new_fe_bh,
@@ -1769,29 +1782,34 @@ static int ocfs2_symlink(struct inode *dir,
                }
        }
 
-       status = ocfs2_add_entry(handle, dentry, inode,
-                                le64_to_cpu(fe->i_blkno), parent_fe_bh,
-                                &lookup);
-       if (status < 0) {
+       /*
+        * Do this before adding the entry to the directory. We add
+        * also set d_op after success so that ->d_iput() will cleanup
+        * the dentry lock even if ocfs2_add_entry() fails below.
+        */
+       status = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno);
+       if (status) {
                mlog_errno(status);
                goto bail;
        }
+       dentry->d_op = &ocfs2_dentry_ops;
 
-       status = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno);
-       if (status) {
+       status = ocfs2_add_entry(handle, dentry, inode,
+                                le64_to_cpu(fe->i_blkno), parent_fe_bh,
+                                &lookup);
+       if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
 
        insert_inode_hash(inode);
-       dentry->d_op = &ocfs2_dentry_ops;
        d_instantiate(dentry, inode);
 bail:
        if (status < 0 && did_quota)
-               vfs_dq_free_space_nodirty(inode,
+               dquot_free_space_nodirty(inode,
                                        ocfs2_clusters_to_bytes(osb->sb, 1));
        if (status < 0 && did_quota_inode)
-               vfs_dq_free_inode(inode);
+               dquot_free_inode(inode);
        if (handle)
                ocfs2_commit_trans(osb, handle);
 
@@ -1809,6 +1827,7 @@ bail:
        if (xattr_ac)
                ocfs2_free_alloc_context(xattr_ac);
        if ((status < 0) && inode) {
+               OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SKIP_ORPHAN_DIR;
                clear_nlink(inode);
                iput(inode);
        }
@@ -1909,7 +1928,7 @@ leave:
 static int ocfs2_orphan_add(struct ocfs2_super *osb,
                            handle_t *handle,
                            struct inode *inode,
-                           struct ocfs2_dinode *fe,
+                           struct buffer_head *fe_bh,
                            char *name,
                            struct ocfs2_dir_lookup_result *lookup,
                            struct inode *orphan_dir_inode)
@@ -1917,6 +1936,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
        struct buffer_head *orphan_dir_bh = NULL;
        int status = 0;
        struct ocfs2_dinode *orphan_fe;
+       struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data;
 
        mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
 
@@ -1957,13 +1977,31 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
                goto leave;
        }
 
+       /*
+        * We're going to journal the change of i_flags and i_orphaned_slot.
+        * It's safe anyway, though some callers may duplicate the journaling.
+        * Journaling within the func just make the logic look more
+        * straightforward.
+        */
+       status = ocfs2_journal_access_di(handle,
+                                        INODE_CACHE(inode),
+                                        fe_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
+       if (status < 0) {
+               mlog_errno(status);
+               goto leave;
+       }
+
        le32_add_cpu(&fe->i_flags, OCFS2_ORPHANED_FL);
+       OCFS2_I(inode)->ip_flags &= ~OCFS2_INODE_SKIP_ORPHAN_DIR;
 
        /* Record which orphan dir our inode now resides
         * in. delete_inode will use this to determine which orphan
         * dir to lock. */
        fe->i_orphaned_slot = cpu_to_le16(osb->slot_num);
 
+       ocfs2_journal_dirty(handle, fe_bh);
+
        mlog(0, "Inode %llu orphaned in slot %d\n",
             (unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num);
 
@@ -2099,15 +2137,12 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
                goto leave;
        }
 
-       /* We don't use standard VFS wrapper because we don't want vfs_dq_init
-        * to be called. */
-       if (sb_any_quota_active(osb->sb) &&
-           osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
-               status = -EDQUOT;
+       status = dquot_alloc_inode(inode);
+       if (status)
                goto leave;
-       }
        did_quota_inode = 1;
 
+       inode->i_nlink = 0;
        /* do the real work now. */
        status = ocfs2_mknod_locked(osb, dir, inode,
                                    0, &new_di_bh, parent_di_bh, handle,
@@ -2124,7 +2159,7 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
        }
 
        di = (struct ocfs2_dinode *)new_di_bh->b_data;
-       status = ocfs2_orphan_add(osb, handle, inode, di, orphan_name,
+       status = ocfs2_orphan_add(osb, handle, inode, new_di_bh, orphan_name,
                                  &orphan_insert, orphan_dir);
        if (status < 0) {
                mlog_errno(status);
@@ -2136,9 +2171,10 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
        if (status < 0)
                mlog_errno(status);
 
+       insert_inode_hash(inode);
 leave:
        if (status < 0 && did_quota_inode)
-               vfs_dq_free_inode(inode);
+               dquot_free_inode(inode);
        if (handle)
                ocfs2_commit_trans(osb, handle);
 
@@ -2267,6 +2303,8 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
        di = (struct ocfs2_dinode *)di_bh->b_data;
        le32_add_cpu(&di->i_flags, -OCFS2_ORPHANED_FL);
        di->i_orphaned_slot = 0;
+       inode->i_nlink = 1;
+       ocfs2_set_links_count(di, inode->i_nlink);
        ocfs2_journal_dirty(handle, di_bh);
 
        status = ocfs2_add_entry(handle, dentry, inode,
@@ -2284,7 +2322,6 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
                goto out_commit;
        }
 
-       insert_inode_hash(inode);
        dentry->d_op = &ocfs2_dentry_ops;
        d_instantiate(dentry, inode);
        status = 0;
@@ -2326,4 +2363,5 @@ const struct inode_operations ocfs2_dir_iops = {
        .getxattr       = generic_getxattr,
        .listxattr      = ocfs2_listxattr,
        .removexattr    = generic_removexattr,
+       .fiemap         = ocfs2_fiemap,
 };