mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-04 17:44:14 +08:00
btrfs: scrub: introduce a helper to locate an extent item
The new helper, find_first_extent_item(), will locate an extent item (either EXTENT_ITEM or METADATA_ITEM) which covers any byte of the search range. This helper will later be used to refactor scrub code. Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
1194a82481
commit
416bd7e7af
107
fs/btrfs/scrub.c
107
fs/btrfs/scrub.c
@ -2859,6 +2859,113 @@ static void scrub_parity_put(struct scrub_parity *sparity)
|
||||
scrub_parity_check_and_repair(sparity);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 if the extent item range covers any byte of the range.
|
||||
* Return <0 if the extent item is before @search_start.
|
||||
* Return >0 if the extent item is after @start_start + @search_len.
|
||||
*/
|
||||
static int compare_extent_item_range(struct btrfs_path *path,
|
||||
u64 search_start, u64 search_len)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = path->nodes[0]->fs_info;
|
||||
u64 len;
|
||||
struct btrfs_key key;
|
||||
|
||||
btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
|
||||
ASSERT(key.type == BTRFS_EXTENT_ITEM_KEY ||
|
||||
key.type == BTRFS_METADATA_ITEM_KEY);
|
||||
if (key.type == BTRFS_METADATA_ITEM_KEY)
|
||||
len = fs_info->nodesize;
|
||||
else
|
||||
len = key.offset;
|
||||
|
||||
if (key.objectid + len <= search_start)
|
||||
return -1;
|
||||
if (key.objectid >= search_start + search_len)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate one extent item which covers any byte in range
|
||||
* [@search_start, @search_start + @search_length)
|
||||
*
|
||||
* If the path is not initialized, we will initialize the search by doing
|
||||
* a btrfs_search_slot().
|
||||
* If the path is already initialized, we will use the path as the initial
|
||||
* slot, to avoid duplicated btrfs_search_slot() calls.
|
||||
*
|
||||
* NOTE: If an extent item starts before @search_start, we will still
|
||||
* return the extent item. This is for data extent crossing stripe boundary.
|
||||
*
|
||||
* Return 0 if we found such extent item, and @path will point to the extent item.
|
||||
* Return >0 if no such extent item can be found, and @path will be released.
|
||||
* Return <0 if hit fatal error, and @path will be released.
|
||||
*/
|
||||
static int find_first_extent_item(struct btrfs_root *extent_root,
|
||||
struct btrfs_path *path,
|
||||
u64 search_start, u64 search_len)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = extent_root->fs_info;
|
||||
struct btrfs_key key;
|
||||
int ret;
|
||||
|
||||
/* Continue using the existing path */
|
||||
if (path->nodes[0])
|
||||
goto search_forward;
|
||||
|
||||
if (btrfs_fs_incompat(fs_info, SKINNY_METADATA))
|
||||
key.type = BTRFS_METADATA_ITEM_KEY;
|
||||
else
|
||||
key.type = BTRFS_EXTENT_ITEM_KEY;
|
||||
key.objectid = search_start;
|
||||
key.offset = (u64)-1;
|
||||
|
||||
ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ASSERT(ret > 0);
|
||||
/*
|
||||
* Here we intentionally pass 0 as @min_objectid, as there could be
|
||||
* an extent item starting before @search_start.
|
||||
*/
|
||||
ret = btrfs_previous_extent_item(extent_root, path, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/*
|
||||
* No matter whether we have found an extent item, the next loop will
|
||||
* properly do every check on the key.
|
||||
*/
|
||||
search_forward:
|
||||
while (true) {
|
||||
btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
|
||||
if (key.objectid >= search_start + search_len)
|
||||
break;
|
||||
if (key.type != BTRFS_METADATA_ITEM_KEY &&
|
||||
key.type != BTRFS_EXTENT_ITEM_KEY)
|
||||
goto next;
|
||||
|
||||
ret = compare_extent_item_range(path, search_start, search_len);
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
if (ret > 0)
|
||||
break;
|
||||
next:
|
||||
path->slots[0]++;
|
||||
if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) {
|
||||
ret = btrfs_next_leaf(extent_root, path);
|
||||
if (ret) {
|
||||
/* Either no more item or fatal error */
|
||||
btrfs_release_path(path);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
btrfs_release_path(path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static noinline_for_stack int scrub_raid56_parity(struct scrub_ctx *sctx,
|
||||
struct map_lookup *map,
|
||||
struct btrfs_device *sdev,
|
||||
|
Loading…
Reference in New Issue
Block a user