On 2/11/20 4:11 AM, John Jore wrote: > Hi and thanks for this one. > > Ran it twice. No errors were found on the second run. > > Let me know if you need a dump or anything for validation purposes? Nah it's all good, thanks for the report. -Eric > > John > > --- > From: Eric Sandeen <sandeen@xxxxxxxxxx> > Sent: 11 February 2020 02:42 > To: linux-xfs > Cc: John Jore > Subject: [PATCH] xfs_repair: fix bad next_unlinked field > > As of xfsprogs-4.17 we started testing whether the di_next_unlinked field > on an inode is valid in the inode verifiers. However, this field is never > tested or repaired during inode processing. > > So if, for example, we had a completely zeroed-out inode, we'd detect and > fix the broken magic and version, but the invalid di_next_unlinked field > would not be touched, fail the write verifier, and prevent the inode from > being properly repaired or even written out. > > Fix this by checking the di_next_unlinked inode field for validity and > clearing it if it is invalid. > > Reported-by: John Jore <john@xxxxxxx> > Fixes: 2949b4677 ("xfs: don't accept inode buffers with suspicious unlinked chains") > Signed-off-by: Eric Sandeen <sandeen@xxxxxxxxxx> > --- > > diff --git a/repair/dinode.c b/repair/dinode.c > index 8af2cb25..c5d2f350 100644 > --- a/repair/dinode.c > +++ b/repair/dinode.c > @@ -2272,6 +2272,7 @@ process_dinode_int(xfs_mount_t *mp, > const int is_free = 0; > const int is_used = 1; > blkmap_t *dblkmap = NULL; > + xfs_agino_t unlinked_ino; > > *dirty = *isa_dir = 0; > *used = is_used; > @@ -2351,6 +2352,23 @@ process_dinode_int(xfs_mount_t *mp, > } > } > > + unlinked_ino = be32_to_cpu(dino->di_next_unlinked); > + if (!xfs_verify_agino_or_null(mp, agno, unlinked_ino)) { > + retval = 1; > + if (!uncertain) > + do_warn(_("bad next_unlinked 0x%x on inode %" PRIu64 "%c"), > + (__s32)dino->di_next_unlinked, lino, > + verify_mode ? '\n' : ','); > + if (!verify_mode) { > + if (!no_modify) { > + do_warn(_(" resetting next_unlinked\n")); > + clear_dinode_unlinked(mp, dino); > + *dirty = 1; > + } else > + do_warn(_(" would reset next_unlinked\n")); > + } > + } > + > /* > * We don't bother checking the CRC here - we cannot guarantee that when > * we are called here that the inode has not already been modified in > > >