aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2014-02-20 05:08:58 -0500
committerJosef Bacik <jbacik@fb.com>2014-03-10 15:16:43 -0400
commit8b050d350c7846462a21e9e054c9154ede9b43cf (patch)
tree3e756c4aeefc74fafa7db71293e92dac20832ed3 /fs/btrfs/file.c
parentbb14a59b619d3a9993c3fa04bb10347db35ca550 (diff)
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.c9
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)
1864 struct dentry *dentry = file->f_path.dentry; 1864 struct dentry *dentry = file->f_path.dentry;
1865 struct inode *inode = dentry->d_inode; 1865 struct inode *inode = dentry->d_inode;
1866 struct btrfs_root *root = BTRFS_I(inode)->root; 1866 struct btrfs_root *root = BTRFS_I(inode)->root;
1867 int ret = 0;
1868 struct btrfs_trans_handle *trans; 1867 struct btrfs_trans_handle *trans;
1868 struct btrfs_log_ctx ctx;
1869 int ret = 0;
1869 bool full_sync = 0; 1870 bool full_sync = 0;
1870 1871
1871 trace_btrfs_sync_file(file, datasync); 1872 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)
1959 } 1960 }
1960 trans->sync = true; 1961 trans->sync = true;
1961 1962
1962 ret = btrfs_log_dentry_safe(trans, root, dentry); 1963 btrfs_init_log_ctx(&ctx);
1964
1965 ret = btrfs_log_dentry_safe(trans, root, dentry, &ctx);
1963 if (ret < 0) { 1966 if (ret < 0) {
1964 /* Fallthrough and commit/free transaction. */ 1967 /* Fallthrough and commit/free transaction. */
1965 ret = 1; 1968 ret = 1;
@@ -1979,7 +1982,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
1979 1982
1980 if (ret != BTRFS_NO_LOG_SYNC) { 1983 if (ret != BTRFS_NO_LOG_SYNC) {
1981 if (!ret) { 1984 if (!ret) {
1982 ret = btrfs_sync_log(trans, root); 1985 ret = btrfs_sync_log(trans, root, &ctx);
1983 if (!ret) { 1986 if (!ret) {
1984 ret = btrfs_end_transaction(trans, root); 1987 ret = btrfs_end_transaction(trans, root);
1985 goto out; 1988 goto out;