diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2014-02-20 18:08:58 +0800 |
---|---|---|
committer | Josef Bacik <jbacik@fb.com> | 2014-03-10 15:16:43 -0400 |
commit | 8b050d350c7846462a21e9e054c9154ede9b43cf (patch) | |
tree | 3e756c4aeefc74fafa7db71293e92dac20832ed3 /fs/btrfs/file.c | |
parent | bb14a59b619d3a9993c3fa04bb10347db35ca550 (diff) | |
download | linux-8b050d350c7846462a21e9e054c9154ede9b43cf.tar.gz linux-8b050d350c7846462a21e9e054c9154ede9b43cf.tar.bz2 linux-8b050d350c7846462a21e9e054c9154ede9b43cf.zip |
Btrfs: fix skipped error handle when log sync failed
It is possible that many tasks sync the log tree at the same time, but
only one task can do the sync work, the others will wait for it. But those
wait tasks didn't get the result of the log sync, and returned 0 when they
ended the wait. It caused those tasks skipped the error handle, and the
serious problem was they told the users the file sync succeeded but in
fact they failed.
This patch fixes this problem by introducing a log context structure,
we insert it into the a global list. When the sync fails, we will set
the error number of every log context in the list, then the waiting tasks
get the error number of the log context and handle the error if need.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fb.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 006af2f4dd98..6acccc4a7f2a 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1864,8 +1864,9 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) struct dentry *dentry = file->f_path.dentry; struct inode *inode = dentry->d_inode; struct btrfs_root *root = BTRFS_I(inode)->root; - int ret = 0; struct btrfs_trans_handle *trans; + struct btrfs_log_ctx ctx; + int ret = 0; bool full_sync = 0; trace_btrfs_sync_file(file, datasync); @@ -1959,7 +1960,9 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) } trans->sync = true; - ret = btrfs_log_dentry_safe(trans, root, dentry); + btrfs_init_log_ctx(&ctx); + + ret = btrfs_log_dentry_safe(trans, root, dentry, &ctx); if (ret < 0) { /* Fallthrough and commit/free transaction. */ ret = 1; @@ -1979,7 +1982,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) if (ret != BTRFS_NO_LOG_SYNC) { if (!ret) { - ret = btrfs_sync_log(trans, root); + ret = btrfs_sync_log(trans, root, &ctx); if (!ret) { ret = btrfs_end_transaction(trans, root); goto out; |