ocfs2: don't pass handle to ocfs2_meta_lock in ocfs2_rename()
Mark Fasheh [Fri, 6 Oct 2006 22:04:51 +0000 (15:04 -0700)]
Take and drop the locks directly.

Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>

fs/ocfs2/namei.c

index 7e9da94..5bd5f99 100644 (file)
@@ -104,13 +104,6 @@ static int ocfs2_fill_new_dir(struct ocfs2_super *osb,
                              struct buffer_head *fe_bh,
                              struct ocfs2_alloc_context *data_ac);
 
-static int ocfs2_double_lock(struct ocfs2_super *osb,
-                            struct ocfs2_journal_handle *handle,
-                            struct buffer_head **bh1,
-                            struct inode *inode1,
-                            struct buffer_head **bh2,
-                            struct inode *inode2);
-
 static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
                                    struct inode **ret_orphan_dir,
                                    struct inode *inode,
@@ -992,7 +985,6 @@ leave:
  * if they have the same id, then the 1st one is the only one locked.
  */
 static int ocfs2_double_lock(struct ocfs2_super *osb,
-                            struct ocfs2_journal_handle *handle,
                             struct buffer_head **bh1,
                             struct inode *inode1,
                             struct buffer_head **bh2,
@@ -1008,8 +1000,6 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
                   (unsigned long long)oi1->ip_blkno,
                   (unsigned long long)oi2->ip_blkno);
 
-       BUG_ON(!handle);
-
        if (*bh1)
                *bh1 = NULL;
        if (*bh2)
@@ -1029,25 +1019,41 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
                        inode1 = tmpinode;
                }
                /* lock id2 */
-               status = ocfs2_meta_lock(inode2, handle, bh2, 1);
+               status = ocfs2_meta_lock(inode2, NULL, bh2, 1);
                if (status < 0) {
                        if (status != -ENOENT)
                                mlog_errno(status);
                        goto bail;
                }
        }
+
        /* lock id1 */
-       status = ocfs2_meta_lock(inode1, handle, bh1, 1);
+       status = ocfs2_meta_lock(inode1, NULL, bh1, 1);
        if (status < 0) {
+               /*
+                * An error return must mean that no cluster locks
+                * were held on function exit.
+                */
+               if (oi1->ip_blkno != oi2->ip_blkno)
+                       ocfs2_meta_unlock(inode2, 1);
+
                if (status != -ENOENT)
                        mlog_errno(status);
-               goto bail;
        }
+
 bail:
        mlog_exit(status);
        return status;
 }
 
+static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2)
+{
+       ocfs2_meta_unlock(inode1, 1);
+
+       if (inode1 != inode2)
+               ocfs2_meta_unlock(inode2, 1);
+}
+
 #define PARENT_INO(buffer) \
        ((struct ocfs2_dir_entry *) \
         ((char *)buffer + \
@@ -1058,7 +1064,8 @@ static int ocfs2_rename(struct inode *old_dir,
                        struct inode *new_dir,
                        struct dentry *new_dentry)
 {
-       int status = 0, rename_lock = 0;
+       int status = 0, rename_lock = 0, parents_locked = 0;
+       int old_child_locked = 0, new_child_locked = 0;
        struct inode *old_inode = old_dentry->d_inode;
        struct inode *new_inode = new_dentry->d_inode;
        struct inode *orphan_dir = NULL;
@@ -1122,13 +1129,13 @@ static int ocfs2_rename(struct inode *old_dir,
        }
 
        /* if old and new are the same, this'll just do one lock. */
-       status = ocfs2_double_lock(osb, handle,
-                                 &old_dir_bh, old_dir,
-                                 &new_dir_bh, new_dir);
+       status = ocfs2_double_lock(osb, &old_dir_bh, old_dir,
+                                  &new_dir_bh, new_dir);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
+       parents_locked = 1;
 
        /* make sure both dirs have bhs
         * get an extra ref on old_dir_bh if old==new */
@@ -1149,12 +1156,13 @@ static int ocfs2_rename(struct inode *old_dir,
         * the vote thread on other nodes won't have to concurrently
         * downconvert the inode and the dentry locks.
         */
-       status = ocfs2_meta_lock(old_inode, handle, NULL, 1);
+       status = ocfs2_meta_lock(old_inode, NULL, NULL, 1);
        if (status < 0) {
                if (status != -ENOENT)
                        mlog_errno(status);
                goto bail;
        }
+       old_child_locked = 1;
 
        status = ocfs2_remote_dentry_delete(old_dentry);
        if (status < 0) {
@@ -1240,12 +1248,13 @@ static int ocfs2_rename(struct inode *old_dir,
                        goto bail;
                }
 
-               status = ocfs2_meta_lock(new_inode, handle, &newfe_bh, 1);
+               status = ocfs2_meta_lock(new_inode, NULL, &newfe_bh, 1);
                if (status < 0) {
                        if (status != -ENOENT)
                                mlog_errno(status);
                        goto bail;
                }
+               new_child_locked = 1;
 
                status = ocfs2_remote_dentry_delete(new_dentry);
                if (status < 0) {
@@ -1435,6 +1444,15 @@ bail:
        if (handle)
                ocfs2_commit_trans(handle);
 
+       if (parents_locked)
+               ocfs2_double_unlock(old_dir, new_dir);
+
+       if (old_child_locked)
+               ocfs2_meta_unlock(old_inode, 1);
+
+       if (new_child_locked)
+               ocfs2_meta_unlock(new_inode, 1);
+
        if (orphan_dir) {
                /* This was locked for us in ocfs2_prepare_orphan_dir() */
                ocfs2_meta_unlock(orphan_dir, 1);