summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_icache.c
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-06-21 10:34:34 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-07-23 18:21:41 -0700
commit422ed1c784e032ce562187e908021be33a05a24e (patch)
tree35b99092c749f640eb13d1117cb556e6f4a1c084 /fs/xfs/xfs_icache.c
parentf86d13d951f850cbd7bb5210ba5bf9c13051e9ea (diff)
xfs: throttle inodegc queuing on backlog
Track the number of inodes in each AG that are queued for inactivation, then use that information to decide if we're going to make threads that has queued an inode for inactivation wait for the background thread. The purpose of this high water mark is to establish a maximum bound on the backlog of work that can accumulate on a non-frozen filesystem. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs/xfs_icache.c')
-rw-r--r--fs/xfs/xfs_icache.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index b8d3a0881c32..3a6cf7972366 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -36,6 +36,12 @@
#define XFS_ICI_INODEGC_TAG 2
/*
+ * Upper bound on the number of inodes in each AG that can be queued for
+ * inactivation at any given time, to avoid monopolizing the workqueue.
+ */
+#define XFS_INODEGC_MAX_BACKLOG (1024 * XFS_INODES_PER_CHUNK)
+
+/*
* The goal for walking incore inodes. These can correspond with incore inode
* radix tree tags when convenient. Avoid existing XFS_IWALK namespace.
*/
@@ -268,6 +274,8 @@ xfs_perag_set_inode_tag(
if (tag == XFS_ICI_RECLAIM_TAG)
pag->pag_ici_reclaimable++;
+ else if (tag == XFS_ICI_INODEGC_TAG)
+ pag->pag_ici_needs_inactive++;
if (was_tagged)
return;
@@ -315,6 +323,8 @@ xfs_perag_clear_inode_tag(
if (tag == XFS_ICI_RECLAIM_TAG)
pag->pag_ici_reclaimable--;
+ else if (tag == XFS_ICI_INODEGC_TAG)
+ pag->pag_ici_needs_inactive--;
if (radix_tree_tagged(&pag->pag_ici_root, tag))
return;
@@ -373,6 +383,12 @@ xfs_inodegc_want_throttle(
if (current->reclaim_state != NULL)
return false;
+ /* Enforce an upper bound on how many inodes can queue up. */
+ if (pag->pag_ici_needs_inactive > XFS_INODEGC_MAX_BACKLOG) {
+ trace_xfs_inodegc_throttle_backlog(pag);
+ return true;
+ }
+
/* Throttle if memory reclaim anywhere has triggered us. */
if (atomic_read(&mp->m_inodegc_reclaim) > 0) {
trace_xfs_inodegc_throttle_mempressure(mp);