@@ -4483,6 +4483,7 @@ next:
memcpy(name_ret, namebuf, len);
*namelen_ret = len;
}
+
/* Check root dir ref */
if (ref_key->objectid == BTRFS_FIRST_FREE_OBJECTID) {
if (index != 0 || len != strlen("..") ||
@@ -5105,6 +5106,33 @@ next:
}
/*
+ * Wrapper function of btrfs_punch_hole.
+ *
+ * Returns 0 means success.
+ */
+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 {
+ btrfs_commit_transaction(trans, root);
+ printf("Added hole [%llu, %llu] in inode [%llu]\n", start, len,
+ ino);
+ }
+ return ret;
+}
+
+/*
* Check file extent datasum/hole, update the size of the file extents,
* check and update the last offset of the file extent.
*
@@ -5222,9 +5250,14 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_key *fkey,
error("root %llu EXTENT_DATA[%llu %llu] shouldn't be hole",
root->objectid, fkey->objectid, fkey->offset);
} else 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;
@@ -5724,9 +5757,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) {
Introduce 'punch_extent_hole' to punch holes while repair file extent. Signed-off-by: Su Yue <suy.fnst@cn.fujitsu.com> --- cmds-check.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 6 deletions(-)