aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2013-12-27 08:11:50 -0500
committerChris Mason <clm@fb.com>2014-01-28 16:20:13 -0500
commite77751aad1facc4973613a11e2ad98ee4bbb04e1 (patch)
tree45d1dc9b9731bc047289c26671d1cfcd0b1a6fe4 /fs/btrfs/inode.c
parent25e293c2a2916b58cdafb8219c0e93d6277762d7 (diff)
Btrfs: fix the wrong nocow range check
The following warning message was outputed when running the 274th case of xfstests with nodatacow option: BUG: Bad page state in process kswapd0 pfn:1c66f page:ffffea0000636848 count:0 mapcount:0 mapping:(null) index:0x78000 page flags: 0x1000000000100a(error|uptodate|private_2) It is because the check of nocow range was wrong, we should compare the start and end position of the extent with the write position to verify if the write position was in the extent, but the current code just used the start postion to do the check, so we got the wrong extent and told the caller that it was a nocow write. And then when we write back the dirty pages, we found we should cow the extent, but at that time, there was no space in the fs, we had to the error flag for the page. When someone reclaimed that page, the above warning outputed. Fix it. 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>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 8e45fdcdbd8e..ffb23e506762 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6503,6 +6503,7 @@ noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len,
6503 int slot; 6503 int slot;
6504 int found_type; 6504 int found_type;
6505 bool nocow = (BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW); 6505 bool nocow = (BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW);
6506
6506 path = btrfs_alloc_path(); 6507 path = btrfs_alloc_path();
6507 if (!path) 6508 if (!path)
6508 return -ENOMEM; 6509 return -ENOMEM;
@@ -6546,6 +6547,10 @@ noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len,
6546 if (!nocow && found_type == BTRFS_FILE_EXTENT_REG) 6547 if (!nocow && found_type == BTRFS_FILE_EXTENT_REG)
6547 goto out; 6548 goto out;
6548 6549
6550 extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi);
6551 if (extent_end <= offset)
6552 goto out;
6553
6549 disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); 6554 disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
6550 if (disk_bytenr == 0) 6555 if (disk_bytenr == 0)
6551 goto out; 6556 goto out;
@@ -6563,8 +6568,6 @@ noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len,
6563 *ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi); 6568 *ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi);
6564 } 6569 }
6565 6570
6566 extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi);
6567
6568 if (btrfs_extent_readonly(root, disk_bytenr)) 6571 if (btrfs_extent_readonly(root, disk_bytenr))
6569 goto out; 6572 goto out;
6570 btrfs_release_path(path); 6573 btrfs_release_path(path);