ext3: Fix waiting on transaction during fsync
authorJan Kara <jack@suse.cz>
Thu, 15 Apr 2010 20:24:26 +0000 (22:24 +0200)
committerJan Kara <jack@suse.cz>
Fri, 21 May 2010 17:30:41 +0000 (19:30 +0200)
log_start_commit() returns 1 only when it started a transaction
commit. Thus in case transaction commit is already running, we
fail to wait for the commit to finish. Fix the issue by always
waiting for the commit regardless of the log_start_commit return
value.

Signed-off-by: Jan Kara <jack@suse.cz>
fs/ext3/fsync.c
fs/jbd/journal.c

index 8209f266e9ade19dbcb244634cc39a02623f2fa5..26289e8f4163c22b16dbb3cdd6c9293e814e354b 100644 (file)
@@ -48,7 +48,7 @@ int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync)
        struct inode *inode = dentry->d_inode;
        struct ext3_inode_info *ei = EXT3_I(inode);
        journal_t *journal = EXT3_SB(inode->i_sb)->s_journal;
-       int ret = 0;
+       int ret, needs_barrier = 0;
        tid_t commit_tid;
 
        if (inode->i_sb->s_flags & MS_RDONLY)
@@ -70,28 +70,26 @@ int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync)
         *  (they were dirtied by commit).  But that's OK - the blocks are
         *  safe in-journal, which is all fsync() needs to ensure.
         */
-       if (ext3_should_journal_data(inode)) {
-               ret = ext3_force_commit(inode->i_sb);
-               goto out;
-       }
+       if (ext3_should_journal_data(inode))
+               return ext3_force_commit(inode->i_sb);
 
        if (datasync)
                commit_tid = atomic_read(&ei->i_datasync_tid);
        else
                commit_tid = atomic_read(&ei->i_sync_tid);
 
-       if (log_start_commit(journal, commit_tid)) {
-               log_wait_commit(journal, commit_tid);
-               goto out;
-       }
+       if (test_opt(inode->i_sb, BARRIER) &&
+           !journal_trans_will_send_data_barrier(journal, commit_tid))
+               needs_barrier = 1;
+       log_start_commit(journal, commit_tid);
+       ret = log_wait_commit(journal, commit_tid);
 
        /*
         * In case we didn't commit a transaction, we have to flush
         * disk caches manually so that data really is on persistent
         * storage
         */
-       if (test_opt(inode->i_sb, BARRIER))
+       if (needs_barrier)
                blkdev_issue_flush(inode->i_sb->s_bdev, NULL);
-out:
        return ret;
 }
index 99c71940155af8beec811e77c677b37d77e1959e..93d1e47647bd48d0cd300358583a80b293ee1a77 100644 (file)
@@ -594,7 +594,7 @@ out:
        spin_unlock(&journal->j_state_lock);
        return ret;
 }
-EXPORT_SYMBOL(journal_commit_will_send_barrier);
+EXPORT_SYMBOL(journal_trans_will_send_data_barrier);
 
 /*
  * Log buffer allocation routines: