diff mbox series

xfs_db: make flist_find_ftyp() to check for field existance on disk

Message ID 20230201172146.1874205-1-aalbersh@redhat.com (mailing list archive)
State Superseded
Headers show
Series xfs_db: make flist_find_ftyp() to check for field existance on disk | expand

Commit Message

Andrey Albershteyn Feb. 1, 2023, 5:21 p.m. UTC
flist_find_ftyp() searches for the field of the requested type. The
first found field/path is returned. However, this doesn't work when
there are multiple fields of the same type. For example, attr3 type
have a few CRC fields. Leaf block (xfs_attr_leaf_hdr ->
xfs_da3_blkinfo) and remote value block (xfs_attr3_rmt_hdr) both
have CRC but goes under attr3 type. This causes 'crc' command to be
unable to find CRC field when we are at remote attribute block as it
tries to use leaf block CRC path:

	$ dd if=/dev/zero bs=4k count=10 | tr '\000' '1' > test.img
	$ touch test.file
	$ setfattr -n user.bigattr -v "$(cat test.img)" test.file

	$ # CRC of the leaf block
	$ xfs_db -r -x /dev/sda5 -c 'inode 132' -c 'ablock 0' -c 'crc'
	Verifying CRC:
	hdr.info.crc = 0x102b5cbf (correct)

	$ # CRC of the remote value block
	$ xfs_db -r -x /dev/sda5 -c 'inode 132' -c 'ablock 1' -c 'crc'
	field info not found
	parsing error

Solve this by making flist_find_ftyp() to also check that field in
question have non-zero count (exist at the current block).

Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
---
 db/crc.c   |  2 +-
 db/flist.c | 13 ++++++++++---
 db/flist.h |  3 ++-
 3 files changed, 13 insertions(+), 5 deletions(-)

Comments

Darrick J. Wong Feb. 7, 2023, 5:39 p.m. UTC | #1
On Wed, Feb 01, 2023 at 06:21:47PM +0100, Andrey Albershteyn wrote:
> flist_find_ftyp() searches for the field of the requested type. The
> first found field/path is returned. However, this doesn't work when
> there are multiple fields of the same type. For example, attr3 type
> have a few CRC fields. Leaf block (xfs_attr_leaf_hdr ->
> xfs_da3_blkinfo) and remote value block (xfs_attr3_rmt_hdr) both
> have CRC but goes under attr3 type. This causes 'crc' command to be
> unable to find CRC field when we are at remote attribute block as it
> tries to use leaf block CRC path:
> 
> 	$ dd if=/dev/zero bs=4k count=10 | tr '\000' '1' > test.img
> 	$ touch test.file
> 	$ setfattr -n user.bigattr -v "$(cat test.img)" test.file
> 
> 	$ # CRC of the leaf block
> 	$ xfs_db -r -x /dev/sda5 -c 'inode 132' -c 'ablock 0' -c 'crc'
> 	Verifying CRC:
> 	hdr.info.crc = 0x102b5cbf (correct)
> 
> 	$ # CRC of the remote value block
> 	$ xfs_db -r -x /dev/sda5 -c 'inode 132' -c 'ablock 1' -c 'crc'
> 	field info not found
> 	parsing error
> 
> Solve this by making flist_find_ftyp() to also check that field in
> question have non-zero count (exist at the current block).
> 
> Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
> ---
>  db/crc.c   |  2 +-
>  db/flist.c | 13 ++++++++++---
>  db/flist.h |  3 ++-
>  3 files changed, 13 insertions(+), 5 deletions(-)
> 
> diff --git a/db/crc.c b/db/crc.c
> index 7428b916..1c73f980 100644
> --- a/db/crc.c
> +++ b/db/crc.c
> @@ -114,7 +114,7 @@ crc_f(
>  	}
>  
>  	/* Search for a CRC field */
> -	fl = flist_find_ftyp(fields, FLDT_CRC);
> +	fl = flist_find_ftyp(fields, FLDT_CRC, iocur_top->data, 0);
>  	if (!fl) {
>  		dbprintf(_("No CRC field found for type %s\n"), cur_typ->name);
>  		return 0;
> diff --git a/db/flist.c b/db/flist.c
> index 0bb6474c..d275abfe 100644
> --- a/db/flist.c
> +++ b/db/flist.c
> @@ -408,11 +408,14 @@ flist_split(
>   */
>  flist_t *
>  flist_find_ftyp(
> -	const field_t *fields,
> -	fldt_t	type)
> +	const field_t	*fields,
> +	fldt_t		type,
> +	void		*obj,
> +	int		startoff)
>  {
>  	flist_t	*fl;
>  	const field_t	*f;
> +	int		count;
>  	const ftattr_t  *fa;
>  
>  	for (f = fields; f->name; f++) {
> @@ -420,11 +423,15 @@ flist_find_ftyp(
>  		fl->fld = f;
>  		if (f->ftyp == type)
>  			return fl;
> +		count = fcount(f, obj, startoff);
> +		if (!count) {
> +			continue;
> +		}

Minor nit: no need for curly braces here.

With that cleaned up,
Reviewed-by: Darrick J. Wong <djwong@kernel.org>

--D

>  		fa = &ftattrtab[f->ftyp];
>  		if (fa->subfld) {
>  			flist_t *nfl;
>  
> -			nfl = flist_find_ftyp(fa->subfld, type);
> +			nfl = flist_find_ftyp(fa->subfld, type, obj, startoff);
>  			if (nfl) {
>  				fl->child = nfl;
>  				return fl;
> diff --git a/db/flist.h b/db/flist.h
> index f0772378..e327a360 100644
> --- a/db/flist.h
> +++ b/db/flist.h
> @@ -38,4 +38,5 @@ extern int	flist_parse(const struct field *fields, flist_t *fl, void *obj,
>  			    int startoff);
>  extern void	flist_print(flist_t *fl);
>  extern flist_t	*flist_scan(char *name);
> -extern flist_t	*flist_find_ftyp(const field_t *fields, fldt_t  type);
> +extern flist_t	*flist_find_ftyp(const field_t *fields, fldt_t  type, void *obj,
> +		int startoff);
> -- 
> 2.31.1
>
diff mbox series

Patch

diff --git a/db/crc.c b/db/crc.c
index 7428b916..1c73f980 100644
--- a/db/crc.c
+++ b/db/crc.c
@@ -114,7 +114,7 @@  crc_f(
 	}
 
 	/* Search for a CRC field */
-	fl = flist_find_ftyp(fields, FLDT_CRC);
+	fl = flist_find_ftyp(fields, FLDT_CRC, iocur_top->data, 0);
 	if (!fl) {
 		dbprintf(_("No CRC field found for type %s\n"), cur_typ->name);
 		return 0;
diff --git a/db/flist.c b/db/flist.c
index 0bb6474c..d275abfe 100644
--- a/db/flist.c
+++ b/db/flist.c
@@ -408,11 +408,14 @@  flist_split(
  */
 flist_t *
 flist_find_ftyp(
-	const field_t *fields,
-	fldt_t	type)
+	const field_t	*fields,
+	fldt_t		type,
+	void		*obj,
+	int		startoff)
 {
 	flist_t	*fl;
 	const field_t	*f;
+	int		count;
 	const ftattr_t  *fa;
 
 	for (f = fields; f->name; f++) {
@@ -420,11 +423,15 @@  flist_find_ftyp(
 		fl->fld = f;
 		if (f->ftyp == type)
 			return fl;
+		count = fcount(f, obj, startoff);
+		if (!count) {
+			continue;
+		}
 		fa = &ftattrtab[f->ftyp];
 		if (fa->subfld) {
 			flist_t *nfl;
 
-			nfl = flist_find_ftyp(fa->subfld, type);
+			nfl = flist_find_ftyp(fa->subfld, type, obj, startoff);
 			if (nfl) {
 				fl->child = nfl;
 				return fl;
diff --git a/db/flist.h b/db/flist.h
index f0772378..e327a360 100644
--- a/db/flist.h
+++ b/db/flist.h
@@ -38,4 +38,5 @@  extern int	flist_parse(const struct field *fields, flist_t *fl, void *obj,
 			    int startoff);
 extern void	flist_print(flist_t *fl);
 extern flist_t	*flist_scan(char *name);
-extern flist_t	*flist_find_ftyp(const field_t *fields, fldt_t  type);
+extern flist_t	*flist_find_ftyp(const field_t *fields, fldt_t  type, void *obj,
+		int startoff);