summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-12-11 15:57:21 -0800
committerDarrick J. Wong <djwong@kernel.org>2021-12-15 17:29:32 -0800
commit2d3f077efc3b642b133ae05ae5601620451e932f (patch)
tree4aedec04c9c505a560ee4e8715831746e22be395
parent40aa09228aee89349864173faaff593636818bfb (diff)
xfs: revert "xfs: introduce online scrub freeze"
Now that we've contained the fs freezing to the one scrubber that needs it, remove all the internal infrastructure for handling freezes. Leave the ABI because we'll have to bump the kernel and userspace for that. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r--fs/xfs/scrub/common.c102
-rw-r--r--fs/xfs/scrub/common.h2
-rw-r--r--fs/xfs/scrub/scrub.c7
-rw-r--r--fs/xfs/scrub/scrub.h1
-rw-r--r--fs/xfs/xfs_mount.h6
-rw-r--r--fs/xfs/xfs_super.c49
-rw-r--r--fs/xfs/xfs_trans.c5
7 files changed, 3 insertions, 169 deletions
diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c
index 5e70268cdd76..b7db2ef781d3 100644
--- a/fs/xfs/scrub/common.c
+++ b/fs/xfs/scrub/common.c
@@ -877,13 +877,9 @@ xchk_trans_alloc(
struct xfs_scrub *sc,
uint resblks)
{
- uint flags = 0;
-
- if (sc->flags & XCHK_FS_FROZEN)
- flags |= XFS_TRANS_NO_WRITECOUNT;
if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR)
return xfs_trans_alloc(sc->mp, &M_RES(sc->mp)->tr_itruncate,
- resblks, 0, flags, &sc->tp);
+ resblks, 0, 0, &sc->tp);
return xchk_trans_alloc_empty(sc);
}
@@ -1276,102 +1272,6 @@ xchk_start_reaping(
sc->flags &= ~XCHK_REAPING_DISABLED;
}
-/*
- * Exclusive Filesystem Access During Scrub and Repair
- * ===================================================
- *
- * While most scrub activity can occur while the filesystem is live, there
- * are certain scenarios where we cannot tolerate concurrent metadata updates.
- * We therefore must freeze the filesystem against all other changes.
- *
- * The typical scenarios envisioned for scrub freezes are (a) to lock out all
- * other filesystem changes in order to check the global summary counters,
- * and anything else that requires unusual behavioral semantics.
- *
- * The typical scenarios envisioned for repair freezes are (a) to avoid ABBA
- * deadlocks when need to take locks in an unusual order; or (b) to update
- * global filesystem state. For example, reconstruction of a damaged reverse
- * mapping btree requires us to hold the AG header locks while scanning
- * inodes, which goes against the usual inode -> AG header locking order.
- *
- * A note about inode reclaim: when we freeze the filesystem, users can't
- * modify things and periodic background reclaim of speculative preallocations
- * and copy-on-write staging extents is stopped. However, the scrub/repair
- * thread must be careful about evicting an inode from memory -- if the
- * eviction would require a transaction, we must defer the iput until after
- * the scrub freeze. The reasons for this are twofold: first, scrub/repair
- * already have a transaction and xfs can't nest transactions; and second, we
- * froze the fs to prevent modifications that we can't control directly.
- * This guarantee is made by freezing the inode inactivation worker while
- * frozen.
- *
- * Userspace is prevented from freezing or thawing the filesystem during a
- * repair freeze by the ->freeze_super and ->thaw_super superblock operations,
- * which block any changes to the freeze state while a repair freeze is
- * running through the use of the m_scrub_freeze mutex. It only makes sense
- * to run one scrub/repair freeze at a time, so the mutex is fine.
- *
- * Scrub/repair freezes cannot be initiated during a regular freeze because
- * freeze_super does not allow nested freeze. Repair activity that does not
- * require a repair freeze is also prevented from running during a regular
- * freeze because transaction allocation blocks on the regular freeze. We
- * assume that the only other users of XFS_TRANS_NO_WRITECOUNT transactions
- * either aren't modifying space metadata in a way that would affect repair,
- * or that we can inhibit any of the ones that do.
- *
- * Note that thaw_super and freeze_super can call deactivate_locked_super
- * which can free the xfs_mount. This can happen if someone freezes the block
- * device, unmounts the filesystem, and thaws the block device. Therefore, we
- * must be careful about who gets to unlock the repair freeze mutex. See the
- * comments in xfs_fs_put_super.
- */
-
-/* Start a scrub/repair freeze. */
-int
-xchk_fs_freeze(
- struct xfs_scrub *sc)
-{
- int error;
-
- if (!(sc->sm->sm_flags & XFS_SCRUB_IFLAG_FREEZE_OK))
- return -EUSERS;
-
- if (sc->flags & ~XCHK_HAVE_FREEZE_PROT) {
- sc->flags &= ~XCHK_HAVE_FREEZE_PROT;
- mnt_drop_write_file(sc->file);
- }
-
- mutex_lock(&sc->mp->m_scrub_freeze);
-
- /*
- * Clear out all the NEEDS_INACTIVE inodes because we won't be able
- * to iget them during any metadata scan.
- */
- xfs_inodegc_flush(sc->mp);
-
- error = freeze_super(sc->mp->m_super);
- if (error) {
- mutex_unlock(&sc->mp->m_scrub_freeze);
- sc->sm->sm_flags &= ~XFS_SCRUB_IFLAG_REPAIR;
- return error;
- }
- sc->flags |= XCHK_FS_FROZEN;
- return 0;
-}
-
-/* Release a scrub/repair freeze. */
-int
-xchk_fs_thaw(
- struct xfs_scrub *sc)
-{
- int error;
-
- sc->flags &= ~XCHK_FS_FROZEN;
- error = thaw_super(sc->mp->m_super);
- mutex_unlock(&sc->mp->m_scrub_freeze);
- return error;
-}
-
/* Complain about failures... */
void
xchk_whine(
diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h
index 36a0be71cfbf..fca7b1540f84 100644
--- a/fs/xfs/scrub/common.h
+++ b/fs/xfs/scrub/common.h
@@ -219,7 +219,5 @@ static inline bool xchk_could_repair(const struct xfs_scrub *sc)
int xchk_metadata_inode_forks(struct xfs_scrub *sc);
void xchk_stop_reaping(struct xfs_scrub *sc);
void xchk_start_reaping(struct xfs_scrub *sc);
-int xchk_fs_freeze(struct xfs_scrub *sc);
-int xchk_fs_thaw(struct xfs_scrub *sc);
#endif /* __XFS_SCRUB_COMMON_H__ */
diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c
index f36f57eb3574..b4a80aa62112 100644
--- a/fs/xfs/scrub/scrub.c
+++ b/fs/xfs/scrub/scrub.c
@@ -179,12 +179,7 @@ xchk_teardown(
xfs_xchg_range_rele_log_assist(sc->mp);
sc->flags &= ~XREP_ATOMIC_EXCHANGE;
}
- if (sc->flags & XCHK_FS_FROZEN) {
- int err2 = xchk_fs_thaw(sc);
-
- if (!error && err2)
- error = err2;
- } else if (sc->flags & XCHK_HAVE_FREEZE_PROT) {
+ if (sc->flags & XCHK_HAVE_FREEZE_PROT) {
sc->flags &= ~XCHK_HAVE_FREEZE_PROT;
mnt_drop_write_file(sc->file);
}
diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h
index b74f629ae459..72a86687b21b 100644
--- a/fs/xfs/scrub/scrub.h
+++ b/fs/xfs/scrub/scrub.h
@@ -131,7 +131,6 @@ struct xfs_scrub {
#define XCHK_TRY_HARDER (1 << 0) /* can't get resources, try again */
#define XCHK_HAVE_FREEZE_PROT (1 << 1) /* do we have freeze protection? */
#define XCHK_REAPING_DISABLED (1 << 2) /* background block reaping paused */
-#define XCHK_FS_FROZEN (1 << 3) /* we froze the fs to do things */
/* uses atomic metadata file content exchange */
#define XREP_ATOMIC_EXCHANGE (1 << 29)
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index e7da1f04d588..23ec64f4125e 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -324,12 +324,6 @@ typedef struct xfs_mount {
unsigned int *m_errortag;
struct xfs_kobj m_errortag_kobj;
#endif
- /*
- * Only allow one thread to initiate a repair freeze at a time. We
- * also use this to block userspace from changing the freeze state
- * while a repair freeze is in progress.
- */
- struct mutex m_scrub_freeze;
/* online file link count check stuff */
struct xfs_hook_chain m_nlink_delta_hooks;
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 2d3261c1b67c..f836ce009110 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -726,8 +726,6 @@ xfs_mount_free(
kfree(mp->m_rtname);
kfree(mp->m_logname);
- ASSERT(!mutex_is_locked(&mp->m_scrub_freeze));
- mutex_destroy(&mp->m_scrub_freeze);
#ifdef CONFIG_XFS_RT
xfs_drain_free(&mp->m_rt_intents);
#endif
@@ -937,50 +935,6 @@ xfs_fs_unfreeze(
return 0;
}
-STATIC int
-xfs_fs_freeze_super(
- struct super_block *sb)
-{
- int error;
-
- /*
- * Don't let userspace freeze while scrub has the filesystem frozen.
- * Take our own private reference to the vfs superblock so that we
- * don't lose the xfs superblock while frozen or trying to freeze.
- */
- atomic_inc(&sb->s_active);
- mutex_lock(&XFS_M(sb)->m_scrub_freeze);
- error = freeze_super(sb);
- mutex_unlock(&XFS_M(sb)->m_scrub_freeze);
- deactivate_super(sb);
-
- return error;
-}
-
-STATIC int
-xfs_fs_thaw_super(
- struct super_block *sb)
-{
- int error;
-
- /*
- * Freeze takes an s_active reference to the filesystem and fs thaw
- * drops it. If a filesystem on a frozen (dm) block device is
- * unmounted before the block device is thawed, the freezer state could
- * contain the one remaining s_active reference to the vfs superblock.
- * Since thaw_super drops that reference (which frees the xfs_mount)
- * and we still have to unlock the scrub freeze mutex, we must take our
- * own private s_active reference to avoid a use-after-free.
- */
- atomic_inc(&sb->s_active);
- mutex_lock(&XFS_M(sb)->m_scrub_freeze);
- error = thaw_super(sb);
- mutex_unlock(&XFS_M(sb)->m_scrub_freeze);
- deactivate_super(sb);
-
- return error;
-}
-
/*
* This function fills in xfs_mount_t fields based on mount args.
* Note: the superblock _has_ now been read in.
@@ -1179,8 +1133,6 @@ static const struct super_operations xfs_super_operations = {
.show_options = xfs_fs_show_options,
.nr_cached_objects = xfs_fs_nr_cached_objects,
.free_cached_objects = xfs_fs_free_cached_objects,
- .freeze_super = xfs_fs_freeze_super,
- .thaw_super = xfs_fs_thaw_super,
};
static int
@@ -1982,7 +1934,6 @@ static int xfs_init_fs_context(
INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
spin_lock_init(&mp->m_perag_lock);
mutex_init(&mp->m_growlock);
- mutex_init(&mp->m_scrub_freeze);
INIT_WORK(&mp->m_flush_inodes_work, xfs_flush_inodes_worker);
INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
mp->m_kobj.kobject.kset = xfs_kset;
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 15bb99bac04e..4d5fcd2f6d7c 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -329,12 +329,9 @@ retry:
/*
* Zero-reservation ("empty") transactions can't modify anything, so
- * they're allowed to run while we're frozen. Scrub is allowed to
- * freeze the filesystem in order to obtain exclusive access to the
- * filesystem.
+ * they're allowed to run while we're frozen.
*/
WARN_ON(resp->tr_logres > 0 &&
- !mutex_is_locked(&mp->m_scrub_freeze) &&
mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE);
ASSERT(!(flags & XFS_TRANS_RES_FDBLKS) ||
xfs_has_lazysbcount(mp));