@@ -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;
}
@@ -455,11 +455,19 @@ static inline void
xfs_blockgc_queue(
struct xfs_perag *pag)
{
+ struct xfs_mount *mp = pag->pag_mount;
+
+ if (!test_bit(XFS_OPFLAG_BLOCKGC_RUNNING_BIT, &mp->m_opflags))
+ return;
+
rcu_read_lock();
- if (radix_tree_tagged(&pag->pag_ici_root, XFS_ICI_BLOCKGC_TAG))
- queue_delayed_work(pag->pag_mount->m_gc_workqueue,
- &pag->pag_blockgc_work,
- msecs_to_jiffies(xfs_blockgc_secs * 1000));
+ if (radix_tree_tagged(&pag->pag_ici_root, XFS_ICI_BLOCKGC_TAG)) {
+ unsigned int delay = xfs_blockgc_secs * 1000;
+
+ trace_xfs_blockgc_queue(pag, delay);
+ queue_delayed_work(mp->m_gc_workqueue, &pag->pag_blockgc_work,
+ msecs_to_jiffies(delay));
+ }
rcu_read_unlock();
}
@@ -1786,8 +1794,12 @@ xfs_blockgc_stop(
struct xfs_perag *pag;
xfs_agnumber_t agno;
- for_each_perag_tag(mp, agno, pag, XFS_ICI_BLOCKGC_TAG)
+ if (!test_and_clear_bit(XFS_OPFLAG_BLOCKGC_RUNNING_BIT, &mp->m_opflags))
+ 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. */
@@ -1798,6 +1810,10 @@ xfs_blockgc_start(
struct xfs_perag *pag;
xfs_agnumber_t agno;
+ if (!test_and_set_bit(XFS_OPFLAG_BLOCKGC_RUNNING_BIT, &mp->m_opflags))
+ return;
+
+ trace_xfs_blockgc_start(mp, __return_address);
for_each_perag_tag(mp, agno, pag, XFS_ICI_BLOCKGC_TAG)
xfs_blockgc_queue(pag);
}
@@ -1855,6 +1871,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;
@@ -1877,13 +1900,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(pag, __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);
}
@@ -791,6 +791,7 @@ xfs_mountfs(
/* Enable background inode inactivation workers. */
xfs_inodegc_start(mp);
+ xfs_blockgc_start(mp);
/*
* Get and sanity-check the root inode.
@@ -278,6 +278,13 @@ enum xfs_opflag_bits {
* waiting to be processed.
*/
XFS_OPFLAG_INODEGC_RUNNING_BIT = 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.
+ */
+ XFS_OPFLAG_BLOCKGC_RUNNING_BIT = 1,
};
/*
@@ -881,14 +881,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;
}
@@ -191,6 +191,8 @@ DEFINE_FS_EVENT(xfs_inodegc_start);
DEFINE_FS_EVENT(xfs_inodegc_stop);
DEFINE_FS_EVENT(xfs_fs_sync_fs);
DEFINE_FS_EVENT(xfs_inodegc_delay_mempressure);
+DEFINE_FS_EVENT(xfs_blockgc_start);
+DEFINE_FS_EVENT(xfs_blockgc_stop);
TRACE_EVENT(xfs_inodegc_requeue_mempressure,
TP_PROTO(struct xfs_perag *pag, unsigned long nr, void *caller_ip),
@@ -239,6 +241,7 @@ DEFINE_EVENT(xfs_perag_class, name, \
TP_ARGS(pag, caller_ip))
DEFINE_PERAG_EVENT(xfs_inodegc_throttled);
DEFINE_PERAG_EVENT(xfs_inodegc_worker);
+DEFINE_PERAG_EVENT(xfs_blockgc_worker);
TRACE_EVENT(xfs_gc_delay_dquot,
TP_PROTO(struct xfs_dquot *dqp, unsigned int tag, unsigned int shift),
@@ -368,6 +371,7 @@ DEFINE_EVENT(xfs_gc_queue_class, name, \
TP_PROTO(struct xfs_perag *pag, unsigned int delay_ms), \
TP_ARGS(pag, delay_ms))
DEFINE_GC_QUEUE_EVENT(xfs_inodegc_queue);
+DEFINE_GC_QUEUE_EVENT(xfs_blockgc_queue);
TRACE_EVENT(xfs_gc_requeue_now,
TP_PROTO(struct xfs_perag *pag, unsigned int tag),