diff mbox series

[07/12] btrfs: add __btrfs_check_node helper

Message ID c78571e0ea619aefd33e2c6d1a6ac274cb15581f.1682798736.git.josef@toxicpanda.com (mailing list archive)
State New, archived
Headers show
Series btrfs: various cleanups to make ctree.c sync easier | expand

Commit Message

Josef Bacik April 29, 2023, 8:07 p.m. UTC
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>
---
 fs/btrfs/tree-checker.c | 29 +++++++++++++++++------------
 fs/btrfs/tree-checker.h |  1 +
 2 files changed, 18 insertions(+), 12 deletions(-)

Comments

Johannes Thumshirn May 2, 2023, 12:10 p.m. UTC | #1
On 29.04.23 22:08, Josef Bacik wrote:
> diff --git a/fs/btrfs/tree-checker.h b/fs/btrfs/tree-checker.h
> index 3b8de6d36141..c0861ce1429b 100644
> --- a/fs/btrfs/tree-checker.h
> +++ b/fs/btrfs/tree-checker.h
> @@ -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);

Sorry for only  noticing now, but shouldn't we do something like

#ifndef KERNEL
enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf);
enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *node);
#endif

and in fs/btrfs/tree-checker.c (or fs.h):

#ifdef KERNEL
#define EXPORT_FOR_PROGS static
#else
#define EXPORT_FOR_PROGS
#endif

Just like we did with EXPORT_FOR_TESTS?
David Sterba May 9, 2023, 10:07 p.m. UTC | #2
On Tue, May 02, 2023 at 12:10:20PM +0000, Johannes Thumshirn wrote:
> On 29.04.23 22:08, Josef Bacik wrote:
> > diff --git a/fs/btrfs/tree-checker.h b/fs/btrfs/tree-checker.h
> > index 3b8de6d36141..c0861ce1429b 100644
> > --- a/fs/btrfs/tree-checker.h
> > +++ b/fs/btrfs/tree-checker.h
> > @@ -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);
> 
> Sorry for only  noticing now, but shouldn't we do something like
> 
> #ifndef KERNEL
> enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf);
> enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *node);
> #endif
> 
> and in fs/btrfs/tree-checker.c (or fs.h):
> 
> #ifdef KERNEL
> #define EXPORT_FOR_PROGS static
> #else
> #define EXPORT_FOR_PROGS
> #endif
> 
> Just like we did with EXPORT_FOR_TESTS?

That's a good idea. Could we do it at the end of the series though? It's
not the cleanest way but the patches are otherwise simple and we won't
need to backport them so having the change split like that should not
cause trouble. I can also edit the patches in place if we insist.

With a separate patch I'd like to see how the conditional definitions
for kernel and userspace should be done first.
diff mbox series

Patch

diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
index 2c330e9d123a..eb9ba48d92aa 100644
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -1846,7 +1846,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);
@@ -1854,13 +1854,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,
@@ -1868,7 +1867,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++) {
@@ -1879,15 +1878,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)) {
@@ -1896,12 +1893,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);
 
diff --git a/fs/btrfs/tree-checker.h b/fs/btrfs/tree-checker.h
index 3b8de6d36141..c0861ce1429b 100644
--- a/fs/btrfs/tree-checker.h
+++ b/fs/btrfs/tree-checker.h
@@ -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);