ext4: start handle at the last possible moment in ext4_unlink()
authorTheodore Ts'o <tytso@mit.edu>
Sat, 9 Feb 2013 14:43:39 +0000 (09:43 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 9 Feb 2013 14:43:39 +0000 (09:43 -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 51841032ca031601c77e40e9de321802a6579681..4a27069d54adc1cb8da9e80f89dfca5e0a664d41 100644 (file)
@@ -2787,7 +2787,7 @@ static int ext4_unlink(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;
 
        trace_ext4_unlink_enter(dir, dentry);
        /* Initialize quotas before so that eventual writes go
@@ -2795,14 +2795,6 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
        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);
-
-       if (IS_DIRSYNC(dir))
-               ext4_handle_sync(handle);
-
        retval = -ENOENT;
        bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
        if (!bh)
@@ -2814,6 +2806,17 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
        if (le32_to_cpu(de->inode) != inode->i_ino)
                goto end_unlink;
 
+       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_unlink;
+       }
+
+       if (IS_DIRSYNC(dir))
+               ext4_handle_sync(handle);
+
        if (!inode->i_nlink) {
                ext4_warning(inode->i_sb,
                             "Deleting nonexistent file (%lu), %d",
@@ -2834,8 +2837,9 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
        retval = 0;
 
 end_unlink:
-       ext4_journal_stop(handle);
        brelse(bh);
+       if (handle)
+               ext4_journal_stop(handle);
        trace_ext4_unlink_exit(dentry, retval);
        return retval;
 }