diff mbox series

btrfs-progs: tree-checker: dump the tree block when hitting an error

Message ID a5ab0e98ae40df23b3bb65235f7bd9296e3b0be4.1705027543.git.wqu@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs-progs: tree-checker: dump the tree block when hitting an error | expand

Commit Message

Qu Wenruo Jan. 12, 2024, 2:46 a.m. UTC
Unlike kernel where tree-checker would provide enough info so later we
can use "btrfs inspect dump-tree" to catch the offending tree block, in
progs we may not even have a btrfs to start "btrfs inspect dump-tree".
E.g during btrfs-convert.

To make later debug easier, let's call btrfs_print_tree() for every
error we hit inside tree-checker.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 kernel-shared/tree-checker.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

Comments

David Sterba Jan. 12, 2024, 3:36 p.m. UTC | #1
On Fri, Jan 12, 2024 at 01:16:20PM +1030, Qu Wenruo wrote:
> Unlike kernel where tree-checker would provide enough info so later we
> can use "btrfs inspect dump-tree" to catch the offending tree block, in
> progs we may not even have a btrfs to start "btrfs inspect dump-tree".
> E.g during btrfs-convert.
> 
> To make later debug easier, let's call btrfs_print_tree() for every
> error we hit inside tree-checker.
> 
> Signed-off-by: Qu Wenruo <wqu@suse.com>

Added to devel, thanks.

> ---
>  kernel-shared/tree-checker.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/kernel-shared/tree-checker.c b/kernel-shared/tree-checker.c
> index 003156795a43..a98553985402 100644
> --- a/kernel-shared/tree-checker.c
> +++ b/kernel-shared/tree-checker.c
> @@ -33,6 +33,7 @@
>  #include "kernel-shared/accessors.h"
>  #include "kernel-shared/file-item.h"
>  #include "kernel-shared/extent_io.h"
> +#include "kernel-shared/print-tree.h"
>  #include "kernel-shared/uapi/btrfs.h"
>  #include "kernel-shared/uapi/btrfs_tree.h"
>  #include "common/internal.h"
> @@ -95,6 +96,8 @@ static void generic_err(const struct extent_buffer *eb, int slot,
>  		btrfs_header_level(eb) == 0 ? "leaf" : "node",
>  		btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, &vaf);
>  	va_end(args);
> +
> +	btrfs_print_tree((struct extent_buffer *)eb, 0);

Printing the eb should not require writable eb, but there are many
functions that would need to be converted to 'const' so the cas is OK
for now but cleaning that up would be welcome.
Qu Wenruo Jan. 12, 2024, 8:33 p.m. UTC | #2
On 2024/1/13 02:06, David Sterba wrote:
> On Fri, Jan 12, 2024 at 01:16:20PM +1030, Qu Wenruo wrote:
>> Unlike kernel where tree-checker would provide enough info so later we
>> can use "btrfs inspect dump-tree" to catch the offending tree block, in
>> progs we may not even have a btrfs to start "btrfs inspect dump-tree".
>> E.g during btrfs-convert.
>>
>> To make later debug easier, let's call btrfs_print_tree() for every
>> error we hit inside tree-checker.
>>
>> Signed-off-by: Qu Wenruo <wqu@suse.com>
>
> Added to devel, thanks.
>
>> ---
>>   kernel-shared/tree-checker.c | 15 +++++++++++++++
>>   1 file changed, 15 insertions(+)
>>
>> diff --git a/kernel-shared/tree-checker.c b/kernel-shared/tree-checker.c
>> index 003156795a43..a98553985402 100644
>> --- a/kernel-shared/tree-checker.c
>> +++ b/kernel-shared/tree-checker.c
>> @@ -33,6 +33,7 @@
>>   #include "kernel-shared/accessors.h"
>>   #include "kernel-shared/file-item.h"
>>   #include "kernel-shared/extent_io.h"
>> +#include "kernel-shared/print-tree.h"
>>   #include "kernel-shared/uapi/btrfs.h"
>>   #include "kernel-shared/uapi/btrfs_tree.h"
>>   #include "common/internal.h"
>> @@ -95,6 +96,8 @@ static void generic_err(const struct extent_buffer *eb, int slot,
>>   		btrfs_header_level(eb) == 0 ? "leaf" : "node",
>>   		btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, &vaf);
>>   	va_end(args);
>> +
>> +	btrfs_print_tree((struct extent_buffer *)eb, 0);
>
> Printing the eb should not require writable eb, but there are many
> functions that would need to be converted to 'const' so the cas is OK
> for now but cleaning that up would be welcome.

I tried but failed.

Most of the call sites are fine to be constified, but there is a special
trap inside bfs_print_children(), where we call extent_buffer_get(),
which can never be called on a const eb pointer.

Thus that's why we are still using the ugly forced convert here.

Thanks,
Qu
>
David Sterba Jan. 15, 2024, 2:54 p.m. UTC | #3
On Sat, Jan 13, 2024 at 07:03:18AM +1030, Qu Wenruo wrote:
> >> +	btrfs_print_tree((struct extent_buffer *)eb, 0);
> >
> > Printing the eb should not require writable eb, but there are many
> > functions that would need to be converted to 'const' so the cas is OK
> > for now but cleaning that up would be welcome.
> 
> I tried but failed.
> 
> Most of the call sites are fine to be constified, but there is a special
> trap inside bfs_print_children(), where we call extent_buffer_get(),
> which can never be called on a const eb pointer.

Oh, I see. We can't remove the ref update but what if we reset the path
slot to NULL before releasing it?
Qu Wenruo Jan. 15, 2024, 10:43 p.m. UTC | #4
On 2024/1/16 01:24, David Sterba wrote:
> On Sat, Jan 13, 2024 at 07:03:18AM +1030, Qu Wenruo wrote:
>>>> +	btrfs_print_tree((struct extent_buffer *)eb, 0);
>>>
>>> Printing the eb should not require writable eb, but there are many
>>> functions that would need to be converted to 'const' so the cas is OK
>>> for now but cleaning that up would be welcome.
>>
>> I tried but failed.
>>
>> Most of the call sites are fine to be constified, but there is a special
>> trap inside bfs_print_children(), where we call extent_buffer_get(),
>> which can never be called on a const eb pointer.
>
> Oh, I see. We can't remove the ref update but what if we reset the path
> slot to NULL before releasing it?

The other solution would be, only consitfy btrfs_print_node() and
btrfs_print_leaf().

For anything that would need to traversal the tree, still allow them to
modify the eb.

I'll give it a try, and if it passed compile, that would be my next step.
Would this be a good idea?

Thanks,
Qu
David Sterba Jan. 16, 2024, 4 p.m. UTC | #5
On Tue, Jan 16, 2024 at 09:13:23AM +1030, Qu Wenruo wrote:
> 
> 
> On 2024/1/16 01:24, David Sterba wrote:
> > On Sat, Jan 13, 2024 at 07:03:18AM +1030, Qu Wenruo wrote:
> >>>> +	btrfs_print_tree((struct extent_buffer *)eb, 0);
> >>>
> >>> Printing the eb should not require writable eb, but there are many
> >>> functions that would need to be converted to 'const' so the cas is OK
> >>> for now but cleaning that up would be welcome.
> >>
> >> I tried but failed.
> >>
> >> Most of the call sites are fine to be constified, but there is a special
> >> trap inside bfs_print_children(), where we call extent_buffer_get(),
> >> which can never be called on a const eb pointer.
> >
> > Oh, I see. We can't remove the ref update but what if we reset the path
> > slot to NULL before releasing it?
> 
> The other solution would be, only consitfy btrfs_print_node() and
> btrfs_print_leaf().
> 
> For anything that would need to traversal the tree, still allow them to
> modify the eb.
> 
> I'll give it a try, and if it passed compile, that would be my next step.
> Would this be a good idea?

Yeah makes sense, we'll se how much can it can be cleaned up. The const
parameters are nice to have as they don't really break anything, but
should be used as a matter of good coding practices.
diff mbox series

Patch

diff --git a/kernel-shared/tree-checker.c b/kernel-shared/tree-checker.c
index 003156795a43..a98553985402 100644
--- a/kernel-shared/tree-checker.c
+++ b/kernel-shared/tree-checker.c
@@ -33,6 +33,7 @@ 
 #include "kernel-shared/accessors.h"
 #include "kernel-shared/file-item.h"
 #include "kernel-shared/extent_io.h"
+#include "kernel-shared/print-tree.h"
 #include "kernel-shared/uapi/btrfs.h"
 #include "kernel-shared/uapi/btrfs_tree.h"
 #include "common/internal.h"
@@ -95,6 +96,8 @@  static void generic_err(const struct extent_buffer *eb, int slot,
 		btrfs_header_level(eb) == 0 ? "leaf" : "node",
 		btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, &vaf);
 	va_end(args);
+
+	btrfs_print_tree((struct extent_buffer *)eb, 0);
 }
 
 /*
@@ -123,6 +126,8 @@  static void file_extent_err(const struct extent_buffer *eb, int slot,
 		btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot,
 		key.objectid, key.offset, &vaf);
 	va_end(args);
+
+	btrfs_print_tree((struct extent_buffer *)eb, 0);
 }
 
 /*
@@ -183,6 +188,8 @@  static void dir_item_err(const struct extent_buffer *eb, int slot,
 		btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot,
 		key.objectid, &vaf);
 	va_end(args);
+
+	btrfs_print_tree((struct extent_buffer *)eb, 0);
 }
 
 /*
@@ -669,6 +676,8 @@  static void block_group_err(const struct extent_buffer *eb, int slot,
 		btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot,
 		key.objectid, key.offset, &vaf);
 	va_end(args);
+
+	btrfs_print_tree((struct extent_buffer *)eb, 0);
 }
 
 static int check_block_group_item(struct extent_buffer *leaf,
@@ -800,6 +809,8 @@  static void chunk_err(const struct extent_buffer *leaf,
 			   BTRFS_CHUNK_TREE_OBJECTID, leaf->start, slot,
 			   logical, &vaf);
 	va_end(args);
+
+	btrfs_print_tree((struct extent_buffer *)leaf, 0);
 }
 
 /*
@@ -1025,6 +1036,8 @@  static void dev_item_err(const struct extent_buffer *eb, int slot,
 		btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot,
 		key.objectid, &vaf);
 	va_end(args);
+
+	btrfs_print_tree((struct extent_buffer *)eb, 0);
 }
 
 static int check_dev_item(struct extent_buffer *leaf,
@@ -1279,6 +1292,8 @@  static void extent_err(const struct extent_buffer *eb, int slot,
 		btrfs_header_level(eb) == 0 ? "leaf" : "node",
 		eb->start, slot, bytenr, len, &vaf);
 	va_end(args);
+
+	btrfs_print_tree((struct extent_buffer *)eb, 0);
 }
 
 static int check_extent_item(struct extent_buffer *leaf,