Introduce 'punch_extent_hole' to punch holes while
repair file extent.

Signed-off-by: Su Yue <suy.f...@cn.fujitsu.com>
---
 cmds-check.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 45 insertions(+), 6 deletions(-)

diff --git a/cmds-check.c b/cmds-check.c
index ae80d5f0..d228fc62 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -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) {
-- 
2.11.1



--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to