jfs: clean up jfs_rename and fix out of order unlock
authorDave Kleikamp <dave.kleikamp@oracle.com>
Wed, 15 Jul 2015 17:52:47 +0000 (12:52 -0500)
committerDave Kleikamp <dave.kleikamp@oracle.com>
Wed, 15 Jul 2015 19:11:30 +0000 (14:11 -0500)
The end of jfs_rename(), which is also used by the error paths,
included a call to IWRITE_UNLOCK(new_ip) after labels out1, out2
and out3. If we come in through these labels, IWRITE_LOCK() has not
been called yet.

In moving that call to the correct spot, I also moved some
exceptional truncate code earlier as well, since the early error
paths don't need to deal with it, and I renamed out4: to out_tx: so
a future patch by Jan Kara doesn't need to deal with renumbering or
confusing out-of-order labels.

Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
fs/jfs/namei.c

index 66db7bc..f7b4037 100644 (file)
@@ -1161,7 +1161,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                rc = dtModify(tid, new_dir, &new_dname, &ino,
                              old_ip->i_ino, JFS_RENAME);
                if (rc)
-                       goto out4;
+                       goto out_tx;
                drop_nlink(new_ip);
                if (S_ISDIR(new_ip->i_mode)) {
                        drop_nlink(new_ip);
@@ -1186,7 +1186,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        if ((new_size = commitZeroLink(tid, new_ip)) < 0) {
                                txAbort(tid, 1);        /* Marks FS Dirty */
                                rc = new_size;
-                               goto out4;
+                               goto out_tx;
                        }
                        tblk = tid_to_tblock(tid);
                        tblk->xflag |= COMMIT_DELETE;
@@ -1204,7 +1204,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                if (rc) {
                        jfs_err("jfs_rename didn't expect dtSearch to fail "
                                "w/rc = %d", rc);
-                       goto out4;
+                       goto out_tx;
                }
 
                ino = old_ip->i_ino;
@@ -1212,7 +1212,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                if (rc) {
                        if (rc == -EIO)
                                jfs_err("jfs_rename: dtInsert returned -EIO");
-                       goto out4;
+                       goto out_tx;
                }
                if (S_ISDIR(old_ip->i_mode))
                        inc_nlink(new_dir);
@@ -1227,7 +1227,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                jfs_err("jfs_rename did not expect dtDelete to return rc = %d",
                        rc);
                txAbort(tid, 1);        /* Marks Filesystem dirty */
-               goto out4;
+               goto out_tx;
        }
        if (S_ISDIR(old_ip->i_mode)) {
                drop_nlink(old_dir);
@@ -1286,7 +1286,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
        rc = txCommit(tid, ipcount, iplist, commit_flag);
 
-      out4:
+      out_tx:
        txEnd(tid);
        if (new_ip)
                mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
@@ -1309,13 +1309,6 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        }
        if (new_ip && (new_ip->i_nlink == 0))
                set_cflag(COMMIT_Nolink, new_ip);
-      out3:
-       free_UCSname(&new_dname);
-      out2:
-       free_UCSname(&old_dname);
-      out1:
-       if (new_ip && !S_ISDIR(new_ip->i_mode))
-               IWRITE_UNLOCK(new_ip);
        /*
         * Truncating the directory index table is not guaranteed.  It
         * may need to be done iteratively
@@ -1326,7 +1319,13 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
                clear_cflag(COMMIT_Stale, old_dir);
        }
-
+       if (new_ip && !S_ISDIR(new_ip->i_mode))
+               IWRITE_UNLOCK(new_ip);
+      out3:
+       free_UCSname(&new_dname);
+      out2:
+       free_UCSname(&old_dname);
+      out1:
        jfs_info("jfs_rename: returning %d", rc);
        return rc;
 }