All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: darrick.wong@oracle.com
Cc: linux-xfs@vger.kernel.org
Subject: [PATCH 10/10] xfs: create a polled function to force inode inactivation
Date: Tue, 31 Dec 2019 17:09:43 -0800	[thread overview]
Message-ID: <157784098338.1362752.12534751621591800147.stgit@magnolia> (raw)
In-Reply-To: <157784092020.1362752.15046503361741521784.stgit@magnolia>

From: Darrick J. Wong <darrick.wong@oracle.com>

Create a polled version of xfs_inactive_force so that we can force
inactivation while holding a lock (usually the umount lock) without
tripping over the softlockup timer.  This is for callers that hold vfs
locks while calling inactivation, which is currently unmount, iunlink
processing during mount, and rw->ro remount.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/xfs_icache.c |   52 +++++++++++++++++++++++++++++++++++++++++++++++++--
 fs/xfs/xfs_icache.h |    2 ++
 fs/xfs/xfs_mount.c  |    2 +-
 fs/xfs/xfs_mount.h  |    6 ++++++
 fs/xfs/xfs_super.c  |    3 ++-
 5 files changed, 61 insertions(+), 4 deletions(-)


diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 5240e9e517d7..892bb789dcbf 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -25,6 +25,7 @@
 #include "xfs_health.h"
 
 #include <linux/iversion.h>
+#include <linux/nmi.h>
 
 STATIC int xfs_inode_free_eofblocks(struct xfs_inode *ip, struct xfs_perag *pag,
 		void *args);
@@ -2284,8 +2285,12 @@ static int
 xfs_inactive_inodes_pag(
 	struct xfs_perag	*pag)
 {
-	return xfs_ici_walk_ag(pag, &xfs_inactive_iwalk_ops, 0, NULL,
+	int			error;
+
+	error = xfs_ici_walk_ag(pag, &xfs_inactive_iwalk_ops, 0, NULL,
 			XFS_ICI_INACTIVE_TAG);
+	wake_up(&pag->pag_mount->m_inactive_wait);
+	return error;
 }
 
 /*
@@ -2298,8 +2303,12 @@ xfs_inactive_inodes(
 	struct xfs_mount	*mp,
 	struct xfs_eofblocks	*eofb)
 {
-	return xfs_ici_walk_fns(mp, &xfs_inactive_iwalk_ops, 0, eofb,
+	int			error;
+
+	error = xfs_ici_walk_fns(mp, &xfs_inactive_iwalk_ops, 0, eofb,
 			XFS_ICI_INACTIVE_TAG);
+	wake_up(&mp->m_inactive_wait);
+	return error;
 }
 
 /* Try to get inode inactivation moving. */
@@ -2406,3 +2415,42 @@ xfs_inactive_schedule_now(
 		spin_unlock(&pag->pag_ici_lock);
 	}
 }
+
+/* Return true if there are inodes still being inactivated. */
+static bool
+xfs_inactive_pending(
+	struct xfs_mount	*mp)
+{
+	struct xfs_perag	*pag;
+	xfs_agnumber_t		agno = 0;
+	bool			ret = false;
+
+	while (!ret &&
+	       (pag = xfs_perag_get_tag(mp, agno, XFS_ICI_INACTIVE_TAG))) {
+		agno = pag->pag_agno + 1;
+		spin_lock(&pag->pag_ici_lock);
+		if (pag->pag_ici_inactive)
+			ret = true;
+		spin_unlock(&pag->pag_ici_lock);
+		xfs_perag_put(pag);
+	}
+
+	return ret;
+}
+
+/*
+ * Flush all pending inactivation work and poll until finished.  This function
+ * is for callers that must flush with vfs locks held, such as unmount,
+ * remount, and iunlinks processing during mount.
+ */
+void
+xfs_inactive_force_poll(
+	struct xfs_mount	*mp)
+{
+	xfs_inactive_schedule_now(mp);
+
+	while (!wait_event_timeout(mp->m_inactive_wait,
+				   xfs_inactive_pending(mp) == false, HZ)) {
+		touch_softlockup_watchdog();
+	}
+}
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index a82b473b88a2..75332d4450ba 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -89,4 +89,6 @@ void xfs_inactive_shutdown(struct xfs_mount *mp);
 void xfs_inactive_cancel_work(struct xfs_mount *mp);
 void xfs_inactive_schedule_now(struct xfs_mount *mp);
 
+void xfs_inactive_force_poll(struct xfs_mount *mp);
+
 #endif
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index b9b37eff4063..5e2ce91f4ab8 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1066,7 +1066,7 @@ xfs_unmountfs(
 	 * Since this can involve finobt updates, do it now before we lose the
 	 * per-AG space reservations.
 	 */
-	xfs_inactive_force(mp);
+	xfs_inactive_force_poll(mp);
 
 	xfs_blockgc_stop(mp);
 	xfs_fs_unreserve_ag_blocks(mp);
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 87a62b0543ec..237a15a136c8 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -206,6 +206,12 @@ typedef struct xfs_mount {
 	 * into a single flush.
 	 */
 	struct work_struct	m_flush_inodes_work;
+
+	/*
+	 * Use this to wait for the inode inactivation workqueue to finish
+	 * inactivating all the inodes.
+	 */
+	struct wait_queue_head	m_inactive_wait;
 } xfs_mount_t;
 
 #define M_IGEO(mp)		(&(mp)->m_ino_geo)
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index fced499ecdc9..af1fe32247cf 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1736,7 +1736,7 @@ xfs_remount_ro(
 	 * Since this can involve finobt updates, do it now before we lose the
 	 * per-AG space reservations.
 	 */
-	xfs_inactive_force(mp);
+	xfs_inactive_force_poll(mp);
 
 	/* Free the per-AG metadata reservation pool. */
 	error = xfs_fs_unreserve_ag_blocks(mp);
@@ -1859,6 +1859,7 @@ static int xfs_init_fs_context(
 	INIT_WORK(&mp->m_flush_inodes_work, xfs_flush_inodes_worker);
 	INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
 	mp->m_kobj.kobject.kset = xfs_kset;
+	init_waitqueue_head(&mp->m_inactive_wait);
 	/*
 	 * We don't create the finobt per-ag space reservation until after log
 	 * recovery, so we must set this to true so that an ifree transaction


      parent reply	other threads:[~2020-01-01  1:09 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-01  1:08 [PATCH v2 00/10] xfs: deferred inode inactivation Darrick J. Wong
2020-01-01  1:08 ` [PATCH 01/10] xfs: decide if inode needs inactivation Darrick J. Wong
2020-01-01  1:08 ` [PATCH 02/10] xfs: track unlinked inactive inode fs summary counters Darrick J. Wong
2020-01-01  1:08 ` [PATCH 03/10] xfs: track unlinked inactive inode quota counters Darrick J. Wong
2020-01-01  1:09 ` [PATCH 04/10] xfs: pass per-ag structure to the xfs_ici_walk execute function Darrick J. Wong
2020-01-01  1:09 ` [PATCH 05/10] xfs: pass around xfs_inode_ag_walk iget/irele helper functions Darrick J. Wong
2020-01-01  1:09 ` [PATCH 06/10] xfs: deferred inode inactivation Darrick J. Wong
2020-01-01  1:09 ` [PATCH 07/10] xfs: force inode inactivation and retry fs writes when there isn't space Darrick J. Wong
2020-01-01  1:09 ` [PATCH 08/10] xfs: force inactivation before fallocate when space is low Darrick J. Wong
2020-01-01  1:09 ` [PATCH 09/10] xfs: parallelize inode inactivation Darrick J. Wong
2020-01-01  1:09 ` Darrick J. Wong [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=157784098338.1362752.12534751621591800147.stgit@magnolia \
    --to=darrick.wong@oracle.com \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.