summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-03-09 10:39:43 -0800
committerDarrick J. Wong <djwong@kernel.org>2021-03-25 17:08:24 -0700
commit108439d25488c0de7085bb290aba795482fe3f8a (patch)
tree623057e6aa844eaa973f902d3e726da668710bba
parenta4ddad7f7acd799c312c19198a071be2ac06ad2c (diff)
xfs: push inactive inodes if the quotacheck scrubber hits themdeferred-inactivation_2021-03-25
If the online quotacheck code encounters an inode that is awaiting inactivation, it won't be able to iget the inode. Push inode gc in the respective AG to try to clear the inode, and try again. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r--fs/xfs/scrub/quotacheck.c7
-rw-r--r--fs/xfs/xfs_icache.c17
-rw-r--r--fs/xfs/xfs_icache.h1
3 files changed, 25 insertions, 0 deletions
diff --git a/fs/xfs/scrub/quotacheck.c b/fs/xfs/scrub/quotacheck.c
index ed3aa84f093b..1717e0f30cdd 100644
--- a/fs/xfs/scrub/quotacheck.c
+++ b/fs/xfs/scrub/quotacheck.c
@@ -511,6 +511,13 @@ xqcheck_collect_counts(
retries = 20;
break;
case -ENOENT:
+ /*¬
+ * It's possible that this inode has lost all of its
+ * links but hasn't yet been inactivated. Try to push
+ * it towards inactivation.
+ */
+ xfs_inodegc_flush_ino(xqc->sc->mp, ino);
+ /* fall through */
case -EINVAL:
/*
* We thought the inode was allocated, but iget failed
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index a24364f25b4b..5fd13ba2482c 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -2010,6 +2010,23 @@ clear:
clear_bit(XFS_OPFLAG_INACTIVATE_NOW_BIT, &mp->m_opflags);
}
+/* Flush inactivation work for all inodes in the same AGs as this inode. */
+void
+xfs_inodegc_flush_ino(
+ struct xfs_mount *mp,
+ xfs_ino_t ino)
+{
+ struct xfs_perag *pag;
+
+ if (!xfs_inodegc_running(mp))
+ return;
+
+ pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino));
+ mod_delayed_work(mp->m_gc_workqueue, &pag->pag_inodegc_work, 0);
+ flush_delayed_work(&pag->pag_inodegc_work);
+ xfs_perag_put(pag);
+}
+
/* Stop all queued inactivation work. */
void
xfs_inodegc_stop(
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index 0f832fa95fd4..1f94ef72fffb 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -75,6 +75,7 @@ void xfs_inew_wait(struct xfs_inode *ip);
void xfs_inodegc_worker(struct work_struct *work);
void xfs_inodegc_flush(struct xfs_mount *mp);
void xfs_inodegc_flush_poll(struct xfs_mount *mp);
+void xfs_inodegc_flush_ino(struct xfs_mount *mp, xfs_ino_t ino);
void xfs_inodegc_stop(struct xfs_mount *mp);
void xfs_inodegc_start(struct xfs_mount *mp);
int xfs_inodegc_free_space(struct xfs_mount *mp, struct xfs_eofblocks *eofb);