summaryrefslogtreecommitdiff
path: root/fs/btrfs/ordered-data.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2012-07-12 17:55:40 +0200
committerArnd Bergmann <arnd@arndb.de>2012-07-12 17:55:40 +0200
commit9c63cd5a955ce8a3de1776a9e4b6b89c69b2a09e (patch)
tree2b628ebdaeb63603d90c92e78bc5dd668856b61d /fs/btrfs/ordered-data.c
parent8c203360a751ecbf876a8324e02c1dcbcc5dd548 (diff)
parent34ae0dadb4e99e8177f9785e069e9cca636ef8c1 (diff)
Merge tag 'imx-defconfig' of git://git.pengutronix.de/git/imx/linux-2.6 into next/defconfig
From Sascha Hauer <s.hauer@pengutronix.de>: ARM i.MX defconfig updates for v3.6 * tag 'imx-defconfig' of git://git.pengutronix.de/git/imx/linux-2.6: ARM: imx_v4_v5_defconfig: update features ARM: imx_v6_v7_defconfig: update features Includes an update to v3.5-rc5 Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'fs/btrfs/ordered-data.c')
-rw-r--r--fs/btrfs/ordered-data.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index 9e138cdc36c5..643335a4fe3c 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -627,7 +627,27 @@ void btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len)
/* start IO across the range first to instantiate any delalloc
* extents
*/
- filemap_write_and_wait_range(inode->i_mapping, start, orig_end);
+ filemap_fdatawrite_range(inode->i_mapping, start, orig_end);
+
+ /*
+ * So with compression we will find and lock a dirty page and clear the
+ * first one as dirty, setup an async extent, and immediately return
+ * with the entire range locked but with nobody actually marked with
+ * writeback. So we can't just filemap_write_and_wait_range() and
+ * expect it to work since it will just kick off a thread to do the
+ * actual work. So we need to call filemap_fdatawrite_range _again_
+ * since it will wait on the page lock, which won't be unlocked until
+ * after the pages have been marked as writeback and so we're good to go
+ * from there. We have to do this otherwise we'll miss the ordered
+ * extents and that results in badness. Please Josef, do not think you
+ * know better and pull this out at some point in the future, it is
+ * right and you are wrong.
+ */
+ if (test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT,
+ &BTRFS_I(inode)->runtime_flags))
+ filemap_fdatawrite_range(inode->i_mapping, start, orig_end);
+
+ filemap_fdatawait_range(inode->i_mapping, start, orig_end);
end = orig_end;
found = 0;