btrfs: add __btrfs_check_node helper
authorJosef Bacik <josef@toxicpanda.com>
Sat, 29 Apr 2023 20:07:16 +0000 (16:07 -0400)
committerDavid Sterba <dsterba@suse.com>
Mon, 19 Jun 2023 11:59:25 +0000 (13:59 +0200)
This helper returns a btrfs_tree_block_status for the various errors,
and then btrfs_check_node() will return -EUCLEAN if it gets anything
other than BTRFS_TREE_BLOCK_CLEAN which will be used by the kernel.  In
the future btrfs-progs will use this helper instead.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/tree-checker.c
fs/btrfs/tree-checker.h

index 870b716b393f557aab2b25fddb92b75c96d80832..bd85205a6249a9a16cb1e7a43e0b7d0add9e89e0 100644 (file)
@@ -1845,7 +1845,7 @@ int btrfs_check_leaf(struct extent_buffer *leaf)
 }
 ALLOW_ERROR_INJECTION(btrfs_check_leaf, ERRNO);
 
-int btrfs_check_node(struct extent_buffer *node)
+enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *node)
 {
        struct btrfs_fs_info *fs_info = node->fs_info;
        unsigned long nr = btrfs_header_nritems(node);
@@ -1853,13 +1853,12 @@ int btrfs_check_node(struct extent_buffer *node)
        int slot;
        int level = btrfs_header_level(node);
        u64 bytenr;
-       int ret = 0;
 
        if (unlikely(level <= 0 || level >= BTRFS_MAX_LEVEL)) {
                generic_err(node, 0,
                        "invalid level for node, have %d expect [1, %d]",
                        level, BTRFS_MAX_LEVEL - 1);
-               return -EUCLEAN;
+               return BTRFS_TREE_BLOCK_INVALID_LEVEL;
        }
        if (unlikely(nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info))) {
                btrfs_crit(fs_info,
@@ -1867,7 +1866,7 @@ int btrfs_check_node(struct extent_buffer *node)
                           btrfs_header_owner(node), node->start,
                           nr == 0 ? "small" : "large", nr,
                           BTRFS_NODEPTRS_PER_BLOCK(fs_info));
-               return -EUCLEAN;
+               return BTRFS_TREE_BLOCK_INVALID_NRITEMS;
        }
 
        for (slot = 0; slot < nr - 1; slot++) {
@@ -1878,15 +1877,13 @@ int btrfs_check_node(struct extent_buffer *node)
                if (unlikely(!bytenr)) {
                        generic_err(node, slot,
                                "invalid NULL node pointer");
-                       ret = -EUCLEAN;
-                       goto out;
+                       return BTRFS_TREE_BLOCK_INVALID_BLOCKPTR;
                }
                if (unlikely(!IS_ALIGNED(bytenr, fs_info->sectorsize))) {
                        generic_err(node, slot,
                        "unaligned pointer, have %llu should be aligned to %u",
                                bytenr, fs_info->sectorsize);
-                       ret = -EUCLEAN;
-                       goto out;
+                       return BTRFS_TREE_BLOCK_INVALID_BLOCKPTR;
                }
 
                if (unlikely(btrfs_comp_cpu_keys(&key, &next_key) >= 0)) {
@@ -1895,12 +1892,20 @@ int btrfs_check_node(struct extent_buffer *node)
                                key.objectid, key.type, key.offset,
                                next_key.objectid, next_key.type,
                                next_key.offset);
-                       ret = -EUCLEAN;
-                       goto out;
+                       return BTRFS_TREE_BLOCK_BAD_KEY_ORDER;
                }
        }
-out:
-       return ret;
+       return BTRFS_TREE_BLOCK_CLEAN;
+}
+
+int btrfs_check_node(struct extent_buffer *node)
+{
+       enum btrfs_tree_block_status ret;
+
+       ret = __btrfs_check_node(node);
+       if (unlikely(ret != BTRFS_TREE_BLOCK_CLEAN))
+               return -EUCLEAN;
+       return 0;
 }
 ALLOW_ERROR_INJECTION(btrfs_check_node, ERRNO);
 
index 3b8de6d36141df9d51b80c7f72b070fb1f995db0..c0861ce1429b1f4105caf295097ab1de17f19aec 100644 (file)
@@ -58,6 +58,7 @@ enum btrfs_tree_block_status {
  * btrfs_tree_block_status return codes.
  */
 enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf);
+enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *node);
 
 int btrfs_check_leaf(struct extent_buffer *leaf);
 int btrfs_check_node(struct extent_buffer *node);