btrfs-progs: check: punch_extent_hole in lowmem
While checking file extents, there are two errors that may occur: 1) There is one hole between the last extent end and beginning of the current extent but no-holes is disabled. 2) No-holes is disabled, one file's nbytes equals 0 but isize is not 0. Those both mean the file may have lost some extents. To avoid btrfsck's error message, fix it by introducing function 'punch_extent_hole' to punch holes. For case 1, punch a hole extent whose length is (current extent begin - last extent end) while checking one extent. For case 2, punch a hole extent whose length is (file isize - actual file size) after traversing one entire file. Then repair_inode_nbytes will set the nbytes to isize. Signed-off-by: Su Yue <suy.fnst@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
3cfd3f608c
commit
a47604de3e
51
cmds-check.c
51
cmds-check.c
|
@ -5322,6 +5322,34 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper function of btrfs_punch_hole.
|
||||
*
|
||||
* Returns 0 means success.
|
||||
* Returns not 0 means error.
|
||||
*/
|
||||
static int punch_extent_hole(struct btrfs_root *root, u64 ino, u64 start,
|
||||
u64 len)
|
||||
{
|
||||
struct btrfs_trans_handle *trans;
|
||||
int ret = 0;
|
||||
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
if (IS_ERR(trans))
|
||||
return PTR_ERR(trans);
|
||||
|
||||
ret = btrfs_punch_hole(trans, root, ino, start, len);
|
||||
if (ret)
|
||||
error("failed to add hole [%llu, %llu] in inode [%llu]",
|
||||
start, len, ino);
|
||||
else
|
||||
printf("Add a hole [%llu, %llu] in inode [%llu]\n", start, len,
|
||||
ino);
|
||||
|
||||
btrfs_commit_transaction(trans, root);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check file extent datasum/hole, update the size of the file extents,
|
||||
* check and update the last offset of the file extent.
|
||||
|
@ -5437,9 +5465,14 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_key *fkey,
|
|||
|
||||
/* Check EXTENT_DATA hole */
|
||||
if (!no_holes && *end != fkey->offset) {
|
||||
err |= FILE_EXTENT_ERROR;
|
||||
error("root %llu EXTENT_DATA[%llu %llu] interrupt",
|
||||
root->objectid, fkey->objectid, fkey->offset);
|
||||
if (repair)
|
||||
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] interrupt",
|
||||
root->objectid, fkey->objectid, fkey->offset);
|
||||
}
|
||||
}
|
||||
|
||||
*end += extent_num_bytes;
|
||||
|
@ -5879,9 +5912,15 @@ out:
|
|||
}
|
||||
|
||||
if (!nbytes && !no_holes && extent_end < isize) {
|
||||
err |= NBYTES_ERROR;
|
||||
error("root %llu INODE[%llu] size (%llu) should have a file extent hole",
|
||||
root->objectid, inode_id, isize);
|
||||
if (repair)
|
||||
ret = punch_extent_hole(root, inode_id,
|
||||
extent_end, isize - extent_end);
|
||||
if (!repair || ret) {
|
||||
err |= NBYTES_ERROR;
|
||||
error(
|
||||
"root %llu INODE[%llu] size %llu should have a file extent hole",
|
||||
root->objectid, inode_id, isize);
|
||||
}
|
||||
}
|
||||
|
||||
if (nbytes != extent_size) {
|
||||
|
|
Loading…
Reference in New Issue