All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chandan Babu R <chandan.babu@oracle.com>
To: gregkh@linuxfoundation.org
Cc: sashal@kernel.org, mcgrof@kernel.org, linux-xfs@vger.kernel.org,
	stable@vger.kernel.org, djwong@kernel.org,
	chandan.babu@oracle.com, amir73il@gmail.com,
	leah.rumancik@gmail.com
Subject: [PATCH 5.4 20/26] xfs: tail updates only need to occur when LSN changes
Date: Wed, 26 Oct 2022 11:58:37 +0530	[thread overview]
Message-ID: <20221026062843.927600-21-chandan.babu@oracle.com> (raw)
In-Reply-To: <20221026062843.927600-1-chandan.babu@oracle.com>

From: Dave Chinner <dchinner@redhat.com>

commit 8eb807bd839938b45bf7a97f0568d2a845ba6929 upstream.

We currently wake anything waiting on the log tail to move whenever
the log item at the tail of the log is removed. Historically this
was fine behaviour because there were very few items at any given
LSN. But with delayed logging, there may be thousands of items at
any given LSN, and we can't move the tail until they are all gone.

Hence if we are removing them in near tail-first order, we might be
waking up processes waiting on the tail LSN to change (e.g. log
space waiters) repeatedly without them being able to make progress.
This also occurs with the new sync push waiters, and can result in
thousands of spurious wakeups every second when under heavy direct
reclaim pressure.

To fix this, check that the tail LSN has actually changed on the
AIL before triggering wakeups. This will reduce the number of
spurious wakeups when doing bulk AIL removal and make this code much
more efficient.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Acked-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
---
 fs/xfs/xfs_inode_item.c | 18 ++++++++++----
 fs/xfs/xfs_trans_ail.c  | 52 ++++++++++++++++++++++++++++-------------
 fs/xfs/xfs_trans_priv.h |  4 ++--
 3 files changed, 51 insertions(+), 23 deletions(-)

diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index a3243a9fa77c..76a60526af94 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -732,19 +732,27 @@ xfs_iflush_done(
 	 * holding the lock before removing the inode from the AIL.
 	 */
 	if (need_ail) {
-		bool			mlip_changed = false;
+		xfs_lsn_t	tail_lsn = 0;
 
 		/* this is an opencoded batch version of xfs_trans_ail_delete */
 		spin_lock(&ailp->ail_lock);
 		list_for_each_entry(blip, &tmp, li_bio_list) {
 			if (INODE_ITEM(blip)->ili_logged &&
-			    blip->li_lsn == INODE_ITEM(blip)->ili_flush_lsn)
-				mlip_changed |= xfs_ail_delete_one(ailp, blip);
-			else {
+			    blip->li_lsn == INODE_ITEM(blip)->ili_flush_lsn) {
+				/*
+				 * xfs_ail_update_finish() only cares about the
+				 * lsn of the first tail item removed, any
+				 * others will be at the same or higher lsn so
+				 * we just ignore them.
+				 */
+				xfs_lsn_t lsn = xfs_ail_delete_one(ailp, blip);
+				if (!tail_lsn && lsn)
+					tail_lsn = lsn;
+			} else {
 				xfs_clear_li_failed(blip);
 			}
 		}
-		xfs_ail_update_finish(ailp, mlip_changed);
+		xfs_ail_update_finish(ailp, tail_lsn);
 	}
 
 	/*
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index effcd0d079b6..af782a7de21a 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -108,17 +108,25 @@ xfs_ail_next(
  * We need the AIL lock in order to get a coherent read of the lsn of the last
  * item in the AIL.
  */
+static xfs_lsn_t
+__xfs_ail_min_lsn(
+	struct xfs_ail		*ailp)
+{
+	struct xfs_log_item	*lip = xfs_ail_min(ailp);
+
+	if (lip)
+		return lip->li_lsn;
+	return 0;
+}
+
 xfs_lsn_t
 xfs_ail_min_lsn(
 	struct xfs_ail		*ailp)
 {
-	xfs_lsn_t		lsn = 0;
-	struct xfs_log_item	*lip;
+	xfs_lsn_t		lsn;
 
 	spin_lock(&ailp->ail_lock);
-	lip = xfs_ail_min(ailp);
-	if (lip)
-		lsn = lip->li_lsn;
+	lsn = __xfs_ail_min_lsn(ailp);
 	spin_unlock(&ailp->ail_lock);
 
 	return lsn;
@@ -683,11 +691,12 @@ xfs_ail_push_all_sync(
 void
 xfs_ail_update_finish(
 	struct xfs_ail		*ailp,
-	bool			do_tail_update) __releases(ailp->ail_lock)
+	xfs_lsn_t		old_lsn) __releases(ailp->ail_lock)
 {
 	struct xfs_mount	*mp = ailp->ail_mount;
 
-	if (!do_tail_update) {
+	/* if the tail lsn hasn't changed, don't do updates or wakeups. */
+	if (!old_lsn || old_lsn == __xfs_ail_min_lsn(ailp)) {
 		spin_unlock(&ailp->ail_lock);
 		return;
 	}
@@ -732,7 +741,7 @@ xfs_trans_ail_update_bulk(
 	xfs_lsn_t		lsn) __releases(ailp->ail_lock)
 {
 	struct xfs_log_item	*mlip;
-	int			mlip_changed = 0;
+	xfs_lsn_t		tail_lsn = 0;
 	int			i;
 	LIST_HEAD(tmp);
 
@@ -747,9 +756,10 @@ xfs_trans_ail_update_bulk(
 				continue;
 
 			trace_xfs_ail_move(lip, lip->li_lsn, lsn);
+			if (mlip == lip && !tail_lsn)
+				tail_lsn = lip->li_lsn;
+
 			xfs_ail_delete(ailp, lip);
-			if (mlip == lip)
-				mlip_changed = 1;
 		} else {
 			trace_xfs_ail_insert(lip, 0, lsn);
 		}
@@ -760,15 +770,23 @@ xfs_trans_ail_update_bulk(
 	if (!list_empty(&tmp))
 		xfs_ail_splice(ailp, cur, &tmp, lsn);
 
-	xfs_ail_update_finish(ailp, mlip_changed);
+	xfs_ail_update_finish(ailp, tail_lsn);
 }
 
-bool
+/*
+ * Delete one log item from the AIL.
+ *
+ * If this item was at the tail of the AIL, return the LSN of the log item so
+ * that we can use it to check if the LSN of the tail of the log has moved
+ * when finishing up the AIL delete process in xfs_ail_update_finish().
+ */
+xfs_lsn_t
 xfs_ail_delete_one(
 	struct xfs_ail		*ailp,
 	struct xfs_log_item	*lip)
 {
 	struct xfs_log_item	*mlip = xfs_ail_min(ailp);
+	xfs_lsn_t		lsn = lip->li_lsn;
 
 	trace_xfs_ail_delete(lip, mlip->li_lsn, lip->li_lsn);
 	xfs_ail_delete(ailp, lip);
@@ -776,7 +794,9 @@ xfs_ail_delete_one(
 	clear_bit(XFS_LI_IN_AIL, &lip->li_flags);
 	lip->li_lsn = 0;
 
-	return mlip == lip;
+	if (mlip == lip)
+		return lsn;
+	return 0;
 }
 
 /**
@@ -807,7 +827,7 @@ xfs_trans_ail_delete(
 	int			shutdown_type)
 {
 	struct xfs_mount	*mp = ailp->ail_mount;
-	bool			need_update;
+	xfs_lsn_t		tail_lsn;
 
 	if (!test_bit(XFS_LI_IN_AIL, &lip->li_flags)) {
 		spin_unlock(&ailp->ail_lock);
@@ -820,8 +840,8 @@ xfs_trans_ail_delete(
 		return;
 	}
 
-	need_update = xfs_ail_delete_one(ailp, lip);
-	xfs_ail_update_finish(ailp, need_update);
+	tail_lsn = xfs_ail_delete_one(ailp, lip);
+	xfs_ail_update_finish(ailp, tail_lsn);
 }
 
 int
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index 64ffa746730e..35655eac01a6 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -91,8 +91,8 @@ xfs_trans_ail_update(
 	xfs_trans_ail_update_bulk(ailp, NULL, &lip, 1, lsn);
 }
 
-bool xfs_ail_delete_one(struct xfs_ail *ailp, struct xfs_log_item *lip);
-void xfs_ail_update_finish(struct xfs_ail *ailp, bool do_tail_update)
+xfs_lsn_t xfs_ail_delete_one(struct xfs_ail *ailp, struct xfs_log_item *lip);
+void xfs_ail_update_finish(struct xfs_ail *ailp, xfs_lsn_t old_lsn)
 			__releases(ailp->ail_lock);
 void xfs_trans_ail_delete(struct xfs_ail *ailp, struct xfs_log_item *lip,
 		int shutdown_type);
-- 
2.35.1


  parent reply	other threads:[~2022-10-26  6:31 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-26  6:28 [PATCH 5.4 00/26] xfs stable candidate patches for 5.4.y (from v5.7) Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 01/26] xfs: open code insert range extent split helper Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 02/26] xfs: rework insert range into an atomic operation Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 03/26] xfs: rework collapse " Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 04/26] xfs: add a function to deal with corrupt buffers post-verifiers Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 05/26] xfs: xfs_buf_corruption_error should take __this_address Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 06/26] xfs: fix buffer corruption reporting when xfs_dir3_free_header_check fails Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 07/26] xfs: check owner of dir3 data blocks Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 08/26] xfs: check owner of dir3 blocks Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 09/26] xfs: Use scnprintf() for avoiding potential buffer overflow Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 10/26] xfs: remove the xfs_disk_dquot_t and xfs_dquot_t Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 11/26] xfs: remove the xfs_dq_logitem_t typedef Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 12/26] xfs: remove the xfs_qoff_logitem_t typedef Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 13/26] xfs: Replace function declaration by actual definition Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 14/26] xfs: factor out quotaoff intent AIL removal and memory free Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 15/26] xfs: fix unmount hang and memory leak on shutdown during quotaoff Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 16/26] xfs: preserve default grace interval during quotacheck Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 17/26] xfs: Lower CIL flush limit for large logs Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 18/26] xfs: Throttle commits on delayed background CIL push Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 19/26] xfs: factor common AIL item deletion code Chandan Babu R
2022-10-26  6:28 ` Chandan Babu R [this message]
2022-10-26  6:28 ` [PATCH 5.4 21/26] xfs: don't write a corrupt unmount record to force summary counter recalc Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 22/26] xfs: trylock underlying buffer on dquot flush Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 23/26] xfs: factor out a new xfs_log_force_inode helper Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 24/26] xfs: reflink should force the log out if mounted with wsync Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 25/26] xfs: move inode flush to the sync workqueue Chandan Babu R
2022-10-26  6:28 ` [PATCH 5.4 26/26] xfs: fix use-after-free on CIL context on shutdown Chandan Babu R
2022-10-26 14:52 ` [PATCH 5.4 00/26] xfs stable candidate patches for 5.4.y (from v5.7) Greg KH
2022-10-27 14:58   ` Greg KH
2022-10-27 15:28     ` Chandan Babu R

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=20221026062843.927600-21-chandan.babu@oracle.com \
    --to=chandan.babu@oracle.com \
    --cc=amir73il@gmail.com \
    --cc=djwong@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=leah.rumancik@gmail.com \
    --cc=linux-xfs@vger.kernel.org \
    --cc=mcgrof@kernel.org \
    --cc=sashal@kernel.org \
    --cc=stable@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.