diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2014-02-27 00:58:04 -0500 |
---|---|---|
committer | Josef Bacik <jbacik@fb.com> | 2014-03-10 15:17:00 -0400 |
commit | c933956ddf80bc455d33cbcf39d35d935daf45a9 (patch) | |
tree | 0417dba0c65787ad3de69f92563e1824086706a6 /fs/btrfs/file.c | |
parent | 9c9ca00bd31989f1a3dcbf54e97c979024e44409 (diff) |
Btrfs: fix wrong lock range and write size in check_can_nocow()
The write range may not be sector-aligned, for example:
|--------|--------| <- write range, sector-unaligned, size: 2blocks
|--------|--------|--------| <- correct lock range, size: 3blocks
But according to the old code, we used the size of write range to calculate
the lock range directly, not considered the offset, we would get a wrong lock
range:
|--------|--------| <- write range, sector-unaligned, size: 2blocks
|--------|--------| <- wrong lock range, size: 2blocks
And besides that, the old code also had the same problem when calculating
the real write size. Correct them.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fb.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 31e48b947060..fc2d21b0a022 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1411,7 +1411,7 @@ static noinline int check_can_nocow(struct inode *inode, loff_t pos, | |||
1411 | int ret; | 1411 | int ret; |
1412 | 1412 | ||
1413 | lockstart = round_down(pos, root->sectorsize); | 1413 | lockstart = round_down(pos, root->sectorsize); |
1414 | lockend = lockstart + round_up(*write_bytes, root->sectorsize) - 1; | 1414 | lockend = round_up(pos + *write_bytes, root->sectorsize) - 1; |
1415 | 1415 | ||
1416 | while (1) { | 1416 | while (1) { |
1417 | lock_extent(&BTRFS_I(inode)->io_tree, lockstart, lockend); | 1417 | lock_extent(&BTRFS_I(inode)->io_tree, lockstart, lockend); |
@@ -1434,7 +1434,8 @@ static noinline int check_can_nocow(struct inode *inode, loff_t pos, | |||
1434 | EXTENT_DIRTY | EXTENT_DELALLOC | | 1434 | EXTENT_DIRTY | EXTENT_DELALLOC | |
1435 | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 0, 0, | 1435 | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 0, 0, |
1436 | NULL, GFP_NOFS); | 1436 | NULL, GFP_NOFS); |
1437 | *write_bytes = min_t(size_t, *write_bytes, num_bytes); | 1437 | *write_bytes = min_t(size_t, *write_bytes , |
1438 | num_bytes - pos + lockstart); | ||
1438 | } | 1439 | } |
1439 | 1440 | ||
1440 | unlock_extent(&BTRFS_I(inode)->io_tree, lockstart, lockend); | 1441 | unlock_extent(&BTRFS_I(inode)->io_tree, lockstart, lockend); |