]> git.hungrycats.org Git - linux/commitdiff
Btrfs: correctly flush compressed data before/after direct IO
authorFilipe Manana <fdmanana@suse.com>
Thu, 9 Oct 2014 20:18:55 +0000 (21:18 +0100)
committerZygo Blaxell <zblaxell@serenity.furryterror.org>
Fri, 23 Jan 2015 13:16:42 +0000 (08:16 -0500)
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>
(cherry picked from commit 075bdbdbe9f21d68950ba5b187f80a4a23105365)

fs/btrfs/file.c
fs/btrfs/inode.c

index 16a450e1775fce7492623ef44d67b91cc91daa21..31560513a52dfb1128099d07ec4dd8ead1013a3e 100644 (file)
@@ -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;
index d1a52850d17d5cea24cebe8716f0c4ba652f44c7..88b85cc0e18b46d386c39ef9d61c885bbbb16357 100644 (file)
@@ -7021,9 +7021,19 @@ static int lock_extent_direct(struct inode *inode, u64 lockstart, u64 lockend,
                        btrfs_put_ordered_extent(ordered);
                } else {
                        /* Screw you mmap */
-                       ret = filemap_write_and_wait_range(inode->i_mapping,
-                                                          lockstart,
-                                                          lockend);
+                       ret = filemap_fdatawrite_range(inode->i_mapping,
+                                                      lockstart,
+                                                      lockend);
+                       if (!ret && test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT,
+                                            &BTRFS_I(inode)->runtime_flags))
+                               ret = filemap_fdatawrite_range(inode->i_mapping,
+                                                              lockstart,
+                                                              lockend);
+                       if (ret)
+                               break;
+                       ret = filemap_fdatawait_range(inode->i_mapping,
+                                                     lockstart,
+                                                     lockend);
                        if (ret)
                                break;