Btrfs: fix stop searching test in replace_one_extent

replace_one_extent searches tree leaves for references to a given extent. It
stops searching if it goes beyond the last possible position.

The last possible position is computed by adding the starting offset of a found
file extent to the full size of the extent. The code uses physical size of the
extent as the full size. This is incorrect when compression is used.

The fix is get the full size from ram_bytes field of file extent item.

Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
This commit is contained in:
Yan Zheng 2009-01-21 10:49:16 -05:00 committed by Chris Mason
parent 95029d7d59
commit 86288a198d

View File

@ -4440,7 +4440,7 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans,
u64 lock_end = 0;
u64 num_bytes;
u64 ext_offset;
u64 first_pos;
u64 search_end = (u64)-1;
u32 nritems;
int nr_scaned = 0;
int extent_locked = 0;
@ -4448,7 +4448,6 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans,
int ret;
memcpy(&key, leaf_key, sizeof(key));
first_pos = INT_LIMIT(loff_t) - extent_key->offset;
if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS) {
if (key.objectid < ref_path->owner_objectid ||
(key.objectid == ref_path->owner_objectid &&
@ -4497,7 +4496,7 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans,
if ((key.objectid > ref_path->owner_objectid) ||
(key.objectid == ref_path->owner_objectid &&
key.type > BTRFS_EXTENT_DATA_KEY) ||
(key.offset >= first_pos + extent_key->offset))
key.offset >= search_end)
break;
}
@ -4530,8 +4529,10 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans,
num_bytes = btrfs_file_extent_num_bytes(leaf, fi);
ext_offset = btrfs_file_extent_offset(leaf, fi);
if (first_pos > key.offset - ext_offset)
first_pos = key.offset - ext_offset;
if (search_end == (u64)-1) {
search_end = key.offset - ext_offset +
btrfs_file_extent_ram_bytes(leaf, fi);
}
if (!extent_locked) {
lock_start = key.offset;
@ -4720,7 +4721,7 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans,
}
skip:
if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS &&
key.offset >= first_pos + extent_key->offset)
key.offset >= search_end)
break;
cond_resched();