summaryrefslogtreecommitdiffstats
path: root/fs/ext3/fsync.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2010-04-15 22:24:26 +0200
committerJan Kara <jack@suse.cz>2010-05-21 19:30:41 +0200
commit5277970878a32e437b27296e34c592e5d351f11d (patch)
tree64f41152b95e670935192ee6061653d922b642f3 /fs/ext3/fsync.c
parentjbd: Provide function to check whether transaction will issue data barrier (diff)
downloadlinux-5277970878a32e437b27296e34c592e5d351f11d.tar.xz
linux-5277970878a32e437b27296e34c592e5d351f11d.zip
ext3: Fix waiting on transaction during fsync
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>
Diffstat (limited to 'fs/ext3/fsync.c')
-rw-r--r--fs/ext3/fsync.c20
1 files changed, 9 insertions, 11 deletions
diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c
index 8209f266e9ad..26289e8f4163 100644
--- a/fs/ext3/fsync.c
+++ b/fs/ext3/fsync.c
@@ -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;
}