Similar to the original mode repair.

Reported-by: Steve Leung <sjle...@shaw.ca>
Signed-off-by: Qu Wenruo <w...@suse.com>
---
 check/mode-lowmem.c | 73 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 72 insertions(+), 1 deletion(-)

diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
index 3280591396bd..cb778ce6f789 100644
--- a/check/mode-lowmem.c
+++ b/check/mode-lowmem.c
@@ -1735,6 +1735,70 @@ static int punch_extent_hole(struct btrfs_root *root, 
u64 ino, u64 start,
        return ret;
 }
 
+static int repair_inline_ram_bytes(struct btrfs_root *root,
+                                  struct btrfs_path *path, u64 *ram_bytes_ret)
+{
+       struct btrfs_trans_handle *trans;
+       struct btrfs_key key;
+       struct btrfs_file_extent_item *fi;
+       struct btrfs_item *i;
+       u32 on_disk_data_len;
+       int ret;
+       int recover_ret;
+
+       trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans)) {
+               ret = PTR_ERR(trans);
+               return ret;
+       }
+       btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
+       btrfs_release_path(path);
+       ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
+       /* Not really possible */
+       if (ret > 0) {
+               ret = -ENOENT;
+               btrfs_release_path(path);
+               goto recover;
+       }
+       if (ret < 0) {
+               goto recover;
+       }
+       i = btrfs_item_nr(path->slots[0]);
+       on_disk_data_len = btrfs_file_extent_inline_item_len(path->nodes[0], i);
+
+       fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
+                           struct btrfs_file_extent_item);
+       if (btrfs_file_extent_type(path->nodes[0], fi) !=
+                       BTRFS_FILE_EXTENT_INLINE ||
+           btrfs_file_extent_compression(path->nodes[0], fi) !=
+                       BTRFS_COMPRESS_NONE)
+               return -EINVAL;
+       btrfs_set_file_extent_ram_bytes(path->nodes[0], fi, on_disk_data_len);
+       btrfs_mark_buffer_dirty(path->nodes[0]);
+
+       ret = btrfs_commit_transaction(trans, root);
+       if (!ret) {
+               printf(
+       "Successfully repaired inline ram_bytes for root %llu ino %llu\n",
+                       root->objectid, key.objectid);
+               *ram_bytes_ret = on_disk_data_len;
+       }
+       return ret;
+
+recover:
+       /*
+        * CoW search failed, mostly due to the extra CoW work
+        * (extent allocation, etc).
+        * Since we have a good path before, readonly search should still
+        * work, or later checks will fail due to empty path
+        */
+       recover_ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+
+       /* This really shouldn't happen, or we have a big trouble */
+       ASSERT(recover_ret == 0);
+       return ret;
+}
+
 /*
  * Check file extent datasum/hole, update the size of the file extents,
  * check and update the last offset of the file extent.
@@ -1817,7 +1881,14 @@ static int check_file_extent(struct btrfs_root *root, 
struct btrfs_path *path,
                "root %llu EXTENT_DATA[%llu %llu] wrong inline size, have: 
%llu, expected: %u",
                                root->objectid, fkey.objectid, fkey.offset,
                                extent_num_bytes, item_inline_len);
-                       err |= FILE_EXTENT_ERROR;
+                       if (repair) {
+                               ret = repair_inline_ram_bytes(root, path,
+                                                             
&extent_num_bytes);
+                               if (ret)
+                                       err |= FILE_EXTENT_ERROR;
+                       } else {
+                               err |= FILE_EXTENT_ERROR;
+                       }
                }
                *end += extent_num_bytes;
                *size += extent_num_bytes;
-- 
2.17.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