summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);