summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorFilipe Manana2014-10-09 22:18:55 +0200
committerChris Mason2014-11-21 02:14:27 +0100
commit075bdbdbe9f21d68950ba5b187f80a4a23105365 (patch)
tree7a8cee33816ea7de60795f985068a176340e660d /fs/btrfs/file.c
parentBtrfs: make inode.c:compress_file_range() return void (diff)
downloadkernel-qcow2-linux-075bdbdbe9f21d68950ba5b187f80a4a23105365.tar.gz
kernel-qcow2-linux-075bdbdbe9f21d68950ba5b187f80a4a23105365.tar.xz
kernel-qcow2-linux-075bdbdbe9f21d68950ba5b187f80a4a23105365.zip
Btrfs: correctly flush compressed data before/after direct IO
For compressed writes, after doing the first filemap_fdatawrite_range() we don't get the pages tagged for writeback immediately. Instead we create a workqueue task, which is run by other kthread, and keep the pages locked. That other kthread compresses data, creates the respective ordered extent/s, tags the pages for writeback and unlocks them. Therefore we need a second call to filemap_fdatawrite_range() if we have compressed writes, as this second call will wait for the pages to become unlocked, then see they became tagged for writeback and finally wait for the writeback to finish. Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index a18ceabd99a8..f5a868ab60f3 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1692,8 +1692,18 @@ static ssize_t __btrfs_direct_write(struct kiocb *iocb,
err = written_buffered;
goto out;
}
+ /*
+ * Ensure all data is persisted. We want the next direct IO read to be
+ * able to read what was just written.
+ */
endbyte = pos + written_buffered - 1;
- err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte);
+ err = filemap_fdatawrite_range(file->f_mapping, pos, endbyte);
+ if (!err && test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT,
+ &BTRFS_I(file_inode(file))->runtime_flags))
+ err = filemap_fdatawrite_range(file->f_mapping, pos, endbyte);
+ if (err)
+ goto out;
+ err = filemap_fdatawait_range(file->f_mapping, pos, endbyte);
if (err)
goto out;
written += written_buffered;