@@ -893,11 +893,12 @@ xchk_start_reaping(
struct xfs_scrub *sc)
{
/*
- * Readonly filesystems do not perform inactivation, so there's no
- * need to restart the worker.
+ * Readonly filesystems do not perform inactivation or speculative
+ * preallocation, so there's no need to restart the workers.
*/
- if (!(sc->mp->m_flags & XFS_MOUNT_RDONLY))
+ if (!(sc->mp->m_flags & XFS_MOUNT_RDONLY)) {
xfs_inodegc_start(sc->mp);
- xfs_blockgc_start(sc->mp);
+ xfs_blockgc_start(sc->mp);
+ }
sc->flags &= ~XCHK_REAPING_DISABLED;
}
@@ -211,6 +211,11 @@ static inline void
xfs_blockgc_queue(
struct xfs_perag *pag)
{
+ struct xfs_mount *mp = pag->pag_mount;
+
+ if (!xfs_is_blockgc_enabled(mp))
+ return;
+
rcu_read_lock();
if (radix_tree_tagged(&pag->pag_ici_root, XFS_ICI_BLOCKGC_TAG))
queue_delayed_work(pag->pag_mount->m_blockgc_wq,
@@ -1366,8 +1371,12 @@ xfs_blockgc_stop(
struct xfs_perag *pag;
xfs_agnumber_t agno;
- for_each_perag_tag(mp, agno, pag, XFS_ICI_BLOCKGC_TAG)
+ if (!xfs_clear_blockgc_enabled(mp))
+ return;
+
+ for_each_perag(mp, agno, pag)
cancel_delayed_work_sync(&pag->pag_blockgc_work);
+ trace_xfs_blockgc_stop(mp, __return_address);
}
/* Enable post-EOF and CoW block auto-reclamation. */
@@ -1378,6 +1387,10 @@ xfs_blockgc_start(
struct xfs_perag *pag;
xfs_agnumber_t agno;
+ if (xfs_set_blockgc_enabled(mp))
+ return;
+
+ trace_xfs_blockgc_start(mp, __return_address);
for_each_perag_tag(mp, agno, pag, XFS_ICI_BLOCKGC_TAG)
xfs_blockgc_queue(pag);
}
@@ -1435,6 +1448,13 @@ xfs_blockgc_scan_inode(
unsigned int lockflags = 0;
int error;
+ /*
+ * Speculative preallocation gc isn't supposed to run when the fs is
+ * frozen because we don't want kernel threads to block on transaction
+ * allocation.
+ */
+ ASSERT(ip->i_mount->m_super->s_writers.frozen < SB_FREEZE_FS);
+
error = xfs_inode_free_eofblocks(ip, icw, &lockflags);
if (error)
goto unlock;
@@ -1457,13 +1477,12 @@ xfs_blockgc_worker(
struct xfs_mount *mp = pag->pag_mount;
int error;
- if (!sb_start_write_trylock(mp->m_super))
- return;
+ trace_xfs_blockgc_worker(mp, __return_address);
+
error = xfs_icwalk_ag(pag, XFS_ICWALK_BLOCKGC, NULL);
if (error)
xfs_info(mp, "AG %u preallocation gc worker failed, err=%d",
pag->pag_agno, error);
- sb_end_write(mp->m_super);
xfs_blockgc_queue(pag);
}
@@ -789,6 +789,7 @@ xfs_mountfs(
/* Enable background inode inactivation workers. */
xfs_inodegc_start(mp);
+ xfs_blockgc_start(mp);
/*
* Get and sanity-check the root inode.
@@ -280,6 +280,13 @@ typedef struct xfs_mount {
*/
#define XFS_STATE_INODEGC_ENABLED 0
+/*
+ * If set, background speculative prealloc gc worker threads will be scheduled
+ * to process queued blockgc work. If not, inodes retain their preallocations
+ * until explicitly deleted.
+ */
+#define XFS_STATE_BLOCKGC_ENABLED 1
+
#define __XFS_IS_STATE(name, NAME) \
static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
{ \
@@ -295,6 +302,7 @@ static inline bool xfs_set_ ## name (struct xfs_mount *mp) \
}
__XFS_IS_STATE(inodegc_enabled, INODEGC_ENABLED)
+__XFS_IS_STATE(blockgc_enabled, BLOCKGC_ENABLED)
/*
* Max and min values for mount-option defined I/O
@@ -912,14 +912,17 @@ xfs_fs_unfreeze(
xfs_restore_resvblks(mp);
xfs_log_work_queue(mp);
- xfs_blockgc_start(mp);
/*
* Don't reactivate the inodegc worker on a readonly filesystem because
- * inodes are sent directly to reclaim.
+ * inodes are sent directly to reclaim. Don't reactivate the blockgc
+ * worker because there are no speculative preallocations on a readonly
+ * filesystem.
*/
- if (!(mp->m_flags & XFS_MOUNT_RDONLY))
+ if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
+ xfs_blockgc_start(mp);
xfs_inodegc_start(mp);
+ }
return 0;
}
@@ -158,7 +158,8 @@ DEFINE_PERAG_REF_EVENT(xfs_perag_set_inode_tag);
DEFINE_PERAG_REF_EVENT(xfs_perag_clear_inode_tag);
#define XFS_STATE_FLAGS \
- { (1UL << XFS_STATE_INODEGC_ENABLED), "inodegc" }
+ { (1UL << XFS_STATE_INODEGC_ENABLED), "inodegc" }, \
+ { (1UL << XFS_STATE_BLOCKGC_ENABLED), "blockgc" }
DECLARE_EVENT_CLASS(xfs_fs_class,
TP_PROTO(struct xfs_mount *mp, void *caller_ip),
@@ -198,6 +199,9 @@ DEFINE_FS_EVENT(xfs_inodegc_worker);
DEFINE_FS_EVENT(xfs_inodegc_queue);
DEFINE_FS_EVENT(xfs_inodegc_throttle);
DEFINE_FS_EVENT(xfs_fs_sync_fs);
+DEFINE_FS_EVENT(xfs_blockgc_start);
+DEFINE_FS_EVENT(xfs_blockgc_stop);
+DEFINE_FS_EVENT(xfs_blockgc_worker);
DECLARE_EVENT_CLASS(xfs_ag_class,
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno),