Re: [PATCH v2] xfs_repair: fix link counts update following repair of a bad block

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Apr 15, 2025 at 10:07:57AM -0700, Darrick J. Wong wrote:
> On Tue, Apr 15, 2025 at 10:01:04AM -0500, bodonnel@xxxxxxxxxx wrote:
> > From: Bill O'Donnell <bodonnel@xxxxxxxxxx>
> > 
> > Updating nlinks, following repair of a bad block needs a bit of work.
> > In unique cases, 2 runs of xfs_repair is needed to adjust the count to
> > the proper value. This patch modifies location of longform_dir2_entry_check,
> > moving longform_dir2_entry_check_data to run after the check_dir3_header
> > error check. This results in the hashtab to be correctly filled and those
> > entries don't end up in lost+found, and nlinks is properly adjusted on the
> > first xfs_repair pass.
> > 
> > Suggested-by: Eric Sandeen <sandeen@xxxxxxxxxxx>
> > 
> > Signed-off-by: Bill O'Donnell <bodonnel@xxxxxxxxxx>
> > ---
> > v2: add logic to cover shortform directory.
> > 
> > 
> >  repair/phase6.c | 20 +++++++++++++++++---
> >  1 file changed, 17 insertions(+), 3 deletions(-)
> > 
> > diff --git a/repair/phase6.c b/repair/phase6.c
> > index dbc090a54139..8fc1c3896d2b 100644
> > --- a/repair/phase6.c
> > +++ b/repair/phase6.c
> > @@ -2426,6 +2426,23 @@ longform_dir2_entry_check(
> >  
> >  		/* check v5 metadata */
> >  		if (xfs_has_crc(mp)) {
> > +			longform_dir2_entry_check_data(mp, ip, num_illegal,
> > +				need_dot,
> > +				irec, ino_offset, bp, hashtab,
> > +				&freetab, da_bno, fmt == XFS_DIR2_FMT_BLOCK);
> > +			error = check_dir3_header(mp, bp, ino);
> > +			if (error) {
> > +				fixit++;
> 
> I think what you're trying to do here is to get
> longform_dir2_entry_check_data to try to find directory entries in the
> directory block (no matter how damaged it is).  Then if the dir3 header
> fields are wrong, we bump fixit so that the directory gets rebuilt from
> the salvaged directory entries.  Right?

Yes.

> 
> So I think you could structure this more like:
> 
> 		/* salvage any dirents that look ok */
> 		longform_dir2_entry_check_data(...);
> 
> 		/* check v5 metadata */
> 		if (xfs_has_crc(mp)) {
> 			error = check_dir3_header(mp, bp, ino);
> 			if (error) {
> 				fixit++;
> 				if (fmt == XFS_DIR2_FMT_BLOCK)
> 					goto out_fix;
> 
> 				libxfs_buf_relse(bp);
> 				bp = NULL;
> 				continue;
> 			}
> 		}
> 
> 		if (fmt == XFS_DIR2_FMT_BLOCK)
> 			break;
> 
> 		libxfs_buf_relse(bp);
> 		bp = NULL;
> 	}

Ah, this makes better sense.

> 
> > +				if (fmt == XFS_DIR2_FMT_BLOCK)
> > +					goto out_fix;
> > +
> > +				libxfs_buf_relse(bp);
> > +				bp = NULL;
> > +				continue;
> > +			}
> > +		}
> > +		else {
> > +			/* No crc. Directory appears to be shortform. */
> >  			error = check_dir3_header(mp, bp, ino);
> 
> dir3 headers (as opposed to dir2 headers) are a crc-only feature, so
> this isn't correct either.

Agree.

> 
> >  			if (error) {
> >  				fixit++;
> > @@ -2438,9 +2455,6 @@ longform_dir2_entry_check(
> >  			}
> >  		}
> >  
> > -		longform_dir2_entry_check_data(mp, ip, num_illegal, need_dot,
> > -				irec, ino_offset, bp, hashtab,
> > -				&freetab, da_bno, fmt == XFS_DIR2_FMT_BLOCK);
> 
> and removing this call means that we never scan a V4 directory at all.

Doh! I'll fix it up and send a v3. Thanks for your review.

-Bill


> 
> --D
> 
> >  		if (fmt == XFS_DIR2_FMT_BLOCK)
> >  			break;
> >  
> > -- 
> > 2.49.0
> > 
> > 
> 





[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux