Btrfs: fix the race between write back and nocow buffered write
authorMiao Xie <miaox@cn.fujitsu.com>
Thu, 9 Jan 2014 02:06:10 +0000 (10:06 +0800)
committerChris Mason <clm@fb.com>
Tue, 28 Jan 2014 21:20:28 +0000 (13:20 -0800)
When we ran the 274th case of xfstests with nodatacow mount option,
We met the following warning message:
WARNING: CPU: 1 PID: 14185 at fs/btrfs/extent-tree.c:3734 btrfs_free_reserved_data_space+0xa6/0xd0

It is caused by the race between the write back and nocow buffered
write:
  Task1 Task2
  __btrfs_buffered_write()
    skip data reservation
    reserve the metadata space
    copy the data
    dirty the pages
    unlock the pages
write back the pages
release the data space
      becasue there is no
  noreserve flag
   set the noreserve flag

This patch fixes this problem by unlocking the pages after
the noreserve flag is set.

Reported-by: Tsutomu Itoh <t-itoh@jp.fujitsu.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fb.com>
Signed-off-by: Chris Mason <clm@fb.com>
fs/btrfs/file.c

index 72df63b0c79985deef815741b198ca78f84069cf..3dfd8db0e2439b3eb9b2cd387fb7f78a2bafeddc 100644 (file)
@@ -1591,9 +1591,10 @@ again:
                        unlock_extent_cached(&BTRFS_I(inode)->io_tree,
                                             lockstart, lockend, &cached_state,
                                             GFP_NOFS);
-               btrfs_drop_pages(pages, num_pages);
-               if (ret)
+               if (ret) {
+                       btrfs_drop_pages(pages, num_pages);
                        break;
+               }
 
                release_bytes = 0;
                if (only_release_metadata && copied > 0) {
@@ -1607,6 +1608,8 @@ again:
                        only_release_metadata = false;
                }
 
+               btrfs_drop_pages(pages, num_pages);
+
                cond_resched();
 
                balance_dirty_pages_ratelimited(inode->i_mapping);