diff options
author | Yan Zheng <zheng.yan@oracle.com> | 2009-01-21 10:49:16 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2009-01-21 10:49:16 -0500 |
commit | 86288a198d8e4e8411ff02f9ab848245e8f11257 (patch) | |
tree | f580414864d322799a750a1dcc371f6dd62ce543 /fs/btrfs | |
parent | 95029d7d598babf62276d9006e575992b1333ba5 (diff) |
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>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/extent-tree.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c643433629a7..1d7f043152b0 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -4440,7 +4440,7 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans, | |||
4440 | u64 lock_end = 0; | 4440 | u64 lock_end = 0; |
4441 | u64 num_bytes; | 4441 | u64 num_bytes; |
4442 | u64 ext_offset; | 4442 | u64 ext_offset; |
4443 | u64 first_pos; | 4443 | u64 search_end = (u64)-1; |
4444 | u32 nritems; | 4444 | u32 nritems; |
4445 | int nr_scaned = 0; | 4445 | int nr_scaned = 0; |
4446 | int extent_locked = 0; | 4446 | int extent_locked = 0; |
@@ -4448,7 +4448,6 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans, | |||
4448 | int ret; | 4448 | int ret; |
4449 | 4449 | ||
4450 | memcpy(&key, leaf_key, sizeof(key)); | 4450 | memcpy(&key, leaf_key, sizeof(key)); |
4451 | first_pos = INT_LIMIT(loff_t) - extent_key->offset; | ||
4452 | if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS) { | 4451 | if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS) { |
4453 | if (key.objectid < ref_path->owner_objectid || | 4452 | if (key.objectid < ref_path->owner_objectid || |
4454 | (key.objectid == ref_path->owner_objectid && | 4453 | (key.objectid == ref_path->owner_objectid && |
@@ -4497,7 +4496,7 @@ next: | |||
4497 | if ((key.objectid > ref_path->owner_objectid) || | 4496 | if ((key.objectid > ref_path->owner_objectid) || |
4498 | (key.objectid == ref_path->owner_objectid && | 4497 | (key.objectid == ref_path->owner_objectid && |
4499 | key.type > BTRFS_EXTENT_DATA_KEY) || | 4498 | key.type > BTRFS_EXTENT_DATA_KEY) || |
4500 | (key.offset >= first_pos + extent_key->offset)) | 4499 | key.offset >= search_end) |
4501 | break; | 4500 | break; |
4502 | } | 4501 | } |
4503 | 4502 | ||
@@ -4530,8 +4529,10 @@ next: | |||
4530 | num_bytes = btrfs_file_extent_num_bytes(leaf, fi); | 4529 | num_bytes = btrfs_file_extent_num_bytes(leaf, fi); |
4531 | ext_offset = btrfs_file_extent_offset(leaf, fi); | 4530 | ext_offset = btrfs_file_extent_offset(leaf, fi); |
4532 | 4531 | ||
4533 | if (first_pos > key.offset - ext_offset) | 4532 | if (search_end == (u64)-1) { |
4534 | first_pos = key.offset - ext_offset; | 4533 | search_end = key.offset - ext_offset + |
4534 | btrfs_file_extent_ram_bytes(leaf, fi); | ||
4535 | } | ||
4535 | 4536 | ||
4536 | if (!extent_locked) { | 4537 | if (!extent_locked) { |
4537 | lock_start = key.offset; | 4538 | lock_start = key.offset; |
@@ -4720,7 +4721,7 @@ next: | |||
4720 | } | 4721 | } |
4721 | skip: | 4722 | skip: |
4722 | if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS && | 4723 | if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS && |
4723 | key.offset >= first_pos + extent_key->offset) | 4724 | key.offset >= search_end) |
4724 | break; | 4725 | break; |
4725 | 4726 | ||
4726 | cond_resched(); | 4727 | cond_resched(); |