All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: sandeen@sandeen.net, djwong@kernel.org
Cc: Allison Henderson <allison.henderson@oracle.com>,
	linux-xfs@vger.kernel.org
Subject: [PATCH 02/48] xfs: port the defer ops capture and continue to resource capture
Date: Wed, 19 Jan 2022 16:23:23 -0800	[thread overview]
Message-ID: <164263820326.865554.8930683632348589030.stgit@magnolia> (raw)
In-Reply-To: <164263819185.865554.6000499997543946756.stgit@magnolia>

From: Darrick J. Wong <djwong@kernel.org>

Source kernel commit: 512edfac85d243ed6a5a5f42f513ebb7c2d32863

When log recovery tries to recover a transaction that had log intent
items attached to it, it has to save certain parts of the transaction
state (reservation, dfops chain, inodes with no automatic unlock) so
that it can finish single-stepping the recovered transactions before
finishing the chains.

This is done with the xfs_defer_ops_capture and xfs_defer_ops_continue
functions.  Right now they open-code this functionality, so let's port
this to the formalized resource capture structure that we introduced in
the previous patch.  This enables us to hold up to two inodes and two
buffers during log recovery, the same way we do for regular runtime.

With this patch applied, we'll be ready to support atomic extent swap
which holds two inodes; and logged xattrs which holds one inode and one
xattr leaf buffer.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 libxfs/libxfs_priv.h |    2 +
 libxfs/xfs_defer.c   |   86 ++++++++++++++++++++++++++++++++++++++------------
 libxfs/xfs_defer.h   |   14 +++-----
 3 files changed, 73 insertions(+), 29 deletions(-)


diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h
index b94ff41e..466865f7 100644
--- a/libxfs/libxfs_priv.h
+++ b/libxfs/libxfs_priv.h
@@ -468,6 +468,8 @@ void __xfs_buf_mark_corrupt(struct xfs_buf *bp, xfs_failaddr_t fa);
 	__mode = __mode; /* no set-but-unused warning */	\
 })
 
+#define xfs_lock_two_inodes(ip1, mode1, ip2, mode2)	((void) 0)
+
 /* space allocation */
 #define XFS_EXTENT_BUSY_DISCARDED	0x01	/* undergoing a discard op. */
 #define XFS_EXTENT_BUSY_SKIP_DISCARD	0x02	/* do not discard */
diff --git a/libxfs/xfs_defer.c b/libxfs/xfs_defer.c
index 35f51f87..40d49abc 100644
--- a/libxfs/xfs_defer.c
+++ b/libxfs/xfs_defer.c
@@ -646,10 +646,11 @@ xfs_defer_move(
  */
 static struct xfs_defer_capture *
 xfs_defer_ops_capture(
-	struct xfs_trans		*tp,
-	struct xfs_inode		*capture_ip)
+	struct xfs_trans		*tp)
 {
 	struct xfs_defer_capture	*dfc;
+	unsigned short			i;
+	int				error;
 
 	if (list_empty(&tp->t_dfops))
 		return NULL;
@@ -673,27 +674,48 @@ xfs_defer_ops_capture(
 	/* Preserve the log reservation size. */
 	dfc->dfc_logres = tp->t_log_res;
 
+	error = xfs_defer_save_resources(&dfc->dfc_held, tp);
+	if (error) {
+		/*
+		 * Resource capture should never fail, but if it does, we
+		 * still have to shut down the log and release things
+		 * properly.
+		 */
+		xfs_force_shutdown(tp->t_mountp, SHUTDOWN_CORRUPT_INCORE);
+	}
+
 	/*
-	 * Grab an extra reference to this inode and attach it to the capture
-	 * structure.
+	 * Grab extra references to the inodes and buffers because callers are
+	 * expected to release their held references after we commit the
+	 * transaction.
 	 */
-	if (capture_ip) {
-		ihold(VFS_I(capture_ip));
-		dfc->dfc_capture_ip = capture_ip;
+	for (i = 0; i < dfc->dfc_held.dr_inos; i++) {
+		ASSERT(xfs_isilocked(dfc->dfc_held.dr_ip[i], XFS_ILOCK_EXCL));
+		ihold(VFS_I(dfc->dfc_held.dr_ip[i]));
 	}
 
+	for (i = 0; i < dfc->dfc_held.dr_bufs; i++)
+		xfs_buf_hold(dfc->dfc_held.dr_bp[i]);
+
 	return dfc;
 }
 
 /* Release all resources that we used to capture deferred ops. */
 void
-xfs_defer_ops_release(
+xfs_defer_ops_capture_free(
 	struct xfs_mount		*mp,
 	struct xfs_defer_capture	*dfc)
 {
+	unsigned short			i;
+
 	xfs_defer_cancel_list(mp, &dfc->dfc_dfops);
-	if (dfc->dfc_capture_ip)
-		xfs_irele(dfc->dfc_capture_ip);
+
+	for (i = 0; i < dfc->dfc_held.dr_bufs; i++)
+		xfs_buf_relse(dfc->dfc_held.dr_bp[i]);
+
+	for (i = 0; i < dfc->dfc_held.dr_inos; i++)
+		xfs_irele(dfc->dfc_held.dr_ip[i]);
+
 	kmem_free(dfc);
 }
 
@@ -708,24 +730,21 @@ xfs_defer_ops_release(
 int
 xfs_defer_ops_capture_and_commit(
 	struct xfs_trans		*tp,
-	struct xfs_inode		*capture_ip,
 	struct list_head		*capture_list)
 {
 	struct xfs_mount		*mp = tp->t_mountp;
 	struct xfs_defer_capture	*dfc;
 	int				error;
 
-	ASSERT(!capture_ip || xfs_isilocked(capture_ip, XFS_ILOCK_EXCL));
-
 	/* If we don't capture anything, commit transaction and exit. */
-	dfc = xfs_defer_ops_capture(tp, capture_ip);
+	dfc = xfs_defer_ops_capture(tp);
 	if (!dfc)
 		return xfs_trans_commit(tp);
 
 	/* Commit the transaction and add the capture structure to the list. */
 	error = xfs_trans_commit(tp);
 	if (error) {
-		xfs_defer_ops_release(mp, dfc);
+		xfs_defer_ops_capture_free(mp, dfc);
 		return error;
 	}
 
@@ -743,17 +762,19 @@ void
 xfs_defer_ops_continue(
 	struct xfs_defer_capture	*dfc,
 	struct xfs_trans		*tp,
-	struct xfs_inode		**captured_ipp)
+	struct xfs_defer_resources	*dres)
 {
 	ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
 	ASSERT(!(tp->t_flags & XFS_TRANS_DIRTY));
 
 	/* Lock and join the captured inode to the new transaction. */
-	if (dfc->dfc_capture_ip) {
-		xfs_ilock(dfc->dfc_capture_ip, XFS_ILOCK_EXCL);
-		xfs_trans_ijoin(tp, dfc->dfc_capture_ip, 0);
-	}
-	*captured_ipp = dfc->dfc_capture_ip;
+	if (dfc->dfc_held.dr_inos == 2)
+		xfs_lock_two_inodes(dfc->dfc_held.dr_ip[0], XFS_ILOCK_EXCL,
+				    dfc->dfc_held.dr_ip[1], XFS_ILOCK_EXCL);
+	else if (dfc->dfc_held.dr_inos == 1)
+		xfs_ilock(dfc->dfc_held.dr_ip[0], XFS_ILOCK_EXCL);
+	xfs_defer_restore_resources(tp, &dfc->dfc_held);
+	memcpy(dres, &dfc->dfc_held, sizeof(struct xfs_defer_resources));
 
 	/* Move captured dfops chain and state to the transaction. */
 	list_splice_init(&dfc->dfc_dfops, &tp->t_dfops);
@@ -761,3 +782,26 @@ xfs_defer_ops_continue(
 
 	kmem_free(dfc);
 }
+
+/* Release the resources captured and continued during recovery. */
+void
+xfs_defer_resources_rele(
+	struct xfs_defer_resources	*dres)
+{
+	unsigned short			i;
+
+	for (i = 0; i < dres->dr_inos; i++) {
+		xfs_iunlock(dres->dr_ip[i], XFS_ILOCK_EXCL);
+		xfs_irele(dres->dr_ip[i]);
+		dres->dr_ip[i] = NULL;
+	}
+
+	for (i = 0; i < dres->dr_bufs; i++) {
+		xfs_buf_relse(dres->dr_bp[i]);
+		dres->dr_bp[i] = NULL;
+	}
+
+	dres->dr_inos = 0;
+	dres->dr_bufs = 0;
+	dres->dr_ordered = 0;
+}
diff --git a/libxfs/xfs_defer.h b/libxfs/xfs_defer.h
index e095abb9..7952695c 100644
--- a/libxfs/xfs_defer.h
+++ b/libxfs/xfs_defer.h
@@ -107,11 +107,7 @@ struct xfs_defer_capture {
 	/* Log reservation saved from the transaction. */
 	unsigned int		dfc_logres;
 
-	/*
-	 * An inode reference that must be maintained to complete the deferred
-	 * work.
-	 */
-	struct xfs_inode	*dfc_capture_ip;
+	struct xfs_defer_resources dfc_held;
 };
 
 /*
@@ -119,9 +115,11 @@ struct xfs_defer_capture {
  * This doesn't normally happen except log recovery.
  */
 int xfs_defer_ops_capture_and_commit(struct xfs_trans *tp,
-		struct xfs_inode *capture_ip, struct list_head *capture_list);
+		struct list_head *capture_list);
 void xfs_defer_ops_continue(struct xfs_defer_capture *d, struct xfs_trans *tp,
-		struct xfs_inode **captured_ipp);
-void xfs_defer_ops_release(struct xfs_mount *mp, struct xfs_defer_capture *d);
+		struct xfs_defer_resources *dres);
+void xfs_defer_ops_capture_free(struct xfs_mount *mp,
+		struct xfs_defer_capture *d);
+void xfs_defer_resources_rele(struct xfs_defer_resources *dres);
 
 #endif /* __XFS_DEFER_H__ */


  parent reply	other threads:[~2022-01-20  0:23 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-20  0:23 [PATCHSET 00/48] xfsprogs: sync libxfs with 5.16 Darrick J. Wong
2022-01-20  0:23 ` [PATCH 01/48] xfs: formalize the process of holding onto resources across a defer roll Darrick J. Wong
2022-01-20  0:23 ` Darrick J. Wong [this message]
2022-01-20  0:23 ` [PATCH 03/48] xfs: fix maxlevels comparisons in the btree staging code Darrick J. Wong
2022-01-20  0:23 ` [PATCH 04/48] xfs: remove xfs_btree_cur_t typedef Darrick J. Wong
2022-01-20  0:23 ` [PATCH 05/48] xfs: check that bc_nlevels never overflows Darrick J. Wong
2022-01-20  0:23 ` [PATCH 06/48] xfs: remove the xfs_dinode_t typedef Darrick J. Wong
2022-01-20  0:23 ` [PATCH 07/48] xfs: remove the xfs_dsb_t typedef Darrick J. Wong
2022-01-20  0:23 ` [PATCH 08/48] xfs: remove the xfs_dqblk_t typedef Darrick J. Wong
2022-01-20  0:24 ` [PATCH 09/48] xfs: fold perag loop iteration logic into helper function Darrick J. Wong
2022-01-20  0:24 ` [PATCH 10/48] xfs: rename the next_agno perag iteration variable Darrick J. Wong
2022-01-20  0:24 ` [PATCH 11/48] xfs: terminate perag iteration reliably on agcount Darrick J. Wong
2022-01-20  0:24 ` [PATCH 12/48] xfs: fix perag reference leak on iteration race with growfs Darrick J. Wong
2022-01-20  0:24 ` [PATCH 13/48] xfs: remove xfs_btree_cur.bc_blocklog Darrick J. Wong
2022-01-20  0:24 ` [PATCH 14/48] xfs: reduce the size of nr_ops for refcount btree cursors Darrick J. Wong
2022-01-20  0:24 ` [PATCH 15/48] xfs: prepare xfs_btree_cur for dynamic cursor heights Darrick J. Wong
2022-01-20  0:24 ` [PATCH 16/48] xfs: rearrange xfs_btree_cur fields for better packing Darrick J. Wong
2022-01-20  0:24 ` [PATCH 17/48] xfs: refactor btree cursor allocation function Darrick J. Wong
2022-01-20  0:24 ` [PATCH 18/48] xfs: encode the max btree height in the cursor Darrick J. Wong
2022-01-20  0:24 ` [PATCH 19/48] xfs: dynamically allocate cursors based on maxlevels Darrick J. Wong
2022-01-20  0:25 ` [PATCH 20/48] xfs: rename m_ag_maxlevels to m_allocbt_maxlevels Darrick J. Wong
2022-01-20  0:25 ` [PATCH 21/48] xfs: compute maximum AG btree height for critical reservation calculation Darrick J. Wong
2022-01-20  0:25 ` [PATCH 22/48] xfs: clean up xfs_btree_{calc_size,compute_maxlevels} Darrick J. Wong
2022-01-20  0:25 ` [PATCH 23/48] xfs: compute the maximum height of the rmap btree when reflink enabled Darrick J. Wong
2022-01-20  0:25 ` [PATCH 24/48] xfs_db: fix metadump level comparisons Darrick J. Wong
2022-04-28  3:02   ` Eric Sandeen
2022-01-20  0:25 ` [PATCH 25/48] xfs_db: warn about suspicious finobt trees when metadumping Darrick J. Wong
2022-01-20  0:25 ` [PATCH 26/48] xfs_db: stop using XFS_BTREE_MAXLEVELS Darrick J. Wong
2022-01-20  0:25 ` [PATCH 27/48] xfs_repair: fix AG header btree level comparisons Darrick J. Wong
2022-04-28  3:03   ` Eric Sandeen
2022-01-20  0:25 ` [PATCH 28/48] xfs_repair: warn about suspicious btree levels in AG headers Darrick J. Wong
2022-01-20  0:25 ` [PATCH 29/48] xfs_repair: stop using XFS_BTREE_MAXLEVELS Darrick J. Wong
2022-01-20  0:25 ` [PATCH 30/48] xfs: kill XFS_BTREE_MAXLEVELS Darrick J. Wong
2022-01-20  0:26 ` [PATCH 31/48] xfs: compute absolute maximum nlevels for each btree type Darrick J. Wong
2022-01-20  0:26 ` [PATCH 32/48] xfs: use separate btree cursor cache " Darrick J. Wong
2022-01-20  0:26 ` [PATCH 33/48] xfs_db: support computing btheight for all cursor types Darrick J. Wong
2022-01-20  0:26 ` [PATCH 34/48] xfs_db: report absolute maxlevels for each btree type Darrick J. Wong
2022-01-20  0:26 ` [PATCH 35/48] libxfs: remove kmem_zone_destroy Darrick J. Wong
2022-01-20  0:26 ` [PATCH 36/48] libxfs: remove kmem_zone_init Darrick J. Wong
2022-01-20  0:26 ` [PATCH 37/48] xfs: remove kmem_zone typedef Darrick J. Wong
2022-01-20  0:26 ` [PATCH 38/48] xfs: rename _zone variables to _cache Darrick J. Wong
2022-01-20  0:26 ` [PATCH 39/48] libxfs: rename all the other " Darrick J. Wong
2022-01-20  0:26 ` [PATCH 40/48] libxfs: change zone to cache for all kmem functions Darrick J. Wong
2022-01-20  0:26 ` [PATCH 41/48] xfs: compact deferred intent item structures Darrick J. Wong
2022-01-20  0:27 ` [PATCH 42/48] xfs: create slab caches for frequently-used deferred items Darrick J. Wong
2022-01-20  0:27 ` [PATCH 43/48] xfs: rename xfs_bmap_add_free to xfs_free_extent_later Darrick J. Wong
2022-01-20  0:27 ` [PATCH 44/48] xfs: reduce the size of struct xfs_extent_free_item Darrick J. Wong
2022-01-20  0:27 ` [PATCH 45/48] xfs: remove unused parameter from refcount code Darrick J. Wong
2022-01-20  0:27 ` [PATCH 46/48] xfs: use swap() to make dabtree code cleaner Darrick J. Wong
2022-01-20  0:27 ` [PATCH 47/48] xfs: Fix the free logic of state in xfs_attr_node_hasname Darrick J. Wong
2022-01-20  0:27 ` [PATCH 48/48] libxfs: remove kernel stubs from xfs_shared.h Darrick J. Wong

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=164263820326.865554.8930683632348589030.stgit@magnolia \
    --to=djwong@kernel.org \
    --cc=allison.henderson@oracle.com \
    --cc=linux-xfs@vger.kernel.org \
    --cc=sandeen@sandeen.net \
    /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.