btrfs-progs: check/lowmem: Prepare check_file_extent() to handle repair

Current check_file_extent() doesn't support later repair work, since it
doesn't accept btrfs_path structure as parameter, thus it can't modify
btrfs trees, or later check will still use the old and wrong path.

Use btrfs_path to replace btrfs_key, extent_buffer and slot parameters,
so we can modify @path directly for repair, and reduce the number of
parameters for check_file_extent().

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Qu Wenruo 2018-06-06 15:27:15 +08:00 committed by David Sterba
parent e5f50be06f
commit cd28b15496
1 changed files with 23 additions and 22 deletions

View File

@ -1740,18 +1740,18 @@ static int punch_extent_hole(struct btrfs_root *root, u64 ino, u64 start,
* check and update the last offset of the file extent.
*
* @root: the root of fs/file tree.
* @fkey: the key of the file extent.
* @nodatasum: INODE_NODATASUM feature.
* @size: the sum of all EXTENT_DATA items size for this inode.
* @end: the offset of the last extent.
*
* Return 0 if no error occurred.
*/
static int check_file_extent(struct btrfs_root *root, struct btrfs_key *fkey,
struct extent_buffer *node, int slot,
static int check_file_extent(struct btrfs_root *root, struct btrfs_path *path,
unsigned int nodatasum, u64 *size, u64 *end)
{
struct btrfs_file_extent_item *fi;
struct btrfs_key fkey;
struct extent_buffer *node = path->nodes[0];
u64 disk_bytenr;
u64 disk_num_bytes;
u64 extent_num_bytes;
@ -1763,10 +1763,12 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_key *fkey,
BTRFS_MAX_INLINE_DATA_SIZE(root->fs_info));
unsigned int extent_type;
unsigned int is_hole;
int slot = path->slots[0];
int compressed = 0;
int ret;
int err = 0;
btrfs_item_key_to_cpu(node, &fkey, slot);
fi = btrfs_item_ptr(node, slot, struct btrfs_file_extent_item);
/* Check inline extent */
@ -1781,23 +1783,23 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_key *fkey,
if (extent_num_bytes == 0) {
error(
"root %llu EXTENT_DATA[%llu %llu] has empty inline extent",
root->objectid, fkey->objectid, fkey->offset);
root->objectid, fkey.objectid, fkey.offset);
err |= FILE_EXTENT_ERROR;
}
if (compressed) {
if (extent_num_bytes > root->fs_info->sectorsize) {
error(
"root %llu EXTENT_DATA[%llu %llu] too large inline extent ram size, have %llu, max: %u",
root->objectid, fkey->objectid,
fkey->offset, extent_num_bytes,
root->objectid, fkey.objectid,
fkey.offset, extent_num_bytes,
root->fs_info->sectorsize - 1);
err |= FILE_EXTENT_ERROR;
}
if (item_inline_len > max_inline_extent_size) {
error(
"root %llu EXTENT_DATA[%llu %llu] too large inline extent on-disk size, have %u, max: %u",
root->objectid, fkey->objectid,
fkey->offset, item_inline_len,
root->objectid, fkey.objectid,
fkey.offset, item_inline_len,
max_inline_extent_size);
err |= FILE_EXTENT_ERROR;
}
@ -1805,7 +1807,7 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_key *fkey,
if (extent_num_bytes > max_inline_extent_size) {
error(
"root %llu EXTENT_DATA[%llu %llu] too large inline extent size, have %llu, max: %u",
root->objectid, fkey->objectid, fkey->offset,
root->objectid, fkey.objectid, fkey.offset,
extent_num_bytes, max_inline_extent_size);
err |= FILE_EXTENT_ERROR;
}
@ -1813,7 +1815,7 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_key *fkey,
if (!compressed && extent_num_bytes != item_inline_len) {
error(
"root %llu EXTENT_DATA[%llu %llu] wrong inline size, have: %llu, expected: %u",
root->objectid, fkey->objectid, fkey->offset,
root->objectid, fkey.objectid, fkey.offset,
extent_num_bytes, item_inline_len);
err |= FILE_EXTENT_ERROR;
}
@ -1827,7 +1829,7 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_key *fkey,
extent_type != BTRFS_FILE_EXTENT_PREALLOC) {
err |= FILE_EXTENT_ERROR;
error("root %llu EXTENT_DATA[%llu %llu] type bad",
root->objectid, fkey->objectid, fkey->offset);
root->objectid, fkey.objectid, fkey.offset);
return err;
}
@ -1864,12 +1866,12 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_key *fkey,
if (csum_found > 0 && nodatasum) {
err |= ODD_CSUM_ITEM;
error("root %llu EXTENT_DATA[%llu %llu] nodatasum shouldn't have datasum",
root->objectid, fkey->objectid, fkey->offset);
root->objectid, fkey.objectid, fkey.offset);
} else if (extent_type == BTRFS_FILE_EXTENT_REG && !nodatasum &&
!is_hole && (ret < 0 || csum_found < search_len)) {
err |= CSUM_ITEM_MISSING;
error("root %llu EXTENT_DATA[%llu %llu] csum missing, have: %llu, expected: %llu",
root->objectid, fkey->objectid, fkey->offset,
root->objectid, fkey.objectid, fkey.offset,
csum_found, search_len);
} else if (extent_type == BTRFS_FILE_EXTENT_PREALLOC &&
csum_found > 0) {
@ -1881,22 +1883,22 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_key *fkey,
err |= ODD_CSUM_ITEM;
error(
"root %llu EXTENT_DATA[%llu %llu] prealloc shouldn't have csum, but has: %llu",
root->objectid, fkey->objectid, fkey->offset,
root->objectid, fkey.objectid, fkey.offset,
csum_found);
}
}
/* Check EXTENT_DATA hole */
if (!no_holes && *end != fkey->offset) {
if (!no_holes && *end != fkey.offset) {
if (repair)
ret = punch_extent_hole(root, fkey->objectid,
*end, fkey->offset - *end);
ret = punch_extent_hole(root, fkey.objectid,
*end, fkey.offset - *end);
if (!repair || ret) {
err |= FILE_EXTENT_ERROR;
error(
"root %llu EXTENT_DATA[%llu %llu] gap exists, expected: EXTENT_DATA[%llu %llu]",
root->objectid, fkey->objectid, fkey->offset,
fkey->objectid, *end);
root->objectid, fkey.objectid, fkey.offset,
fkey.objectid, *end);
}
}
@ -2374,9 +2376,8 @@ static int check_inode_item(struct btrfs_root *root, struct btrfs_path *path)
root->objectid, inode_id, key.objectid,
key.offset);
}
ret = check_file_extent(root, &key, node, slot,
nodatasum, &extent_size,
&extent_end);
ret = check_file_extent(root, path, nodatasum,
&extent_size, &extent_end);
err |= ret;
break;
case BTRFS_XATTR_ITEM_KEY: