* [PATCH 0/2 V3] xfs_repair: rework inode clearing and free inode validation @ 2018-07-24 2:27 Eric Sandeen 2018-07-24 2:34 ` [PATCH 1/2 V3] xfs_repair: notify user if free inodes contain errors Eric Sandeen 2018-07-24 2:50 ` [PATCH 2/2 V3] xfs_repair: clear_dinode should simply clear, not check contents Eric Sandeen 0 siblings, 2 replies; 9+ messages in thread From: Eric Sandeen @ 2018-07-24 2:27 UTC (permalink / raw) To: linux-xfs Warn the user if any free inodes contain errors, and set exit code in the process. Do this by running the existing dinode verifier and clearing / warning if it fails. 2nd patch separates out the inode validation from the clearing function There is a functional change here which I'm on the fence about; free inodes are now only cleared if they won't pass the dinode verifier, which is the only thing the kernel would squawk about. But that's a subset of the clear_inode checks. The old clear_dinode function checked a lot of things that the verifier simply doesn't care about, but I think it's ok for those tests to go away; if the kernel does care about, say, extent count on a free inode, the verifier should test it. ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2 V3] xfs_repair: notify user if free inodes contain errors 2018-07-24 2:27 [PATCH 0/2 V3] xfs_repair: rework inode clearing and free inode validation Eric Sandeen @ 2018-07-24 2:34 ` Eric Sandeen 2018-07-24 4:35 ` Eric Sandeen ` (2 more replies) 2018-07-24 2:50 ` [PATCH 2/2 V3] xfs_repair: clear_dinode should simply clear, not check contents Eric Sandeen 1 sibling, 3 replies; 9+ messages in thread From: Eric Sandeen @ 2018-07-24 2:34 UTC (permalink / raw) To: Eric Sandeen, linux-xfs xfs_repair checks allocated but unused (free) inodes in on-disk clusters, and up until now silently repairs any errors, and as a result does not alter exit status if errors are found. The in-kernel verifiers will be noisy about these errors and instruct the user to run repair, so it's best if repair is explicit about any fixes it makes as a result. To ensure we catch anything the kernel would complain about, re-use xfs_dinode_verify to determine whether we must clear a free inode. Note, however, that the verifier contains only a subset of the checks currently in clear_dinode. This should be ok; if it's not, the checks should be added to the verifier in any case. Signed-off-by: Eric Sandeen <sandeen@redhat.com> --- diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index a98483b..05c06a7 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -134,6 +134,7 @@ #define xfs_symlink_hdr_ok libxfs_symlink_hdr_ok #define xfs_verify_cksum libxfs_verify_cksum +#define xfs_dinode_verify libxfs_dinode_verify #define xfs_alloc_ag_max_usable libxfs_alloc_ag_max_usable #define xfs_allocbt_maxrecs libxfs_allocbt_maxrecs diff --git a/repair/dinode.c b/repair/dinode.c index d36338f..c0db15a 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -2560,12 +2560,20 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), */ if (was_free) { /* - * easy case, inode free -- inode and map agree, clear + * easy case, inode free -- inode and map agree, check * it just in case to ensure that format, etc. are * set correctly */ - if (!no_modify) - *dirty += clear_dinode(mp, dino, lino); + if (libxfs_dinode_verify(mp, lino, dino) != NULL) { + do_warn( + _("free inode %" PRIu64 " contains errors, "), lino); + if (!no_modify) { + *dirty += clear_dinode(mp, dino, lino); + do_warn(_("corrected\n")); + } else { + do_warn(_("would correct\n")); + } + } *used = is_free; return 0; } ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2 V3] xfs_repair: notify user if free inodes contain errors 2018-07-24 2:34 ` [PATCH 1/2 V3] xfs_repair: notify user if free inodes contain errors Eric Sandeen @ 2018-07-24 4:35 ` Eric Sandeen 2018-07-24 21:43 ` Eric Sandeen 2018-07-25 4:25 ` Carlos Maiolino 2018-07-25 16:31 ` Darrick J. Wong 2 siblings, 1 reply; 9+ messages in thread From: Eric Sandeen @ 2018-07-24 4:35 UTC (permalink / raw) To: Eric Sandeen, linux-xfs On 7/23/18 7:34 PM, Eric Sandeen wrote: > xfs_repair checks allocated but unused (free) inodes in on-disk clusters, > and up until now silently repairs any errors, and as a result does not > alter exit status if errors are found. > > The in-kernel verifiers will be noisy about these errors and instruct > the user to run repair, so it's best if repair is explicit about any > fixes it makes as a result. > > To ensure we catch anything the kernel would complain about, re-use > xfs_dinode_verify to determine whether we must clear a free inode. > > Note, however, that the verifier contains only a subset of the checks > currently in clear_dinode. This should be ok; if it's not, the checks > should be added to the verifier in any case. > > Signed-off-by: Eric Sandeen <sandeen@redhat.com> Ugh, dammit, pulled the trigger too soon, tests were looking fine until the last few. Need to look at this more. > --- > > diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h > index a98483b..05c06a7 100644 > --- a/libxfs/libxfs_api_defs.h > +++ b/libxfs/libxfs_api_defs.h > @@ -134,6 +134,7 @@ > #define xfs_symlink_hdr_ok libxfs_symlink_hdr_ok > > #define xfs_verify_cksum libxfs_verify_cksum > +#define xfs_dinode_verify libxfs_dinode_verify > > #define xfs_alloc_ag_max_usable libxfs_alloc_ag_max_usable > #define xfs_allocbt_maxrecs libxfs_allocbt_maxrecs > diff --git a/repair/dinode.c b/repair/dinode.c > index d36338f..c0db15a 100644 > --- a/repair/dinode.c > +++ b/repair/dinode.c > @@ -2560,12 +2560,20 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), > */ > if (was_free) { > /* > - * easy case, inode free -- inode and map agree, clear > + * easy case, inode free -- inode and map agree, check > * it just in case to ensure that format, etc. are > * set correctly > */ > - if (!no_modify) > - *dirty += clear_dinode(mp, dino, lino); > + if (libxfs_dinode_verify(mp, lino, dino) != NULL) { > + do_warn( > + _("free inode %" PRIu64 " contains errors, "), lino); > + if (!no_modify) { > + *dirty += clear_dinode(mp, dino, lino); > + do_warn(_("corrected\n")); > + } else { > + do_warn(_("would correct\n")); > + } > + } > *used = is_free; > return 0; > } > > -- > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2 V3] xfs_repair: notify user if free inodes contain errors 2018-07-24 4:35 ` Eric Sandeen @ 2018-07-24 21:43 ` Eric Sandeen 0 siblings, 0 replies; 9+ messages in thread From: Eric Sandeen @ 2018-07-24 21:43 UTC (permalink / raw) To: Eric Sandeen, linux-xfs On 7/23/18 9:35 PM, Eric Sandeen wrote: > On 7/23/18 7:34 PM, Eric Sandeen wrote: >> xfs_repair checks allocated but unused (free) inodes in on-disk clusters, >> and up until now silently repairs any errors, and as a result does not >> alter exit status if errors are found. >> >> The in-kernel verifiers will be noisy about these errors and instruct >> the user to run repair, so it's best if repair is explicit about any >> fixes it makes as a result. >> >> To ensure we catch anything the kernel would complain about, re-use >> xfs_dinode_verify to determine whether we must clear a free inode. >> >> Note, however, that the verifier contains only a subset of the checks >> currently in clear_dinode. This should be ok; if it's not, the checks >> should be added to the verifier in any case. >> >> Signed-off-by: Eric Sandeen <sandeen@redhat.com> > Ugh, dammit, pulled the trigger too soon, tests were looking fine until > the last few. Need to look at this more. With the free inode extent validator fix I sent earlier today I think it's safe to resume normal review activities for these 2 patches. :) Thanks, -Eric ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2 V3] xfs_repair: notify user if free inodes contain errors 2018-07-24 2:34 ` [PATCH 1/2 V3] xfs_repair: notify user if free inodes contain errors Eric Sandeen 2018-07-24 4:35 ` Eric Sandeen @ 2018-07-25 4:25 ` Carlos Maiolino 2018-07-25 16:31 ` Darrick J. Wong 2 siblings, 0 replies; 9+ messages in thread From: Carlos Maiolino @ 2018-07-25 4:25 UTC (permalink / raw) To: Eric Sandeen; +Cc: linux-xfs On Mon, Jul 23, 2018 at 07:34:13PM -0700, Eric Sandeen wrote: > xfs_repair checks allocated but unused (free) inodes in on-disk clusters, > and up until now silently repairs any errors, and as a result does not > alter exit status if errors are found. > > The in-kernel verifiers will be noisy about these errors and instruct > the user to run repair, so it's best if repair is explicit about any > fixes it makes as a result. > > To ensure we catch anything the kernel would complain about, re-use > xfs_dinode_verify to determine whether we must clear a free inode. > > Note, however, that the verifier contains only a subset of the checks > currently in clear_dinode. This should be ok; if it's not, the checks > should be added to the verifier in any case. > > Signed-off-by: Eric Sandeen <sandeen@redhat.com> > --- > Looks good Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com> > diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h > index a98483b..05c06a7 100644 > --- a/libxfs/libxfs_api_defs.h > +++ b/libxfs/libxfs_api_defs.h > @@ -134,6 +134,7 @@ > #define xfs_symlink_hdr_ok libxfs_symlink_hdr_ok > > #define xfs_verify_cksum libxfs_verify_cksum > +#define xfs_dinode_verify libxfs_dinode_verify > > #define xfs_alloc_ag_max_usable libxfs_alloc_ag_max_usable > #define xfs_allocbt_maxrecs libxfs_allocbt_maxrecs > diff --git a/repair/dinode.c b/repair/dinode.c > index d36338f..c0db15a 100644 > --- a/repair/dinode.c > +++ b/repair/dinode.c > @@ -2560,12 +2560,20 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), > */ > if (was_free) { > /* > - * easy case, inode free -- inode and map agree, clear > + * easy case, inode free -- inode and map agree, check > * it just in case to ensure that format, etc. are > * set correctly > */ > - if (!no_modify) > - *dirty += clear_dinode(mp, dino, lino); > + if (libxfs_dinode_verify(mp, lino, dino) != NULL) { > + do_warn( > + _("free inode %" PRIu64 " contains errors, "), lino); > + if (!no_modify) { > + *dirty += clear_dinode(mp, dino, lino); > + do_warn(_("corrected\n")); > + } else { > + do_warn(_("would correct\n")); > + } > + } > *used = is_free; > return 0; > } > > -- > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Carlos ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2 V3] xfs_repair: notify user if free inodes contain errors 2018-07-24 2:34 ` [PATCH 1/2 V3] xfs_repair: notify user if free inodes contain errors Eric Sandeen 2018-07-24 4:35 ` Eric Sandeen 2018-07-25 4:25 ` Carlos Maiolino @ 2018-07-25 16:31 ` Darrick J. Wong 2 siblings, 0 replies; 9+ messages in thread From: Darrick J. Wong @ 2018-07-25 16:31 UTC (permalink / raw) To: Eric Sandeen; +Cc: Eric Sandeen, linux-xfs On Mon, Jul 23, 2018 at 07:34:13PM -0700, Eric Sandeen wrote: > xfs_repair checks allocated but unused (free) inodes in on-disk clusters, > and up until now silently repairs any errors, and as a result does not > alter exit status if errors are found. > > The in-kernel verifiers will be noisy about these errors and instruct > the user to run repair, so it's best if repair is explicit about any > fixes it makes as a result. > > To ensure we catch anything the kernel would complain about, re-use > xfs_dinode_verify to determine whether we must clear a free inode. > > Note, however, that the verifier contains only a subset of the checks > currently in clear_dinode. This should be ok; if it's not, the checks > should be added to the verifier in any case. > > Signed-off-by: Eric Sandeen <sandeen@redhat.com> Looks ok, Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> --D > --- > > diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h > index a98483b..05c06a7 100644 > --- a/libxfs/libxfs_api_defs.h > +++ b/libxfs/libxfs_api_defs.h > @@ -134,6 +134,7 @@ > #define xfs_symlink_hdr_ok libxfs_symlink_hdr_ok > > #define xfs_verify_cksum libxfs_verify_cksum > +#define xfs_dinode_verify libxfs_dinode_verify > > #define xfs_alloc_ag_max_usable libxfs_alloc_ag_max_usable > #define xfs_allocbt_maxrecs libxfs_allocbt_maxrecs > diff --git a/repair/dinode.c b/repair/dinode.c > index d36338f..c0db15a 100644 > --- a/repair/dinode.c > +++ b/repair/dinode.c > @@ -2560,12 +2560,20 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), > */ > if (was_free) { > /* > - * easy case, inode free -- inode and map agree, clear > + * easy case, inode free -- inode and map agree, check > * it just in case to ensure that format, etc. are > * set correctly > */ > - if (!no_modify) > - *dirty += clear_dinode(mp, dino, lino); > + if (libxfs_dinode_verify(mp, lino, dino) != NULL) { > + do_warn( > + _("free inode %" PRIu64 " contains errors, "), lino); > + if (!no_modify) { > + *dirty += clear_dinode(mp, dino, lino); > + do_warn(_("corrected\n")); > + } else { > + do_warn(_("would correct\n")); > + } > + } > *used = is_free; > return 0; > } > > -- > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2 V3] xfs_repair: clear_dinode should simply clear, not check contents 2018-07-24 2:27 [PATCH 0/2 V3] xfs_repair: rework inode clearing and free inode validation Eric Sandeen 2018-07-24 2:34 ` [PATCH 1/2 V3] xfs_repair: notify user if free inodes contain errors Eric Sandeen @ 2018-07-24 2:50 ` Eric Sandeen 2018-07-25 4:48 ` Carlos Maiolino 2018-07-25 16:32 ` Darrick J. Wong 1 sibling, 2 replies; 9+ messages in thread From: Eric Sandeen @ 2018-07-24 2:50 UTC (permalink / raw) To: Eric Sandeen, linux-xfs Today clear_inode performs 2 separate tasks - it clears a disk inode when the calling code detects an inconsistency, and it also validates free inodes to some extent by checking each field before zeroing it out. This leads to unnecessary checks in the former case where we just want to zap the inode, and duplicates some of the existing verifier checks in the latter case. Now that we're using xfs_dinode_verify to validate free inodes, there's no reason to repeat all the checks inside clear_inode_core. Drop them all and simply clear it when told to do so. Signed-off-by: Eric Sandeen <sandeen@redhat.com> --- diff --git a/repair/dinode.c b/repair/dinode.c index c0db15a..5b9fd9a 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -117,137 +117,24 @@ _("would have cleared inode %" PRIu64 " attributes\n"), ino_num); return(1); } -static int +static void clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num) { - int dirty = 0; - int i; - -#define __dirty_no_modify_ret(dirty) \ - ({ (dirty) = 1; if (no_modify) return 1; }) - - if (be16_to_cpu(dinoc->di_magic) != XFS_DINODE_MAGIC) { - __dirty_no_modify_ret(dirty); - dinoc->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); - } - - if (!libxfs_dinode_good_version(mp, dinoc->di_version)) { - __dirty_no_modify_ret(dirty); - if (xfs_sb_version_hascrc(&mp->m_sb)) - dinoc->di_version = 3; - else - dinoc->di_version = 2; - } - - if (be16_to_cpu(dinoc->di_mode) != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_mode = 0; - } - - if (be16_to_cpu(dinoc->di_flags) != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_flags = 0; - } - - if (be32_to_cpu(dinoc->di_dmevmask) != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_dmevmask = 0; - } - - if (dinoc->di_forkoff != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_forkoff = 0; - } - - if (dinoc->di_format != XFS_DINODE_FMT_EXTENTS) { - __dirty_no_modify_ret(dirty); - dinoc->di_format = XFS_DINODE_FMT_EXTENTS; - } - - if (dinoc->di_aformat != XFS_DINODE_FMT_EXTENTS) { - __dirty_no_modify_ret(dirty); - dinoc->di_aformat = XFS_DINODE_FMT_EXTENTS; - } - - if (be64_to_cpu(dinoc->di_size) != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_size = 0; - } - - if (be64_to_cpu(dinoc->di_nblocks) != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_nblocks = 0; - } - - if (be16_to_cpu(dinoc->di_onlink) != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_onlink = 0; - } - - if (be32_to_cpu(dinoc->di_nextents) != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_nextents = 0; - } - - if (be16_to_cpu(dinoc->di_anextents) != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_anextents = 0; - } - - if (be32_to_cpu(dinoc->di_extsize) != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_extsize = 0; - } - - if (dinoc->di_version > 1 && - be32_to_cpu(dinoc->di_nlink) != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_nlink = 0; - } - + memset(dinoc, 0, sizeof(*dinoc)); + dinoc->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); + if (xfs_sb_version_hascrc(&mp->m_sb)) + dinoc->di_version = 3; + else + dinoc->di_version = 2; + dinoc->di_gen = cpu_to_be32(random()); + dinoc->di_format = XFS_DINODE_FMT_EXTENTS; + dinoc->di_aformat = XFS_DINODE_FMT_EXTENTS; /* we are done for version 1/2 inodes */ if (dinoc->di_version < 3) - return dirty; - - if (be64_to_cpu(dinoc->di_ino) != ino_num) { - __dirty_no_modify_ret(dirty); - dinoc->di_ino = cpu_to_be64(ino_num); - } - - if (platform_uuid_compare(&dinoc->di_uuid, &mp->m_sb.sb_meta_uuid)) { - __dirty_no_modify_ret(dirty); - platform_uuid_copy(&dinoc->di_uuid, &mp->m_sb.sb_meta_uuid); - } - - for (i = 0; i < sizeof(dinoc->di_pad2)/sizeof(dinoc->di_pad2[0]); i++) { - if (dinoc->di_pad2[i] != 0) { - __dirty_no_modify_ret(dirty); - memset(dinoc->di_pad2, 0, sizeof(dinoc->di_pad2)); - break; - } - } - - if (be64_to_cpu(dinoc->di_flags2) != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_flags2 = 0; - } - - if (be64_to_cpu(dinoc->di_lsn) != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_lsn = 0; - } - - if (be64_to_cpu(dinoc->di_changecount) != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_changecount = 0; - } - - if (be32_to_cpu(dinoc->di_cowextsize) != 0) { - __dirty_no_modify_ret(dirty); - dinoc->di_cowextsize = 0; - } - - return dirty; + return; + dinoc->di_ino = cpu_to_be64(ino_num); + platform_uuid_copy(&dinoc->di_uuid, &mp->m_sb.sb_meta_uuid); + return; } static int @@ -268,21 +155,15 @@ clear_dinode_unlinked(xfs_mount_t *mp, xfs_dinode_t *dino) * until after the agi unlinked lists are walked in phase 3. * returns > zero if the inode has been altered while being cleared */ -static int +static void clear_dinode(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_ino_t ino_num) { - int dirty; - - dirty = clear_dinode_core(mp, dino, ino_num); - dirty += clear_dinode_unlinked(mp, dino); + clear_dinode_core(mp, dino, ino_num); + clear_dinode_unlinked(mp, dino); /* and clear the forks */ - - if (dirty && !no_modify) - memset(XFS_DFORK_DPTR(dino), 0, - XFS_LITINO(mp, dino->di_version)); - - return(dirty); + memset(XFS_DFORK_DPTR(dino), 0, XFS_LITINO(mp, dino->di_version)); + return; } @@ -2140,8 +2021,8 @@ process_inode_data_fork( if (err) { do_warn(_("bad data fork in inode %" PRIu64 "\n"), lino); if (!no_modify) { - *dirty += clear_dinode(mp, dino, lino); - ASSERT(*dirty > 0); + clear_dinode(mp, dino, lino); + *dirty += 1; } return 1; } @@ -2551,7 +2432,7 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), } /* - * if not in verify mode, check to sii if the inode and imap + * if not in verify mode, check to see if the inode and imap * agree that the inode is free */ if (!verify_mode && di_mode == 0) { @@ -2568,8 +2449,9 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), do_warn( _("free inode %" PRIu64 " contains errors, "), lino); if (!no_modify) { - *dirty += clear_dinode(mp, dino, lino); + clear_dinode(mp, dino, lino); do_warn(_("corrected\n")); + *dirty += 1; } else { do_warn(_("would correct\n")); } @@ -2586,7 +2468,8 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), _("imap claims a free inode %" PRIu64 " is in use, "), lino); if (!no_modify) { do_warn(_("correcting imap and clearing inode\n")); - *dirty += clear_dinode(mp, dino, lino); + clear_dinode(mp, dino, lino); + *dirty += 1; retval = 1; } else do_warn(_("would correct imap and clear inode\n")); @@ -2804,8 +2687,10 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), * we're going to find. check_dups is set to 1 only during * phase 4. Ugly. */ - if (check_dups && !no_modify) - *dirty += clear_dinode_unlinked(mp, dino); + if (check_dups && !no_modify) { + clear_dinode_unlinked(mp, dino); + *dirty += 1; + } /* set type and map type info */ @@ -3024,8 +2909,8 @@ _("Cannot have CoW extent size of zero on cowextsize inode %" PRIu64 ", "), clear_bad_out: if (!no_modify) { - *dirty += clear_dinode(mp, dino, lino); - ASSERT(*dirty > 0); + clear_dinode(mp, dino, lino); + *dirty += 1; } bad_out: *used = is_free; ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2 V3] xfs_repair: clear_dinode should simply clear, not check contents 2018-07-24 2:50 ` [PATCH 2/2 V3] xfs_repair: clear_dinode should simply clear, not check contents Eric Sandeen @ 2018-07-25 4:48 ` Carlos Maiolino 2018-07-25 16:32 ` Darrick J. Wong 1 sibling, 0 replies; 9+ messages in thread From: Carlos Maiolino @ 2018-07-25 4:48 UTC (permalink / raw) To: Eric Sandeen; +Cc: linux-xfs On Mon, Jul 23, 2018 at 07:50:13PM -0700, Eric Sandeen wrote: > Today clear_inode performs 2 separate tasks - it clears a disk inode > when the calling code detects an inconsistency, and it also validates > free inodes to some extent by checking each field before zeroing it > out. This leads to unnecessary checks in the former case where we > just want to zap the inode, and duplicates some of the existing > verifier checks in the latter case. > > Now that we're using xfs_dinode_verify to validate free inodes, > there's no reason to repeat all the checks inside clear_inode_core. > Drop them all and simply clear it when told to do so. > > Signed-off-by: Eric Sandeen <sandeen@redhat.com> > --- Looks good. Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com> > > diff --git a/repair/dinode.c b/repair/dinode.c > index c0db15a..5b9fd9a 100644 > --- a/repair/dinode.c > +++ b/repair/dinode.c > @@ -117,137 +117,24 @@ _("would have cleared inode %" PRIu64 " attributes\n"), ino_num); > return(1); > } > > -static int > +static void > clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num) > { > - int dirty = 0; > - int i; > - > -#define __dirty_no_modify_ret(dirty) \ > - ({ (dirty) = 1; if (no_modify) return 1; }) > - > - if (be16_to_cpu(dinoc->di_magic) != XFS_DINODE_MAGIC) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); > - } > - > - if (!libxfs_dinode_good_version(mp, dinoc->di_version)) { > - __dirty_no_modify_ret(dirty); > - if (xfs_sb_version_hascrc(&mp->m_sb)) > - dinoc->di_version = 3; > - else > - dinoc->di_version = 2; > - } > - > - if (be16_to_cpu(dinoc->di_mode) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_mode = 0; > - } > - > - if (be16_to_cpu(dinoc->di_flags) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_flags = 0; > - } > - > - if (be32_to_cpu(dinoc->di_dmevmask) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_dmevmask = 0; > - } > - > - if (dinoc->di_forkoff != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_forkoff = 0; > - } > - > - if (dinoc->di_format != XFS_DINODE_FMT_EXTENTS) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_format = XFS_DINODE_FMT_EXTENTS; > - } > - > - if (dinoc->di_aformat != XFS_DINODE_FMT_EXTENTS) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_aformat = XFS_DINODE_FMT_EXTENTS; > - } > - > - if (be64_to_cpu(dinoc->di_size) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_size = 0; > - } > - > - if (be64_to_cpu(dinoc->di_nblocks) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_nblocks = 0; > - } > - > - if (be16_to_cpu(dinoc->di_onlink) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_onlink = 0; > - } > - > - if (be32_to_cpu(dinoc->di_nextents) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_nextents = 0; > - } > - > - if (be16_to_cpu(dinoc->di_anextents) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_anextents = 0; > - } > - > - if (be32_to_cpu(dinoc->di_extsize) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_extsize = 0; > - } > - > - if (dinoc->di_version > 1 && > - be32_to_cpu(dinoc->di_nlink) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_nlink = 0; > - } > - > + memset(dinoc, 0, sizeof(*dinoc)); > + dinoc->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); > + if (xfs_sb_version_hascrc(&mp->m_sb)) > + dinoc->di_version = 3; > + else > + dinoc->di_version = 2; > + dinoc->di_gen = cpu_to_be32(random()); > + dinoc->di_format = XFS_DINODE_FMT_EXTENTS; > + dinoc->di_aformat = XFS_DINODE_FMT_EXTENTS; > /* we are done for version 1/2 inodes */ > if (dinoc->di_version < 3) > - return dirty; > - > - if (be64_to_cpu(dinoc->di_ino) != ino_num) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_ino = cpu_to_be64(ino_num); > - } > - > - if (platform_uuid_compare(&dinoc->di_uuid, &mp->m_sb.sb_meta_uuid)) { > - __dirty_no_modify_ret(dirty); > - platform_uuid_copy(&dinoc->di_uuid, &mp->m_sb.sb_meta_uuid); > - } > - > - for (i = 0; i < sizeof(dinoc->di_pad2)/sizeof(dinoc->di_pad2[0]); i++) { > - if (dinoc->di_pad2[i] != 0) { > - __dirty_no_modify_ret(dirty); > - memset(dinoc->di_pad2, 0, sizeof(dinoc->di_pad2)); > - break; > - } > - } > - > - if (be64_to_cpu(dinoc->di_flags2) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_flags2 = 0; > - } > - > - if (be64_to_cpu(dinoc->di_lsn) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_lsn = 0; > - } > - > - if (be64_to_cpu(dinoc->di_changecount) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_changecount = 0; > - } > - > - if (be32_to_cpu(dinoc->di_cowextsize) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_cowextsize = 0; > - } > - > - return dirty; > + return; > + dinoc->di_ino = cpu_to_be64(ino_num); > + platform_uuid_copy(&dinoc->di_uuid, &mp->m_sb.sb_meta_uuid); > + return; > } > > static int > @@ -268,21 +155,15 @@ clear_dinode_unlinked(xfs_mount_t *mp, xfs_dinode_t *dino) > * until after the agi unlinked lists are walked in phase 3. > * returns > zero if the inode has been altered while being cleared > */ > -static int > +static void > clear_dinode(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_ino_t ino_num) > { > - int dirty; > - > - dirty = clear_dinode_core(mp, dino, ino_num); > - dirty += clear_dinode_unlinked(mp, dino); > + clear_dinode_core(mp, dino, ino_num); > + clear_dinode_unlinked(mp, dino); > > /* and clear the forks */ > - > - if (dirty && !no_modify) > - memset(XFS_DFORK_DPTR(dino), 0, > - XFS_LITINO(mp, dino->di_version)); > - > - return(dirty); > + memset(XFS_DFORK_DPTR(dino), 0, XFS_LITINO(mp, dino->di_version)); > + return; > } > > > @@ -2140,8 +2021,8 @@ process_inode_data_fork( > if (err) { > do_warn(_("bad data fork in inode %" PRIu64 "\n"), lino); > if (!no_modify) { > - *dirty += clear_dinode(mp, dino, lino); > - ASSERT(*dirty > 0); > + clear_dinode(mp, dino, lino); > + *dirty += 1; > } > return 1; > } > @@ -2551,7 +2432,7 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), > } > > /* > - * if not in verify mode, check to sii if the inode and imap > + * if not in verify mode, check to see if the inode and imap > * agree that the inode is free > */ > if (!verify_mode && di_mode == 0) { > @@ -2568,8 +2449,9 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), > do_warn( > _("free inode %" PRIu64 " contains errors, "), lino); > if (!no_modify) { > - *dirty += clear_dinode(mp, dino, lino); > + clear_dinode(mp, dino, lino); > do_warn(_("corrected\n")); > + *dirty += 1; > } else { > do_warn(_("would correct\n")); > } > @@ -2586,7 +2468,8 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), > _("imap claims a free inode %" PRIu64 " is in use, "), lino); > if (!no_modify) { > do_warn(_("correcting imap and clearing inode\n")); > - *dirty += clear_dinode(mp, dino, lino); > + clear_dinode(mp, dino, lino); > + *dirty += 1; > retval = 1; > } else > do_warn(_("would correct imap and clear inode\n")); > @@ -2804,8 +2687,10 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), > * we're going to find. check_dups is set to 1 only during > * phase 4. Ugly. > */ > - if (check_dups && !no_modify) > - *dirty += clear_dinode_unlinked(mp, dino); > + if (check_dups && !no_modify) { > + clear_dinode_unlinked(mp, dino); > + *dirty += 1; > + } > > /* set type and map type info */ > > @@ -3024,8 +2909,8 @@ _("Cannot have CoW extent size of zero on cowextsize inode %" PRIu64 ", "), > > clear_bad_out: > if (!no_modify) { > - *dirty += clear_dinode(mp, dino, lino); > - ASSERT(*dirty > 0); > + clear_dinode(mp, dino, lino); > + *dirty += 1; > } > bad_out: > *used = is_free; > > -- > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Carlos ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2 V3] xfs_repair: clear_dinode should simply clear, not check contents 2018-07-24 2:50 ` [PATCH 2/2 V3] xfs_repair: clear_dinode should simply clear, not check contents Eric Sandeen 2018-07-25 4:48 ` Carlos Maiolino @ 2018-07-25 16:32 ` Darrick J. Wong 1 sibling, 0 replies; 9+ messages in thread From: Darrick J. Wong @ 2018-07-25 16:32 UTC (permalink / raw) To: Eric Sandeen; +Cc: Eric Sandeen, linux-xfs On Mon, Jul 23, 2018 at 07:50:13PM -0700, Eric Sandeen wrote: > Today clear_inode performs 2 separate tasks - it clears a disk inode > when the calling code detects an inconsistency, and it also validates > free inodes to some extent by checking each field before zeroing it > out. This leads to unnecessary checks in the former case where we > just want to zap the inode, and duplicates some of the existing > verifier checks in the latter case. > > Now that we're using xfs_dinode_verify to validate free inodes, > there's no reason to repeat all the checks inside clear_inode_core. > Drop them all and simply clear it when told to do so. > > Signed-off-by: Eric Sandeen <sandeen@redhat.com> Looks ok, Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> --D > --- > > diff --git a/repair/dinode.c b/repair/dinode.c > index c0db15a..5b9fd9a 100644 > --- a/repair/dinode.c > +++ b/repair/dinode.c > @@ -117,137 +117,24 @@ _("would have cleared inode %" PRIu64 " attributes\n"), ino_num); > return(1); > } > > -static int > +static void > clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num) > { > - int dirty = 0; > - int i; > - > -#define __dirty_no_modify_ret(dirty) \ > - ({ (dirty) = 1; if (no_modify) return 1; }) > - > - if (be16_to_cpu(dinoc->di_magic) != XFS_DINODE_MAGIC) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); > - } > - > - if (!libxfs_dinode_good_version(mp, dinoc->di_version)) { > - __dirty_no_modify_ret(dirty); > - if (xfs_sb_version_hascrc(&mp->m_sb)) > - dinoc->di_version = 3; > - else > - dinoc->di_version = 2; > - } > - > - if (be16_to_cpu(dinoc->di_mode) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_mode = 0; > - } > - > - if (be16_to_cpu(dinoc->di_flags) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_flags = 0; > - } > - > - if (be32_to_cpu(dinoc->di_dmevmask) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_dmevmask = 0; > - } > - > - if (dinoc->di_forkoff != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_forkoff = 0; > - } > - > - if (dinoc->di_format != XFS_DINODE_FMT_EXTENTS) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_format = XFS_DINODE_FMT_EXTENTS; > - } > - > - if (dinoc->di_aformat != XFS_DINODE_FMT_EXTENTS) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_aformat = XFS_DINODE_FMT_EXTENTS; > - } > - > - if (be64_to_cpu(dinoc->di_size) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_size = 0; > - } > - > - if (be64_to_cpu(dinoc->di_nblocks) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_nblocks = 0; > - } > - > - if (be16_to_cpu(dinoc->di_onlink) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_onlink = 0; > - } > - > - if (be32_to_cpu(dinoc->di_nextents) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_nextents = 0; > - } > - > - if (be16_to_cpu(dinoc->di_anextents) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_anextents = 0; > - } > - > - if (be32_to_cpu(dinoc->di_extsize) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_extsize = 0; > - } > - > - if (dinoc->di_version > 1 && > - be32_to_cpu(dinoc->di_nlink) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_nlink = 0; > - } > - > + memset(dinoc, 0, sizeof(*dinoc)); > + dinoc->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); > + if (xfs_sb_version_hascrc(&mp->m_sb)) > + dinoc->di_version = 3; > + else > + dinoc->di_version = 2; > + dinoc->di_gen = cpu_to_be32(random()); > + dinoc->di_format = XFS_DINODE_FMT_EXTENTS; > + dinoc->di_aformat = XFS_DINODE_FMT_EXTENTS; > /* we are done for version 1/2 inodes */ > if (dinoc->di_version < 3) > - return dirty; > - > - if (be64_to_cpu(dinoc->di_ino) != ino_num) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_ino = cpu_to_be64(ino_num); > - } > - > - if (platform_uuid_compare(&dinoc->di_uuid, &mp->m_sb.sb_meta_uuid)) { > - __dirty_no_modify_ret(dirty); > - platform_uuid_copy(&dinoc->di_uuid, &mp->m_sb.sb_meta_uuid); > - } > - > - for (i = 0; i < sizeof(dinoc->di_pad2)/sizeof(dinoc->di_pad2[0]); i++) { > - if (dinoc->di_pad2[i] != 0) { > - __dirty_no_modify_ret(dirty); > - memset(dinoc->di_pad2, 0, sizeof(dinoc->di_pad2)); > - break; > - } > - } > - > - if (be64_to_cpu(dinoc->di_flags2) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_flags2 = 0; > - } > - > - if (be64_to_cpu(dinoc->di_lsn) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_lsn = 0; > - } > - > - if (be64_to_cpu(dinoc->di_changecount) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_changecount = 0; > - } > - > - if (be32_to_cpu(dinoc->di_cowextsize) != 0) { > - __dirty_no_modify_ret(dirty); > - dinoc->di_cowextsize = 0; > - } > - > - return dirty; > + return; > + dinoc->di_ino = cpu_to_be64(ino_num); > + platform_uuid_copy(&dinoc->di_uuid, &mp->m_sb.sb_meta_uuid); > + return; > } > > static int > @@ -268,21 +155,15 @@ clear_dinode_unlinked(xfs_mount_t *mp, xfs_dinode_t *dino) > * until after the agi unlinked lists are walked in phase 3. > * returns > zero if the inode has been altered while being cleared > */ > -static int > +static void > clear_dinode(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_ino_t ino_num) > { > - int dirty; > - > - dirty = clear_dinode_core(mp, dino, ino_num); > - dirty += clear_dinode_unlinked(mp, dino); > + clear_dinode_core(mp, dino, ino_num); > + clear_dinode_unlinked(mp, dino); > > /* and clear the forks */ > - > - if (dirty && !no_modify) > - memset(XFS_DFORK_DPTR(dino), 0, > - XFS_LITINO(mp, dino->di_version)); > - > - return(dirty); > + memset(XFS_DFORK_DPTR(dino), 0, XFS_LITINO(mp, dino->di_version)); > + return; > } > > > @@ -2140,8 +2021,8 @@ process_inode_data_fork( > if (err) { > do_warn(_("bad data fork in inode %" PRIu64 "\n"), lino); > if (!no_modify) { > - *dirty += clear_dinode(mp, dino, lino); > - ASSERT(*dirty > 0); > + clear_dinode(mp, dino, lino); > + *dirty += 1; > } > return 1; > } > @@ -2551,7 +2432,7 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), > } > > /* > - * if not in verify mode, check to sii if the inode and imap > + * if not in verify mode, check to see if the inode and imap > * agree that the inode is free > */ > if (!verify_mode && di_mode == 0) { > @@ -2568,8 +2449,9 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), > do_warn( > _("free inode %" PRIu64 " contains errors, "), lino); > if (!no_modify) { > - *dirty += clear_dinode(mp, dino, lino); > + clear_dinode(mp, dino, lino); > do_warn(_("corrected\n")); > + *dirty += 1; > } else { > do_warn(_("would correct\n")); > } > @@ -2586,7 +2468,8 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), > _("imap claims a free inode %" PRIu64 " is in use, "), lino); > if (!no_modify) { > do_warn(_("correcting imap and clearing inode\n")); > - *dirty += clear_dinode(mp, dino, lino); > + clear_dinode(mp, dino, lino); > + *dirty += 1; > retval = 1; > } else > do_warn(_("would correct imap and clear inode\n")); > @@ -2804,8 +2687,10 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), > * we're going to find. check_dups is set to 1 only during > * phase 4. Ugly. > */ > - if (check_dups && !no_modify) > - *dirty += clear_dinode_unlinked(mp, dino); > + if (check_dups && !no_modify) { > + clear_dinode_unlinked(mp, dino); > + *dirty += 1; > + } > > /* set type and map type info */ > > @@ -3024,8 +2909,8 @@ _("Cannot have CoW extent size of zero on cowextsize inode %" PRIu64 ", "), > > clear_bad_out: > if (!no_modify) { > - *dirty += clear_dinode(mp, dino, lino); > - ASSERT(*dirty > 0); > + clear_dinode(mp, dino, lino); > + *dirty += 1; > } > bad_out: > *used = is_free; > > -- > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2018-07-25 17:44 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2018-07-24 2:27 [PATCH 0/2 V3] xfs_repair: rework inode clearing and free inode validation Eric Sandeen 2018-07-24 2:34 ` [PATCH 1/2 V3] xfs_repair: notify user if free inodes contain errors Eric Sandeen 2018-07-24 4:35 ` Eric Sandeen 2018-07-24 21:43 ` Eric Sandeen 2018-07-25 4:25 ` Carlos Maiolino 2018-07-25 16:31 ` Darrick J. Wong 2018-07-24 2:50 ` [PATCH 2/2 V3] xfs_repair: clear_dinode should simply clear, not check contents Eric Sandeen 2018-07-25 4:48 ` Carlos Maiolino 2018-07-25 16:32 ` Darrick J. Wong
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).