ext4: start handle at the last possible moment in ext4_rmdir()
authorTheodore Ts'o <tytso@mit.edu>
Sat, 9 Feb 2013 14:45:11 +0000 (09:45 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 9 Feb 2013 14:45:11 +0000 (09:45 -0500)
Don't start the jbd2 transaction handle until after the directory
entry has been found, to minimize the amount of time that a handle is
held active.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Reviewed-by: Jan Kara <jack@suse.cz>
fs/ext4/namei.c

index 4a27069..36a4afd 100644 (file)
@@ -2725,26 +2725,18 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
        struct inode *inode;
        struct buffer_head *bh;
        struct ext4_dir_entry_2 *de;
-       handle_t *handle;
+       handle_t *handle = NULL;
 
        /* Initialize quotas before so that eventual writes go in
         * separate transaction */
        dquot_initialize(dir);
        dquot_initialize(dentry->d_inode);
 
-       handle = ext4_journal_start(dir, EXT4_HT_DIR,
-                                   EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
-       if (IS_ERR(handle))
-               return PTR_ERR(handle);
-
        retval = -ENOENT;
        bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
        if (!bh)
                goto end_rmdir;
 
-       if (IS_DIRSYNC(dir))
-               ext4_handle_sync(handle);
-
        inode = dentry->d_inode;
 
        retval = -EIO;
@@ -2755,6 +2747,17 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
        if (!empty_dir(inode))
                goto end_rmdir;
 
+       handle = ext4_journal_start(dir, EXT4_HT_DIR,
+                                   EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
+       if (IS_ERR(handle)) {
+               retval = PTR_ERR(handle);
+               handle = NULL;
+               goto end_rmdir;
+       }
+
+       if (IS_DIRSYNC(dir))
+               ext4_handle_sync(handle);
+
        retval = ext4_delete_entry(handle, dir, de, bh);
        if (retval)
                goto end_rmdir;
@@ -2776,8 +2779,9 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
        ext4_mark_inode_dirty(handle, dir);
 
 end_rmdir:
-       ext4_journal_stop(handle);
        brelse(bh);
+       if (handle)
+               ext4_journal_stop(handle);
        return retval;
 }