]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - fs/btrfs/ordered-data.c
Merge branch 'fixes-for-grant' of git://sources.calxeda.com/kernel/linux
[karo-tx-linux.git] / fs / btrfs / ordered-data.c
index 9e138cdc36c5eb7d66bf80dfc37829878eeaa6e2..643335a4fe3c6699a894c19d01e79bed9ef631c7 100644 (file)
@@ -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;