diff options
-rw-r--r-- | fs/xfs/scrub/attr_repair.c | 3 | ||||
-rw-r--r-- | fs/xfs/scrub/dir_repair.c | 3 | ||||
-rw-r--r-- | fs/xfs/scrub/nlinks_repair.c | 4 | ||||
-rw-r--r-- | fs/xfs/scrub/orphanage.c | 49 | ||||
-rw-r--r-- | fs/xfs/scrub/parent_repair.c | 10 | ||||
-rw-r--r-- | fs/xfs/scrub/rtsummary_repair.c | 10 | ||||
-rw-r--r-- | fs/xfs/scrub/scrub.c | 8 | ||||
-rw-r--r-- | fs/xfs/scrub/scrub.h | 7 | ||||
-rw-r--r-- | fs/xfs/scrub/symlink_repair.c | 3 | ||||
-rw-r--r-- | fs/xfs/scrub/tempexch.h | 1 | ||||
-rw-r--r-- | fs/xfs/scrub/tempfile.c | 24 | ||||
-rw-r--r-- | fs/xfs/scrub/trace.h | 3 |
12 files changed, 49 insertions, 76 deletions
diff --git a/fs/xfs/scrub/attr_repair.c b/fs/xfs/scrub/attr_repair.c index e059813b92b7..c7eb94069caf 100644 --- a/fs/xfs/scrub/attr_repair.c +++ b/fs/xfs/scrub/attr_repair.c @@ -1630,6 +1630,9 @@ xrep_xattr( /* The rmapbt is required to reap the old attr fork. */ if (!xfs_has_rmapbt(sc->mp)) return -EOPNOTSUPP; + /* We require atomic file exchange range to rebuild anything. */ + if (!xfs_has_exchange_range(sc->mp)) + return -EOPNOTSUPP; error = xrep_xattr_setup_scan(sc, &rx); if (error) diff --git a/fs/xfs/scrub/dir_repair.c b/fs/xfs/scrub/dir_repair.c index e968150fe0f0..6ad40f8aafb8 100644 --- a/fs/xfs/scrub/dir_repair.c +++ b/fs/xfs/scrub/dir_repair.c @@ -1993,6 +1993,9 @@ xrep_directory( /* The rmapbt is required to reap the old data fork. */ if (!xfs_has_rmapbt(sc->mp)) return -EOPNOTSUPP; + /* We require atomic file exchange range to rebuild anything. */ + if (!xfs_has_exchange_range(sc->mp)) + return -EOPNOTSUPP; error = xrep_dir_setup_scan(rd); if (error) diff --git a/fs/xfs/scrub/nlinks_repair.c b/fs/xfs/scrub/nlinks_repair.c index 78d0f650fe89..b3e707f47b7b 100644 --- a/fs/xfs/scrub/nlinks_repair.c +++ b/fs/xfs/scrub/nlinks_repair.c @@ -138,8 +138,10 @@ xrep_nlinks_repair_inode( error = xfs_trans_alloc(mp, &M_RES(mp)->tr_link, 0, 0, 0, &sc->tp); - if (error) + if (error) { + xchk_iunlock(sc, XFS_IOLOCK_EXCL); return error; + } xchk_ilock(sc, XFS_ILOCK_EXCL); xfs_trans_ijoin(sc->tp, ip, 0); diff --git a/fs/xfs/scrub/orphanage.c b/fs/xfs/scrub/orphanage.c index b1c6c60ee1da..7148d8362db8 100644 --- a/fs/xfs/scrub/orphanage.c +++ b/fs/xfs/scrub/orphanage.c @@ -382,7 +382,7 @@ xrep_adoption_trans_alloc( out_cancel: xchk_trans_cancel(sc); xrep_orphanage_iunlock(sc, XFS_ILOCK_EXCL); - xrep_orphanage_iunlock(sc, XFS_IOLOCK_EXCL); + xchk_iunlock(sc, XFS_ILOCK_EXCL); return error; } @@ -434,16 +434,17 @@ xrep_adoption_check_dcache( { struct qstr qname = QSTR_INIT(adopt->xname->name, adopt->xname->len); + struct xfs_scrub *sc = adopt->sc; struct dentry *d_orphanage, *d_child; int error = 0; - d_orphanage = d_find_alias(VFS_I(adopt->sc->orphanage)); + d_orphanage = d_find_alias(VFS_I(sc->orphanage)); if (!d_orphanage) return 0; d_child = d_hash_and_lookup(d_orphanage, &qname); if (d_child) { - trace_xrep_adoption_check_child(adopt->sc->mp, d_child); + trace_xrep_adoption_check_child(sc->mp, d_child); if (d_is_positive(d_child)) { ASSERT(d_is_negative(d_child)); @@ -454,33 +455,15 @@ xrep_adoption_check_dcache( } dput(d_orphanage); - if (error) - return error; - - /* - * Do we need to update d_parent of the dentry for the file being - * repaired? There shouldn't be a hashed dentry with a parent since - * the file had nonzero nlink but wasn't connected to any parent dir. - */ - d_child = d_find_alias(VFS_I(adopt->sc->ip)); - if (!d_child) - return 0; - - trace_xrep_adoption_check_alias(adopt->sc->mp, d_child); - - if (d_child->d_parent && !d_unhashed(d_child)) { - ASSERT(d_child->d_parent == NULL || d_unhashed(d_child)); - error = -EFSCORRUPTED; - } - - dput(d_child); return error; } /* - * Remove all negative dentries from the dcache. There should not be any - * positive entries, since we've maintained our lock on the orphanage - * directory. + * Invalidate all dentries for the name that was added to the orphanage + * directory, and all dentries pointing to the child inode that was moved. + * + * There should not be any positive entries for the name, since we've + * maintained our lock on the orphanage directory. */ static void xrep_adoption_zap_dcache( @@ -488,15 +471,17 @@ xrep_adoption_zap_dcache( { struct qstr qname = QSTR_INIT(adopt->xname->name, adopt->xname->len); + struct xfs_scrub *sc = adopt->sc; struct dentry *d_orphanage, *d_child; - d_orphanage = d_find_alias(VFS_I(adopt->sc->orphanage)); + /* Invalidate all dentries for the adoption name */ + d_orphanage = d_find_alias(VFS_I(sc->orphanage)); if (!d_orphanage) return; d_child = d_hash_and_lookup(d_orphanage, &qname); while (d_child != NULL) { - trace_xrep_adoption_invalidate_child(adopt->sc->mp, d_child); + trace_xrep_adoption_invalidate_child(sc->mp, d_child); ASSERT(d_is_negative(d_child)); d_invalidate(d_child); @@ -505,6 +490,14 @@ xrep_adoption_zap_dcache( } dput(d_orphanage); + + /* Invalidate all the dentries pointing down to this file. */ + while ((d_child = d_find_alias(VFS_I(sc->ip))) != NULL) { + trace_xrep_adoption_invalidate_child(sc->mp, d_child); + + d_invalidate(d_child); + dput(d_child); + } } /* diff --git a/fs/xfs/scrub/parent_repair.c b/fs/xfs/scrub/parent_repair.c index ee88ce5a12b8..7b42b7f65a0b 100644 --- a/fs/xfs/scrub/parent_repair.c +++ b/fs/xfs/scrub/parent_repair.c @@ -1571,10 +1571,14 @@ xrep_parent( /* * When the parent pointers feature is enabled, repairs are committed * by atomically committing a new xattr structure and reaping the old - * attr fork. Reaping requires rmap to be enabled. + * attr fork. Reaping requires rmap and exchange-range to be enabled. */ - if (xfs_has_parent(sc->mp) && !xfs_has_rmapbt(sc->mp)) - return -EOPNOTSUPP; + if (xfs_has_parent(sc->mp)) { + if (!xfs_has_rmapbt(sc->mp)) + return -EOPNOTSUPP; + if (!xfs_has_exchange_range(sc->mp)) + return -EOPNOTSUPP; + } error = xrep_parent_setup_scan(rp); if (error) diff --git a/fs/xfs/scrub/rtsummary_repair.c b/fs/xfs/scrub/rtsummary_repair.c index c8bb6c4f15d0..d9e971c4c79f 100644 --- a/fs/xfs/scrub/rtsummary_repair.c +++ b/fs/xfs/scrub/rtsummary_repair.c @@ -62,12 +62,7 @@ xrep_setup_rtsummary( return -EOPNOTSUPP; rts->resblks += blocks; - - /* - * Grab support for atomic file content exchanges before we allocate - * any transactions or grab ILOCKs. - */ - return xrep_tempexch_enable(sc); + return 0; } static int @@ -111,6 +106,9 @@ xrep_rtsummary( /* We require the rmapbt to rebuild anything. */ if (!xfs_has_rmapbt(mp)) return -EOPNOTSUPP; + /* We require atomic file exchange range to rebuild anything. */ + if (!xfs_has_exchange_range(mp)) + return -EOPNOTSUPP; /* Walk away if we disagree on the size of the rt bitmap. */ if (rts->rbmblocks != mp->m_sb.sb_rbmblocks) diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c index 43af5ce1f99f..c013f0ba4f36 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -154,15 +154,14 @@ xchk_probe( /* Scrub setup and teardown */ -#define FSGATES_MASK (XCHK_FSGATES_ALL | XREP_FSGATES_ALL) static inline void xchk_fsgates_disable( struct xfs_scrub *sc) { - if (!(sc->flags & FSGATES_MASK)) + if (!(sc->flags & XCHK_FSGATES_ALL)) return; - trace_xchk_fsgates_disable(sc, sc->flags & FSGATES_MASK); + trace_xchk_fsgates_disable(sc, sc->flags & XCHK_FSGATES_ALL); if (sc->flags & XCHK_FSGATES_DRAIN) xfs_drain_wait_disable(); @@ -176,9 +175,8 @@ xchk_fsgates_disable( if (sc->flags & XCHK_FSGATES_RMAP) xfs_rmap_hook_disable(); - sc->flags &= ~FSGATES_MASK; + sc->flags &= ~XCHK_FSGATES_ALL; } -#undef FSGATES_MASK /* Free the resources associated with a scrub subtype. */ void diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h index 1da10182f7f4..1bc33f010d0e 100644 --- a/fs/xfs/scrub/scrub.h +++ b/fs/xfs/scrub/scrub.h @@ -188,7 +188,6 @@ struct xfs_scrub { #define XCHK_FSGATES_QUOTA (1U << 4) /* quota live update enabled */ #define XCHK_FSGATES_DIRENTS (1U << 5) /* directory live update enabled */ #define XCHK_FSGATES_RMAP (1U << 6) /* rmapbt live update enabled */ -#define XREP_FSGATES_EXCHANGE_RANGE (1U << 29) /* uses file content exchange */ #define XREP_RESET_PERAG_RESV (1U << 30) /* must reset AG space reservation */ #define XREP_ALREADY_FIXED (1U << 31) /* checking our repair work */ @@ -203,12 +202,6 @@ struct xfs_scrub { XCHK_FSGATES_DIRENTS | \ XCHK_FSGATES_RMAP) -/* - * The sole XREP_FSGATES* flag reflects a log intent item that is protected - * by a log-incompat feature flag. No code patching in use here. - */ -#define XREP_FSGATES_ALL (XREP_FSGATES_EXCHANGE_RANGE) - struct xfs_scrub_subord { struct xfs_scrub sc; struct xfs_scrub *parent_sc; diff --git a/fs/xfs/scrub/symlink_repair.c b/fs/xfs/scrub/symlink_repair.c index c8b5a5b878ac..d015a86ef460 100644 --- a/fs/xfs/scrub/symlink_repair.c +++ b/fs/xfs/scrub/symlink_repair.c @@ -490,6 +490,9 @@ xrep_symlink( /* The rmapbt is required to reap the old data fork. */ if (!xfs_has_rmapbt(sc->mp)) return -EOPNOTSUPP; + /* We require atomic file exchange range to rebuild anything. */ + if (!xfs_has_exchange_range(sc->mp)) + return -EOPNOTSUPP; ASSERT(sc->ilock_flags & XFS_ILOCK_EXCL); diff --git a/fs/xfs/scrub/tempexch.h b/fs/xfs/scrub/tempexch.h index c1dd4adec4f1..995ba187c5aa 100644 --- a/fs/xfs/scrub/tempexch.h +++ b/fs/xfs/scrub/tempexch.h @@ -11,7 +11,6 @@ struct xrep_tempexch { struct xfs_exchmaps_req req; }; -int xrep_tempexch_enable(struct xfs_scrub *sc); int xrep_tempexch_trans_reserve(struct xfs_scrub *sc, int whichfork, struct xrep_tempexch *ti); int xrep_tempexch_trans_alloc(struct xfs_scrub *sc, int whichfork, diff --git a/fs/xfs/scrub/tempfile.c b/fs/xfs/scrub/tempfile.c index ddbcccb3dba1..b747b625c5ee 100644 --- a/fs/xfs/scrub/tempfile.c +++ b/fs/xfs/scrub/tempfile.c @@ -486,23 +486,6 @@ xrep_tempfile_roll_trans( return 0; } -/* Enable file content exchanges. */ -int -xrep_tempexch_enable( - struct xfs_scrub *sc) -{ - if (sc->flags & XREP_FSGATES_EXCHANGE_RANGE) - return 0; - - if (!xfs_has_exchange_range(sc->mp)) - return -EOPNOTSUPP; - - trace_xchk_fsgates_enable(sc, XREP_FSGATES_EXCHANGE_RANGE); - - sc->flags |= XREP_FSGATES_EXCHANGE_RANGE; - return 0; -} - /* * Fill out the mapping exchange request in preparation for atomically * committing the contents of a metadata file that we've rebuilt in the temp @@ -745,6 +728,7 @@ xrep_tempexch_trans_alloc( int error; ASSERT(sc->tp == NULL); + ASSERT(xfs_has_exchange_range(sc->mp)); error = xrep_tempexch_prep_request(sc, whichfork, tx); if (error) @@ -757,10 +741,6 @@ xrep_tempexch_trans_alloc( if (xfs_has_lazysbcount(sc->mp)) flags |= XFS_TRANS_RES_FDBLKS; - error = xrep_tempexch_enable(sc); - if (error) - return error; - error = xfs_trans_alloc(sc->mp, &M_RES(sc->mp)->tr_itruncate, tx->req.resblks, 0, flags, &sc->tp); if (error) @@ -785,7 +765,7 @@ xrep_tempexch_contents( { int error; - ASSERT(sc->flags & XREP_FSGATES_EXCHANGE_RANGE); + ASSERT(xfs_has_exchange_range(sc->mp)); xfs_exchange_mappings(sc->tp, &tx->req); error = xfs_defer_finish(&sc->tp); diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h index 8ce74bd8530a..e27daa51cab6 100644 --- a/fs/xfs/scrub/trace.h +++ b/fs/xfs/scrub/trace.h @@ -122,7 +122,6 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_BARRIER); { XCHK_FSGATES_QUOTA, "fsgates_quota" }, \ { XCHK_FSGATES_DIRENTS, "fsgates_dirents" }, \ { XCHK_FSGATES_RMAP, "fsgates_rmap" }, \ - { XREP_FSGATES_EXCHANGE_RANGE, "fsgates_exchrange" }, \ { XREP_RESET_PERAG_RESV, "reset_perag_resv" }, \ { XREP_ALREADY_FIXED, "already_fixed" } @@ -3266,8 +3265,6 @@ DEFINE_EVENT(xrep_dentry_class, name, \ TP_PROTO(struct xfs_mount *mp, const struct dentry *dentry), \ TP_ARGS(mp, dentry)) DEFINE_REPAIR_DENTRY_EVENT(xrep_adoption_check_child); -DEFINE_REPAIR_DENTRY_EVENT(xrep_adoption_check_alias); -DEFINE_REPAIR_DENTRY_EVENT(xrep_adoption_check_dentry); DEFINE_REPAIR_DENTRY_EVENT(xrep_adoption_invalidate_child); DEFINE_REPAIR_DENTRY_EVENT(xrep_dirtree_delete_child); |