All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/15] xfs: condense dfops and automatic relogging
@ 2018-07-30 16:45 Brian Foster
  2018-07-30 16:45 ` [PATCH 01/15] xfs: refactor internal dfops initialization Brian Foster
                   ` (14 more replies)
  0 siblings, 15 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

Hi all,

Here is the (actual) final dfops cleanup series. ;P This essentially
pares down xfs_defer_ops to a single list_head for queued deferred ops
and folds said list into the transaction, eliminating the need for the
xfs_defer_ops structure.

To facilitate this, the low free space mode flag is converted into a
transaction flag and carried across tx rolls to preserve current
behavior. The pending list is converted to an on-stack list with the
help of a change to cancel pending ops on xfs_defer_finish() failure.
The joined inode/buffer lists are also converted to on-stack lists once
said items are automatically relogged across dfops transaction rolls via
item hold/lock state.

The only real behavior change here should be patch 6 which adds the
missing xfs_defer_ijoin() calls that would, in absence of patch 6, be
implied by the automatic inode relogging patch. In other words, these
are the inodes that patch 8 would start to relog that weren't relogged
before. Technically patch 6 is unnecessary, but I had already identified
these sites as part of the initial investigation and so figured it would
be more clear to add them explicitly.

This survives xfstests and a weekend long fsstress run so far. I have
some fsx testing in progress now.

Thoughts, reviews, flames appreciated.

Brian

Brian Foster (15):
  xfs: refactor internal dfops initialization
  xfs: use transaction for intent recovery instead of raw dfops
  xfs: remove unused __xfs_defer_cancel() internal helper
  xfs: pass transaction to dfops reset/move helpers
  xfs: replace dop_low with transaction flag
  xfs: add missing defer ijoins for held inodes
  xfs: automatic dfops buffer relogging
  xfs: automatic dfops inode relogging
  xfs: drop dop param from xfs_defer_op_type ->finish_item() callback
  xfs: clean out superfluous dfops dop params/vars
  xfs: cancel dfops on xfs_defer_finish() error
  xfs: replace xfs_defer_ops ->dop_pending with on-stack list
  xfs: pass transaction to xfs_defer_add()
  xfs: always defer agfl block frees
  xfs: fold dfops into the transaction

 fs/xfs/libxfs/xfs_alloc.c       |  18 +--
 fs/xfs/libxfs/xfs_attr.c        |  26 +--
 fs/xfs/libxfs/xfs_attr_remote.c |   6 +-
 fs/xfs/libxfs/xfs_bmap.c        |  93 +++++------
 fs/xfs/libxfs/xfs_bmap.h        |  25 ++-
 fs/xfs/libxfs/xfs_bmap_btree.c  |   6 +-
 fs/xfs/libxfs/xfs_btree.h       |   1 -
 fs/xfs/libxfs/xfs_da_btree.h    |   1 -
 fs/xfs/libxfs/xfs_defer.c       | 273 ++++++++++++++------------------
 fs/xfs/libxfs/xfs_defer.h       |  28 +---
 fs/xfs/libxfs/xfs_dir2.c        |   2 -
 fs/xfs/libxfs/xfs_dir2.h        |   1 -
 fs/xfs/libxfs/xfs_ialloc.c      |  25 +--
 fs/xfs/libxfs/xfs_refcount.c    |  76 ++++-----
 fs/xfs/libxfs/xfs_refcount.h    |  25 ++-
 fs/xfs/libxfs/xfs_rmap.c        |  53 +++----
 fs/xfs/libxfs/xfs_rmap.h        |  22 ++-
 fs/xfs/libxfs/xfs_shared.h      |  12 ++
 fs/xfs/xfs_bmap_item.c          |  20 ++-
 fs/xfs/xfs_bmap_item.h          |   3 +-
 fs/xfs/xfs_bmap_util.c          |  18 +--
 fs/xfs/xfs_dquot.c              |   3 +-
 fs/xfs/xfs_filestream.c         |   3 +-
 fs/xfs/xfs_inode.c              |   3 +-
 fs/xfs/xfs_inode.h              |   1 -
 fs/xfs/xfs_log_recover.c        |  42 +++--
 fs/xfs/xfs_refcount_item.c      |  30 ++--
 fs/xfs/xfs_refcount_item.h      |   3 +-
 fs/xfs/xfs_reflink.c            |  33 ++--
 fs/xfs/xfs_symlink.c            |   1 -
 fs/xfs/xfs_trace.h              |  40 ++---
 fs/xfs/xfs_trans.c              |  32 +---
 fs/xfs/xfs_trans.h              |  28 +---
 fs/xfs/xfs_trans_bmap.c         |   6 +-
 fs/xfs/xfs_trans_extfree.c      |   2 -
 fs/xfs/xfs_trans_refcount.c     |   6 +-
 fs/xfs/xfs_trans_rmap.c         |   1 -
 37 files changed, 394 insertions(+), 574 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH 01/15] xfs: refactor internal dfops initialization
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 19:30   ` Darrick J. Wong
  2018-07-30 16:45 ` [PATCH 02/15] xfs: use transaction for intent recovery instead of raw dfops Brian Foster
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

The current transaction allocation code conditionally initializes
the ->t_dfops indirection pointer. Transaction commit/cancel check
the validity of the pointer to determine whether to finish/cancel
the internal dfops.

This disallows the ability to use the internal dfops list as a
temporary container (via xfs_trans_alloc_empty()). Refactor
transaction allocation to always initialize ->t_dfops and check
permanent reservation state on transaction commit/cancel.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/xfs_trans.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 7bf5c1202719..8d3b7f28b193 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -281,13 +281,7 @@ xfs_trans_alloc(
 	INIT_LIST_HEAD(&tp->t_items);
 	INIT_LIST_HEAD(&tp->t_busy);
 	tp->t_firstblock = NULLFSBLOCK;
-	/*
-	 * We only roll transactions with permanent log reservation. Don't init
-	 * ->t_dfops to skip attempts to finish or cancel an empty dfops with a
-	 * non-permanent res.
-	 */
-	if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES)
-		xfs_defer_init(tp, &tp->t_dfops_internal);
+	xfs_defer_init(tp, &tp->t_dfops_internal);
 
 	error = xfs_trans_reserve(tp, resp, blocks, rtextents);
 	if (error) {
@@ -932,7 +926,7 @@ __xfs_trans_commit(
 	trace_xfs_trans_commit(tp, _RET_IP_);
 
 	/* finish deferred items on final commit */
-	if (!regrant && tp->t_dfops) {
+	if (!regrant && (tp->t_flags & XFS_TRANS_PERM_LOG_RES)) {
 		error = xfs_defer_finish_noroll(&tp);
 		if (error) {
 			xfs_defer_cancel(tp);
@@ -1029,7 +1023,7 @@ xfs_trans_cancel(
 
 	trace_xfs_trans_cancel(tp, _RET_IP_);
 
-	if (tp->t_dfops)
+	if (tp->t_flags & XFS_TRANS_PERM_LOG_RES)
 		xfs_defer_cancel(tp);
 
 	/*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 02/15] xfs: use transaction for intent recovery instead of raw dfops
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
  2018-07-30 16:45 ` [PATCH 01/15] xfs: refactor internal dfops initialization Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 20:09   ` Darrick J. Wong
  2018-07-31  8:13   ` Christoph Hellwig
  2018-07-30 16:45 ` [PATCH 03/15] xfs: remove unused __xfs_defer_cancel() internal helper Brian Foster
                   ` (12 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

Log intent recovery is the last user of an external (on-stack)
dfops. The pattern exists because the dfops is used to collect
additional deferred operations queued during the whole recovery
sequence. The dfops is finished with a new transaction after intent
recovery completes.

We already have a mechanism to create an empty, container-like
transaction to support the scrub infrastructure. We can reuse that
mechanism here to drop the final user of external dfops. This
facilitates folding dfops state (i.e., dop_low) into the
transaction, the elimination of now unused external dfops support
and also eliminates the only caller of __xfs_defer_cancel().

Replace the on-stack dfops with an empty transaction and pass it
around to the various helpers that queue and finish deferred
operations during intent recovery.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/xfs_bmap_item.c     | 12 +++++------
 fs/xfs/xfs_bmap_item.h     |  3 +--
 fs/xfs/xfs_log_recover.c   | 42 ++++++++++++++++++--------------------
 fs/xfs/xfs_refcount_item.c | 12 +++++------
 fs/xfs/xfs_refcount_item.h |  3 +--
 5 files changed, 34 insertions(+), 38 deletions(-)

diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
index e1d6c127b07d..992235e7c761 100644
--- a/fs/xfs/xfs_bmap_item.c
+++ b/fs/xfs/xfs_bmap_item.c
@@ -375,9 +375,8 @@ xfs_bud_init(
  */
 int
 xfs_bui_recover(
-	struct xfs_mount		*mp,
-	struct xfs_bui_log_item		*buip,
-	struct xfs_defer_ops		*dfops)
+	struct xfs_trans		*itp,
+	struct xfs_bui_log_item		*buip)
 {
 	int				error = 0;
 	unsigned int			bui_type;
@@ -393,6 +392,7 @@ xfs_bui_recover(
 	struct xfs_trans		*tp;
 	struct xfs_inode		*ip = NULL;
 	struct xfs_bmbt_irec		irec;
+	struct xfs_mount		*mp = itp->t_mountp;
 
 	ASSERT(!test_bit(XFS_BUI_RECOVERED, &buip->bui_flags));
 
@@ -446,7 +446,7 @@ xfs_bui_recover(
 	 * finishes them on completion. Transfer current dfops state to this
 	 * transaction and transfer the result back before we return.
 	 */
-	xfs_defer_move(tp->t_dfops, dfops);
+	xfs_defer_move(tp->t_dfops, itp->t_dfops);
 	budp = xfs_trans_get_bud(tp, buip);
 
 	/* Grab the inode. */
@@ -494,7 +494,7 @@ xfs_bui_recover(
 	}
 
 	set_bit(XFS_BUI_RECOVERED, &buip->bui_flags);
-	xfs_defer_move(dfops, tp->t_dfops);
+	xfs_defer_move(itp->t_dfops, tp->t_dfops);
 	error = xfs_trans_commit(tp);
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	xfs_irele(ip);
@@ -502,7 +502,7 @@ xfs_bui_recover(
 	return error;
 
 err_inode:
-	xfs_defer_move(dfops, tp->t_dfops);
+	xfs_defer_move(itp->t_dfops, tp->t_dfops);
 	xfs_trans_cancel(tp);
 	if (ip) {
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
diff --git a/fs/xfs/xfs_bmap_item.h b/fs/xfs/xfs_bmap_item.h
index fd1a1b13df51..ebf6cd6d33e2 100644
--- a/fs/xfs/xfs_bmap_item.h
+++ b/fs/xfs/xfs_bmap_item.h
@@ -79,7 +79,6 @@ struct xfs_bud_log_item *xfs_bud_init(struct xfs_mount *,
 		struct xfs_bui_log_item *);
 void xfs_bui_item_free(struct xfs_bui_log_item *);
 void xfs_bui_release(struct xfs_bui_log_item *);
-int xfs_bui_recover(struct xfs_mount *mp, struct xfs_bui_log_item *buip,
-		struct xfs_defer_ops *dfops);
+int xfs_bui_recover(struct xfs_trans *itp, struct xfs_bui_log_item *buip);
 
 #endif	/* __XFS_BMAP_ITEM_H__ */
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 7776fde9430c..6650b790e43b 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -4733,10 +4733,9 @@ xlog_recover_cancel_rui(
 /* Recover the CUI if necessary. */
 STATIC int
 xlog_recover_process_cui(
-	struct xfs_mount		*mp,
+	struct xfs_trans		*tp,
 	struct xfs_ail			*ailp,
-	struct xfs_log_item		*lip,
-	struct xfs_defer_ops		*dfops)
+	struct xfs_log_item		*lip)
 {
 	struct xfs_cui_log_item		*cuip;
 	int				error;
@@ -4749,7 +4748,7 @@ xlog_recover_process_cui(
 		return 0;
 
 	spin_unlock(&ailp->ail_lock);
-	error = xfs_cui_recover(mp, cuip, dfops);
+	error = xfs_cui_recover(tp, cuip);
 	spin_lock(&ailp->ail_lock);
 
 	return error;
@@ -4774,10 +4773,9 @@ xlog_recover_cancel_cui(
 /* Recover the BUI if necessary. */
 STATIC int
 xlog_recover_process_bui(
-	struct xfs_mount		*mp,
+	struct xfs_trans		*tp,
 	struct xfs_ail			*ailp,
-	struct xfs_log_item		*lip,
-	struct xfs_defer_ops		*dfops)
+	struct xfs_log_item		*lip)
 {
 	struct xfs_bui_log_item		*buip;
 	int				error;
@@ -4790,7 +4788,7 @@ xlog_recover_process_bui(
 		return 0;
 
 	spin_unlock(&ailp->ail_lock);
-	error = xfs_bui_recover(mp, buip, dfops);
+	error = xfs_bui_recover(tp, buip);
 	spin_lock(&ailp->ail_lock);
 
 	return error;
@@ -4829,9 +4827,9 @@ static inline bool xlog_item_is_intent(struct xfs_log_item *lip)
 /* Take all the collected deferred ops and finish them in order. */
 static int
 xlog_finish_defer_ops(
-	struct xfs_mount	*mp,
-	struct xfs_defer_ops	*dfops)
+	struct xfs_trans	*itp)
 {
+	struct xfs_mount	*mp = itp->t_mountp;
 	struct xfs_trans	*tp;
 	int64_t			freeblks;
 	uint			resblks;
@@ -4855,7 +4853,7 @@ xlog_finish_defer_ops(
 	if (error)
 		return error;
 	/* transfer all collected dfops to this transaction */
-	xfs_defer_move(tp->t_dfops, dfops);
+	xfs_defer_move(tp->t_dfops, itp->t_dfops);
 
 	return xfs_trans_commit(tp);
 }
@@ -4880,22 +4878,25 @@ STATIC int
 xlog_recover_process_intents(
 	struct xlog		*log)
 {
-	struct xfs_defer_ops	dfops;
+	struct xfs_trans	*tp;
 	struct xfs_ail_cursor	cur;
 	struct xfs_log_item	*lip;
 	struct xfs_ail		*ailp;
-	int			error = 0;
+	int			error;
 #if defined(DEBUG) || defined(XFS_WARN)
 	xfs_lsn_t		last_lsn;
 #endif
 
+	error = xfs_trans_alloc_empty(log->l_mp, &tp);
+	if (error)
+		return error;
+
 	ailp = log->l_ailp;
 	spin_lock(&ailp->ail_lock);
 	lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
 #if defined(DEBUG) || defined(XFS_WARN)
 	last_lsn = xlog_assign_lsn(log->l_curr_cycle, log->l_curr_block);
 #endif
-	xfs_defer_init(NULL, &dfops);
 	while (lip != NULL) {
 		/*
 		 * We're done when we see something other than an intent.
@@ -4930,12 +4931,10 @@ xlog_recover_process_intents(
 			error = xlog_recover_process_rui(log->l_mp, ailp, lip);
 			break;
 		case XFS_LI_CUI:
-			error = xlog_recover_process_cui(log->l_mp, ailp, lip,
-					&dfops);
+			error = xlog_recover_process_cui(tp, ailp, lip);
 			break;
 		case XFS_LI_BUI:
-			error = xlog_recover_process_bui(log->l_mp, ailp, lip,
-					&dfops);
+			error = xlog_recover_process_bui(tp, ailp, lip);
 			break;
 		}
 		if (error)
@@ -4945,10 +4944,9 @@ xlog_recover_process_intents(
 out:
 	xfs_trans_ail_cursor_done(&cur);
 	spin_unlock(&ailp->ail_lock);
-	if (error)
-		__xfs_defer_cancel(&dfops);
-	else
-		error = xlog_finish_defer_ops(log->l_mp, &dfops);
+	if (!error)
+		error = xlog_finish_defer_ops(tp);
+	xfs_trans_cancel(tp);
 
 	return error;
 }
diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
index d3582a06626f..d663ea1f4076 100644
--- a/fs/xfs/xfs_refcount_item.c
+++ b/fs/xfs/xfs_refcount_item.c
@@ -380,9 +380,8 @@ xfs_cud_init(
  */
 int
 xfs_cui_recover(
-	struct xfs_mount		*mp,
-	struct xfs_cui_log_item		*cuip,
-	struct xfs_defer_ops		*dfops)
+	struct xfs_trans		*itp,
+	struct xfs_cui_log_item		*cuip)
 {
 	int				i;
 	int				error = 0;
@@ -398,6 +397,7 @@ xfs_cui_recover(
 	xfs_extlen_t			new_len;
 	struct xfs_bmbt_irec		irec;
 	bool				requeue_only = false;
+	struct xfs_mount		*mp = itp->t_mountp;
 
 	ASSERT(!test_bit(XFS_CUI_RECOVERED, &cuip->cui_flags));
 
@@ -457,7 +457,7 @@ xfs_cui_recover(
 	 * finishes them on completion. Transfer current dfops state to this
 	 * transaction and transfer the result back before we return.
 	 */
-	xfs_defer_move(tp->t_dfops, dfops);
+	xfs_defer_move(tp->t_dfops, itp->t_dfops);
 	cudp = xfs_trans_get_cud(tp, cuip);
 
 	for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
@@ -522,13 +522,13 @@ xfs_cui_recover(
 
 	xfs_refcount_finish_one_cleanup(tp, rcur, error);
 	set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags);
-	xfs_defer_move(dfops, tp->t_dfops);
+	xfs_defer_move(itp->t_dfops, tp->t_dfops);
 	error = xfs_trans_commit(tp);
 	return error;
 
 abort_error:
 	xfs_refcount_finish_one_cleanup(tp, rcur, error);
-	xfs_defer_move(dfops, tp->t_dfops);
+	xfs_defer_move(itp->t_dfops, tp->t_dfops);
 	xfs_trans_cancel(tp);
 	return error;
 }
diff --git a/fs/xfs/xfs_refcount_item.h b/fs/xfs/xfs_refcount_item.h
index dd830b69cd1e..98895da52c1f 100644
--- a/fs/xfs/xfs_refcount_item.h
+++ b/fs/xfs/xfs_refcount_item.h
@@ -82,7 +82,6 @@ struct xfs_cud_log_item *xfs_cud_init(struct xfs_mount *,
 		struct xfs_cui_log_item *);
 void xfs_cui_item_free(struct xfs_cui_log_item *);
 void xfs_cui_release(struct xfs_cui_log_item *);
-int xfs_cui_recover(struct xfs_mount *mp, struct xfs_cui_log_item *cuip,
-		struct xfs_defer_ops *dfops);
+int xfs_cui_recover(struct xfs_trans *itp, struct xfs_cui_log_item *cuip);
 
 #endif	/* __XFS_REFCOUNT_ITEM_H__ */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 03/15] xfs: remove unused __xfs_defer_cancel() internal helper
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
  2018-07-30 16:45 ` [PATCH 01/15] xfs: refactor internal dfops initialization Brian Foster
  2018-07-30 16:45 ` [PATCH 02/15] xfs: use transaction for intent recovery instead of raw dfops Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 20:09   ` Darrick J. Wong
  2018-07-31  8:13   ` Christoph Hellwig
  2018-07-30 16:45 ` [PATCH 04/15] xfs: pass transaction to dfops reset/move helpers Brian Foster
                   ` (11 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

With no more external dfops users, there is no need for an
xfs_defer_ops cancel wrapper.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/libxfs/xfs_defer.c | 5 +++--
 fs/xfs/libxfs/xfs_defer.h | 2 +-
 fs/xfs/xfs_trans.c        | 7 -------
 fs/xfs/xfs_trans.h        | 3 ---
 4 files changed, 4 insertions(+), 13 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
index a5f7dc18a62f..ebead781613f 100644
--- a/fs/xfs/libxfs/xfs_defer.c
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -465,9 +465,10 @@ xfs_defer_finish(
  * Free up any items left in the list.
  */
 void
-__xfs_defer_cancel(
-	struct xfs_defer_ops		*dop)
+xfs_defer_cancel(
+	struct xfs_trans		*tp)
 {
+	struct xfs_defer_ops		*dop = tp->t_dfops;
 	struct xfs_defer_pending	*dfp;
 	struct xfs_defer_pending	*pli;
 	struct list_head		*pwi;
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
index 85c41fe4dbae..da145fc04ae1 100644
--- a/fs/xfs/libxfs/xfs_defer.h
+++ b/fs/xfs/libxfs/xfs_defer.h
@@ -50,7 +50,7 @@ void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type,
 		struct list_head *h);
 int xfs_defer_finish_noroll(struct xfs_trans **tp);
 int xfs_defer_finish(struct xfs_trans **tp);
-void __xfs_defer_cancel(struct xfs_defer_ops *dop);
+void xfs_defer_cancel(struct xfs_trans *);
 void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
 bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);
 int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 8d3b7f28b193..b0eeeaf6d24e 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -1105,10 +1105,3 @@ xfs_trans_roll(
 	tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
 	return xfs_trans_reserve(*tpp, &tres, 0, 0);
 }
-
-void
-xfs_defer_cancel(
-	struct xfs_trans	*tp)
-{
-	__xfs_defer_cancel(tp->t_dfops);
-}
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 5170e89bec02..dc79e3c1d3e8 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -214,9 +214,6 @@ xfs_trans_read_buf(
 				      flags, bpp, ops);
 }
 
-/* cancel dfops associated with a transaction */
-void xfs_defer_cancel(struct xfs_trans *);
-
 struct xfs_buf	*xfs_trans_getsb(xfs_trans_t *, struct xfs_mount *, int);
 
 void		xfs_trans_brelse(xfs_trans_t *, struct xfs_buf *);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 04/15] xfs: pass transaction to dfops reset/move helpers
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
                   ` (2 preceding siblings ...)
  2018-07-30 16:45 ` [PATCH 03/15] xfs: remove unused __xfs_defer_cancel() internal helper Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 20:10   ` Darrick J. Wong
  2018-07-31  8:14   ` Christoph Hellwig
  2018-07-30 16:45 ` [PATCH 05/15] xfs: replace dop_low with transaction flag Brian Foster
                   ` (10 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

All callers pass ->t_dfops of the associated transactions. Refactor
the helpers to receive the transactions and facilitate further
cleanups between xfs_defer_ops and xfs_trans.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/libxfs/xfs_defer.c  | 15 ++++++++++-----
 fs/xfs/libxfs/xfs_defer.h  |  2 +-
 fs/xfs/xfs_bmap_item.c     |  6 +++---
 fs/xfs/xfs_log_recover.c   |  2 +-
 fs/xfs/xfs_refcount_item.c |  6 +++---
 fs/xfs/xfs_trans.c         |  2 +-
 6 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
index ebead781613f..e3517a53c525 100644
--- a/fs/xfs/libxfs/xfs_defer.c
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -324,9 +324,12 @@ xfs_defer_bjoin(
  */
 static void
 xfs_defer_reset(
-	struct xfs_defer_ops	*dop)
+	struct xfs_trans	*tp)
 {
+	struct xfs_defer_ops	*dop = tp->t_dfops;
+
 	ASSERT(!xfs_defer_has_unfinished_work(dop));
+
 	dop->dop_low = false;
 	memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes));
 	memset(dop->dop_bufs, 0, sizeof(dop->dop_bufs));
@@ -457,7 +460,7 @@ xfs_defer_finish(
 		if (error)
 			return error;
 	}
-	xfs_defer_reset((*tp)->t_dfops);
+	xfs_defer_reset(*tp);
 	return 0;
 }
 
@@ -575,9 +578,11 @@ xfs_defer_init(
  */
 void
 xfs_defer_move(
-	struct xfs_defer_ops	*dst,
-	struct xfs_defer_ops	*src)
+	struct xfs_trans	*dtp,
+	struct xfs_trans	*stp)
 {
+	struct xfs_defer_ops	*dst = dtp->t_dfops;
+	struct xfs_defer_ops	*src = stp->t_dfops;
 	ASSERT(dst != src);
 
 	list_splice_init(&src->dop_intake, &dst->dop_intake);
@@ -587,5 +592,5 @@ xfs_defer_move(
 	memcpy(dst->dop_bufs, src->dop_bufs, sizeof(dst->dop_bufs));
 	dst->dop_low = src->dop_low;
 
-	xfs_defer_reset(src);
+	xfs_defer_reset(stp);
 }
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
index da145fc04ae1..d60c50498fdf 100644
--- a/fs/xfs/libxfs/xfs_defer.h
+++ b/fs/xfs/libxfs/xfs_defer.h
@@ -55,7 +55,7 @@ void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
 bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);
 int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip);
 int xfs_defer_bjoin(struct xfs_defer_ops *dop, struct xfs_buf *bp);
-void xfs_defer_move(struct xfs_defer_ops *dst, struct xfs_defer_ops *src);
+void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
 
 /* Description of a deferred type. */
 struct xfs_defer_op_type {
diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
index 992235e7c761..4b4318ea4b76 100644
--- a/fs/xfs/xfs_bmap_item.c
+++ b/fs/xfs/xfs_bmap_item.c
@@ -446,7 +446,7 @@ xfs_bui_recover(
 	 * finishes them on completion. Transfer current dfops state to this
 	 * transaction and transfer the result back before we return.
 	 */
-	xfs_defer_move(tp->t_dfops, itp->t_dfops);
+	xfs_defer_move(tp, itp);
 	budp = xfs_trans_get_bud(tp, buip);
 
 	/* Grab the inode. */
@@ -494,7 +494,7 @@ xfs_bui_recover(
 	}
 
 	set_bit(XFS_BUI_RECOVERED, &buip->bui_flags);
-	xfs_defer_move(itp->t_dfops, tp->t_dfops);
+	xfs_defer_move(itp, tp);
 	error = xfs_trans_commit(tp);
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	xfs_irele(ip);
@@ -502,7 +502,7 @@ xfs_bui_recover(
 	return error;
 
 err_inode:
-	xfs_defer_move(itp->t_dfops, tp->t_dfops);
+	xfs_defer_move(itp, tp);
 	xfs_trans_cancel(tp);
 	if (ip) {
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 6650b790e43b..b4edd93a18e9 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -4853,7 +4853,7 @@ xlog_finish_defer_ops(
 	if (error)
 		return error;
 	/* transfer all collected dfops to this transaction */
-	xfs_defer_move(tp->t_dfops, itp->t_dfops);
+	xfs_defer_move(tp, itp);
 
 	return xfs_trans_commit(tp);
 }
diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
index d663ea1f4076..829b7a5bc707 100644
--- a/fs/xfs/xfs_refcount_item.c
+++ b/fs/xfs/xfs_refcount_item.c
@@ -457,7 +457,7 @@ xfs_cui_recover(
 	 * finishes them on completion. Transfer current dfops state to this
 	 * transaction and transfer the result back before we return.
 	 */
-	xfs_defer_move(tp->t_dfops, itp->t_dfops);
+	xfs_defer_move(tp, itp);
 	cudp = xfs_trans_get_cud(tp, cuip);
 
 	for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
@@ -522,13 +522,13 @@ xfs_cui_recover(
 
 	xfs_refcount_finish_one_cleanup(tp, rcur, error);
 	set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags);
-	xfs_defer_move(itp->t_dfops, tp->t_dfops);
+	xfs_defer_move(itp, tp);
 	error = xfs_trans_commit(tp);
 	return error;
 
 abort_error:
 	xfs_refcount_finish_one_cleanup(tp, rcur, error);
-	xfs_defer_move(itp->t_dfops, tp->t_dfops);
+	xfs_defer_move(itp, tp);
 	xfs_trans_cancel(tp);
 	return error;
 }
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index b0eeeaf6d24e..8c088568b05d 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -125,7 +125,7 @@ xfs_trans_dup(
 	if (tp->t_dfops != &tp->t_dfops_internal)
 		ntp->t_dfops = tp->t_dfops;
 	else
-		xfs_defer_move(ntp->t_dfops, tp->t_dfops);
+		xfs_defer_move(ntp, tp);
 
 	xfs_trans_dup_dqinfo(tp, ntp);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 05/15] xfs: replace dop_low with transaction flag
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
                   ` (3 preceding siblings ...)
  2018-07-30 16:45 ` [PATCH 04/15] xfs: pass transaction to dfops reset/move helpers Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 20:11   ` Darrick J. Wong
  2018-07-31  8:16   ` Christoph Hellwig
  2018-07-30 16:45 ` [PATCH 06/15] xfs: add missing defer ijoins for held inodes Brian Foster
                   ` (9 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

The dop_low field enables the low free space allocation mode when a
previous allocation has detected difficulty allocating blocks. It
has historically been part of the xfs_defer_ops structure, which
means if enabled, it remains enabled across a set of transactions
until the deferred operations have completed and the dfops is reset.

Now that the dfops is embedded in the transaction, we can save a bit
more space by using a transaction flag rather than a standalone
boolean. Drop the ->dop_low field and replace it with a transaction
flag that is set at the same points, carried across rolling
transactions and cleared on completion of deferred operations. This
essentially emulates the behavior of ->dop_low and so should not
change behavior.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/libxfs/xfs_bmap.c       |  8 ++++----
 fs/xfs/libxfs/xfs_bmap_btree.c |  4 ++--
 fs/xfs/libxfs/xfs_defer.c      | 16 ++++++++++++++--
 fs/xfs/libxfs/xfs_defer.h      | 11 -----------
 fs/xfs/libxfs/xfs_shared.h     | 12 ++++++++++++
 fs/xfs/xfs_filestream.c        |  3 ++-
 fs/xfs/xfs_trace.h             | 10 ++--------
 fs/xfs/xfs_trans.h             |  2 --
 8 files changed, 36 insertions(+), 30 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index a85c0445b38f..8edf7522aaff 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -700,7 +700,7 @@ xfs_bmap_extents_to_btree(
 	if (tp->t_firstblock == NULLFSBLOCK) {
 		args.type = XFS_ALLOCTYPE_START_BNO;
 		args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
-	} else if (tp->t_dfops->dop_low) {
+	} else if (tp->t_flags & XFS_TRANS_LOWMODE) {
 		args.type = XFS_ALLOCTYPE_START_BNO;
 		args.fsbno = tp->t_firstblock;
 	} else {
@@ -3449,7 +3449,7 @@ xfs_bmap_btalloc(
 			error = xfs_bmap_btalloc_nullfb(ap, &args, &blen);
 		if (error)
 			return error;
-	} else if (ap->tp->t_dfops->dop_low) {
+	} else if (ap->tp->t_flags & XFS_TRANS_LOWMODE) {
 		if (xfs_inode_is_filestream(ap->ip))
 			args.type = XFS_ALLOCTYPE_FIRST_AG;
 		else
@@ -3484,7 +3484,7 @@ xfs_bmap_btalloc(
 	 * is >= the stripe unit and the allocation offset is
 	 * at the end of file.
 	 */
-	if (!ap->tp->t_dfops->dop_low && ap->aeof) {
+	if (!(ap->tp->t_flags & XFS_TRANS_LOWMODE) && ap->aeof) {
 		if (!ap->offset) {
 			args.alignment = stripe_align;
 			atype = args.type;
@@ -3576,7 +3576,7 @@ xfs_bmap_btalloc(
 		args.total = ap->minlen;
 		if ((error = xfs_alloc_vextent(&args)))
 			return error;
-		ap->tp->t_dfops->dop_low = true;
+		ap->tp->t_flags |= XFS_TRANS_LOWMODE;
 	}
 	if (args.fsbno != NULLFSBLOCK) {
 		/*
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index 01489714a253..955e29de8cae 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -226,7 +226,7 @@ xfs_bmbt_alloc_block(
 		 * block allocation here and corrupt the filesystem.
 		 */
 		args.minleft = args.tp->t_blk_res;
-	} else if (cur->bc_tp->t_dfops->dop_low) {
+	} else if (cur->bc_tp->t_flags & XFS_TRANS_LOWMODE) {
 		args.type = XFS_ALLOCTYPE_START_BNO;
 	} else {
 		args.type = XFS_ALLOCTYPE_NEAR_BNO;
@@ -253,7 +253,7 @@ xfs_bmbt_alloc_block(
 		error = xfs_alloc_vextent(&args);
 		if (error)
 			goto error0;
-		cur->bc_tp->t_dfops->dop_low = true;
+		cur->bc_tp->t_flags |= XFS_TRANS_LOWMODE;
 	}
 	if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
 		*stat = 0;
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
index e3517a53c525..0306187b5f56 100644
--- a/fs/xfs/libxfs/xfs_defer.c
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -330,9 +330,14 @@ xfs_defer_reset(
 
 	ASSERT(!xfs_defer_has_unfinished_work(dop));
 
-	dop->dop_low = false;
 	memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes));
 	memset(dop->dop_bufs, 0, sizeof(dop->dop_bufs));
+
+	/*
+	 * Low mode state transfers across transaction rolls to mirror dfops
+	 * lifetime. Clear it now that dfops is reset.
+	 */
+	tp->t_flags &= ~XFS_TRANS_LOWMODE;
 }
 
 /*
@@ -590,7 +595,14 @@ xfs_defer_move(
 
 	memcpy(dst->dop_inodes, src->dop_inodes, sizeof(dst->dop_inodes));
 	memcpy(dst->dop_bufs, src->dop_bufs, sizeof(dst->dop_bufs));
-	dst->dop_low = src->dop_low;
+
+	/*
+	 * Low free space mode was historically controlled by a dfops field.
+	 * This meant that low mode state potentially carried across multiple
+	 * transaction rolls. Transfer low mode on a dfops move to preserve
+	 * that behavior.
+	 */
+	dtp->t_flags |= stp->t_flags & XFS_TRANS_LOWMODE;
 
 	xfs_defer_reset(stp);
 }
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
index d60c50498fdf..8908a2716774 100644
--- a/fs/xfs/libxfs/xfs_defer.h
+++ b/fs/xfs/libxfs/xfs_defer.h
@@ -25,17 +25,6 @@ struct xfs_defer_pending {
 
 /*
  * Header for deferred operation list.
- *
- * dop_low is used by the allocator to activate the lowspace algorithm -
- * when free space is running low the extent allocator may choose to
- * allocate an extent from an AG without leaving sufficient space for
- * a btree split when inserting the new extent.  In this case the allocator
- * will enable the lowspace algorithm which is supposed to allow further
- * allocations (such as btree splits and newroots) to allocate from
- * sequential AGs.  In order to avoid locking AGs out of order the lowspace
- * algorithm will start searching for free space from AG 0.  If the correct
- * transaction reservations have been made then this algorithm will eventually
- * find all the space it needs.
  */
 enum xfs_defer_ops_type {
 	XFS_DEFER_OPS_TYPE_BMAP,
diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h
index 22089f1c880a..1c5debe748f0 100644
--- a/fs/xfs/libxfs/xfs_shared.h
+++ b/fs/xfs/libxfs/xfs_shared.h
@@ -64,6 +64,18 @@ void	xfs_log_get_max_trans_res(struct xfs_mount *mp,
 #define XFS_TRANS_RESERVE	0x20    /* OK to use reserved data blocks */
 #define XFS_TRANS_NO_WRITECOUNT 0x40	/* do not elevate SB writecount */
 #define XFS_TRANS_NOFS		0x80	/* pass KM_NOFS to kmem_alloc */
+/*
+ * LOWMODE is used by the allocator to activate the lowspace algorithm - when
+ * free space is running low the extent allocator may choose to allocate an
+ * extent from an AG without leaving sufficient space for a btree split when
+ * inserting the new extent. In this case the allocator will enable the
+ * lowspace algorithm which is supposed to allow further allocations (such as
+ * btree splits and newroots) to allocate from sequential AGs. In order to
+ * avoid locking AGs out of order the lowspace algorithm will start searching
+ * for free space from AG 0. If the correct transaction reservations have been
+ * made then this algorithm will eventually find all the space it needs.
+ */
+#define XFS_TRANS_LOWMODE	0x100	/* allocate in low space mode */
 
 /*
  * Field values for xfs_trans_mod_sb.
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
index 212173c62588..182501373af2 100644
--- a/fs/xfs/xfs_filestream.c
+++ b/fs/xfs/xfs_filestream.c
@@ -20,6 +20,7 @@
 #include "xfs_trace.h"
 #include "xfs_ag_resv.h"
 #include "xfs_trans.h"
+#include "xfs_shared.h"
 
 struct xfs_fstrm_item {
 	struct xfs_mru_cache_elem	mru;
@@ -378,7 +379,7 @@ xfs_filestream_new_ag(
 
 	if (xfs_alloc_is_userdata(ap->datatype))
 		flags |= XFS_PICK_USERDATA;
-	if (ap->tp->t_dfops->dop_low)
+	if (ap->tp->t_flags & XFS_TRANS_LOWMODE)
 		flags |= XFS_PICK_LOWSPACE;
 
 	err = xfs_filestream_pick_ag(pip, startag, agp, flags, minlen);
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index cc6995cfce66..8807f1bb814a 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -2223,19 +2223,16 @@ DECLARE_EVENT_CLASS(xfs_defer_class,
 		__field(dev_t, dev)
 		__field(void *, dop)
 		__field(char, committed)
-		__field(char, low)
 		__field(unsigned long, caller_ip)
 	),
 	TP_fast_assign(
 		__entry->dev = mp ? mp->m_super->s_dev : 0;
 		__entry->dop = dop;
-		__entry->low = dop->dop_low;
 		__entry->caller_ip = caller_ip;
 	),
-	TP_printk("dev %d:%d ops %p low %d, caller %pS",
+	TP_printk("dev %d:%d ops %p caller %pS",
 		  MAJOR(__entry->dev), MINOR(__entry->dev),
 		  __entry->dop,
-		  __entry->low,
 		  (char *)__entry->caller_ip)
 )
 #define DEFINE_DEFER_EVENT(name) \
@@ -2251,19 +2248,16 @@ DECLARE_EVENT_CLASS(xfs_defer_error_class,
 		__field(dev_t, dev)
 		__field(void *, dop)
 		__field(char, committed)
-		__field(char, low)
 		__field(int, error)
 	),
 	TP_fast_assign(
 		__entry->dev = mp ? mp->m_super->s_dev : 0;
 		__entry->dop = dop;
-		__entry->low = dop->dop_low;
 		__entry->error = error;
 	),
-	TP_printk("dev %d:%d ops %p low %d err %d",
+	TP_printk("dev %d:%d ops %p err %d",
 		  MAJOR(__entry->dev), MINOR(__entry->dev),
 		  __entry->dop,
-		  __entry->low,
 		  __entry->error)
 )
 #define DEFINE_DEFER_ERROR_EVENT(name) \
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index dc79e3c1d3e8..7e493221160e 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -101,8 +101,6 @@ struct xfs_defer_ops {
 	/* relog these with each roll */
 	struct xfs_inode	*dop_inodes[XFS_DEFER_OPS_NR_INODES];
 	struct xfs_buf		*dop_bufs[XFS_DEFER_OPS_NR_BUFS];
-
-	bool			dop_low;	/* alloc in low mode */
 };
 
 /*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 06/15] xfs: add missing defer ijoins for held inodes
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
                   ` (4 preceding siblings ...)
  2018-07-30 16:45 ` [PATCH 05/15] xfs: replace dop_low with transaction flag Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 20:15   ` Darrick J. Wong
  2018-07-31  8:17   ` Christoph Hellwig
  2018-07-30 16:45 ` [PATCH 07/15] xfs: automatic dfops buffer relogging Brian Foster
                   ` (8 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

Log items that require relogging during deferred operations
processing are explicitly joined to the associated dfops via the
xfs_defer_*join() helpers. These calls imply that the associated
object is "held" by the transaction such that when rolled, the item
can be immediately joined to a follow up transaction. For buffers,
this means the buffer remains locked and held after each roll. For
inodes, this means that the inode remains locked.

Failure to join a held item to the dfops structure means the
associated object pins the tail of the log while dfops processing
completes, because the item never relogs and is not unlocked or
released until deferred processing completes.

Currently, all buffers that are held in transactions (XFS_BLI_HOLD)
with deferred operations are explicitly joined to the dfops. This is
not the case for inodes, however, as various contexts defer
operations to transactions with held inodes without explicit joins
to the associated dfops (and thus not relogging).

While this is not a catastrophic problem, it is not ideal. Given
that we want to eventually relog such items automatically during
dfops processing, start by explicitly adding these missing
xfs_defer_ijoin() calls. A call is added everywhere an inode is
joined to a transaction without transferring lock ownership and
said transaction runs deferred operations.

All xfs_defer_ijoin() calls will eventually be replaced by automatic
dfops inode relogging. This patch essentially implements the
behavior change that would otherwise occur due to automatic inode
dfops relogging.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/libxfs/xfs_bmap.c | 1 +
 fs/xfs/xfs_bmap_util.c   | 1 +
 fs/xfs/xfs_inode.c       | 1 +
 fs/xfs/xfs_iomap.c       | 3 +++
 fs/xfs/xfs_reflink.c     | 1 +
 5 files changed, 7 insertions(+)

diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 8edf7522aaff..71687d805f79 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -1119,6 +1119,7 @@ xfs_bmap_add_attrfork(
 			xfs_log_sb(tp);
 	}
 
+	xfs_defer_ijoin(tp->t_dfops, ip);
 	error = xfs_trans_commit(tp);
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	return error;
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 412dc58ae54d..0c58a66b39e5 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -979,6 +979,7 @@ xfs_alloc_file_space(
 		/*
 		 * Complete the transaction
 		 */
+		xfs_defer_ijoin(tp->t_dfops, ip);
 		error = xfs_trans_commit(tp);
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 		if (error)
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 5fc1815c2b62..441c8593cfd7 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1810,6 +1810,7 @@ xfs_inactive_ifree(
 	 * Just ignore errors at this point.  There is nothing we can do except
 	 * to try to keep going. Make sure it's not a silent error.
 	 */
+	xfs_defer_ijoin(tp->t_dfops, ip);
 	error = xfs_trans_commit(tp);
 	if (error)
 		xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 8e8ca9f03f0e..464b4b3225bb 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -261,6 +261,7 @@ xfs_iomap_write_direct(
 	/*
 	 * Complete the transaction
 	 */
+	xfs_defer_ijoin(tp->t_dfops, ip);
 	error = xfs_trans_commit(tp);
 	if (error)
 		goto out_unlock;
@@ -762,6 +763,7 @@ xfs_iomap_write_allocate(
 			if (error)
 				goto trans_cancel;
 
+			xfs_defer_ijoin(tp->t_dfops, ip);
 			error = xfs_trans_commit(tp);
 			if (error)
 				goto error0;
@@ -879,6 +881,7 @@ xfs_iomap_write_unwritten(
 			xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 		}
 
+		xfs_defer_ijoin(tp->t_dfops, ip);
 		error = xfs_trans_commit(tp);
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 		if (error)
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index 9a0a56526266..e986fcf928e5 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -435,6 +435,7 @@ xfs_reflink_allocate_cow(
 	xfs_inode_set_cowblocks_tag(ip);
 
 	/* Finish up. */
+	xfs_defer_ijoin(tp->t_dfops, ip);
 	error = xfs_trans_commit(tp);
 	if (error)
 		return error;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 07/15] xfs: automatic dfops buffer relogging
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
                   ` (5 preceding siblings ...)
  2018-07-30 16:45 ` [PATCH 06/15] xfs: add missing defer ijoins for held inodes Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 20:20   ` Darrick J. Wong
  2018-07-31  8:19   ` Christoph Hellwig
  2018-07-30 16:45 ` [PATCH 08/15] xfs: automatic dfops inode relogging Brian Foster
                   ` (7 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

Buffers that are held across deferred operations are explicitly
joined to the dfops structure to ensure appropriate relogging.
While buffers are currently joined explicitly, we can detect the
conditions that require relogging at dfops finish time by inspecting
the transaction item list for held buffers.

Replace the xfs_defer_bjoin() infrastructure with such detection and
automatic relogging of held buffers. This eliminates the need for
the per-dfops buffer list, replaced by an on-stack variant in
xfs_defer_trans_roll().

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/libxfs/xfs_attr.c  |  1 -
 fs/xfs/libxfs/xfs_defer.c | 55 ++++++++++++++++-----------------------
 fs/xfs/libxfs/xfs_defer.h |  1 -
 fs/xfs/xfs_dquot.c        |  1 -
 fs/xfs/xfs_trans.h        |  1 -
 5 files changed, 23 insertions(+), 36 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index 3deb5cdadf08..227887bee00d 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -320,7 +320,6 @@ xfs_attr_set(
 		 * buffer and run into problems with the write verifier.
 		 */
 		xfs_trans_bhold(args.trans, leaf_bp);
-		xfs_defer_bjoin(args.trans->t_dfops, leaf_bp);
 		xfs_defer_ijoin(args.trans->t_dfops, dp);
 		error = xfs_defer_finish(&args.trans);
 		if (error)
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
index 0306187b5f56..d0ee55048a7a 100644
--- a/fs/xfs/libxfs/xfs_defer.c
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -14,6 +14,7 @@
 #include "xfs_mount.h"
 #include "xfs_defer.h"
 #include "xfs_trans.h"
+#include "xfs_buf_item.h"
 #include "xfs_trace.h"
 
 /*
@@ -228,6 +229,10 @@ xfs_defer_trans_roll(
 	struct xfs_trans		**tp)
 {
 	struct xfs_defer_ops		*dop = (*tp)->t_dfops;
+	struct xfs_buf_log_item		*bli;
+	struct xfs_log_item		*lip;
+	struct xfs_buf			*bplist[XFS_DEFER_OPS_NR_BUFS];
+	int				bpcount = 0;
 	int				i;
 	int				error;
 
@@ -235,9 +240,21 @@ xfs_defer_trans_roll(
 	for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++)
 		xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE);
 
-	/* Hold the (previously bjoin'd) buffer locked across the roll. */
-	for (i = 0; i < XFS_DEFER_OPS_NR_BUFS && dop->dop_bufs[i]; i++)
-		xfs_trans_dirty_buf(*tp, dop->dop_bufs[i]);
+	list_for_each_entry(lip, &(*tp)->t_items, li_trans) {
+		switch (lip->li_type) {
+		case XFS_LI_BUF:
+			bli = container_of(lip, struct xfs_buf_log_item,
+					   bli_item);
+			if (bli->bli_flags & XFS_BLI_HOLD) {
+				ASSERT(bpcount < XFS_DEFER_OPS_NR_BUFS);
+				xfs_trans_dirty_buf(*tp, bli->bli_buf);
+				bplist[bpcount++] = bli->bli_buf;
+			}
+			break;
+		default:
+			break;
+		}
+	}
 
 	trace_xfs_defer_trans_roll((*tp)->t_mountp, dop, _RET_IP_);
 
@@ -255,9 +272,9 @@ xfs_defer_trans_roll(
 		xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0);
 
 	/* Rejoin the buffers and dirty them so the log moves forward. */
-	for (i = 0; i < XFS_DEFER_OPS_NR_BUFS && dop->dop_bufs[i]; i++) {
-		xfs_trans_bjoin(*tp, dop->dop_bufs[i]);
-		xfs_trans_bhold(*tp, dop->dop_bufs[i]);
+	for (i = 0; i < bpcount; i++) {
+		xfs_trans_bjoin(*tp, bplist[i]);
+		xfs_trans_bhold(*tp, bplist[i]);
 	}
 
 	return error;
@@ -295,30 +312,6 @@ xfs_defer_ijoin(
 	return -EFSCORRUPTED;
 }
 
-/*
- * Add this buffer to the deferred op.  Each joined buffer is relogged
- * each time we roll the transaction.
- */
-int
-xfs_defer_bjoin(
-	struct xfs_defer_ops		*dop,
-	struct xfs_buf			*bp)
-{
-	int				i;
-
-	for (i = 0; i < XFS_DEFER_OPS_NR_BUFS; i++) {
-		if (dop->dop_bufs[i] == bp)
-			return 0;
-		else if (dop->dop_bufs[i] == NULL) {
-			dop->dop_bufs[i] = bp;
-			return 0;
-		}
-	}
-
-	ASSERT(0);
-	return -EFSCORRUPTED;
-}
-
 /*
  * Reset an already used dfops after finish.
  */
@@ -331,7 +324,6 @@ xfs_defer_reset(
 	ASSERT(!xfs_defer_has_unfinished_work(dop));
 
 	memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes));
-	memset(dop->dop_bufs, 0, sizeof(dop->dop_bufs));
 
 	/*
 	 * Low mode state transfers across transaction rolls to mirror dfops
@@ -594,7 +586,6 @@ xfs_defer_move(
 	list_splice_init(&src->dop_pending, &dst->dop_pending);
 
 	memcpy(dst->dop_inodes, src->dop_inodes, sizeof(dst->dop_inodes));
-	memcpy(dst->dop_bufs, src->dop_bufs, sizeof(dst->dop_bufs));
 
 	/*
 	 * Low free space mode was historically controlled by a dfops field.
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
index 8908a2716774..4a8bb838adf2 100644
--- a/fs/xfs/libxfs/xfs_defer.h
+++ b/fs/xfs/libxfs/xfs_defer.h
@@ -43,7 +43,6 @@ void xfs_defer_cancel(struct xfs_trans *);
 void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
 bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);
 int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip);
-int xfs_defer_bjoin(struct xfs_defer_ops *dop, struct xfs_buf *bp);
 void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
 
 /* Description of a deferred type. */
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index da5c55cec966..e1196854dbcd 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -362,7 +362,6 @@ xfs_dquot_disk_alloc(
 	 * manually or by committing the transaction.
 	 */
 	xfs_trans_bhold(tp, bp);
-	error = xfs_defer_bjoin(tp->t_dfops, bp);
 	if (error) {
 		xfs_trans_bhold_release(tp, bp);
 		xfs_trans_brelse(tp, bp);
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 7e493221160e..581456c79197 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -100,7 +100,6 @@ struct xfs_defer_ops {
 
 	/* relog these with each roll */
 	struct xfs_inode	*dop_inodes[XFS_DEFER_OPS_NR_INODES];
-	struct xfs_buf		*dop_bufs[XFS_DEFER_OPS_NR_BUFS];
 };
 
 /*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 08/15] xfs: automatic dfops inode relogging
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
                   ` (6 preceding siblings ...)
  2018-07-30 16:45 ` [PATCH 07/15] xfs: automatic dfops buffer relogging Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 20:22   ` Darrick J. Wong
  2018-07-31  8:19   ` Christoph Hellwig
  2018-07-30 16:45 ` [PATCH 09/15] xfs: drop dop param from xfs_defer_op_type ->finish_item() callback Brian Foster
                   ` (6 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

Inodes that are held across deferred operations are explicitly
joined to the dfops structure to ensure appropriate relogging.
While inodes are currently joined explicitly, we can detect the
conditions that require relogging at dfops finish time by inspecting
the transaction item list for inodes with ili_lock_flags == 0.

Replace the xfs_defer_ijoin() infrastructure with such detection and
automatic relogging of held inodes. This eliminates the need for the
per-dfops inode list, replaced by an on-stack variant in
xfs_defer_trans_roll().

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/libxfs/xfs_attr.c        |  9 ------
 fs/xfs/libxfs/xfs_attr_remote.c |  2 --
 fs/xfs/libxfs/xfs_bmap.c        |  8 -----
 fs/xfs/libxfs/xfs_defer.c       | 56 +++++++++++----------------------
 fs/xfs/libxfs/xfs_defer.h       |  1 -
 fs/xfs/xfs_bmap_util.c          |  4 ---
 fs/xfs/xfs_inode.c              |  2 --
 fs/xfs/xfs_iomap.c              |  3 --
 fs/xfs/xfs_reflink.c            |  4 ---
 fs/xfs/xfs_symlink.c            |  1 -
 fs/xfs/xfs_trans.h              |  3 --
 11 files changed, 18 insertions(+), 75 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index 227887bee00d..3190dfc21b60 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -320,7 +320,6 @@ xfs_attr_set(
 		 * buffer and run into problems with the write verifier.
 		 */
 		xfs_trans_bhold(args.trans, leaf_bp);
-		xfs_defer_ijoin(args.trans->t_dfops, dp);
 		error = xfs_defer_finish(&args.trans);
 		if (error)
 			goto out;
@@ -589,7 +588,6 @@ xfs_attr_leaf_addname(
 		error = xfs_attr3_leaf_to_node(args);
 		if (error)
 			goto out_defer_cancel;
-		xfs_defer_ijoin(args->trans->t_dfops, dp);
 		error = xfs_defer_finish(&args->trans);
 		if (error)
 			goto out_defer_cancel;
@@ -678,7 +676,6 @@ xfs_attr_leaf_addname(
 			/* bp is gone due to xfs_da_shrink_inode */
 			if (error)
 				goto out_defer_cancel;
-			xfs_defer_ijoin(args->trans->t_dfops, dp);
 			error = xfs_defer_finish(&args->trans);
 			if (error)
 				goto out_defer_cancel;
@@ -742,7 +739,6 @@ xfs_attr_leaf_removename(
 		/* bp is gone due to xfs_da_shrink_inode */
 		if (error)
 			goto out_defer_cancel;
-		xfs_defer_ijoin(args->trans->t_dfops, dp);
 		error = xfs_defer_finish(&args->trans);
 		if (error)
 			goto out_defer_cancel;
@@ -869,7 +865,6 @@ xfs_attr_node_addname(
 			error = xfs_attr3_leaf_to_node(args);
 			if (error)
 				goto out_defer_cancel;
-			xfs_defer_ijoin(args->trans->t_dfops, dp);
 			error = xfs_defer_finish(&args->trans);
 			if (error)
 				goto out_defer_cancel;
@@ -894,7 +889,6 @@ xfs_attr_node_addname(
 		error = xfs_da3_split(state);
 		if (error)
 			goto out_defer_cancel;
-		xfs_defer_ijoin(args->trans->t_dfops, dp);
 		error = xfs_defer_finish(&args->trans);
 		if (error)
 			goto out_defer_cancel;
@@ -991,7 +985,6 @@ xfs_attr_node_addname(
 			error = xfs_da3_join(state);
 			if (error)
 				goto out_defer_cancel;
-			xfs_defer_ijoin(args->trans->t_dfops, dp);
 			error = xfs_defer_finish(&args->trans);
 			if (error)
 				goto out_defer_cancel;
@@ -1115,7 +1108,6 @@ xfs_attr_node_removename(
 		error = xfs_da3_join(state);
 		if (error)
 			goto out_defer_cancel;
-		xfs_defer_ijoin(args->trans->t_dfops, dp);
 		error = xfs_defer_finish(&args->trans);
 		if (error)
 			goto out_defer_cancel;
@@ -1147,7 +1139,6 @@ xfs_attr_node_removename(
 			/* bp is gone due to xfs_da_shrink_inode */
 			if (error)
 				goto out_defer_cancel;
-			xfs_defer_ijoin(args->trans->t_dfops, dp);
 			error = xfs_defer_finish(&args->trans);
 			if (error)
 				goto out_defer_cancel;
diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c
index 77ca38586913..f52552313773 100644
--- a/fs/xfs/libxfs/xfs_attr_remote.c
+++ b/fs/xfs/libxfs/xfs_attr_remote.c
@@ -486,7 +486,6 @@ xfs_attr_rmtval_set(
 				  &nmap);
 		if (error)
 			goto out_defer_cancel;
-		xfs_defer_ijoin(args->trans->t_dfops, dp);
 		error = xfs_defer_finish(&args->trans);
 		if (error)
 			goto out_defer_cancel;
@@ -627,7 +626,6 @@ xfs_attr_rmtval_remove(
 				    XFS_BMAPI_ATTRFORK, 1, &done);
 		if (error)
 			goto out_defer_cancel;
-		xfs_defer_ijoin(args->trans->t_dfops, args->dp);
 		error = xfs_defer_finish(&args->trans);
 		if (error)
 			goto out_defer_cancel;
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 71687d805f79..5cd490dc891a 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -1119,7 +1119,6 @@ xfs_bmap_add_attrfork(
 			xfs_log_sb(tp);
 	}
 
-	xfs_defer_ijoin(tp->t_dfops, ip);
 	error = xfs_trans_commit(tp);
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	return error;
@@ -5987,7 +5986,6 @@ __xfs_bmap_add(
 	int				whichfork,
 	struct xfs_bmbt_irec		*bmap)
 {
-	int				error;
 	struct xfs_bmap_intent		*bi;
 
 	trace_xfs_bmap_defer(mp,
@@ -6006,12 +6004,6 @@ __xfs_bmap_add(
 	bi->bi_whichfork = whichfork;
 	bi->bi_bmap = *bmap;
 
-	error = xfs_defer_ijoin(dfops, bi->bi_owner);
-	if (error) {
-		kmem_free(bi);
-		return error;
-	}
-
 	xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_BMAP, &bi->bi_list);
 	return 0;
 }
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
index d0ee55048a7a..6230e74163ac 100644
--- a/fs/xfs/libxfs/xfs_defer.c
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -15,6 +15,8 @@
 #include "xfs_defer.h"
 #include "xfs_trans.h"
 #include "xfs_buf_item.h"
+#include "xfs_inode.h"
+#include "xfs_inode_item.h"
 #include "xfs_trace.h"
 
 /*
@@ -230,16 +232,14 @@ xfs_defer_trans_roll(
 {
 	struct xfs_defer_ops		*dop = (*tp)->t_dfops;
 	struct xfs_buf_log_item		*bli;
+	struct xfs_inode_log_item	*ili;
 	struct xfs_log_item		*lip;
 	struct xfs_buf			*bplist[XFS_DEFER_OPS_NR_BUFS];
-	int				bpcount = 0;
+	struct xfs_inode		*iplist[XFS_DEFER_OPS_NR_INODES];
+	int				bpcount = 0, ipcount = 0;
 	int				i;
 	int				error;
 
-	/* Log all the joined inodes. */
-	for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++)
-		xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE);
-
 	list_for_each_entry(lip, &(*tp)->t_items, li_trans) {
 		switch (lip->li_type) {
 		case XFS_LI_BUF:
@@ -251,6 +251,16 @@ xfs_defer_trans_roll(
 				bplist[bpcount++] = bli->bli_buf;
 			}
 			break;
+		case XFS_LI_INODE:
+			ili = container_of(lip, struct xfs_inode_log_item,
+					   ili_item);
+			if (ili->ili_lock_flags == 0) {
+				ASSERT(ipcount < XFS_DEFER_OPS_NR_INODES);
+				xfs_trans_log_inode(*tp, ili->ili_inode,
+						    XFS_ILOG_CORE);
+				iplist[ipcount++] = ili->ili_inode;
+			}
+			break;
 		default:
 			break;
 		}
@@ -268,8 +278,8 @@ xfs_defer_trans_roll(
 	}
 
 	/* Rejoin the joined inodes. */
-	for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++)
-		xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0);
+	for (i = 0; i < ipcount; i++)
+		xfs_trans_ijoin(*tp, iplist[i], 0);
 
 	/* Rejoin the buffers and dirty them so the log moves forward. */
 	for (i = 0; i < bpcount; i++) {
@@ -288,30 +298,6 @@ xfs_defer_has_unfinished_work(
 	return !list_empty(&dop->dop_pending) || !list_empty(&dop->dop_intake);
 }
 
-/*
- * Add this inode to the deferred op.  Each joined inode is relogged
- * each time we roll the transaction.
- */
-int
-xfs_defer_ijoin(
-	struct xfs_defer_ops		*dop,
-	struct xfs_inode		*ip)
-{
-	int				i;
-
-	for (i = 0; i < XFS_DEFER_OPS_NR_INODES; i++) {
-		if (dop->dop_inodes[i] == ip)
-			return 0;
-		else if (dop->dop_inodes[i] == NULL) {
-			dop->dop_inodes[i] = ip;
-			return 0;
-		}
-	}
-
-	ASSERT(0);
-	return -EFSCORRUPTED;
-}
-
 /*
  * Reset an already used dfops after finish.
  */
@@ -319,11 +305,7 @@ static void
 xfs_defer_reset(
 	struct xfs_trans	*tp)
 {
-	struct xfs_defer_ops	*dop = tp->t_dfops;
-
-	ASSERT(!xfs_defer_has_unfinished_work(dop));
-
-	memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes));
+	ASSERT(!xfs_defer_has_unfinished_work(tp->t_dfops));
 
 	/*
 	 * Low mode state transfers across transaction rolls to mirror dfops
@@ -585,8 +567,6 @@ xfs_defer_move(
 	list_splice_init(&src->dop_intake, &dst->dop_intake);
 	list_splice_init(&src->dop_pending, &dst->dop_pending);
 
-	memcpy(dst->dop_inodes, src->dop_inodes, sizeof(dst->dop_inodes));
-
 	/*
 	 * Low free space mode was historically controlled by a dfops field.
 	 * This meant that low mode state potentially carried across multiple
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
index 4a8bb838adf2..bf1e9f78561e 100644
--- a/fs/xfs/libxfs/xfs_defer.h
+++ b/fs/xfs/libxfs/xfs_defer.h
@@ -42,7 +42,6 @@ int xfs_defer_finish(struct xfs_trans **tp);
 void xfs_defer_cancel(struct xfs_trans *);
 void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
 bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);
-int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip);
 void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
 
 /* Description of a deferred type. */
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 0c58a66b39e5..30ac1300dc49 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -979,7 +979,6 @@ xfs_alloc_file_space(
 		/*
 		 * Complete the transaction
 		 */
-		xfs_defer_ijoin(tp->t_dfops, ip);
 		error = xfs_trans_commit(tp);
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 		if (error)
@@ -1037,8 +1036,6 @@ xfs_unmap_extent(
 	if (error)
 		goto out_trans_cancel;
 
-	xfs_defer_ijoin(tp->t_dfops, ip);
-
 	error = xfs_trans_commit(tp);
 out_unlock:
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
@@ -1624,7 +1621,6 @@ xfs_swap_extent_rmap(
 			if (error)
 				goto out_defer;
 
-			xfs_defer_ijoin(tp->t_dfops, ip);
 			error = xfs_defer_finish(tpp);
 			tp = *tpp;
 			if (error)
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 441c8593cfd7..7bb46a0eecfc 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1569,7 +1569,6 @@ xfs_itruncate_extents_flags(
 		 * Duplicate the transaction that has the permanent
 		 * reservation and commit the old transaction.
 		 */
-		xfs_defer_ijoin(tp->t_dfops, ip);
 		error = xfs_defer_finish(&tp);
 		if (error)
 			goto out_bmap_cancel;
@@ -1810,7 +1809,6 @@ xfs_inactive_ifree(
 	 * Just ignore errors at this point.  There is nothing we can do except
 	 * to try to keep going. Make sure it's not a silent error.
 	 */
-	xfs_defer_ijoin(tp->t_dfops, ip);
 	error = xfs_trans_commit(tp);
 	if (error)
 		xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 464b4b3225bb..8e8ca9f03f0e 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -261,7 +261,6 @@ xfs_iomap_write_direct(
 	/*
 	 * Complete the transaction
 	 */
-	xfs_defer_ijoin(tp->t_dfops, ip);
 	error = xfs_trans_commit(tp);
 	if (error)
 		goto out_unlock;
@@ -763,7 +762,6 @@ xfs_iomap_write_allocate(
 			if (error)
 				goto trans_cancel;
 
-			xfs_defer_ijoin(tp->t_dfops, ip);
 			error = xfs_trans_commit(tp);
 			if (error)
 				goto error0;
@@ -881,7 +879,6 @@ xfs_iomap_write_unwritten(
 			xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 		}
 
-		xfs_defer_ijoin(tp->t_dfops, ip);
 		error = xfs_trans_commit(tp);
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 		if (error)
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index e986fcf928e5..dce8ba8ab681 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -435,7 +435,6 @@ xfs_reflink_allocate_cow(
 	xfs_inode_set_cowblocks_tag(ip);
 
 	/* Finish up. */
-	xfs_defer_ijoin(tp->t_dfops, ip);
 	error = xfs_trans_commit(tp);
 	if (error)
 		return error;
@@ -518,7 +517,6 @@ xfs_reflink_cancel_cow_blocks(
 					NULL);
 
 			/* Roll the transaction */
-			xfs_defer_ijoin((*tpp)->t_dfops, ip);
 			error = xfs_defer_finish(tpp);
 			if (error) {
 				xfs_defer_cancel(*tpp);
@@ -716,7 +714,6 @@ xfs_reflink_end_cow(
 		/* Remove the mapping from the CoW fork. */
 		xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
 
-		xfs_defer_ijoin(tp->t_dfops, ip);
 		error = xfs_defer_finish(&tp);
 		if (error)
 			goto out_cancel;
@@ -1077,7 +1074,6 @@ xfs_reflink_remap_extent(
 
 next_extent:
 		/* Process all the deferred stuff. */
-		xfs_defer_ijoin(tp->t_dfops, ip);
 		error = xfs_defer_finish(&tp);
 		if (error)
 			goto out_cancel;
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index 2bfe7fbbedb2..a3e98c64b6e3 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -454,7 +454,6 @@ xfs_inactive_symlink_rmt(
 	 * Commit the transaction. This first logs the EFI and the inode, then
 	 * rolls and commits the transaction that frees the extents.
 	 */
-	xfs_defer_ijoin(tp->t_dfops, ip);
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 	error = xfs_trans_commit(tp);
 	if (error) {
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 581456c79197..8665d45b82c6 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -97,9 +97,6 @@ void	xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item,
 struct xfs_defer_ops {
 	struct list_head	dop_intake;	/* unlogged pending work */
 	struct list_head	dop_pending;	/* logged pending work */
-
-	/* relog these with each roll */
-	struct xfs_inode	*dop_inodes[XFS_DEFER_OPS_NR_INODES];
 };
 
 /*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 09/15] xfs: drop dop param from xfs_defer_op_type ->finish_item() callback
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
                   ` (7 preceding siblings ...)
  2018-07-30 16:45 ` [PATCH 08/15] xfs: automatic dfops inode relogging Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 20:23   ` Darrick J. Wong
  2018-07-31  8:20   ` Christoph Hellwig
  2018-07-30 16:45 ` [PATCH 10/15] xfs: clean out superfluous dfops dop params/vars Brian Foster
                   ` (5 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

The dfops infrastructure ->finish_item() callback passes the
transaction and dfops as separate parameters. Since dfops is always
part of a transaction, the latter parameter is no longer necessary.
Remove it from the various callbacks.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/libxfs/xfs_bmap.c     |  2 --
 fs/xfs/libxfs/xfs_bmap.h     |  6 +++---
 fs/xfs/libxfs/xfs_defer.c    |  2 +-
 fs/xfs/libxfs/xfs_defer.h    |  4 ++--
 fs/xfs/libxfs/xfs_refcount.c |  2 +-
 fs/xfs/libxfs/xfs_refcount.h |  7 +++----
 fs/xfs/xfs_bmap_item.c       |  5 ++---
 fs/xfs/xfs_refcount_item.c   |  4 ++--
 fs/xfs/xfs_trans.h           | 10 +++++-----
 fs/xfs/xfs_trans_bmap.c      |  6 ++----
 fs/xfs/xfs_trans_extfree.c   |  2 --
 fs/xfs/xfs_trans_refcount.c  |  6 ++----
 fs/xfs/xfs_trans_rmap.c      |  1 -
 13 files changed, 23 insertions(+), 34 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 5cd490dc891a..d20f541b7061 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -6045,7 +6045,6 @@ xfs_bmap_unmap_extent(
 int
 xfs_bmap_finish_one(
 	struct xfs_trans		*tp,
-	struct xfs_defer_ops		*dfops,
 	struct xfs_inode		*ip,
 	enum xfs_bmap_intent_type	type,
 	int				whichfork,
@@ -6072,7 +6071,6 @@ xfs_bmap_finish_one(
 
 	switch (type) {
 	case XFS_BMAP_MAP:
-		ASSERT(dfops == tp->t_dfops);
 		error = xfs_bmapi_remap(tp, ip, startoff, *blockcount,
 				startblock, 0);
 		*blockcount = 0;
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index 2e8555c1229a..9165a878edcd 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -252,9 +252,9 @@ struct xfs_bmap_intent {
 	struct xfs_bmbt_irec			bi_bmap;
 };
 
-int	xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_defer_ops *dfops,
-		struct xfs_inode *ip, enum xfs_bmap_intent_type type,
-		int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock,
+int	xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_inode *ip,
+		enum xfs_bmap_intent_type type, int whichfork,
+		xfs_fileoff_t startoff, xfs_fsblock_t startblock,
 		xfs_filblks_t *blockcount, xfs_exntst_t state);
 int	xfs_bmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
 		struct xfs_inode *ip, struct xfs_bmbt_irec *imap);
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
index 6230e74163ac..7fb7edd5d63e 100644
--- a/fs/xfs/libxfs/xfs_defer.c
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -365,7 +365,7 @@ xfs_defer_finish_noroll(
 		list_for_each_safe(li, n, &dfp->dfp_work) {
 			list_del(li);
 			dfp->dfp_count--;
-			error = dfp->dfp_type->finish_item(*tp, dop, li,
+			error = dfp->dfp_type->finish_item(*tp, li,
 					dfp->dfp_done, &state);
 			if (error == -EAGAIN) {
 				/*
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
index bf1e9f78561e..0de7504e5651 100644
--- a/fs/xfs/libxfs/xfs_defer.h
+++ b/fs/xfs/libxfs/xfs_defer.h
@@ -50,8 +50,8 @@ struct xfs_defer_op_type {
 	unsigned int		max_items;
 	void (*abort_intent)(void *);
 	void *(*create_done)(struct xfs_trans *, void *, unsigned int);
-	int (*finish_item)(struct xfs_trans *, struct xfs_defer_ops *,
-			struct list_head *, void *, void **);
+	int (*finish_item)(struct xfs_trans *, struct list_head *, void *,
+			void **);
 	void (*finish_cleanup)(struct xfs_trans *, void *, int);
 	void (*cancel_item)(struct list_head *);
 	int (*diff_items)(void *, struct list_head *, struct list_head *);
diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c
index 4cbc2efb099e..86f297ca90cd 100644
--- a/fs/xfs/libxfs/xfs_refcount.c
+++ b/fs/xfs/libxfs/xfs_refcount.c
@@ -1082,7 +1082,6 @@ xfs_refcount_finish_one_cleanup(
 int
 xfs_refcount_finish_one(
 	struct xfs_trans		*tp,
-	struct xfs_defer_ops		*dfops,
 	enum xfs_refcount_intent_type	type,
 	xfs_fsblock_t			startblock,
 	xfs_extlen_t			blockcount,
@@ -1091,6 +1090,7 @@ xfs_refcount_finish_one(
 	struct xfs_btree_cur		**pcur)
 {
 	struct xfs_mount		*mp = tp->t_mountp;
+	struct xfs_defer_ops		*dfops = tp->t_dfops;
 	struct xfs_btree_cur		*rcur;
 	struct xfs_buf			*agbp = NULL;
 	int				error = 0;
diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h
index 5fef74412727..3b72c6dbf6ad 100644
--- a/fs/xfs/libxfs/xfs_refcount.h
+++ b/fs/xfs/libxfs/xfs_refcount.h
@@ -37,10 +37,9 @@ extern int xfs_refcount_decrease_extent(struct xfs_mount *mp,
 extern void xfs_refcount_finish_one_cleanup(struct xfs_trans *tp,
 		struct xfs_btree_cur *rcur, int error);
 extern int xfs_refcount_finish_one(struct xfs_trans *tp,
-		struct xfs_defer_ops *dfops, enum xfs_refcount_intent_type type,
-		xfs_fsblock_t startblock, xfs_extlen_t blockcount,
-		xfs_fsblock_t *new_fsb, xfs_extlen_t *new_len,
-		struct xfs_btree_cur **pcur);
+		enum xfs_refcount_intent_type type, xfs_fsblock_t startblock,
+		xfs_extlen_t blockcount, xfs_fsblock_t *new_fsb,
+		xfs_extlen_t *new_len, struct xfs_btree_cur **pcur);
 
 extern int xfs_refcount_find_shared(struct xfs_btree_cur *cur,
 		xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno,
diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
index 4b4318ea4b76..328a5c60000b 100644
--- a/fs/xfs/xfs_bmap_item.c
+++ b/fs/xfs/xfs_bmap_item.c
@@ -475,9 +475,8 @@ xfs_bui_recover(
 	xfs_trans_ijoin(tp, ip, 0);
 
 	count = bmap->me_len;
-	error = xfs_trans_log_finish_bmap_update(tp, budp, tp->t_dfops, type,
-			ip, whichfork, bmap->me_startoff,
-			bmap->me_startblock, &count, state);
+	error = xfs_trans_log_finish_bmap_update(tp, budp, type, ip, whichfork,
+			bmap->me_startoff, bmap->me_startblock, &count, state);
 	if (error)
 		goto err_inode;
 
diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
index 829b7a5bc707..f6a3249aa2d4 100644
--- a/fs/xfs/xfs_refcount_item.c
+++ b/fs/xfs/xfs_refcount_item.c
@@ -479,8 +479,8 @@ xfs_cui_recover(
 			new_len = refc->pe_len;
 		} else
 			error = xfs_trans_log_finish_refcount_update(tp, cudp,
-				tp->t_dfops, type, refc->pe_startblock,
-				refc->pe_len, &new_fsb, &new_len, &rcur);
+				type, refc->pe_startblock, refc->pe_len,
+				&new_fsb, &new_len, &rcur);
 		if (error)
 			goto abort_error;
 
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 8665d45b82c6..299656dbf324 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -268,7 +268,7 @@ void xfs_refcount_update_init_defer_op(void);
 struct xfs_cud_log_item *xfs_trans_get_cud(struct xfs_trans *tp,
 		struct xfs_cui_log_item *cuip);
 int xfs_trans_log_finish_refcount_update(struct xfs_trans *tp,
-		struct xfs_cud_log_item *cudp, struct xfs_defer_ops *dfops,
+		struct xfs_cud_log_item *cudp,
 		enum xfs_refcount_intent_type type, xfs_fsblock_t startblock,
 		xfs_extlen_t blockcount, xfs_fsblock_t *new_fsb,
 		xfs_extlen_t *new_len, struct xfs_btree_cur **pcur);
@@ -280,9 +280,9 @@ void xfs_bmap_update_init_defer_op(void);
 struct xfs_bud_log_item *xfs_trans_get_bud(struct xfs_trans *tp,
 		struct xfs_bui_log_item *buip);
 int xfs_trans_log_finish_bmap_update(struct xfs_trans *tp,
-		struct xfs_bud_log_item *rudp, struct xfs_defer_ops *dfops,
-		enum xfs_bmap_intent_type type, struct xfs_inode *ip,
-		int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock,
-		xfs_filblks_t *blockcount, xfs_exntst_t state);
+		struct xfs_bud_log_item *rudp, enum xfs_bmap_intent_type type,
+		struct xfs_inode *ip, int whichfork, xfs_fileoff_t startoff,
+		xfs_fsblock_t startblock, xfs_filblks_t *blockcount,
+		xfs_exntst_t state);
 
 #endif	/* __XFS_TRANS_H__ */
diff --git a/fs/xfs/xfs_trans_bmap.c b/fs/xfs/xfs_trans_bmap.c
index a15a5cd867f9..741c558b2179 100644
--- a/fs/xfs/xfs_trans_bmap.c
+++ b/fs/xfs/xfs_trans_bmap.c
@@ -43,7 +43,6 @@ int
 xfs_trans_log_finish_bmap_update(
 	struct xfs_trans		*tp,
 	struct xfs_bud_log_item		*budp,
-	struct xfs_defer_ops		*dop,
 	enum xfs_bmap_intent_type	type,
 	struct xfs_inode		*ip,
 	int				whichfork,
@@ -54,7 +53,7 @@ xfs_trans_log_finish_bmap_update(
 {
 	int				error;
 
-	error = xfs_bmap_finish_one(tp, dop, ip, type, whichfork, startoff,
+	error = xfs_bmap_finish_one(tp, ip, type, whichfork, startoff,
 			startblock, blockcount, state);
 
 	/*
@@ -176,7 +175,6 @@ xfs_bmap_update_create_done(
 STATIC int
 xfs_bmap_update_finish_item(
 	struct xfs_trans		*tp,
-	struct xfs_defer_ops		*dop,
 	struct list_head		*item,
 	void				*done_item,
 	void				**state)
@@ -187,7 +185,7 @@ xfs_bmap_update_finish_item(
 
 	bmap = container_of(item, struct xfs_bmap_intent, bi_list);
 	count = bmap->bi_bmap.br_blockcount;
-	error = xfs_trans_log_finish_bmap_update(tp, done_item, dop,
+	error = xfs_trans_log_finish_bmap_update(tp, done_item,
 			bmap->bi_type,
 			bmap->bi_owner, bmap->bi_whichfork,
 			bmap->bi_bmap.br_startoff,
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c
index bd66c76f55e6..855c0b651fd4 100644
--- a/fs/xfs/xfs_trans_extfree.c
+++ b/fs/xfs/xfs_trans_extfree.c
@@ -171,7 +171,6 @@ xfs_extent_free_create_done(
 STATIC int
 xfs_extent_free_finish_item(
 	struct xfs_trans		*tp,
-	struct xfs_defer_ops		*dop,
 	struct list_head		*item,
 	void				*done_item,
 	void				**state)
@@ -226,7 +225,6 @@ static const struct xfs_defer_op_type xfs_extent_free_defer_type = {
 STATIC int
 xfs_agfl_free_finish_item(
 	struct xfs_trans		*tp,
-	struct xfs_defer_ops		*dop,
 	struct list_head		*item,
 	void				*done_item,
 	void				**state)
diff --git a/fs/xfs/xfs_trans_refcount.c b/fs/xfs/xfs_trans_refcount.c
index 46dd4fca8aa7..523c55663954 100644
--- a/fs/xfs/xfs_trans_refcount.c
+++ b/fs/xfs/xfs_trans_refcount.c
@@ -42,7 +42,6 @@ int
 xfs_trans_log_finish_refcount_update(
 	struct xfs_trans		*tp,
 	struct xfs_cud_log_item		*cudp,
-	struct xfs_defer_ops		*dop,
 	enum xfs_refcount_intent_type	type,
 	xfs_fsblock_t			startblock,
 	xfs_extlen_t			blockcount,
@@ -52,7 +51,7 @@ xfs_trans_log_finish_refcount_update(
 {
 	int				error;
 
-	error = xfs_refcount_finish_one(tp, dop, type, startblock,
+	error = xfs_refcount_finish_one(tp, type, startblock,
 			blockcount, new_fsb, new_len, pcur);
 
 	/*
@@ -169,7 +168,6 @@ xfs_refcount_update_create_done(
 STATIC int
 xfs_refcount_update_finish_item(
 	struct xfs_trans		*tp,
-	struct xfs_defer_ops		*dop,
 	struct list_head		*item,
 	void				*done_item,
 	void				**state)
@@ -180,7 +178,7 @@ xfs_refcount_update_finish_item(
 	int				error;
 
 	refc = container_of(item, struct xfs_refcount_intent, ri_list);
-	error = xfs_trans_log_finish_refcount_update(tp, done_item, dop,
+	error = xfs_trans_log_finish_refcount_update(tp, done_item,
 			refc->ri_type,
 			refc->ri_startblock,
 			refc->ri_blockcount,
diff --git a/fs/xfs/xfs_trans_rmap.c b/fs/xfs/xfs_trans_rmap.c
index 726d8e2c0558..05b00e40251f 100644
--- a/fs/xfs/xfs_trans_rmap.c
+++ b/fs/xfs/xfs_trans_rmap.c
@@ -193,7 +193,6 @@ xfs_rmap_update_create_done(
 STATIC int
 xfs_rmap_update_finish_item(
 	struct xfs_trans		*tp,
-	struct xfs_defer_ops		*dop,
 	struct list_head		*item,
 	void				*done_item,
 	void				**state)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 10/15] xfs: clean out superfluous dfops dop params/vars
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
                   ` (8 preceding siblings ...)
  2018-07-30 16:45 ` [PATCH 09/15] xfs: drop dop param from xfs_defer_op_type ->finish_item() callback Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 20:24   ` Darrick J. Wong
  2018-07-31  8:20   ` Christoph Hellwig
  2018-07-30 16:45 ` [PATCH 11/15] xfs: cancel dfops on xfs_defer_finish() error Brian Foster
                   ` (4 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

The dfops code still passes around the xfs_defer_ops pointer
superfluously in a few places. Clean this up wherever the
transaction will suffice.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/libxfs/xfs_defer.c | 43 +++++++++++++++++++--------------------
 fs/xfs/libxfs/xfs_defer.h |  2 +-
 2 files changed, 22 insertions(+), 23 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
index 7fb7edd5d63e..7b84e3a4b7f3 100644
--- a/fs/xfs/libxfs/xfs_defer.c
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -181,9 +181,9 @@ static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX];
  */
 STATIC void
 xfs_defer_intake_work(
-	struct xfs_trans		*tp,
-	struct xfs_defer_ops		*dop)
+	struct xfs_trans		*tp)
 {
+	struct xfs_defer_ops		*dop = tp->t_dfops;
 	struct list_head		*li;
 	struct xfs_defer_pending	*dfp;
 
@@ -204,9 +204,9 @@ xfs_defer_intake_work(
 STATIC void
 xfs_defer_trans_abort(
 	struct xfs_trans		*tp,
-	struct xfs_defer_ops		*dop,
 	int				error)
 {
+	struct xfs_defer_ops		*dop = tp->t_dfops;
 	struct xfs_defer_pending	*dfp;
 
 	trace_xfs_defer_trans_abort(tp->t_mountp, dop, _RET_IP_);
@@ -230,7 +230,6 @@ STATIC int
 xfs_defer_trans_roll(
 	struct xfs_trans		**tp)
 {
-	struct xfs_defer_ops		*dop = (*tp)->t_dfops;
 	struct xfs_buf_log_item		*bli;
 	struct xfs_inode_log_item	*ili;
 	struct xfs_log_item		*lip;
@@ -266,14 +265,14 @@ xfs_defer_trans_roll(
 		}
 	}
 
-	trace_xfs_defer_trans_roll((*tp)->t_mountp, dop, _RET_IP_);
+	trace_xfs_defer_trans_roll((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_);
 
 	/* Roll the transaction. */
 	error = xfs_trans_roll(tp);
-	dop = (*tp)->t_dfops;
 	if (error) {
-		trace_xfs_defer_trans_roll_error((*tp)->t_mountp, dop, error);
-		xfs_defer_trans_abort(*tp, dop, error);
+		trace_xfs_defer_trans_roll_error((*tp)->t_mountp,
+						 (*tp)->t_dfops, error);
+		xfs_defer_trans_abort(*tp,  error);
 		return error;
 	}
 
@@ -293,9 +292,10 @@ xfs_defer_trans_roll(
 /* Do we have any work items to finish? */
 bool
 xfs_defer_has_unfinished_work(
-	struct xfs_defer_ops		*dop)
+	struct xfs_trans		*tp)
 {
-	return !list_empty(&dop->dop_pending) || !list_empty(&dop->dop_intake);
+	return !list_empty(&tp->t_dfops->dop_pending) ||
+		!list_empty(&tp->t_dfops->dop_intake);
 }
 
 /*
@@ -305,7 +305,7 @@ static void
 xfs_defer_reset(
 	struct xfs_trans	*tp)
 {
-	ASSERT(!xfs_defer_has_unfinished_work(tp->t_dfops));
+	ASSERT(!xfs_defer_has_unfinished_work(tp));
 
 	/*
 	 * Low mode state transfers across transaction rolls to mirror dfops
@@ -326,7 +326,6 @@ int
 xfs_defer_finish_noroll(
 	struct xfs_trans		**tp)
 {
-	struct xfs_defer_ops		*dop = (*tp)->t_dfops;
 	struct xfs_defer_pending	*dfp;
 	struct list_head		*li;
 	struct list_head		*n;
@@ -336,24 +335,22 @@ xfs_defer_finish_noroll(
 
 	ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
 
-	trace_xfs_defer_finish((*tp)->t_mountp, dop, _RET_IP_);
+	trace_xfs_defer_finish((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_);
 
 	/* Until we run out of pending work to finish... */
-	while (xfs_defer_has_unfinished_work(dop)) {
+	while (xfs_defer_has_unfinished_work(*tp)) {
 		/* Log intents for work items sitting in the intake. */
-		xfs_defer_intake_work(*tp, dop);
+		xfs_defer_intake_work(*tp);
 
 		/*
-		 * Roll the transaction and update dop in case dfops was
-		 * embedded in the transaction.
+		 * Roll the transaction.
 		 */
 		error = xfs_defer_trans_roll(tp);
 		if (error)
 			goto out;
-		dop = (*tp)->t_dfops;
 
 		/* Log an intent-done item for the first pending item. */
-		dfp = list_first_entry(&dop->dop_pending,
+		dfp = list_first_entry(&(*tp)->t_dfops->dop_pending,
 				struct xfs_defer_pending, dfp_list);
 		trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp);
 		dfp->dfp_done = dfp->dfp_type->create_done(*tp, dfp->dfp_intent,
@@ -384,7 +381,7 @@ xfs_defer_finish_noroll(
 				 */
 				if (cleanup_fn)
 					cleanup_fn(*tp, state, error);
-				xfs_defer_trans_abort(*tp, dop, error);
+				xfs_defer_trans_abort(*tp, error);
 				goto out;
 			}
 		}
@@ -414,9 +411,11 @@ xfs_defer_finish_noroll(
 
 out:
 	if (error)
-		trace_xfs_defer_finish_error((*tp)->t_mountp, dop, error);
+		trace_xfs_defer_finish_error((*tp)->t_mountp, (*tp)->t_dfops,
+					     error);
 	 else
-		trace_xfs_defer_finish_done((*tp)->t_mountp, dop, _RET_IP_);
+		trace_xfs_defer_finish_done((*tp)->t_mountp, (*tp)->t_dfops,
+					    _RET_IP_);
 
 	return error;
 }
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
index 0de7504e5651..f051c8056141 100644
--- a/fs/xfs/libxfs/xfs_defer.h
+++ b/fs/xfs/libxfs/xfs_defer.h
@@ -41,7 +41,7 @@ int xfs_defer_finish_noroll(struct xfs_trans **tp);
 int xfs_defer_finish(struct xfs_trans **tp);
 void xfs_defer_cancel(struct xfs_trans *);
 void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
-bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);
+bool xfs_defer_has_unfinished_work(struct xfs_trans *tp);
 void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
 
 /* Description of a deferred type. */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 11/15] xfs: cancel dfops on xfs_defer_finish() error
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
                   ` (9 preceding siblings ...)
  2018-07-30 16:45 ` [PATCH 10/15] xfs: clean out superfluous dfops dop params/vars Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 20:27   ` Darrick J. Wong
  2018-07-31  8:21   ` Christoph Hellwig
  2018-07-30 16:45 ` [PATCH 12/15] xfs: replace xfs_defer_ops ->dop_pending with on-stack list Brian Foster
                   ` (3 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

The current semantics of xfs_defer_finish() require the caller to
call xfs_defer_cancel() on error. This is slightly inconsistent with
transaction commit error handling where a failed commit cleans up
the transaction before returning.

More significantly, the only requirement for exposure of
->dop_pending outside of xfs_defer_finish() is so that
xfs_defer_cancel() can drain it on error. Since the only recourse of
xfs_defer_finish() errors is cancellation, mirror the transaction
logic and cancel remaining dfops before returning from
xfs_defer_finish() with an error.

Beside simplifying xfs_defer_finish() semantics, this ensures that
xfs_defer_finish() always returns with an empty ->dop_pending and
thus facilitates removal of the list from xfs_defer_ops.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/libxfs/xfs_attr.c        | 16 ++++++++--------
 fs/xfs/libxfs/xfs_attr_remote.c |  4 ++--
 fs/xfs/libxfs/xfs_defer.c       | 11 ++++++-----
 fs/xfs/xfs_bmap_util.c          |  2 +-
 fs/xfs/xfs_dquot.c              |  2 +-
 fs/xfs/xfs_inode.c              |  2 +-
 fs/xfs/xfs_reflink.c            |  4 +---
 fs/xfs/xfs_trans.c              |  4 +---
 8 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index 3190dfc21b60..1e671d4eb6fa 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -590,7 +590,7 @@ xfs_attr_leaf_addname(
 			goto out_defer_cancel;
 		error = xfs_defer_finish(&args->trans);
 		if (error)
-			goto out_defer_cancel;
+			return error;
 
 		/*
 		 * Commit the current trans (including the inode) and start
@@ -678,7 +678,7 @@ xfs_attr_leaf_addname(
 				goto out_defer_cancel;
 			error = xfs_defer_finish(&args->trans);
 			if (error)
-				goto out_defer_cancel;
+				return error;
 		}
 
 		/*
@@ -741,7 +741,7 @@ xfs_attr_leaf_removename(
 			goto out_defer_cancel;
 		error = xfs_defer_finish(&args->trans);
 		if (error)
-			goto out_defer_cancel;
+			return error;
 	}
 	return 0;
 out_defer_cancel:
@@ -867,7 +867,7 @@ xfs_attr_node_addname(
 				goto out_defer_cancel;
 			error = xfs_defer_finish(&args->trans);
 			if (error)
-				goto out_defer_cancel;
+				goto out;
 
 			/*
 			 * Commit the node conversion and start the next
@@ -891,7 +891,7 @@ xfs_attr_node_addname(
 			goto out_defer_cancel;
 		error = xfs_defer_finish(&args->trans);
 		if (error)
-			goto out_defer_cancel;
+			goto out;
 	} else {
 		/*
 		 * Addition succeeded, update Btree hashvals.
@@ -987,7 +987,7 @@ xfs_attr_node_addname(
 				goto out_defer_cancel;
 			error = xfs_defer_finish(&args->trans);
 			if (error)
-				goto out_defer_cancel;
+				goto out;
 		}
 
 		/*
@@ -1110,7 +1110,7 @@ xfs_attr_node_removename(
 			goto out_defer_cancel;
 		error = xfs_defer_finish(&args->trans);
 		if (error)
-			goto out_defer_cancel;
+			goto out;
 		/*
 		 * Commit the Btree join operation and start a new trans.
 		 */
@@ -1141,7 +1141,7 @@ xfs_attr_node_removename(
 				goto out_defer_cancel;
 			error = xfs_defer_finish(&args->trans);
 			if (error)
-				goto out_defer_cancel;
+				goto out;
 		} else
 			xfs_trans_brelse(args->trans, bp);
 	}
diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c
index f52552313773..af094063e402 100644
--- a/fs/xfs/libxfs/xfs_attr_remote.c
+++ b/fs/xfs/libxfs/xfs_attr_remote.c
@@ -488,7 +488,7 @@ xfs_attr_rmtval_set(
 			goto out_defer_cancel;
 		error = xfs_defer_finish(&args->trans);
 		if (error)
-			goto out_defer_cancel;
+			return error;
 
 		ASSERT(nmap == 1);
 		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
@@ -628,7 +628,7 @@ xfs_attr_rmtval_remove(
 			goto out_defer_cancel;
 		error = xfs_defer_finish(&args->trans);
 		if (error)
-			goto out_defer_cancel;
+			return error;
 
 		/*
 		 * Close out trans and start the next one in the chain.
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
index 7b84e3a4b7f3..66848ede62c0 100644
--- a/fs/xfs/libxfs/xfs_defer.c
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -410,14 +410,15 @@ xfs_defer_finish_noroll(
 	}
 
 out:
-	if (error)
+	if (error) {
 		trace_xfs_defer_finish_error((*tp)->t_mountp, (*tp)->t_dfops,
 					     error);
-	 else
-		trace_xfs_defer_finish_done((*tp)->t_mountp, (*tp)->t_dfops,
-					    _RET_IP_);
+		xfs_defer_cancel(*tp);
+		return error;
+	}
 
-	return error;
+	trace_xfs_defer_finish_done((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_);
+	return 0;
 }
 
 int
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 30ac1300dc49..d9dad399440a 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1624,7 +1624,7 @@ xfs_swap_extent_rmap(
 			error = xfs_defer_finish(tpp);
 			tp = *tpp;
 			if (error)
-				goto out_defer;
+				goto out;
 
 			tirec.br_startoff += rlen;
 			if (tirec.br_startblock != HOLESTARTBLOCK &&
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index e1196854dbcd..70a76ac41f01 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -371,7 +371,7 @@ xfs_dquot_disk_alloc(
 	tp = *tpp;
 	if (error) {
 		xfs_buf_relse(bp);
-		goto error1;
+		goto error0;
 	}
 	*bpp = bp;
 	return 0;
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 7bb46a0eecfc..d957a46dc1cb 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1571,7 +1571,7 @@ xfs_itruncate_extents_flags(
 		 */
 		error = xfs_defer_finish(&tp);
 		if (error)
-			goto out_bmap_cancel;
+			goto out;
 
 		error = xfs_trans_roll_inode(&tp, ip);
 		if (error)
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index dce8ba8ab681..2ec562d75494 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -518,10 +518,8 @@ xfs_reflink_cancel_cow_blocks(
 
 			/* Roll the transaction */
 			error = xfs_defer_finish(tpp);
-			if (error) {
-				xfs_defer_cancel(*tpp);
+			if (error)
 				break;
-			}
 
 			/* Remove the mapping from the CoW fork. */
 			xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 8c088568b05d..20750cd9c9e7 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -928,10 +928,8 @@ __xfs_trans_commit(
 	/* finish deferred items on final commit */
 	if (!regrant && (tp->t_flags & XFS_TRANS_PERM_LOG_RES)) {
 		error = xfs_defer_finish_noroll(&tp);
-		if (error) {
-			xfs_defer_cancel(tp);
+		if (error)
 			goto out_unreserve;
-		}
 	}
 
 	/*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 12/15] xfs: replace xfs_defer_ops ->dop_pending with on-stack list
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
                   ` (10 preceding siblings ...)
  2018-07-30 16:45 ` [PATCH 11/15] xfs: cancel dfops on xfs_defer_finish() error Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 20:47   ` Darrick J. Wong
  2018-07-31  8:30   ` Christoph Hellwig
  2018-07-30 16:45 ` [PATCH 13/15] xfs: pass transaction to xfs_defer_add() Brian Foster
                   ` (2 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

The xfs_defer_ops ->dop_pending list is used to track active
deferred operations once intents are logged. These items must be
aborted in the event of an error. The list is populated as intents
are logged and items are removed as they complete (or are aborted).

Now that xfs_defer_finish() cancels on error, there is no need to
ever access ->dop_pending outside of xfs_defer_finish(). The list is
only ever populated after xfs_defer_finish() begins and is either
completed or cancelled before it returns.

Remove ->dop_pending from xfs_defer_ops and replace it with a local
list in the xfs_defer_finish() path. Pass the local list to the
various helpers now that it is not accessible via dfops. Note that
we have to check for NULL in the abort case as the final tx roll
occurs outside of the scope of the new local list (once the dfops
has completed and thus drained the list).

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/libxfs/xfs_defer.c | 80 ++++++++++++++++++++-------------------
 fs/xfs/libxfs/xfs_defer.h |  3 +-
 fs/xfs/xfs_trace.h        |  1 -
 fs/xfs/xfs_trans.h        |  1 -
 4 files changed, 43 insertions(+), 42 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
index 66848ede62c0..6bf792e2d61b 100644
--- a/fs/xfs/libxfs/xfs_defer.c
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -174,6 +174,8 @@
 
 static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX];
 
+static void __xfs_defer_cancel(struct list_head *);
+
 /*
  * For each pending item in the intake list, log its intent item and the
  * associated extents, then add the entire intake list to the end of
@@ -181,7 +183,8 @@ static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX];
  */
 STATIC void
 xfs_defer_intake_work(
-	struct xfs_trans		*tp)
+	struct xfs_trans		*tp,
+	struct list_head		*dop_pending)
 {
 	struct xfs_defer_ops		*dop = tp->t_dfops;
 	struct list_head		*li;
@@ -197,13 +200,14 @@ xfs_defer_intake_work(
 			dfp->dfp_type->log_item(tp, dfp->dfp_intent, li);
 	}
 
-	list_splice_tail_init(&dop->dop_intake, &dop->dop_pending);
+	list_splice_tail_init(&dop->dop_intake, dop_pending);
 }
 
 /* Abort all the intents that were committed. */
 STATIC void
 xfs_defer_trans_abort(
 	struct xfs_trans		*tp,
+	struct list_head		*dop_pending,
 	int				error)
 {
 	struct xfs_defer_ops		*dop = tp->t_dfops;
@@ -212,11 +216,13 @@ xfs_defer_trans_abort(
 	trace_xfs_defer_trans_abort(tp->t_mountp, dop, _RET_IP_);
 
 	/* Abort intent items that don't have a done item. */
-	list_for_each_entry(dfp, &dop->dop_pending, dfp_list) {
-		trace_xfs_defer_pending_abort(tp->t_mountp, dfp);
-		if (dfp->dfp_intent && !dfp->dfp_done) {
-			dfp->dfp_type->abort_intent(dfp->dfp_intent);
-			dfp->dfp_intent = NULL;
+	if (dop_pending) {
+		list_for_each_entry(dfp, dop_pending, dfp_list) {
+			trace_xfs_defer_pending_abort(tp->t_mountp, dfp);
+			if (dfp->dfp_intent && !dfp->dfp_done) {
+				dfp->dfp_type->abort_intent(dfp->dfp_intent);
+				dfp->dfp_intent = NULL;
+			}
 		}
 	}
 
@@ -228,7 +234,8 @@ xfs_defer_trans_abort(
 /* Roll a transaction so we can do some deferred op processing. */
 STATIC int
 xfs_defer_trans_roll(
-	struct xfs_trans		**tp)
+	struct xfs_trans		**tp,
+	struct list_head		*dop_pending)
 {
 	struct xfs_buf_log_item		*bli;
 	struct xfs_inode_log_item	*ili;
@@ -272,7 +279,7 @@ xfs_defer_trans_roll(
 	if (error) {
 		trace_xfs_defer_trans_roll_error((*tp)->t_mountp,
 						 (*tp)->t_dfops, error);
-		xfs_defer_trans_abort(*tp,  error);
+		xfs_defer_trans_abort(*tp,  dop_pending, error);
 		return error;
 	}
 
@@ -292,9 +299,10 @@ xfs_defer_trans_roll(
 /* Do we have any work items to finish? */
 bool
 xfs_defer_has_unfinished_work(
-	struct xfs_trans		*tp)
+	struct xfs_trans		*tp,
+	struct list_head		*dop_pending)
 {
-	return !list_empty(&tp->t_dfops->dop_pending) ||
+	return !list_empty(dop_pending) ||
 		!list_empty(&tp->t_dfops->dop_intake);
 }
 
@@ -305,7 +313,7 @@ static void
 xfs_defer_reset(
 	struct xfs_trans	*tp)
 {
-	ASSERT(!xfs_defer_has_unfinished_work(tp));
+	ASSERT(list_empty(&tp->t_dfops->dop_intake));
 
 	/*
 	 * Low mode state transfers across transaction rolls to mirror dfops
@@ -332,26 +340,27 @@ xfs_defer_finish_noroll(
 	void				*state;
 	int				error = 0;
 	void				(*cleanup_fn)(struct xfs_trans *, void *, int);
+	LIST_HEAD(dop_pending);
 
 	ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
 
 	trace_xfs_defer_finish((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_);
 
 	/* Until we run out of pending work to finish... */
-	while (xfs_defer_has_unfinished_work(*tp)) {
+	while (xfs_defer_has_unfinished_work(*tp, &dop_pending)) {
 		/* Log intents for work items sitting in the intake. */
-		xfs_defer_intake_work(*tp);
+		xfs_defer_intake_work(*tp, &dop_pending);
 
 		/*
 		 * Roll the transaction.
 		 */
-		error = xfs_defer_trans_roll(tp);
+		error = xfs_defer_trans_roll(tp, &dop_pending);
 		if (error)
 			goto out;
 
 		/* Log an intent-done item for the first pending item. */
-		dfp = list_first_entry(&(*tp)->t_dfops->dop_pending,
-				struct xfs_defer_pending, dfp_list);
+		dfp = list_first_entry(&dop_pending, struct xfs_defer_pending,
+				       dfp_list);
 		trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp);
 		dfp->dfp_done = dfp->dfp_type->create_done(*tp, dfp->dfp_intent,
 				dfp->dfp_count);
@@ -381,7 +390,7 @@ xfs_defer_finish_noroll(
 				 */
 				if (cleanup_fn)
 					cleanup_fn(*tp, state, error);
-				xfs_defer_trans_abort(*tp, error);
+				xfs_defer_trans_abort(*tp, &dop_pending, error);
 				goto out;
 			}
 		}
@@ -413,6 +422,7 @@ xfs_defer_finish_noroll(
 	if (error) {
 		trace_xfs_defer_finish_error((*tp)->t_mountp, (*tp)->t_dfops,
 					     error);
+		__xfs_defer_cancel(&dop_pending);
 		xfs_defer_cancel(*tp);
 		return error;
 	}
@@ -435,7 +445,7 @@ xfs_defer_finish(
 	if (error)
 		return error;
 	if ((*tp)->t_flags & XFS_TRANS_DIRTY) {
-		error = xfs_defer_trans_roll(tp);
+		error = xfs_defer_trans_roll(tp, NULL);
 		if (error)
 			return error;
 	}
@@ -446,34 +456,20 @@ xfs_defer_finish(
 /*
  * Free up any items left in the list.
  */
-void
-xfs_defer_cancel(
-	struct xfs_trans		*tp)
+static void
+__xfs_defer_cancel(
+	struct list_head		*dop_list)
 {
-	struct xfs_defer_ops		*dop = tp->t_dfops;
 	struct xfs_defer_pending	*dfp;
 	struct xfs_defer_pending	*pli;
 	struct list_head		*pwi;
 	struct list_head		*n;
 
-	trace_xfs_defer_cancel(NULL, dop, _RET_IP_);
-
 	/*
 	 * Free the pending items.  Caller should already have arranged
 	 * for the intent items to be released.
 	 */
-	list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) {
-		trace_xfs_defer_intake_cancel(NULL, dfp);
-		list_del(&dfp->dfp_list);
-		list_for_each_safe(pwi, n, &dfp->dfp_work) {
-			list_del(pwi);
-			dfp->dfp_count--;
-			dfp->dfp_type->cancel_item(pwi);
-		}
-		ASSERT(dfp->dfp_count == 0);
-		kmem_free(dfp);
-	}
-	list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) {
+	list_for_each_entry_safe(dfp, pli, dop_list, dfp_list) {
 		trace_xfs_defer_pending_cancel(NULL, dfp);
 		list_del(&dfp->dfp_list);
 		list_for_each_safe(pwi, n, &dfp->dfp_work) {
@@ -486,6 +482,14 @@ xfs_defer_cancel(
 	}
 }
 
+void
+xfs_defer_cancel(
+	struct xfs_trans	*tp)
+{
+	trace_xfs_defer_cancel(NULL, tp->t_dfops, _RET_IP_);
+	__xfs_defer_cancel(&tp->t_dfops->dop_intake);
+}
+
 /* Add an item for later deferred processing. */
 void
 xfs_defer_add(
@@ -541,7 +545,6 @@ xfs_defer_init(
 
 	memset(dop, 0, sizeof(struct xfs_defer_ops));
 	INIT_LIST_HEAD(&dop->dop_intake);
-	INIT_LIST_HEAD(&dop->dop_pending);
 	if (tp) {
 		ASSERT(tp->t_firstblock == NULLFSBLOCK);
 		tp->t_dfops = dop;
@@ -565,7 +568,6 @@ xfs_defer_move(
 	ASSERT(dst != src);
 
 	list_splice_init(&src->dop_intake, &dst->dop_intake);
-	list_splice_init(&src->dop_pending, &dst->dop_pending);
 
 	/*
 	 * Low free space mode was historically controlled by a dfops field.
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
index f051c8056141..363af16328cb 100644
--- a/fs/xfs/libxfs/xfs_defer.h
+++ b/fs/xfs/libxfs/xfs_defer.h
@@ -41,7 +41,8 @@ int xfs_defer_finish_noroll(struct xfs_trans **tp);
 int xfs_defer_finish(struct xfs_trans **tp);
 void xfs_defer_cancel(struct xfs_trans *);
 void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
-bool xfs_defer_has_unfinished_work(struct xfs_trans *tp);
+bool xfs_defer_has_unfinished_work(struct xfs_trans *tp,
+		struct list_head *dop_pending);
 void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
 
 /* Description of a deferred type. */
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 8807f1bb814a..6b55bbc09578 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -2393,7 +2393,6 @@ DEFINE_DEFER_ERROR_EVENT(xfs_defer_trans_roll_error);
 DEFINE_DEFER_ERROR_EVENT(xfs_defer_finish_error);
 
 DEFINE_DEFER_PENDING_EVENT(xfs_defer_intake_work);
-DEFINE_DEFER_PENDING_EVENT(xfs_defer_intake_cancel);
 DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_cancel);
 DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_finish);
 DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_abort);
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 299656dbf324..1cdc7c0ebeac 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -96,7 +96,6 @@ void	xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item,
 #define XFS_DEFER_OPS_NR_BUFS	2	/* join up to two buffers */
 struct xfs_defer_ops {
 	struct list_head	dop_intake;	/* unlogged pending work */
-	struct list_head	dop_pending;	/* logged pending work */
 };
 
 /*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 13/15] xfs: pass transaction to xfs_defer_add()
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
                   ` (11 preceding siblings ...)
  2018-07-30 16:45 ` [PATCH 12/15] xfs: replace xfs_defer_ops ->dop_pending with on-stack list Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 20:49   ` Darrick J. Wong
  2018-07-31  8:31   ` Christoph Hellwig
  2018-07-30 16:45 ` [PATCH 14/15] xfs: always defer agfl block frees Brian Foster
  2018-07-30 16:45 ` [PATCH 15/15] xfs: fold dfops into the transaction Brian Foster
  14 siblings, 2 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

The majority of remaining references to struct xfs_defer_ops in XFS
are associated with xfs_defer_add(). At this point, there are no
more external xfs_defer_ops users left. All instances of
xfs_defer_ops are embedded in the transaction, which means we can
safely pass the transaction down to the dfops add interface.

Update xfs_defer_add() to receive the transaction as a parameter.
Various subsystems implement wrappers to allocate and construct the
context specific data structures for the associated deferred
operation type. Update these to also carry the transaction down as
needed and clean up unused dfops parameters along the way.

This removes most of the remaining references to struct
xfs_defer_ops throughout the code and facilitates removal of the
structure.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/libxfs/xfs_alloc.c      |  9 ++--
 fs/xfs/libxfs/xfs_bmap.c       | 75 +++++++++++++++------------------
 fs/xfs/libxfs/xfs_bmap.h       | 19 ++++-----
 fs/xfs/libxfs/xfs_bmap_btree.c |  2 +-
 fs/xfs/libxfs/xfs_defer.c      |  3 +-
 fs/xfs/libxfs/xfs_defer.h      |  2 +-
 fs/xfs/libxfs/xfs_ialloc.c     | 25 +++++------
 fs/xfs/libxfs/xfs_refcount.c   | 76 ++++++++++++++--------------------
 fs/xfs/libxfs/xfs_refcount.h   | 18 ++++----
 fs/xfs/libxfs/xfs_rmap.c       | 53 ++++++++++++------------
 fs/xfs/libxfs/xfs_rmap.h       | 22 ++++------
 fs/xfs/xfs_bmap_item.c         |  3 +-
 fs/xfs/xfs_bmap_util.c         | 13 ++----
 fs/xfs/xfs_refcount_item.c     | 14 ++-----
 fs/xfs/xfs_reflink.c           | 21 ++++------
 15 files changed, 156 insertions(+), 199 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 3c3f2d5119ea..6bacdc31a439 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -2198,12 +2198,12 @@ xfs_agfl_reset(
  */
 STATIC void
 xfs_defer_agfl_block(
-	struct xfs_mount		*mp,
-	struct xfs_defer_ops		*dfops,
+	struct xfs_trans		*tp,
 	xfs_agnumber_t			agno,
 	xfs_fsblock_t			agbno,
 	struct xfs_owner_info		*oinfo)
 {
+	struct xfs_mount		*mp = tp->t_mountp;
 	struct xfs_extent_free_item	*new;		/* new element */
 
 	ASSERT(xfs_bmap_free_item_zone != NULL);
@@ -2216,7 +2216,7 @@ xfs_defer_agfl_block(
 
 	trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1);
 
-	xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_AGFL_FREE, &new->xefi_list);
+	xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_AGFL_FREE, &new->xefi_list);
 }
 
 /*
@@ -2325,8 +2325,7 @@ xfs_alloc_fix_freelist(
 
 		/* defer agfl frees if dfops is provided */
 		if (tp->t_dfops) {
-			xfs_defer_agfl_block(mp, tp->t_dfops, args->agno,
-					     bno, &targs.oinfo);
+			xfs_defer_agfl_block(tp, args->agno, bno, &targs.oinfo);
 		} else {
 			error = xfs_free_agfl_block(tp, args->agno, bno, agbp,
 						    &targs.oinfo);
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index d20f541b7061..f5f1fc47923e 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -533,13 +533,13 @@ xfs_bmap_validate_ret(
  */
 void
 __xfs_bmap_add_free(
-	struct xfs_mount		*mp,
-	struct xfs_defer_ops		*dfops,
+	struct xfs_trans		*tp,
 	xfs_fsblock_t			bno,
 	xfs_filblks_t			len,
 	struct xfs_owner_info		*oinfo,
 	bool				skip_discard)
 {
+	struct xfs_mount		*mp = tp->t_mountp;
 	struct xfs_extent_free_item	*new;		/* new element */
 #ifdef DEBUG
 	xfs_agnumber_t		agno;
@@ -568,7 +568,7 @@ __xfs_bmap_add_free(
 	new->xefi_skip_discard = skip_discard;
 	trace_xfs_bmap_free_defer(mp, XFS_FSB_TO_AGNO(mp, bno), 0,
 			XFS_FSB_TO_AGBNO(mp, bno), len);
-	xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list);
+	xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list);
 }
 
 /*
@@ -624,7 +624,7 @@ xfs_bmap_btree_to_extents(
 	if ((error = xfs_btree_check_block(cur, cblock, 0, cbp)))
 		return error;
 	xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork);
-	xfs_bmap_add_free(mp, cur->bc_tp->t_dfops, cbno, 1, &oinfo);
+	xfs_bmap_add_free(cur->bc_tp, cbno, 1, &oinfo);
 	ip->i_d.di_nblocks--;
 	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
 	xfs_trans_binval(tp, cbp);
@@ -1961,8 +1961,7 @@ xfs_bmap_add_extent_delay_real(
 
 	/* add reverse mapping unless caller opted out */
 	if (!(bma->flags & XFS_BMAPI_NORMAP)) {
-		error = xfs_rmap_map_extent(mp, bma->tp->t_dfops, bma->ip,
-				whichfork, new);
+		error = xfs_rmap_map_extent(bma->tp, bma->ip, whichfork, new);
 		if (error)
 			goto done;
 	}
@@ -2026,7 +2025,6 @@ xfs_bmap_add_extent_unwritten_real(
 	int			state = xfs_bmap_fork_to_state(whichfork);
 	struct xfs_mount	*mp = ip->i_mount;
 	struct xfs_bmbt_irec	old;
-	struct xfs_defer_ops	*dfops = tp ? tp->t_dfops : NULL;
 
 	*logflagsp = 0;
 
@@ -2445,7 +2443,7 @@ xfs_bmap_add_extent_unwritten_real(
 	}
 
 	/* update reverse mappings */
-	error = xfs_rmap_convert_extent(mp, dfops, ip, whichfork, new);
+	error = xfs_rmap_convert_extent(mp, tp, ip, whichfork, new);
 	if (error)
 		goto done;
 
@@ -2806,8 +2804,7 @@ xfs_bmap_add_extent_hole_real(
 
 	/* add reverse mapping unless caller opted out */
 	if (!(flags & XFS_BMAPI_NORMAP)) {
-		error = xfs_rmap_map_extent(mp, tp->t_dfops, ip, whichfork,
-				new);
+		error = xfs_rmap_map_extent(tp, ip, whichfork, new);
 		if (error)
 			goto done;
 	}
@@ -4364,9 +4361,8 @@ xfs_bmapi_write(
 			 * the refcount btree for orphan recovery.
 			 */
 			if (whichfork == XFS_COW_FORK) {
-				error = xfs_refcount_alloc_cow_extent(mp,
-						tp->t_dfops, bma.blkno,
-						bma.length);
+				error = xfs_refcount_alloc_cow_extent(tp,
+						bma.blkno, bma.length);
 				if (error)
 					goto error0;
 			}
@@ -4852,7 +4848,6 @@ xfs_bmap_del_extent_real(
 	uint			qfield;	/* quota field to update */
 	int			state = xfs_bmap_fork_to_state(whichfork);
 	struct xfs_bmbt_irec	old;
-	struct xfs_defer_ops	*dfops = tp ? tp->t_dfops : NULL;
 
 	mp = ip->i_mount;
 	XFS_STATS_INC(mp, xs_del_exlist);
@@ -5036,7 +5031,7 @@ xfs_bmap_del_extent_real(
 	}
 
 	/* remove reverse mapping */
-	error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, del);
+	error = xfs_rmap_unmap_extent(tp, ip, whichfork, del);
 	if (error)
 		goto done;
 
@@ -5045,11 +5040,11 @@ xfs_bmap_del_extent_real(
 	 */
 	if (do_fx && !(bflags & XFS_BMAPI_REMAP)) {
 		if (xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK) {
-			error = xfs_refcount_decrease_extent(mp, dfops, del);
+			error = xfs_refcount_decrease_extent(tp, del);
 			if (error)
 				goto done;
 		} else {
-			__xfs_bmap_add_free(mp, dfops, del->br_startblock,
+			__xfs_bmap_add_free(tp, del->br_startblock,
 					del->br_blockcount, NULL,
 					(bflags & XFS_BMAPI_NODISCARD) ||
 					del->br_state == XFS_EXT_UNWRITTEN);
@@ -5489,6 +5484,7 @@ xfs_bmse_can_merge(
  */
 STATIC int
 xfs_bmse_merge(
+	struct xfs_trans		*tp,
 	struct xfs_inode		*ip,
 	int				whichfork,
 	xfs_fileoff_t			shift,		/* shift fsb */
@@ -5496,8 +5492,7 @@ xfs_bmse_merge(
 	struct xfs_bmbt_irec		*got,		/* extent to shift */
 	struct xfs_bmbt_irec		*left,		/* preceding extent */
 	struct xfs_btree_cur		*cur,
-	int				*logflags,	/* output */
-	struct xfs_defer_ops		*dfops)
+	int				*logflags)	/* output */
 {
 	struct xfs_bmbt_irec		new;
 	xfs_filblks_t			blockcount;
@@ -5553,23 +5548,23 @@ xfs_bmse_merge(
 			&new);
 
 	/* update reverse mapping. rmap functions merge the rmaps for us */
-	error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, got);
+	error = xfs_rmap_unmap_extent(tp, ip, whichfork, got);
 	if (error)
 		return error;
 	memcpy(&new, got, sizeof(new));
 	new.br_startoff = left->br_startoff + left->br_blockcount;
-	return xfs_rmap_map_extent(mp, dfops, ip, whichfork, &new);
+	return xfs_rmap_map_extent(tp, ip, whichfork, &new);
 }
 
 static int
 xfs_bmap_shift_update_extent(
+	struct xfs_trans	*tp,
 	struct xfs_inode	*ip,
 	int			whichfork,
 	struct xfs_iext_cursor	*icur,
 	struct xfs_bmbt_irec	*got,
 	struct xfs_btree_cur	*cur,
 	int			*logflags,
-	struct xfs_defer_ops	*dfops,
 	xfs_fileoff_t		startoff)
 {
 	struct xfs_mount	*mp = ip->i_mount;
@@ -5597,10 +5592,10 @@ xfs_bmap_shift_update_extent(
 			got);
 
 	/* update reverse mapping */
-	error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, &prev);
+	error = xfs_rmap_unmap_extent(tp, ip, whichfork, &prev);
 	if (error)
 		return error;
-	return xfs_rmap_map_extent(mp, dfops, ip, whichfork, got);
+	return xfs_rmap_map_extent(tp, ip, whichfork, got);
 }
 
 int
@@ -5660,9 +5655,9 @@ xfs_bmap_collapse_extents(
 		}
 
 		if (xfs_bmse_can_merge(&prev, &got, offset_shift_fsb)) {
-			error = xfs_bmse_merge(ip, whichfork, offset_shift_fsb,
-					&icur, &got, &prev, cur, &logflags,
-					tp->t_dfops);
+			error = xfs_bmse_merge(tp, ip, whichfork,
+					offset_shift_fsb, &icur, &got, &prev,
+					cur, &logflags);
 			if (error)
 				goto del_cursor;
 			goto done;
@@ -5674,8 +5669,8 @@ xfs_bmap_collapse_extents(
 		}
 	}
 
-	error = xfs_bmap_shift_update_extent(ip, whichfork, &icur, &got, cur,
-			&logflags, tp->t_dfops, new_startoff);
+	error = xfs_bmap_shift_update_extent(tp, ip, whichfork, &icur, &got,
+			cur, &logflags, new_startoff);
 	if (error)
 		goto del_cursor;
 
@@ -5801,8 +5796,8 @@ xfs_bmap_insert_extents(
 			WARN_ON_ONCE(1);
 	}
 
-	error = xfs_bmap_shift_update_extent(ip, whichfork, &icur, &got, cur,
-			&logflags, tp->t_dfops, new_startoff);
+	error = xfs_bmap_shift_update_extent(tp, ip, whichfork, &icur, &got,
+			cur, &logflags, new_startoff);
 	if (error)
 		goto del_cursor;
 
@@ -5979,13 +5974,13 @@ xfs_bmap_is_update_needed(
 /* Record a bmap intent. */
 static int
 __xfs_bmap_add(
-	struct xfs_mount		*mp,
-	struct xfs_defer_ops		*dfops,
+	struct xfs_trans		*tp,
 	enum xfs_bmap_intent_type	type,
 	struct xfs_inode		*ip,
 	int				whichfork,
 	struct xfs_bmbt_irec		*bmap)
 {
+	struct xfs_mount		*mp = tp->t_mountp;
 	struct xfs_bmap_intent		*bi;
 
 	trace_xfs_bmap_defer(mp,
@@ -6004,38 +5999,34 @@ __xfs_bmap_add(
 	bi->bi_whichfork = whichfork;
 	bi->bi_bmap = *bmap;
 
-	xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_BMAP, &bi->bi_list);
+	xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_BMAP, &bi->bi_list);
 	return 0;
 }
 
 /* Map an extent into a file. */
 int
 xfs_bmap_map_extent(
-	struct xfs_mount	*mp,
-	struct xfs_defer_ops	*dfops,
+	struct xfs_trans	*tp,
 	struct xfs_inode	*ip,
 	struct xfs_bmbt_irec	*PREV)
 {
 	if (!xfs_bmap_is_update_needed(PREV))
 		return 0;
 
-	return __xfs_bmap_add(mp, dfops, XFS_BMAP_MAP, ip,
-			XFS_DATA_FORK, PREV);
+	return __xfs_bmap_add(tp, XFS_BMAP_MAP, ip, XFS_DATA_FORK, PREV);
 }
 
 /* Unmap an extent out of a file. */
 int
 xfs_bmap_unmap_extent(
-	struct xfs_mount	*mp,
-	struct xfs_defer_ops	*dfops,
+	struct xfs_trans	*tp,
 	struct xfs_inode	*ip,
 	struct xfs_bmbt_irec	*PREV)
 {
 	if (!xfs_bmap_is_update_needed(PREV))
 		return 0;
 
-	return __xfs_bmap_add(mp, dfops, XFS_BMAP_UNMAP, ip,
-			XFS_DATA_FORK, PREV);
+	return __xfs_bmap_add(tp, XFS_BMAP_UNMAP, ip, XFS_DATA_FORK, PREV);
 }
 
 /*
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index 9165a878edcd..b6e9b639e731 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -184,9 +184,9 @@ void	xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno,
 void	xfs_trim_extent_eof(struct xfs_bmbt_irec *, struct xfs_inode *);
 int	xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
 void	xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
-void	__xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
-			  xfs_fsblock_t bno, xfs_filblks_t len,
-			  struct xfs_owner_info *oinfo, bool skip_discard);
+void	__xfs_bmap_add_free(struct xfs_trans *tp, xfs_fsblock_t bno,
+		xfs_filblks_t len, struct xfs_owner_info *oinfo,
+		bool skip_discard);
 void	xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork);
 int	xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip,
 		xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork);
@@ -230,13 +230,12 @@ int	xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork,
 
 static inline void
 xfs_bmap_add_free(
-	struct xfs_mount		*mp,
-	struct xfs_defer_ops		*dfops,
+	struct xfs_trans		*tp,
 	xfs_fsblock_t			bno,
 	xfs_filblks_t			len,
 	struct xfs_owner_info		*oinfo)
 {
-	__xfs_bmap_add_free(mp, dfops, bno, len, oinfo, false);
+	__xfs_bmap_add_free(tp, bno, len, oinfo, false);
 }
 
 enum xfs_bmap_intent_type {
@@ -256,10 +255,10 @@ int	xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_inode *ip,
 		enum xfs_bmap_intent_type type, int whichfork,
 		xfs_fileoff_t startoff, xfs_fsblock_t startblock,
 		xfs_filblks_t *blockcount, xfs_exntst_t state);
-int	xfs_bmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
-		struct xfs_inode *ip, struct xfs_bmbt_irec *imap);
-int	xfs_bmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
-		struct xfs_inode *ip, struct xfs_bmbt_irec *imap);
+int	xfs_bmap_map_extent(struct xfs_trans *tp, struct xfs_inode *ip,
+		struct xfs_bmbt_irec *imap);
+int	xfs_bmap_unmap_extent(struct xfs_trans *tp, struct xfs_inode *ip,
+		struct xfs_bmbt_irec *imap);
 
 static inline int xfs_bmap_fork_to_state(int whichfork)
 {
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index 955e29de8cae..cdb74d2e2a43 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -289,7 +289,7 @@ xfs_bmbt_free_block(
 	struct xfs_owner_info	oinfo;
 
 	xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_private.b.whichfork);
-	xfs_bmap_add_free(mp, cur->bc_tp->t_dfops, fsbno, 1, &oinfo);
+	xfs_bmap_add_free(cur->bc_tp, fsbno, 1, &oinfo);
 	ip->i_d.di_nblocks--;
 
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
index 6bf792e2d61b..152190a69432 100644
--- a/fs/xfs/libxfs/xfs_defer.c
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -493,10 +493,11 @@ xfs_defer_cancel(
 /* Add an item for later deferred processing. */
 void
 xfs_defer_add(
-	struct xfs_defer_ops		*dop,
+	struct xfs_trans		*tp,
 	enum xfs_defer_ops_type		type,
 	struct list_head		*li)
 {
+	struct xfs_defer_ops		*dop = tp->t_dfops;
 	struct xfs_defer_pending	*dfp = NULL;
 
 	/*
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
index 363af16328cb..295703737272 100644
--- a/fs/xfs/libxfs/xfs_defer.h
+++ b/fs/xfs/libxfs/xfs_defer.h
@@ -35,7 +35,7 @@ enum xfs_defer_ops_type {
 	XFS_DEFER_OPS_TYPE_MAX,
 };
 
-void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type,
+void xfs_defer_add(struct xfs_trans *tp, enum xfs_defer_ops_type type,
 		struct list_head *h);
 int xfs_defer_finish_noroll(struct xfs_trans **tp);
 int xfs_defer_finish(struct xfs_trans **tp);
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 295304ad1bc1..a8f6db735d5d 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -1838,23 +1838,24 @@ xfs_dialloc(
  */
 STATIC void
 xfs_difree_inode_chunk(
-	struct xfs_mount		*mp,
+	struct xfs_trans		*tp,
 	xfs_agnumber_t			agno,
-	struct xfs_inobt_rec_incore	*rec,
-	struct xfs_defer_ops		*dfops)
+	struct xfs_inobt_rec_incore	*rec)
 {
-	xfs_agblock_t	sagbno = XFS_AGINO_TO_AGBNO(mp, rec->ir_startino);
-	int		startidx, endidx;
-	int		nextbit;
-	xfs_agblock_t	agbno;
-	int		contigblk;
-	struct xfs_owner_info	oinfo;
+	struct xfs_mount		*mp = tp->t_mountp;
+	xfs_agblock_t			sagbno = XFS_AGINO_TO_AGBNO(mp,
+							rec->ir_startino);
+	int				startidx, endidx;
+	int				nextbit;
+	xfs_agblock_t			agbno;
+	int				contigblk;
+	struct xfs_owner_info		oinfo;
 	DECLARE_BITMAP(holemask, XFS_INOBT_HOLEMASK_BITS);
 	xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES);
 
 	if (!xfs_inobt_issparse(rec->ir_holemask)) {
 		/* not sparse, calculate extent info directly */
-		xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, sagbno),
+		xfs_bmap_add_free(tp, XFS_AGB_TO_FSB(mp, agno, sagbno),
 				  mp->m_ialloc_blks, &oinfo);
 		return;
 	}
@@ -1898,7 +1899,7 @@ xfs_difree_inode_chunk(
 
 		ASSERT(agbno % mp->m_sb.sb_spino_align == 0);
 		ASSERT(contigblk % mp->m_sb.sb_spino_align == 0);
-		xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, agbno),
+		xfs_bmap_add_free(tp, XFS_AGB_TO_FSB(mp, agno, agbno),
 				  contigblk, &oinfo);
 
 		/* reset range to current bit and carry on... */
@@ -2002,7 +2003,7 @@ xfs_difree_inobt(
 			goto error0;
 		}
 
-		xfs_difree_inode_chunk(mp, agno, &rec, tp->t_dfops);
+		xfs_difree_inode_chunk(tp, agno, &rec);
 	} else {
 		xic->deleted = false;
 
diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c
index 86f297ca90cd..c713c49200d3 100644
--- a/fs/xfs/libxfs/xfs_refcount.c
+++ b/fs/xfs/libxfs/xfs_refcount.c
@@ -34,11 +34,9 @@ enum xfs_refc_adjust_op {
 };
 
 STATIC int __xfs_refcount_cow_alloc(struct xfs_btree_cur *rcur,
-		xfs_agblock_t agbno, xfs_extlen_t aglen,
-		struct xfs_defer_ops *dfops);
+		xfs_agblock_t agbno, xfs_extlen_t aglen);
 STATIC int __xfs_refcount_cow_free(struct xfs_btree_cur *rcur,
-		xfs_agblock_t agbno, xfs_extlen_t aglen,
-		struct xfs_defer_ops *dfops);
+		xfs_agblock_t agbno, xfs_extlen_t aglen);
 
 /*
  * Look up the first record less than or equal to [bno, len] in the btree
@@ -870,7 +868,6 @@ xfs_refcount_adjust_extents(
 	xfs_agblock_t		*agbno,
 	xfs_extlen_t		*aglen,
 	enum xfs_refc_adjust_op	adj,
-	struct xfs_defer_ops	*dfops,
 	struct xfs_owner_info	*oinfo)
 {
 	struct xfs_refcount_irec	ext, tmp;
@@ -925,8 +922,8 @@ xfs_refcount_adjust_extents(
 				fsbno = XFS_AGB_TO_FSB(cur->bc_mp,
 						cur->bc_private.a.agno,
 						tmp.rc_startblock);
-				xfs_bmap_add_free(cur->bc_mp, dfops, fsbno,
-						tmp.rc_blockcount, oinfo);
+				xfs_bmap_add_free(cur->bc_tp, fsbno,
+						  tmp.rc_blockcount, oinfo);
 			}
 
 			(*agbno) += tmp.rc_blockcount;
@@ -968,8 +965,8 @@ xfs_refcount_adjust_extents(
 			fsbno = XFS_AGB_TO_FSB(cur->bc_mp,
 					cur->bc_private.a.agno,
 					ext.rc_startblock);
-			xfs_bmap_add_free(cur->bc_mp, dfops, fsbno,
-					ext.rc_blockcount, oinfo);
+			xfs_bmap_add_free(cur->bc_tp, fsbno, ext.rc_blockcount,
+					  oinfo);
 		}
 
 skip:
@@ -998,7 +995,6 @@ xfs_refcount_adjust(
 	xfs_agblock_t		*new_agbno,
 	xfs_extlen_t		*new_aglen,
 	enum xfs_refc_adjust_op	adj,
-	struct xfs_defer_ops	*dfops,
 	struct xfs_owner_info	*oinfo)
 {
 	bool			shape_changed;
@@ -1043,7 +1039,7 @@ xfs_refcount_adjust(
 
 	/* Now that we've taken care of the ends, adjust the middle extents */
 	error = xfs_refcount_adjust_extents(cur, new_agbno, new_aglen,
-			adj, dfops, oinfo);
+			adj, oinfo);
 	if (error)
 		goto out_error;
 
@@ -1090,7 +1086,6 @@ xfs_refcount_finish_one(
 	struct xfs_btree_cur		**pcur)
 {
 	struct xfs_mount		*mp = tp->t_mountp;
-	struct xfs_defer_ops		*dfops = tp->t_dfops;
 	struct xfs_btree_cur		*rcur;
 	struct xfs_buf			*agbp = NULL;
 	int				error = 0;
@@ -1145,23 +1140,23 @@ xfs_refcount_finish_one(
 	switch (type) {
 	case XFS_REFCOUNT_INCREASE:
 		error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno,
-			new_len, XFS_REFCOUNT_ADJUST_INCREASE, dfops, NULL);
+			new_len, XFS_REFCOUNT_ADJUST_INCREASE, NULL);
 		*new_fsb = XFS_AGB_TO_FSB(mp, agno, new_agbno);
 		break;
 	case XFS_REFCOUNT_DECREASE:
 		error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno,
-			new_len, XFS_REFCOUNT_ADJUST_DECREASE, dfops, NULL);
+			new_len, XFS_REFCOUNT_ADJUST_DECREASE, NULL);
 		*new_fsb = XFS_AGB_TO_FSB(mp, agno, new_agbno);
 		break;
 	case XFS_REFCOUNT_ALLOC_COW:
 		*new_fsb = startblock + blockcount;
 		*new_len = 0;
-		error = __xfs_refcount_cow_alloc(rcur, bno, blockcount, dfops);
+		error = __xfs_refcount_cow_alloc(rcur, bno, blockcount);
 		break;
 	case XFS_REFCOUNT_FREE_COW:
 		*new_fsb = startblock + blockcount;
 		*new_len = 0;
-		error = __xfs_refcount_cow_free(rcur, bno, blockcount, dfops);
+		error = __xfs_refcount_cow_free(rcur, bno, blockcount);
 		break;
 	default:
 		ASSERT(0);
@@ -1183,12 +1178,12 @@ xfs_refcount_finish_one(
  */
 static int
 __xfs_refcount_add(
-	struct xfs_mount		*mp,
-	struct xfs_defer_ops		*dfops,
+	struct xfs_trans		*tp,
 	enum xfs_refcount_intent_type	type,
 	xfs_fsblock_t			startblock,
 	xfs_extlen_t			blockcount)
 {
+	struct xfs_mount		*mp = tp->t_mountp;
 	struct xfs_refcount_intent	*ri;
 
 	trace_xfs_refcount_defer(mp, XFS_FSB_TO_AGNO(mp, startblock),
@@ -1202,7 +1197,7 @@ __xfs_refcount_add(
 	ri->ri_startblock = startblock;
 	ri->ri_blockcount = blockcount;
 
-	xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_REFCOUNT, &ri->ri_list);
+	xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_REFCOUNT, &ri->ri_list);
 	return 0;
 }
 
@@ -1211,14 +1206,13 @@ __xfs_refcount_add(
  */
 int
 xfs_refcount_increase_extent(
-	struct xfs_mount		*mp,
-	struct xfs_defer_ops		*dfops,
+	struct xfs_trans		*tp,
 	struct xfs_bmbt_irec		*PREV)
 {
-	if (!xfs_sb_version_hasreflink(&mp->m_sb))
+	if (!xfs_sb_version_hasreflink(&tp->t_mountp->m_sb))
 		return 0;
 
-	return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_INCREASE,
+	return __xfs_refcount_add(tp, XFS_REFCOUNT_INCREASE,
 			PREV->br_startblock, PREV->br_blockcount);
 }
 
@@ -1227,14 +1221,13 @@ xfs_refcount_increase_extent(
  */
 int
 xfs_refcount_decrease_extent(
-	struct xfs_mount		*mp,
-	struct xfs_defer_ops		*dfops,
+	struct xfs_trans		*tp,
 	struct xfs_bmbt_irec		*PREV)
 {
-	if (!xfs_sb_version_hasreflink(&mp->m_sb))
+	if (!xfs_sb_version_hasreflink(&tp->t_mountp->m_sb))
 		return 0;
 
-	return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_DECREASE,
+	return __xfs_refcount_add(tp, XFS_REFCOUNT_DECREASE,
 			PREV->br_startblock, PREV->br_blockcount);
 }
 
@@ -1522,8 +1515,7 @@ STATIC int
 __xfs_refcount_cow_alloc(
 	struct xfs_btree_cur	*rcur,
 	xfs_agblock_t		agbno,
-	xfs_extlen_t		aglen,
-	struct xfs_defer_ops	*dfops)
+	xfs_extlen_t		aglen)
 {
 	trace_xfs_refcount_cow_increase(rcur->bc_mp, rcur->bc_private.a.agno,
 			agbno, aglen);
@@ -1540,8 +1532,7 @@ STATIC int
 __xfs_refcount_cow_free(
 	struct xfs_btree_cur	*rcur,
 	xfs_agblock_t		agbno,
-	xfs_extlen_t		aglen,
-	struct xfs_defer_ops	*dfops)
+	xfs_extlen_t		aglen)
 {
 	trace_xfs_refcount_cow_decrease(rcur->bc_mp, rcur->bc_private.a.agno,
 			agbno, aglen);
@@ -1554,47 +1545,45 @@ __xfs_refcount_cow_free(
 /* Record a CoW staging extent in the refcount btree. */
 int
 xfs_refcount_alloc_cow_extent(
-	struct xfs_mount		*mp,
-	struct xfs_defer_ops		*dfops,
+	struct xfs_trans		*tp,
 	xfs_fsblock_t			fsb,
 	xfs_extlen_t			len)
 {
+	struct xfs_mount		*mp = tp->t_mountp;
 	int				error;
 
 	if (!xfs_sb_version_hasreflink(&mp->m_sb))
 		return 0;
 
-	error = __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_ALLOC_COW,
-			fsb, len);
+	error = __xfs_refcount_add(tp, XFS_REFCOUNT_ALLOC_COW, fsb, len);
 	if (error)
 		return error;
 
 	/* Add rmap entry */
-	return xfs_rmap_alloc_extent(mp, dfops, XFS_FSB_TO_AGNO(mp, fsb),
+	return xfs_rmap_alloc_extent(tp, XFS_FSB_TO_AGNO(mp, fsb),
 			XFS_FSB_TO_AGBNO(mp, fsb), len, XFS_RMAP_OWN_COW);
 }
 
 /* Forget a CoW staging event in the refcount btree. */
 int
 xfs_refcount_free_cow_extent(
-	struct xfs_mount		*mp,
-	struct xfs_defer_ops		*dfops,
+	struct xfs_trans		*tp,
 	xfs_fsblock_t			fsb,
 	xfs_extlen_t			len)
 {
+	struct xfs_mount		*mp = tp->t_mountp;
 	int				error;
 
 	if (!xfs_sb_version_hasreflink(&mp->m_sb))
 		return 0;
 
 	/* Remove rmap entry */
-	error = xfs_rmap_free_extent(mp, dfops, XFS_FSB_TO_AGNO(mp, fsb),
+	error = xfs_rmap_free_extent(tp, XFS_FSB_TO_AGNO(mp, fsb),
 			XFS_FSB_TO_AGBNO(mp, fsb), len, XFS_RMAP_OWN_COW);
 	if (error)
 		return error;
 
-	return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_FREE_COW,
-			fsb, len);
+	return __xfs_refcount_add(tp, XFS_REFCOUNT_FREE_COW, fsb, len);
 }
 
 struct xfs_refcount_recovery {
@@ -1692,14 +1681,13 @@ xfs_refcount_recover_cow_leftovers(
 		/* Free the orphan record */
 		agbno = rr->rr_rrec.rc_startblock - XFS_REFC_COW_START;
 		fsb = XFS_AGB_TO_FSB(mp, agno, agbno);
-		error = xfs_refcount_free_cow_extent(mp, tp->t_dfops, fsb,
+		error = xfs_refcount_free_cow_extent(tp, fsb,
 				rr->rr_rrec.rc_blockcount);
 		if (error)
 			goto out_trans;
 
 		/* Free the block. */
-		xfs_bmap_add_free(mp, tp->t_dfops, fsb,
-				rr->rr_rrec.rc_blockcount, NULL);
+		xfs_bmap_add_free(tp, fsb, rr->rr_rrec.rc_blockcount, NULL);
 
 		error = xfs_trans_commit(tp);
 		if (error)
diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h
index 3b72c6dbf6ad..1d9c518575e7 100644
--- a/fs/xfs/libxfs/xfs_refcount.h
+++ b/fs/xfs/libxfs/xfs_refcount.h
@@ -29,10 +29,10 @@ struct xfs_refcount_intent {
 	xfs_extlen_t				ri_blockcount;
 };
 
-extern int xfs_refcount_increase_extent(struct xfs_mount *mp,
-		struct xfs_defer_ops *dfops, struct xfs_bmbt_irec *irec);
-extern int xfs_refcount_decrease_extent(struct xfs_mount *mp,
-		struct xfs_defer_ops *dfops, struct xfs_bmbt_irec *irec);
+extern int xfs_refcount_increase_extent(struct xfs_trans *tp,
+		struct xfs_bmbt_irec *irec);
+extern int xfs_refcount_decrease_extent(struct xfs_trans *tp,
+		struct xfs_bmbt_irec *irec);
 
 extern void xfs_refcount_finish_one_cleanup(struct xfs_trans *tp,
 		struct xfs_btree_cur *rcur, int error);
@@ -45,12 +45,10 @@ extern int xfs_refcount_find_shared(struct xfs_btree_cur *cur,
 		xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno,
 		xfs_extlen_t *flen, bool find_end_of_shared);
 
-extern int xfs_refcount_alloc_cow_extent(struct xfs_mount *mp,
-		struct xfs_defer_ops *dfops, xfs_fsblock_t fsb,
-		xfs_extlen_t len);
-extern int xfs_refcount_free_cow_extent(struct xfs_mount *mp,
-		struct xfs_defer_ops *dfops, xfs_fsblock_t fsb,
-		xfs_extlen_t len);
+extern int xfs_refcount_alloc_cow_extent(struct xfs_trans *tp,
+		xfs_fsblock_t fsb, xfs_extlen_t len);
+extern int xfs_refcount_free_cow_extent(struct xfs_trans *tp,
+		xfs_fsblock_t fsb, xfs_extlen_t len);
 extern int xfs_refcount_recover_cow_leftovers(struct xfs_mount *mp,
 		xfs_agnumber_t agno);
 
diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
index fb266fa2cc45..aa683eda6b70 100644
--- a/fs/xfs/libxfs/xfs_rmap.c
+++ b/fs/xfs/libxfs/xfs_rmap.c
@@ -2277,14 +2277,14 @@ xfs_rmap_update_is_needed(
  */
 static int
 __xfs_rmap_add(
-	struct xfs_mount		*mp,
-	struct xfs_defer_ops		*dfops,
+	struct xfs_trans		*tp,
 	enum xfs_rmap_intent_type	type,
 	uint64_t			owner,
 	int				whichfork,
 	struct xfs_bmbt_irec		*bmap)
 {
-	struct xfs_rmap_intent	*ri;
+	struct xfs_mount		*mp = tp->t_mountp;
+	struct xfs_rmap_intent		*ri;
 
 	trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
 			type,
@@ -2301,23 +2301,22 @@ __xfs_rmap_add(
 	ri->ri_whichfork = whichfork;
 	ri->ri_bmap = *bmap;
 
-	xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
+	xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
 	return 0;
 }
 
 /* Map an extent into a file. */
 int
 xfs_rmap_map_extent(
-	struct xfs_mount	*mp,
-	struct xfs_defer_ops	*dfops,
+	struct xfs_trans	*tp,
 	struct xfs_inode	*ip,
 	int			whichfork,
 	struct xfs_bmbt_irec	*PREV)
 {
-	if (!xfs_rmap_update_is_needed(mp, whichfork))
+	if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
 		return 0;
 
-	return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
+	return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
 			XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
 			whichfork, PREV);
 }
@@ -2325,25 +2324,29 @@ xfs_rmap_map_extent(
 /* Unmap an extent out of a file. */
 int
 xfs_rmap_unmap_extent(
-	struct xfs_mount	*mp,
-	struct xfs_defer_ops	*dfops,
+	struct xfs_trans	*tp,
 	struct xfs_inode	*ip,
 	int			whichfork,
 	struct xfs_bmbt_irec	*PREV)
 {
-	if (!xfs_rmap_update_is_needed(mp, whichfork))
+	if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
 		return 0;
 
-	return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
+	return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
 			XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
 			whichfork, PREV);
 }
 
-/* Convert a data fork extent from unwritten to real or vice versa. */
+/*
+ * Convert a data fork extent from unwritten to real or vice versa.
+ *
+ * Note that tp can be NULL here as no transaction is used for COW fork
+ * unwritten conversion.
+ */
 int
 xfs_rmap_convert_extent(
 	struct xfs_mount	*mp,
-	struct xfs_defer_ops	*dfops,
+	struct xfs_trans	*tp,
 	struct xfs_inode	*ip,
 	int			whichfork,
 	struct xfs_bmbt_irec	*PREV)
@@ -2351,7 +2354,7 @@ xfs_rmap_convert_extent(
 	if (!xfs_rmap_update_is_needed(mp, whichfork))
 		return 0;
 
-	return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
+	return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
 			XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
 			whichfork, PREV);
 }
@@ -2359,8 +2362,7 @@ xfs_rmap_convert_extent(
 /* Schedule the creation of an rmap for non-file data. */
 int
 xfs_rmap_alloc_extent(
-	struct xfs_mount	*mp,
-	struct xfs_defer_ops	*dfops,
+	struct xfs_trans	*tp,
 	xfs_agnumber_t		agno,
 	xfs_agblock_t		bno,
 	xfs_extlen_t		len,
@@ -2368,23 +2370,21 @@ xfs_rmap_alloc_extent(
 {
 	struct xfs_bmbt_irec	bmap;
 
-	if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
+	if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
 		return 0;
 
-	bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
+	bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
 	bmap.br_blockcount = len;
 	bmap.br_startoff = 0;
 	bmap.br_state = XFS_EXT_NORM;
 
-	return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner,
-			XFS_DATA_FORK, &bmap);
+	return __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
 }
 
 /* Schedule the deletion of an rmap for non-file data. */
 int
 xfs_rmap_free_extent(
-	struct xfs_mount	*mp,
-	struct xfs_defer_ops	*dfops,
+	struct xfs_trans	*tp,
 	xfs_agnumber_t		agno,
 	xfs_agblock_t		bno,
 	xfs_extlen_t		len,
@@ -2392,16 +2392,15 @@ xfs_rmap_free_extent(
 {
 	struct xfs_bmbt_irec	bmap;
 
-	if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
+	if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
 		return 0;
 
-	bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
+	bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
 	bmap.br_blockcount = len;
 	bmap.br_startoff = 0;
 	bmap.br_state = XFS_EXT_NORM;
 
-	return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner,
-			XFS_DATA_FORK, &bmap);
+	return __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
 }
 
 /* Compare rmap records.  Returns -1 if a < b, 1 if a > b, and 0 if equal. */
diff --git a/fs/xfs/libxfs/xfs_rmap.h b/fs/xfs/libxfs/xfs_rmap.h
index 9f19454768b2..157dc722ad35 100644
--- a/fs/xfs/libxfs/xfs_rmap.h
+++ b/fs/xfs/libxfs/xfs_rmap.h
@@ -185,21 +185,17 @@ struct xfs_rmap_intent {
 };
 
 /* functions for updating the rmapbt based on bmbt map/unmap operations */
-int xfs_rmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
+int xfs_rmap_map_extent(struct xfs_trans *tp, struct xfs_inode *ip,
+		int whichfork, struct xfs_bmbt_irec *imap);
+int xfs_rmap_unmap_extent(struct xfs_trans *tp, struct xfs_inode *ip,
+		int whichfork, struct xfs_bmbt_irec *imap);
+int xfs_rmap_convert_extent(struct xfs_mount *mp, struct xfs_trans *tp,
 		struct xfs_inode *ip, int whichfork,
 		struct xfs_bmbt_irec *imap);
-int xfs_rmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
-		struct xfs_inode *ip, int whichfork,
-		struct xfs_bmbt_irec *imap);
-int xfs_rmap_convert_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
-		struct xfs_inode *ip, int whichfork,
-		struct xfs_bmbt_irec *imap);
-int xfs_rmap_alloc_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
-		xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
-		uint64_t owner);
-int xfs_rmap_free_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
-		xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
-		uint64_t owner);
+int xfs_rmap_alloc_extent(struct xfs_trans *tp, xfs_agnumber_t agno,
+		xfs_agblock_t bno, xfs_extlen_t len, uint64_t owner);
+int xfs_rmap_free_extent(struct xfs_trans *tp, xfs_agnumber_t agno,
+		xfs_agblock_t bno, xfs_extlen_t len, uint64_t owner);
 
 void xfs_rmap_finish_one_cleanup(struct xfs_trans *tp,
 		struct xfs_btree_cur *rcur, int error);
diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
index 328a5c60000b..ffe42147a032 100644
--- a/fs/xfs/xfs_bmap_item.c
+++ b/fs/xfs/xfs_bmap_item.c
@@ -486,8 +486,7 @@ xfs_bui_recover(
 		irec.br_blockcount = count;
 		irec.br_startoff = bmap->me_startoff;
 		irec.br_state = state;
-		error = xfs_bmap_unmap_extent(tp->t_mountp, tp->t_dfops, ip,
-					      &irec);
+		error = xfs_bmap_unmap_extent(tp, ip, &irec);
 		if (error)
 			goto err_inode;
 	}
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index d9dad399440a..addbd74ecd8e 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1534,7 +1534,6 @@ xfs_swap_extent_rmap(
 	struct xfs_inode		*tip)
 {
 	struct xfs_trans		*tp = *tpp;
-	struct xfs_mount		*mp = tp->t_mountp;
 	struct xfs_bmbt_irec		irec;
 	struct xfs_bmbt_irec		uirec;
 	struct xfs_bmbt_irec		tirec;
@@ -1598,26 +1597,22 @@ xfs_swap_extent_rmap(
 			trace_xfs_swap_extent_rmap_remap_piece(tip, &uirec);
 
 			/* Remove the mapping from the donor file. */
-			error = xfs_bmap_unmap_extent(mp, tp->t_dfops, tip,
-					&uirec);
+			error = xfs_bmap_unmap_extent(tp, tip, &uirec);
 			if (error)
 				goto out_defer;
 
 			/* Remove the mapping from the source file. */
-			error = xfs_bmap_unmap_extent(mp, tp->t_dfops, ip,
-					&irec);
+			error = xfs_bmap_unmap_extent(tp, ip, &irec);
 			if (error)
 				goto out_defer;
 
 			/* Map the donor file's blocks into the source file. */
-			error = xfs_bmap_map_extent(mp, tp->t_dfops, ip,
-					&uirec);
+			error = xfs_bmap_map_extent(tp, ip, &uirec);
 			if (error)
 				goto out_defer;
 
 			/* Map the source file's blocks into the donor file. */
-			error = xfs_bmap_map_extent(mp, tp->t_dfops, tip,
-					&irec);
+			error = xfs_bmap_map_extent(tp, tip, &irec);
 			if (error)
 				goto out_defer;
 
diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
index f6a3249aa2d4..c626fc5d3464 100644
--- a/fs/xfs/xfs_refcount_item.c
+++ b/fs/xfs/xfs_refcount_item.c
@@ -490,24 +490,18 @@ xfs_cui_recover(
 			irec.br_blockcount = new_len;
 			switch (type) {
 			case XFS_REFCOUNT_INCREASE:
-				error = xfs_refcount_increase_extent(
-						tp->t_mountp, tp->t_dfops,
-						&irec);
+				error = xfs_refcount_increase_extent(tp, &irec);
 				break;
 			case XFS_REFCOUNT_DECREASE:
-				error = xfs_refcount_decrease_extent(
-						tp->t_mountp, tp->t_dfops,
-						&irec);
+				error = xfs_refcount_decrease_extent(tp, &irec);
 				break;
 			case XFS_REFCOUNT_ALLOC_COW:
-				error = xfs_refcount_alloc_cow_extent(
-						tp->t_mountp, tp->t_dfops,
+				error = xfs_refcount_alloc_cow_extent(tp,
 						irec.br_startblock,
 						irec.br_blockcount);
 				break;
 			case XFS_REFCOUNT_FREE_COW:
-				error = xfs_refcount_free_cow_extent(
-						tp->t_mountp, tp->t_dfops,
+				error = xfs_refcount_free_cow_extent(tp,
 						irec.br_startblock,
 						irec.br_blockcount);
 				break;
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index 2ec562d75494..cbceb320a2e7 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -506,15 +506,13 @@ xfs_reflink_cancel_cow_blocks(
 			ASSERT((*tpp)->t_firstblock == NULLFSBLOCK);
 
 			/* Free the CoW orphan record. */
-			error = xfs_refcount_free_cow_extent(ip->i_mount,
-					(*tpp)->t_dfops, del.br_startblock,
-					del.br_blockcount);
+			error = xfs_refcount_free_cow_extent(*tpp,
+					del.br_startblock, del.br_blockcount);
 			if (error)
 				break;
 
-			xfs_bmap_add_free(ip->i_mount, (*tpp)->t_dfops,
-					del.br_startblock, del.br_blockcount,
-					NULL);
+			xfs_bmap_add_free(*tpp, del.br_startblock,
+					  del.br_blockcount, NULL);
 
 			/* Roll the transaction */
 			error = xfs_defer_finish(tpp);
@@ -694,14 +692,13 @@ xfs_reflink_end_cow(
 		trace_xfs_reflink_cow_remap(ip, &del);
 
 		/* Free the CoW orphan record. */
-		error = xfs_refcount_free_cow_extent(tp->t_mountp, tp->t_dfops,
-				del.br_startblock, del.br_blockcount);
+		error = xfs_refcount_free_cow_extent(tp, del.br_startblock,
+				del.br_blockcount);
 		if (error)
 			goto out_cancel;
 
 		/* Map the new blocks into the data fork. */
-		error = xfs_bmap_map_extent(tp->t_mountp, tp->t_dfops, ip,
-					    &del);
+		error = xfs_bmap_map_extent(tp, ip, &del);
 		if (error)
 			goto out_cancel;
 
@@ -1046,12 +1043,12 @@ xfs_reflink_remap_extent(
 				uirec.br_blockcount, uirec.br_startblock);
 
 		/* Update the refcount tree */
-		error = xfs_refcount_increase_extent(mp, tp->t_dfops, &uirec);
+		error = xfs_refcount_increase_extent(tp, &uirec);
 		if (error)
 			goto out_cancel;
 
 		/* Map the new blocks into the data fork. */
-		error = xfs_bmap_map_extent(mp, tp->t_dfops, ip, &uirec);
+		error = xfs_bmap_map_extent(tp, ip, &uirec);
 		if (error)
 			goto out_cancel;
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 14/15] xfs: always defer agfl block frees
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
                   ` (12 preceding siblings ...)
  2018-07-30 16:45 ` [PATCH 13/15] xfs: pass transaction to xfs_defer_add() Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 20:49   ` Darrick J. Wong
  2018-07-31  8:32   ` Christoph Hellwig
  2018-07-30 16:45 ` [PATCH 15/15] xfs: fold dfops into the transaction Brian Foster
  14 siblings, 2 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

The AGFL fixup code conditionally defers block frees from the free
list based on whether the current transaction has an associated
xfs_defer_ops structure. Now that dfops is embedded in the
transaction and the internal dfops is used unconditionally, this
invariant is always true.

Remove the now dead logic to check for ->t_dfops in
xfs_alloc_fix_freelist() and unconditionally defer AGFL block frees.

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/libxfs/xfs_alloc.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 6bacdc31a439..32a370665d71 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -2323,15 +2323,8 @@ xfs_alloc_fix_freelist(
 		if (error)
 			goto out_agbp_relse;
 
-		/* defer agfl frees if dfops is provided */
-		if (tp->t_dfops) {
-			xfs_defer_agfl_block(tp, args->agno, bno, &targs.oinfo);
-		} else {
-			error = xfs_free_agfl_block(tp, args->agno, bno, agbp,
-						    &targs.oinfo);
-			if (error)
-				goto out_agbp_relse;
-		}
+		/* defer agfl frees */
+		xfs_defer_agfl_block(tp, args->agno, bno, &targs.oinfo);
 	}
 
 	targs.tp = tp;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 15/15] xfs: fold dfops into the transaction
  2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
                   ` (13 preceding siblings ...)
  2018-07-30 16:45 ` [PATCH 14/15] xfs: always defer agfl block frees Brian Foster
@ 2018-07-30 16:45 ` Brian Foster
  2018-07-30 20:51   ` Darrick J. Wong
  2018-07-31  8:36   ` Christoph Hellwig
  14 siblings, 2 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-30 16:45 UTC (permalink / raw)
  To: linux-xfs

struct xfs_defer_ops has now been reduced to a single list_head. The
external dfops mechanism is unused and thus everywhere a (permanent)
transaction is accessible the associated dfops structure is as well.

Remove the xfs_defer_ops structure and fold the list_head into the
transaction. Also remove the last remnant of external dfops in
xfs_trans_dup().

Signed-off-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/libxfs/xfs_bmap.c     |  1 -
 fs/xfs/libxfs/xfs_btree.h    |  1 -
 fs/xfs/libxfs/xfs_da_btree.h |  1 -
 fs/xfs/libxfs/xfs_defer.c    | 65 +++++++++++-------------------------
 fs/xfs/libxfs/xfs_defer.h    |  2 --
 fs/xfs/libxfs/xfs_dir2.c     |  2 --
 fs/xfs/libxfs/xfs_dir2.h     |  1 -
 fs/xfs/xfs_inode.h           |  1 -
 fs/xfs/xfs_reflink.c         |  5 ++-
 fs/xfs/xfs_trace.h           | 33 +++++++++---------
 fs/xfs/xfs_trans.c           | 11 +++---
 fs/xfs/xfs_trans.h           |  8 ++---
 12 files changed, 43 insertions(+), 88 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index f5f1fc47923e..0f9f522ab792 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -4285,7 +4285,6 @@ xfs_bmapi_write(
 	bma.ip = ip;
 	bma.total = total;
 	bma.datatype = 0;
-	ASSERT(!tp || tp->t_dfops);
 
 	while (bno < end && n < *nmap) {
 		bool			need_alloc = false, wasdelay = false;
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index 503615f4d729..e3b3e9dce5da 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -7,7 +7,6 @@
 #define	__XFS_BTREE_H__
 
 struct xfs_buf;
-struct xfs_defer_ops;
 struct xfs_inode;
 struct xfs_mount;
 struct xfs_trans;
diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h
index 59e290ef334f..84dd865b6c3d 100644
--- a/fs/xfs/libxfs/xfs_da_btree.h
+++ b/fs/xfs/libxfs/xfs_da_btree.h
@@ -7,7 +7,6 @@
 #ifndef __XFS_DA_BTREE_H__
 #define	__XFS_DA_BTREE_H__
 
-struct xfs_defer_ops;
 struct xfs_inode;
 struct xfs_trans;
 struct zone;
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
index 152190a69432..9ce9e1c75e23 100644
--- a/fs/xfs/libxfs/xfs_defer.c
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -186,11 +186,10 @@ xfs_defer_intake_work(
 	struct xfs_trans		*tp,
 	struct list_head		*dop_pending)
 {
-	struct xfs_defer_ops		*dop = tp->t_dfops;
 	struct list_head		*li;
 	struct xfs_defer_pending	*dfp;
 
-	list_for_each_entry(dfp, &dop->dop_intake, dfp_list) {
+	list_for_each_entry(dfp, &tp->t_dfops, dfp_list) {
 		dfp->dfp_intent = dfp->dfp_type->create_intent(tp,
 				dfp->dfp_count);
 		trace_xfs_defer_intake_work(tp->t_mountp, dfp);
@@ -200,7 +199,7 @@ xfs_defer_intake_work(
 			dfp->dfp_type->log_item(tp, dfp->dfp_intent, li);
 	}
 
-	list_splice_tail_init(&dop->dop_intake, dop_pending);
+	list_splice_tail_init(&tp->t_dfops, dop_pending);
 }
 
 /* Abort all the intents that were committed. */
@@ -210,10 +209,9 @@ xfs_defer_trans_abort(
 	struct list_head		*dop_pending,
 	int				error)
 {
-	struct xfs_defer_ops		*dop = tp->t_dfops;
 	struct xfs_defer_pending	*dfp;
 
-	trace_xfs_defer_trans_abort(tp->t_mountp, dop, _RET_IP_);
+	trace_xfs_defer_trans_abort(tp->t_mountp, tp, _RET_IP_);
 
 	/* Abort intent items that don't have a done item. */
 	if (dop_pending) {
@@ -272,13 +270,12 @@ xfs_defer_trans_roll(
 		}
 	}
 
-	trace_xfs_defer_trans_roll((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_);
+	trace_xfs_defer_trans_roll((*tp)->t_mountp, *tp, _RET_IP_);
 
 	/* Roll the transaction. */
 	error = xfs_trans_roll(tp);
 	if (error) {
-		trace_xfs_defer_trans_roll_error((*tp)->t_mountp,
-						 (*tp)->t_dfops, error);
+		trace_xfs_defer_trans_roll_error((*tp)->t_mountp, *tp, error);
 		xfs_defer_trans_abort(*tp,  dop_pending, error);
 		return error;
 	}
@@ -303,7 +300,7 @@ xfs_defer_has_unfinished_work(
 	struct list_head		*dop_pending)
 {
 	return !list_empty(dop_pending) ||
-		!list_empty(&tp->t_dfops->dop_intake);
+		!list_empty(&tp->t_dfops);
 }
 
 /*
@@ -313,7 +310,7 @@ static void
 xfs_defer_reset(
 	struct xfs_trans	*tp)
 {
-	ASSERT(list_empty(&tp->t_dfops->dop_intake));
+	ASSERT(list_empty(&tp->t_dfops));
 
 	/*
 	 * Low mode state transfers across transaction rolls to mirror dfops
@@ -344,7 +341,7 @@ xfs_defer_finish_noroll(
 
 	ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
 
-	trace_xfs_defer_finish((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_);
+	trace_xfs_defer_finish((*tp)->t_mountp, *tp, _RET_IP_);
 
 	/* Until we run out of pending work to finish... */
 	while (xfs_defer_has_unfinished_work(*tp, &dop_pending)) {
@@ -420,14 +417,13 @@ xfs_defer_finish_noroll(
 
 out:
 	if (error) {
-		trace_xfs_defer_finish_error((*tp)->t_mountp, (*tp)->t_dfops,
-					     error);
+		trace_xfs_defer_finish_error((*tp)->t_mountp, *tp, error);
 		__xfs_defer_cancel(&dop_pending);
 		xfs_defer_cancel(*tp);
 		return error;
 	}
 
-	trace_xfs_defer_finish_done((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_);
+	trace_xfs_defer_finish_done((*tp)->t_mountp, *tp, _RET_IP_);
 	return 0;
 }
 
@@ -486,8 +482,8 @@ void
 xfs_defer_cancel(
 	struct xfs_trans	*tp)
 {
-	trace_xfs_defer_cancel(NULL, tp->t_dfops, _RET_IP_);
-	__xfs_defer_cancel(&tp->t_dfops->dop_intake);
+	trace_xfs_defer_cancel(NULL, tp, _RET_IP_);
+	__xfs_defer_cancel(&tp->t_dfops);
 }
 
 /* Add an item for later deferred processing. */
@@ -497,7 +493,6 @@ xfs_defer_add(
 	enum xfs_defer_ops_type		type,
 	struct list_head		*li)
 {
-	struct xfs_defer_ops		*dop = tp->t_dfops;
 	struct xfs_defer_pending	*dfp = NULL;
 
 	/*
@@ -505,8 +500,8 @@ xfs_defer_add(
 	 * If the last pending item has the same type, reuse it.  Else,
 	 * create a new pending item at the end of the intake list.
 	 */
-	if (!list_empty(&dop->dop_intake)) {
-		dfp = list_last_entry(&dop->dop_intake,
+	if (!list_empty(&tp->t_dfops)) {
+		dfp = list_last_entry(&tp->t_dfops,
 				struct xfs_defer_pending, dfp_list);
 		if (dfp->dfp_type->type != type ||
 		    (dfp->dfp_type->max_items &&
@@ -521,7 +516,7 @@ xfs_defer_add(
 		dfp->dfp_done = NULL;
 		dfp->dfp_count = 0;
 		INIT_LIST_HEAD(&dfp->dfp_work);
-		list_add_tail(&dfp->dfp_list, &dop->dop_intake);
+		list_add_tail(&dfp->dfp_list, &tp->t_dfops);
 	}
 
 	list_add_tail(li, &dfp->dfp_work);
@@ -536,39 +531,17 @@ xfs_defer_init_op_type(
 	defer_op_types[type->type] = type;
 }
 
-/* Initialize a deferred operation. */
-void
-xfs_defer_init(
-	struct xfs_trans		*tp,
-	struct xfs_defer_ops		*dop)
-{
-	struct xfs_mount		*mp = NULL;
-
-	memset(dop, 0, sizeof(struct xfs_defer_ops));
-	INIT_LIST_HEAD(&dop->dop_intake);
-	if (tp) {
-		ASSERT(tp->t_firstblock == NULLFSBLOCK);
-		tp->t_dfops = dop;
-		mp = tp->t_mountp;
-	}
-	trace_xfs_defer_init(mp, dop, _RET_IP_);
-}
-
 /*
- * Move state from one xfs_defer_ops to another and reset the source to initial
- * state. This is primarily used to carry state forward across transaction rolls
- * with internal dfops.
+ * Move deferred ops from one transaction to another and reset the source to
+ * initial state. This is primarily used to carry state forward across
+ * transaction rolls with pending dfops.
  */
 void
 xfs_defer_move(
 	struct xfs_trans	*dtp,
 	struct xfs_trans	*stp)
 {
-	struct xfs_defer_ops	*dst = dtp->t_dfops;
-	struct xfs_defer_ops	*src = stp->t_dfops;
-	ASSERT(dst != src);
-
-	list_splice_init(&src->dop_intake, &dst->dop_intake);
+	list_splice_init(&stp->t_dfops, &dtp->t_dfops);
 
 	/*
 	 * Low free space mode was historically controlled by a dfops field.
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
index 295703737272..9ea37a8c464a 100644
--- a/fs/xfs/libxfs/xfs_defer.h
+++ b/fs/xfs/libxfs/xfs_defer.h
@@ -7,7 +7,6 @@
 #define	__XFS_DEFER_H__
 
 struct xfs_defer_op_type;
-struct xfs_defer_ops;
 
 /*
  * Save a log intent item and a list of extents, so that we can replay
@@ -40,7 +39,6 @@ void xfs_defer_add(struct xfs_trans *tp, enum xfs_defer_ops_type type,
 int xfs_defer_finish_noroll(struct xfs_trans **tp);
 int xfs_defer_finish(struct xfs_trans **tp);
 void xfs_defer_cancel(struct xfs_trans *);
-void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
 bool xfs_defer_has_unfinished_work(struct xfs_trans *tp,
 		struct list_head *dop_pending);
 void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c
index 4ea1fddb126f..229152cd1a24 100644
--- a/fs/xfs/libxfs/xfs_dir2.c
+++ b/fs/xfs/libxfs/xfs_dir2.c
@@ -424,7 +424,6 @@ xfs_dir_removename(
 	int			v;		/* type-checking value */
 
 	ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
-	ASSERT(tp->t_dfops);
 	XFS_STATS_INC(dp->i_mount, xs_dir_remove);
 
 	args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
@@ -483,7 +482,6 @@ xfs_dir_replace(
 	int			v;		/* type-checking value */
 
 	ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
-	ASSERT(tp->t_dfops);
 
 	rval = xfs_dir_ino_validate(tp->t_mountp, inum);
 	if (rval)
diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h
index ba5acd03de94..c3e3f6b813d8 100644
--- a/fs/xfs/libxfs/xfs_dir2.h
+++ b/fs/xfs/libxfs/xfs_dir2.h
@@ -9,7 +9,6 @@
 #include "xfs_da_format.h"
 #include "xfs_da_btree.h"
 
-struct xfs_defer_ops;
 struct xfs_da_args;
 struct xfs_inode;
 struct xfs_mount;
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 79a3e61a6991..be2014520155 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -15,7 +15,6 @@
 struct xfs_dinode;
 struct xfs_inode;
 struct xfs_buf;
-struct xfs_defer_ops;
 struct xfs_bmbt_irec;
 struct xfs_inode_log_item;
 struct xfs_mount;
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index cbceb320a2e7..38f405415b88 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -502,7 +502,6 @@ xfs_reflink_cancel_cow_blocks(
 			if (error)
 				break;
 		} else if (del.br_state == XFS_EXT_UNWRITTEN || cancel_real) {
-			ASSERT((*tpp)->t_dfops);
 			ASSERT((*tpp)->t_firstblock == NULLFSBLOCK);
 
 			/* Free the CoW orphan record. */
@@ -678,7 +677,7 @@ xfs_reflink_end_cow(
 			goto prev_extent;
 
 		/* Unmap the old blocks in the data fork. */
-		ASSERT(tp->t_dfops && tp->t_firstblock == NULLFSBLOCK);
+		ASSERT(tp->t_firstblock == NULLFSBLOCK);
 		rlen = del.br_blockcount;
 		error = __xfs_bunmapi(tp, ip, del.br_startoff, &rlen, 0, 1);
 		if (error)
@@ -1021,7 +1020,7 @@ xfs_reflink_remap_extent(
 	/* Unmap the old blocks in the data fork. */
 	rlen = unmap_len;
 	while (rlen) {
-		ASSERT(tp->t_dfops && tp->t_firstblock == NULLFSBLOCK);
+		ASSERT(tp->t_firstblock == NULLFSBLOCK);
 		error = __xfs_bunmapi(tp, ip, destoff, &rlen, 0, 1);
 		if (error)
 			goto out_cancel;
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 6b55bbc09578..023c0445a231 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -2213,57 +2213,56 @@ DEFINE_BTREE_CUR_EVENT(xfs_btree_overlapped_query_range);
 
 /* deferred ops */
 struct xfs_defer_pending;
-struct xfs_defer_ops;
 
 DECLARE_EVENT_CLASS(xfs_defer_class,
-	TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop,
+	TP_PROTO(struct xfs_mount *mp, struct xfs_trans *tp,
 		 unsigned long caller_ip),
-	TP_ARGS(mp, dop, caller_ip),
+	TP_ARGS(mp, tp, caller_ip),
 	TP_STRUCT__entry(
 		__field(dev_t, dev)
-		__field(void *, dop)
+		__field(void *, tp)
 		__field(char, committed)
 		__field(unsigned long, caller_ip)
 	),
 	TP_fast_assign(
 		__entry->dev = mp ? mp->m_super->s_dev : 0;
-		__entry->dop = dop;
+		__entry->tp = tp;
 		__entry->caller_ip = caller_ip;
 	),
-	TP_printk("dev %d:%d ops %p caller %pS",
+	TP_printk("dev %d:%d tp %p caller %pS",
 		  MAJOR(__entry->dev), MINOR(__entry->dev),
-		  __entry->dop,
+		  __entry->tp,
 		  (char *)__entry->caller_ip)
 )
 #define DEFINE_DEFER_EVENT(name) \
 DEFINE_EVENT(xfs_defer_class, name, \
-	TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, \
+	TP_PROTO(struct xfs_mount *mp, struct xfs_trans *tp, \
 		 unsigned long caller_ip), \
-	TP_ARGS(mp, dop, caller_ip))
+	TP_ARGS(mp, tp, caller_ip))
 
 DECLARE_EVENT_CLASS(xfs_defer_error_class,
-	TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, int error),
-	TP_ARGS(mp, dop, error),
+	TP_PROTO(struct xfs_mount *mp, struct xfs_trans *tp, int error),
+	TP_ARGS(mp, tp, error),
 	TP_STRUCT__entry(
 		__field(dev_t, dev)
-		__field(void *, dop)
+		__field(void *, tp)
 		__field(char, committed)
 		__field(int, error)
 	),
 	TP_fast_assign(
 		__entry->dev = mp ? mp->m_super->s_dev : 0;
-		__entry->dop = dop;
+		__entry->tp = tp;
 		__entry->error = error;
 	),
-	TP_printk("dev %d:%d ops %p err %d",
+	TP_printk("dev %d:%d tp %p err %d",
 		  MAJOR(__entry->dev), MINOR(__entry->dev),
-		  __entry->dop,
+		  __entry->tp,
 		  __entry->error)
 )
 #define DEFINE_DEFER_ERROR_EVENT(name) \
 DEFINE_EVENT(xfs_defer_error_class, name, \
-	TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, int error), \
-	TP_ARGS(mp, dop, error))
+	TP_PROTO(struct xfs_mount *mp, struct xfs_trans *tp, int error), \
+	TP_ARGS(mp, tp, error))
 
 DECLARE_EVENT_CLASS(xfs_defer_pending_class,
 	TP_PROTO(struct xfs_mount *mp, struct xfs_defer_pending *dfp),
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 20750cd9c9e7..d4faa0414927 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -100,6 +100,7 @@ xfs_trans_dup(
 	ntp->t_mountp = tp->t_mountp;
 	INIT_LIST_HEAD(&ntp->t_items);
 	INIT_LIST_HEAD(&ntp->t_busy);
+	INIT_LIST_HEAD(&ntp->t_dfops);
 	ntp->t_firstblock = NULLFSBLOCK;
 
 	ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
@@ -120,12 +121,8 @@ xfs_trans_dup(
 	tp->t_rtx_res = tp->t_rtx_res_used;
 	ntp->t_pflags = tp->t_pflags;
 
-	/* copy the dfops pointer if it's external, otherwise move it */
-	xfs_defer_init(ntp, &ntp->t_dfops_internal);
-	if (tp->t_dfops != &tp->t_dfops_internal)
-		ntp->t_dfops = tp->t_dfops;
-	else
-		xfs_defer_move(ntp, tp);
+	/* move deferred ops over to the new tp */
+	xfs_defer_move(ntp, tp);
 
 	xfs_trans_dup_dqinfo(tp, ntp);
 
@@ -280,8 +277,8 @@ xfs_trans_alloc(
 	tp->t_mountp = mp;
 	INIT_LIST_HEAD(&tp->t_items);
 	INIT_LIST_HEAD(&tp->t_busy);
+	INIT_LIST_HEAD(&tp->t_dfops);
 	tp->t_firstblock = NULLFSBLOCK;
-	xfs_defer_init(tp, &tp->t_dfops_internal);
 
 	error = xfs_trans_reserve(tp, resp, blocks, rtextents);
 	if (error) {
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 1cdc7c0ebeac..c3d278e96ad1 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -90,13 +90,10 @@ void	xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item,
 #define XFS_ITEM_FLUSHING	3
 
 /*
- * Deferred operations tracking structure.
+ * Deferred operation item relogging limits.
  */
 #define XFS_DEFER_OPS_NR_INODES	2	/* join up to two inodes */
 #define XFS_DEFER_OPS_NR_BUFS	2	/* join up to two buffers */
-struct xfs_defer_ops {
-	struct list_head	dop_intake;	/* unlogged pending work */
-};
 
 /*
  * This is the structure maintained for every active transaction.
@@ -114,7 +111,6 @@ typedef struct xfs_trans {
 	struct xlog_ticket	*t_ticket;	/* log mgr ticket */
 	struct xfs_mount	*t_mountp;	/* ptr to fs mount struct */
 	struct xfs_dquot_acct   *t_dqinfo;	/* acctg info for dquots */
-	struct xfs_defer_ops	*t_dfops;	/* dfops reference */
 	int64_t			t_icount_delta;	/* superblock icount change */
 	int64_t			t_ifree_delta;	/* superblock ifree change */
 	int64_t			t_fdblocks_delta; /* superblock fdblocks chg */
@@ -136,8 +132,8 @@ typedef struct xfs_trans {
 	int64_t			t_rextslog_delta;/* superblocks rextslog chg */
 	struct list_head	t_items;	/* log item descriptors */
 	struct list_head	t_busy;		/* list of busy extents */
+	struct list_head	t_dfops;	/* deferred operations */
 	unsigned long		t_pflags;	/* saved process flags state */
-	struct xfs_defer_ops	t_dfops_internal;
 } xfs_trans_t;
 
 /*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH 01/15] xfs: refactor internal dfops initialization
  2018-07-30 16:45 ` [PATCH 01/15] xfs: refactor internal dfops initialization Brian Foster
@ 2018-07-30 19:30   ` Darrick J. Wong
  2018-07-31  8:10     ` Christoph Hellwig
  2018-07-31 11:47     ` Brian Foster
  0 siblings, 2 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 19:30 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:06PM -0400, Brian Foster wrote:
> The current transaction allocation code conditionally initializes
> the ->t_dfops indirection pointer. Transaction commit/cancel check
> the validity of the pointer to determine whether to finish/cancel
> the internal dfops.
> 
> This disallows the ability to use the internal dfops list as a
> temporary container (via xfs_trans_alloc_empty()). Refactor
> transaction allocation to always initialize ->t_dfops and check
> permanent reservation state on transaction commit/cancel.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>
> ---
>  fs/xfs/xfs_trans.c | 12 +++---------
>  1 file changed, 3 insertions(+), 9 deletions(-)
> 
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index 7bf5c1202719..8d3b7f28b193 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -281,13 +281,7 @@ xfs_trans_alloc(
>  	INIT_LIST_HEAD(&tp->t_items);
>  	INIT_LIST_HEAD(&tp->t_busy);
>  	tp->t_firstblock = NULLFSBLOCK;
> -	/*
> -	 * We only roll transactions with permanent log reservation. Don't init
> -	 * ->t_dfops to skip attempts to finish or cancel an empty dfops with a
> -	 * non-permanent res.
> -	 */
> -	if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES)
> -		xfs_defer_init(tp, &tp->t_dfops_internal);
> +	xfs_defer_init(tp, &tp->t_dfops_internal);
>  
>  	error = xfs_trans_reserve(tp, resp, blocks, rtextents);
>  	if (error) {
> @@ -932,7 +926,7 @@ __xfs_trans_commit(
>  	trace_xfs_trans_commit(tp, _RET_IP_);
>  
>  	/* finish deferred items on final commit */
> -	if (!regrant && tp->t_dfops) {
> +	if (!regrant && (tp->t_flags & XFS_TRANS_PERM_LOG_RES)) {

The usage model of deferred ops is that one has to create a transaction
with a permanent reservation, and only then start attaching deferred ops
to the dfops inside the transaction.  It's a programming error if a
caller tries to finish deferred ops using a non-permanent transaction,
and prior to this patch t_dfops would be NULL and we'd blow up
immediately in xfs_defer_add(..., tp->t_dfops, ...);

However, now that we initialize t_dfops unconditionally, won't this
cause the above programming mistake to leak silently any incorrectly
queued defer ops?

--D

>  		error = xfs_defer_finish_noroll(&tp);
>  		if (error) {
>  			xfs_defer_cancel(tp);
> @@ -1029,7 +1023,7 @@ xfs_trans_cancel(
>  
>  	trace_xfs_trans_cancel(tp, _RET_IP_);
>  
> -	if (tp->t_dfops)
> +	if (tp->t_flags & XFS_TRANS_PERM_LOG_RES)
>  		xfs_defer_cancel(tp);
>  
>  	/*
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 02/15] xfs: use transaction for intent recovery instead of raw dfops
  2018-07-30 16:45 ` [PATCH 02/15] xfs: use transaction for intent recovery instead of raw dfops Brian Foster
@ 2018-07-30 20:09   ` Darrick J. Wong
  2018-07-31  8:12     ` Christoph Hellwig
  2018-07-31 11:47     ` Brian Foster
  2018-07-31  8:13   ` Christoph Hellwig
  1 sibling, 2 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 20:09 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:07PM -0400, Brian Foster wrote:
> Log intent recovery is the last user of an external (on-stack)
> dfops. The pattern exists because the dfops is used to collect
> additional deferred operations queued during the whole recovery
> sequence. The dfops is finished with a new transaction after intent
> recovery completes.
> 
> We already have a mechanism to create an empty, container-like
> transaction to support the scrub infrastructure. We can reuse that
> mechanism here to drop the final user of external dfops. This
> facilitates folding dfops state (i.e., dop_low) into the
> transaction, the elimination of now unused external dfops support
> and also eliminates the only caller of __xfs_defer_cancel().
> 
> Replace the on-stack dfops with an empty transaction and pass it
> around to the various helpers that queue and finish deferred
> operations during intent recovery.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>
> ---
>  fs/xfs/xfs_bmap_item.c     | 12 +++++------
>  fs/xfs/xfs_bmap_item.h     |  3 +--
>  fs/xfs/xfs_log_recover.c   | 42 ++++++++++++++++++--------------------
>  fs/xfs/xfs_refcount_item.c | 12 +++++------
>  fs/xfs/xfs_refcount_item.h |  3 +--
>  5 files changed, 34 insertions(+), 38 deletions(-)
> 
> diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
> index e1d6c127b07d..992235e7c761 100644
> --- a/fs/xfs/xfs_bmap_item.c
> +++ b/fs/xfs/xfs_bmap_item.c
> @@ -375,9 +375,8 @@ xfs_bud_init(
>   */
>  int
>  xfs_bui_recover(
> -	struct xfs_mount		*mp,
> -	struct xfs_bui_log_item		*buip,
> -	struct xfs_defer_ops		*dfops)
> +	struct xfs_trans		*itp,

"itp"?

Oh, the intent-holder transaction...

> +	struct xfs_bui_log_item		*buip)
>  {
>  	int				error = 0;
>  	unsigned int			bui_type;
> @@ -393,6 +392,7 @@ xfs_bui_recover(
>  	struct xfs_trans		*tp;
>  	struct xfs_inode		*ip = NULL;
>  	struct xfs_bmbt_irec		irec;
> +	struct xfs_mount		*mp = itp->t_mountp;
>  
>  	ASSERT(!test_bit(XFS_BUI_RECOVERED, &buip->bui_flags));
>  
> @@ -446,7 +446,7 @@ xfs_bui_recover(
>  	 * finishes them on completion. Transfer current dfops state to this
>  	 * transaction and transfer the result back before we return.
>  	 */
> -	xfs_defer_move(tp->t_dfops, dfops);
> +	xfs_defer_move(tp->t_dfops, itp->t_dfops);
>  	budp = xfs_trans_get_bud(tp, buip);
>  
>  	/* Grab the inode. */
> @@ -494,7 +494,7 @@ xfs_bui_recover(
>  	}
>  
>  	set_bit(XFS_BUI_RECOVERED, &buip->bui_flags);
> -	xfs_defer_move(dfops, tp->t_dfops);
> +	xfs_defer_move(itp->t_dfops, tp->t_dfops);
>  	error = xfs_trans_commit(tp);
>  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
>  	xfs_irele(ip);
> @@ -502,7 +502,7 @@ xfs_bui_recover(
>  	return error;
>  
>  err_inode:
> -	xfs_defer_move(dfops, tp->t_dfops);
> +	xfs_defer_move(itp->t_dfops, tp->t_dfops);
>  	xfs_trans_cancel(tp);
>  	if (ip) {
>  		xfs_iunlock(ip, XFS_ILOCK_EXCL);
> diff --git a/fs/xfs/xfs_bmap_item.h b/fs/xfs/xfs_bmap_item.h
> index fd1a1b13df51..ebf6cd6d33e2 100644
> --- a/fs/xfs/xfs_bmap_item.h
> +++ b/fs/xfs/xfs_bmap_item.h
> @@ -79,7 +79,6 @@ struct xfs_bud_log_item *xfs_bud_init(struct xfs_mount *,
>  		struct xfs_bui_log_item *);
>  void xfs_bui_item_free(struct xfs_bui_log_item *);
>  void xfs_bui_release(struct xfs_bui_log_item *);
> -int xfs_bui_recover(struct xfs_mount *mp, struct xfs_bui_log_item *buip,
> -		struct xfs_defer_ops *dfops);
> +int xfs_bui_recover(struct xfs_trans *itp, struct xfs_bui_log_item *buip);
>  
>  #endif	/* __XFS_BMAP_ITEM_H__ */
> diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
> index 7776fde9430c..6650b790e43b 100644
> --- a/fs/xfs/xfs_log_recover.c
> +++ b/fs/xfs/xfs_log_recover.c
> @@ -4733,10 +4733,9 @@ xlog_recover_cancel_rui(
>  /* Recover the CUI if necessary. */
>  STATIC int
>  xlog_recover_process_cui(
> -	struct xfs_mount		*mp,
> +	struct xfs_trans		*tp,

This parameter is the intent-placeholder transaction, right?
Shouldn't it be "itp"?

>  	struct xfs_ail			*ailp,
> -	struct xfs_log_item		*lip,
> -	struct xfs_defer_ops		*dfops)
> +	struct xfs_log_item		*lip)
>  {
>  	struct xfs_cui_log_item		*cuip;
>  	int				error;
> @@ -4749,7 +4748,7 @@ xlog_recover_process_cui(
>  		return 0;
>  
>  	spin_unlock(&ailp->ail_lock);
> -	error = xfs_cui_recover(mp, cuip, dfops);
> +	error = xfs_cui_recover(tp, cuip);
>  	spin_lock(&ailp->ail_lock);
>  
>  	return error;
> @@ -4774,10 +4773,9 @@ xlog_recover_cancel_cui(
>  /* Recover the BUI if necessary. */
>  STATIC int
>  xlog_recover_process_bui(
> -	struct xfs_mount		*mp,
> +	struct xfs_trans		*tp,
>  	struct xfs_ail			*ailp,
> -	struct xfs_log_item		*lip,
> -	struct xfs_defer_ops		*dfops)
> +	struct xfs_log_item		*lip)
>  {
>  	struct xfs_bui_log_item		*buip;
>  	int				error;
> @@ -4790,7 +4788,7 @@ xlog_recover_process_bui(
>  		return 0;
>  
>  	spin_unlock(&ailp->ail_lock);
> -	error = xfs_bui_recover(mp, buip, dfops);
> +	error = xfs_bui_recover(tp, buip);
>  	spin_lock(&ailp->ail_lock);
>  
>  	return error;
> @@ -4829,9 +4827,9 @@ static inline bool xlog_item_is_intent(struct xfs_log_item *lip)
>  /* Take all the collected deferred ops and finish them in order. */
>  static int
>  xlog_finish_defer_ops(
> -	struct xfs_mount	*mp,
> -	struct xfs_defer_ops	*dfops)
> +	struct xfs_trans	*itp)
>  {
> +	struct xfs_mount	*mp = itp->t_mountp;
>  	struct xfs_trans	*tp;
>  	int64_t			freeblks;
>  	uint			resblks;
> @@ -4855,7 +4853,7 @@ xlog_finish_defer_ops(
>  	if (error)
>  		return error;
>  	/* transfer all collected dfops to this transaction */
> -	xfs_defer_move(tp->t_dfops, dfops);
> +	xfs_defer_move(tp->t_dfops, itp->t_dfops);
>  
>  	return xfs_trans_commit(tp);
>  }
> @@ -4880,22 +4878,25 @@ STATIC int
>  xlog_recover_process_intents(
>  	struct xlog		*log)
>  {
> -	struct xfs_defer_ops	dfops;
> +	struct xfs_trans	*tp;
>  	struct xfs_ail_cursor	cur;
>  	struct xfs_log_item	*lip;
>  	struct xfs_ail		*ailp;
> -	int			error = 0;
> +	int			error;
>  #if defined(DEBUG) || defined(XFS_WARN)
>  	xfs_lsn_t		last_lsn;
>  #endif
>  
> +	error = xfs_trans_alloc_empty(log->l_mp, &tp);

Here's where we allocate the intent-placeholder transaction, so why
isn't this named "itp" as well?

I think I have a handle on what this patch does, though the variable
naming itp/tp is a little confusing.

--D

> +	if (error)
> +		return error;
> +
>  	ailp = log->l_ailp;
>  	spin_lock(&ailp->ail_lock);
>  	lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
>  #if defined(DEBUG) || defined(XFS_WARN)
>  	last_lsn = xlog_assign_lsn(log->l_curr_cycle, log->l_curr_block);
>  #endif
> -	xfs_defer_init(NULL, &dfops);
>  	while (lip != NULL) {
>  		/*
>  		 * We're done when we see something other than an intent.
> @@ -4930,12 +4931,10 @@ xlog_recover_process_intents(
>  			error = xlog_recover_process_rui(log->l_mp, ailp, lip);
>  			break;
>  		case XFS_LI_CUI:
> -			error = xlog_recover_process_cui(log->l_mp, ailp, lip,
> -					&dfops);
> +			error = xlog_recover_process_cui(tp, ailp, lip);
>  			break;
>  		case XFS_LI_BUI:
> -			error = xlog_recover_process_bui(log->l_mp, ailp, lip,
> -					&dfops);
> +			error = xlog_recover_process_bui(tp, ailp, lip);
>  			break;
>  		}
>  		if (error)
> @@ -4945,10 +4944,9 @@ xlog_recover_process_intents(
>  out:
>  	xfs_trans_ail_cursor_done(&cur);
>  	spin_unlock(&ailp->ail_lock);
> -	if (error)
> -		__xfs_defer_cancel(&dfops);
> -	else
> -		error = xlog_finish_defer_ops(log->l_mp, &dfops);
> +	if (!error)
> +		error = xlog_finish_defer_ops(tp);
> +	xfs_trans_cancel(tp);
>  
>  	return error;
>  }
> diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
> index d3582a06626f..d663ea1f4076 100644
> --- a/fs/xfs/xfs_refcount_item.c
> +++ b/fs/xfs/xfs_refcount_item.c
> @@ -380,9 +380,8 @@ xfs_cud_init(
>   */
>  int
>  xfs_cui_recover(
> -	struct xfs_mount		*mp,
> -	struct xfs_cui_log_item		*cuip,
> -	struct xfs_defer_ops		*dfops)
> +	struct xfs_trans		*itp,
> +	struct xfs_cui_log_item		*cuip)
>  {
>  	int				i;
>  	int				error = 0;
> @@ -398,6 +397,7 @@ xfs_cui_recover(
>  	xfs_extlen_t			new_len;
>  	struct xfs_bmbt_irec		irec;
>  	bool				requeue_only = false;
> +	struct xfs_mount		*mp = itp->t_mountp;
>  
>  	ASSERT(!test_bit(XFS_CUI_RECOVERED, &cuip->cui_flags));
>  
> @@ -457,7 +457,7 @@ xfs_cui_recover(
>  	 * finishes them on completion. Transfer current dfops state to this
>  	 * transaction and transfer the result back before we return.
>  	 */
> -	xfs_defer_move(tp->t_dfops, dfops);
> +	xfs_defer_move(tp->t_dfops, itp->t_dfops);
>  	cudp = xfs_trans_get_cud(tp, cuip);
>  
>  	for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
> @@ -522,13 +522,13 @@ xfs_cui_recover(
>  
>  	xfs_refcount_finish_one_cleanup(tp, rcur, error);
>  	set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags);
> -	xfs_defer_move(dfops, tp->t_dfops);
> +	xfs_defer_move(itp->t_dfops, tp->t_dfops);
>  	error = xfs_trans_commit(tp);
>  	return error;
>  
>  abort_error:
>  	xfs_refcount_finish_one_cleanup(tp, rcur, error);
> -	xfs_defer_move(dfops, tp->t_dfops);
> +	xfs_defer_move(itp->t_dfops, tp->t_dfops);
>  	xfs_trans_cancel(tp);
>  	return error;
>  }
> diff --git a/fs/xfs/xfs_refcount_item.h b/fs/xfs/xfs_refcount_item.h
> index dd830b69cd1e..98895da52c1f 100644
> --- a/fs/xfs/xfs_refcount_item.h
> +++ b/fs/xfs/xfs_refcount_item.h
> @@ -82,7 +82,6 @@ struct xfs_cud_log_item *xfs_cud_init(struct xfs_mount *,
>  		struct xfs_cui_log_item *);
>  void xfs_cui_item_free(struct xfs_cui_log_item *);
>  void xfs_cui_release(struct xfs_cui_log_item *);
> -int xfs_cui_recover(struct xfs_mount *mp, struct xfs_cui_log_item *cuip,
> -		struct xfs_defer_ops *dfops);
> +int xfs_cui_recover(struct xfs_trans *itp, struct xfs_cui_log_item *cuip);
>  
>  #endif	/* __XFS_REFCOUNT_ITEM_H__ */
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 03/15] xfs: remove unused __xfs_defer_cancel() internal helper
  2018-07-30 16:45 ` [PATCH 03/15] xfs: remove unused __xfs_defer_cancel() internal helper Brian Foster
@ 2018-07-30 20:09   ` Darrick J. Wong
  2018-07-31  8:13   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 20:09 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:08PM -0400, Brian Foster wrote:
> With no more external dfops users, there is no need for an
> xfs_defer_ops cancel wrapper.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks ok,
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/xfs/libxfs/xfs_defer.c | 5 +++--
>  fs/xfs/libxfs/xfs_defer.h | 2 +-
>  fs/xfs/xfs_trans.c        | 7 -------
>  fs/xfs/xfs_trans.h        | 3 ---
>  4 files changed, 4 insertions(+), 13 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> index a5f7dc18a62f..ebead781613f 100644
> --- a/fs/xfs/libxfs/xfs_defer.c
> +++ b/fs/xfs/libxfs/xfs_defer.c
> @@ -465,9 +465,10 @@ xfs_defer_finish(
>   * Free up any items left in the list.
>   */
>  void
> -__xfs_defer_cancel(
> -	struct xfs_defer_ops		*dop)
> +xfs_defer_cancel(
> +	struct xfs_trans		*tp)
>  {
> +	struct xfs_defer_ops		*dop = tp->t_dfops;
>  	struct xfs_defer_pending	*dfp;
>  	struct xfs_defer_pending	*pli;
>  	struct list_head		*pwi;
> diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
> index 85c41fe4dbae..da145fc04ae1 100644
> --- a/fs/xfs/libxfs/xfs_defer.h
> +++ b/fs/xfs/libxfs/xfs_defer.h
> @@ -50,7 +50,7 @@ void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type,
>  		struct list_head *h);
>  int xfs_defer_finish_noroll(struct xfs_trans **tp);
>  int xfs_defer_finish(struct xfs_trans **tp);
> -void __xfs_defer_cancel(struct xfs_defer_ops *dop);
> +void xfs_defer_cancel(struct xfs_trans *);
>  void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
>  bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);
>  int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip);
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index 8d3b7f28b193..b0eeeaf6d24e 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -1105,10 +1105,3 @@ xfs_trans_roll(
>  	tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
>  	return xfs_trans_reserve(*tpp, &tres, 0, 0);
>  }
> -
> -void
> -xfs_defer_cancel(
> -	struct xfs_trans	*tp)
> -{
> -	__xfs_defer_cancel(tp->t_dfops);
> -}
> diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> index 5170e89bec02..dc79e3c1d3e8 100644
> --- a/fs/xfs/xfs_trans.h
> +++ b/fs/xfs/xfs_trans.h
> @@ -214,9 +214,6 @@ xfs_trans_read_buf(
>  				      flags, bpp, ops);
>  }
>  
> -/* cancel dfops associated with a transaction */
> -void xfs_defer_cancel(struct xfs_trans *);
> -
>  struct xfs_buf	*xfs_trans_getsb(xfs_trans_t *, struct xfs_mount *, int);
>  
>  void		xfs_trans_brelse(xfs_trans_t *, struct xfs_buf *);
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 04/15] xfs: pass transaction to dfops reset/move helpers
  2018-07-30 16:45 ` [PATCH 04/15] xfs: pass transaction to dfops reset/move helpers Brian Foster
@ 2018-07-30 20:10   ` Darrick J. Wong
  2018-07-31  8:14   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 20:10 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:09PM -0400, Brian Foster wrote:
> All callers pass ->t_dfops of the associated transactions. Refactor
> the helpers to receive the transactions and facilitate further
> cleanups between xfs_defer_ops and xfs_trans.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks ok,
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/xfs/libxfs/xfs_defer.c  | 15 ++++++++++-----
>  fs/xfs/libxfs/xfs_defer.h  |  2 +-
>  fs/xfs/xfs_bmap_item.c     |  6 +++---
>  fs/xfs/xfs_log_recover.c   |  2 +-
>  fs/xfs/xfs_refcount_item.c |  6 +++---
>  fs/xfs/xfs_trans.c         |  2 +-
>  6 files changed, 19 insertions(+), 14 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> index ebead781613f..e3517a53c525 100644
> --- a/fs/xfs/libxfs/xfs_defer.c
> +++ b/fs/xfs/libxfs/xfs_defer.c
> @@ -324,9 +324,12 @@ xfs_defer_bjoin(
>   */
>  static void
>  xfs_defer_reset(
> -	struct xfs_defer_ops	*dop)
> +	struct xfs_trans	*tp)
>  {
> +	struct xfs_defer_ops	*dop = tp->t_dfops;
> +
>  	ASSERT(!xfs_defer_has_unfinished_work(dop));
> +
>  	dop->dop_low = false;
>  	memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes));
>  	memset(dop->dop_bufs, 0, sizeof(dop->dop_bufs));
> @@ -457,7 +460,7 @@ xfs_defer_finish(
>  		if (error)
>  			return error;
>  	}
> -	xfs_defer_reset((*tp)->t_dfops);
> +	xfs_defer_reset(*tp);
>  	return 0;
>  }
>  
> @@ -575,9 +578,11 @@ xfs_defer_init(
>   */
>  void
>  xfs_defer_move(
> -	struct xfs_defer_ops	*dst,
> -	struct xfs_defer_ops	*src)
> +	struct xfs_trans	*dtp,
> +	struct xfs_trans	*stp)
>  {
> +	struct xfs_defer_ops	*dst = dtp->t_dfops;
> +	struct xfs_defer_ops	*src = stp->t_dfops;
>  	ASSERT(dst != src);
>  
>  	list_splice_init(&src->dop_intake, &dst->dop_intake);
> @@ -587,5 +592,5 @@ xfs_defer_move(
>  	memcpy(dst->dop_bufs, src->dop_bufs, sizeof(dst->dop_bufs));
>  	dst->dop_low = src->dop_low;
>  
> -	xfs_defer_reset(src);
> +	xfs_defer_reset(stp);
>  }
> diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
> index da145fc04ae1..d60c50498fdf 100644
> --- a/fs/xfs/libxfs/xfs_defer.h
> +++ b/fs/xfs/libxfs/xfs_defer.h
> @@ -55,7 +55,7 @@ void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
>  bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);
>  int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip);
>  int xfs_defer_bjoin(struct xfs_defer_ops *dop, struct xfs_buf *bp);
> -void xfs_defer_move(struct xfs_defer_ops *dst, struct xfs_defer_ops *src);
> +void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
>  
>  /* Description of a deferred type. */
>  struct xfs_defer_op_type {
> diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
> index 992235e7c761..4b4318ea4b76 100644
> --- a/fs/xfs/xfs_bmap_item.c
> +++ b/fs/xfs/xfs_bmap_item.c
> @@ -446,7 +446,7 @@ xfs_bui_recover(
>  	 * finishes them on completion. Transfer current dfops state to this
>  	 * transaction and transfer the result back before we return.
>  	 */
> -	xfs_defer_move(tp->t_dfops, itp->t_dfops);
> +	xfs_defer_move(tp, itp);
>  	budp = xfs_trans_get_bud(tp, buip);
>  
>  	/* Grab the inode. */
> @@ -494,7 +494,7 @@ xfs_bui_recover(
>  	}
>  
>  	set_bit(XFS_BUI_RECOVERED, &buip->bui_flags);
> -	xfs_defer_move(itp->t_dfops, tp->t_dfops);
> +	xfs_defer_move(itp, tp);
>  	error = xfs_trans_commit(tp);
>  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
>  	xfs_irele(ip);
> @@ -502,7 +502,7 @@ xfs_bui_recover(
>  	return error;
>  
>  err_inode:
> -	xfs_defer_move(itp->t_dfops, tp->t_dfops);
> +	xfs_defer_move(itp, tp);
>  	xfs_trans_cancel(tp);
>  	if (ip) {
>  		xfs_iunlock(ip, XFS_ILOCK_EXCL);
> diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
> index 6650b790e43b..b4edd93a18e9 100644
> --- a/fs/xfs/xfs_log_recover.c
> +++ b/fs/xfs/xfs_log_recover.c
> @@ -4853,7 +4853,7 @@ xlog_finish_defer_ops(
>  	if (error)
>  		return error;
>  	/* transfer all collected dfops to this transaction */
> -	xfs_defer_move(tp->t_dfops, itp->t_dfops);
> +	xfs_defer_move(tp, itp);
>  
>  	return xfs_trans_commit(tp);
>  }
> diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
> index d663ea1f4076..829b7a5bc707 100644
> --- a/fs/xfs/xfs_refcount_item.c
> +++ b/fs/xfs/xfs_refcount_item.c
> @@ -457,7 +457,7 @@ xfs_cui_recover(
>  	 * finishes them on completion. Transfer current dfops state to this
>  	 * transaction and transfer the result back before we return.
>  	 */
> -	xfs_defer_move(tp->t_dfops, itp->t_dfops);
> +	xfs_defer_move(tp, itp);
>  	cudp = xfs_trans_get_cud(tp, cuip);
>  
>  	for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
> @@ -522,13 +522,13 @@ xfs_cui_recover(
>  
>  	xfs_refcount_finish_one_cleanup(tp, rcur, error);
>  	set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags);
> -	xfs_defer_move(itp->t_dfops, tp->t_dfops);
> +	xfs_defer_move(itp, tp);
>  	error = xfs_trans_commit(tp);
>  	return error;
>  
>  abort_error:
>  	xfs_refcount_finish_one_cleanup(tp, rcur, error);
> -	xfs_defer_move(itp->t_dfops, tp->t_dfops);
> +	xfs_defer_move(itp, tp);
>  	xfs_trans_cancel(tp);
>  	return error;
>  }
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index b0eeeaf6d24e..8c088568b05d 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -125,7 +125,7 @@ xfs_trans_dup(
>  	if (tp->t_dfops != &tp->t_dfops_internal)
>  		ntp->t_dfops = tp->t_dfops;
>  	else
> -		xfs_defer_move(ntp->t_dfops, tp->t_dfops);
> +		xfs_defer_move(ntp, tp);
>  
>  	xfs_trans_dup_dqinfo(tp, ntp);
>  
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 05/15] xfs: replace dop_low with transaction flag
  2018-07-30 16:45 ` [PATCH 05/15] xfs: replace dop_low with transaction flag Brian Foster
@ 2018-07-30 20:11   ` Darrick J. Wong
  2018-07-31  8:16   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 20:11 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:10PM -0400, Brian Foster wrote:
> The dop_low field enables the low free space allocation mode when a
> previous allocation has detected difficulty allocating blocks. It
> has historically been part of the xfs_defer_ops structure, which
> means if enabled, it remains enabled across a set of transactions
> until the deferred operations have completed and the dfops is reset.
> 
> Now that the dfops is embedded in the transaction, we can save a bit
> more space by using a transaction flag rather than a standalone
> boolean. Drop the ->dop_low field and replace it with a transaction
> flag that is set at the same points, carried across rolling
> transactions and cleared on completion of deferred operations. This
> essentially emulates the behavior of ->dop_low and so should not
> change behavior.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks ok,
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/xfs/libxfs/xfs_bmap.c       |  8 ++++----
>  fs/xfs/libxfs/xfs_bmap_btree.c |  4 ++--
>  fs/xfs/libxfs/xfs_defer.c      | 16 ++++++++++++++--
>  fs/xfs/libxfs/xfs_defer.h      | 11 -----------
>  fs/xfs/libxfs/xfs_shared.h     | 12 ++++++++++++
>  fs/xfs/xfs_filestream.c        |  3 ++-
>  fs/xfs/xfs_trace.h             | 10 ++--------
>  fs/xfs/xfs_trans.h             |  2 --
>  8 files changed, 36 insertions(+), 30 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index a85c0445b38f..8edf7522aaff 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -700,7 +700,7 @@ xfs_bmap_extents_to_btree(
>  	if (tp->t_firstblock == NULLFSBLOCK) {
>  		args.type = XFS_ALLOCTYPE_START_BNO;
>  		args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
> -	} else if (tp->t_dfops->dop_low) {
> +	} else if (tp->t_flags & XFS_TRANS_LOWMODE) {
>  		args.type = XFS_ALLOCTYPE_START_BNO;
>  		args.fsbno = tp->t_firstblock;
>  	} else {
> @@ -3449,7 +3449,7 @@ xfs_bmap_btalloc(
>  			error = xfs_bmap_btalloc_nullfb(ap, &args, &blen);
>  		if (error)
>  			return error;
> -	} else if (ap->tp->t_dfops->dop_low) {
> +	} else if (ap->tp->t_flags & XFS_TRANS_LOWMODE) {
>  		if (xfs_inode_is_filestream(ap->ip))
>  			args.type = XFS_ALLOCTYPE_FIRST_AG;
>  		else
> @@ -3484,7 +3484,7 @@ xfs_bmap_btalloc(
>  	 * is >= the stripe unit and the allocation offset is
>  	 * at the end of file.
>  	 */
> -	if (!ap->tp->t_dfops->dop_low && ap->aeof) {
> +	if (!(ap->tp->t_flags & XFS_TRANS_LOWMODE) && ap->aeof) {
>  		if (!ap->offset) {
>  			args.alignment = stripe_align;
>  			atype = args.type;
> @@ -3576,7 +3576,7 @@ xfs_bmap_btalloc(
>  		args.total = ap->minlen;
>  		if ((error = xfs_alloc_vextent(&args)))
>  			return error;
> -		ap->tp->t_dfops->dop_low = true;
> +		ap->tp->t_flags |= XFS_TRANS_LOWMODE;
>  	}
>  	if (args.fsbno != NULLFSBLOCK) {
>  		/*
> diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
> index 01489714a253..955e29de8cae 100644
> --- a/fs/xfs/libxfs/xfs_bmap_btree.c
> +++ b/fs/xfs/libxfs/xfs_bmap_btree.c
> @@ -226,7 +226,7 @@ xfs_bmbt_alloc_block(
>  		 * block allocation here and corrupt the filesystem.
>  		 */
>  		args.minleft = args.tp->t_blk_res;
> -	} else if (cur->bc_tp->t_dfops->dop_low) {
> +	} else if (cur->bc_tp->t_flags & XFS_TRANS_LOWMODE) {
>  		args.type = XFS_ALLOCTYPE_START_BNO;
>  	} else {
>  		args.type = XFS_ALLOCTYPE_NEAR_BNO;
> @@ -253,7 +253,7 @@ xfs_bmbt_alloc_block(
>  		error = xfs_alloc_vextent(&args);
>  		if (error)
>  			goto error0;
> -		cur->bc_tp->t_dfops->dop_low = true;
> +		cur->bc_tp->t_flags |= XFS_TRANS_LOWMODE;
>  	}
>  	if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
>  		*stat = 0;
> diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> index e3517a53c525..0306187b5f56 100644
> --- a/fs/xfs/libxfs/xfs_defer.c
> +++ b/fs/xfs/libxfs/xfs_defer.c
> @@ -330,9 +330,14 @@ xfs_defer_reset(
>  
>  	ASSERT(!xfs_defer_has_unfinished_work(dop));
>  
> -	dop->dop_low = false;
>  	memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes));
>  	memset(dop->dop_bufs, 0, sizeof(dop->dop_bufs));
> +
> +	/*
> +	 * Low mode state transfers across transaction rolls to mirror dfops
> +	 * lifetime. Clear it now that dfops is reset.
> +	 */
> +	tp->t_flags &= ~XFS_TRANS_LOWMODE;
>  }
>  
>  /*
> @@ -590,7 +595,14 @@ xfs_defer_move(
>  
>  	memcpy(dst->dop_inodes, src->dop_inodes, sizeof(dst->dop_inodes));
>  	memcpy(dst->dop_bufs, src->dop_bufs, sizeof(dst->dop_bufs));
> -	dst->dop_low = src->dop_low;
> +
> +	/*
> +	 * Low free space mode was historically controlled by a dfops field.
> +	 * This meant that low mode state potentially carried across multiple
> +	 * transaction rolls. Transfer low mode on a dfops move to preserve
> +	 * that behavior.
> +	 */
> +	dtp->t_flags |= stp->t_flags & XFS_TRANS_LOWMODE;
>  
>  	xfs_defer_reset(stp);
>  }
> diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
> index d60c50498fdf..8908a2716774 100644
> --- a/fs/xfs/libxfs/xfs_defer.h
> +++ b/fs/xfs/libxfs/xfs_defer.h
> @@ -25,17 +25,6 @@ struct xfs_defer_pending {
>  
>  /*
>   * Header for deferred operation list.
> - *
> - * dop_low is used by the allocator to activate the lowspace algorithm -
> - * when free space is running low the extent allocator may choose to
> - * allocate an extent from an AG without leaving sufficient space for
> - * a btree split when inserting the new extent.  In this case the allocator
> - * will enable the lowspace algorithm which is supposed to allow further
> - * allocations (such as btree splits and newroots) to allocate from
> - * sequential AGs.  In order to avoid locking AGs out of order the lowspace
> - * algorithm will start searching for free space from AG 0.  If the correct
> - * transaction reservations have been made then this algorithm will eventually
> - * find all the space it needs.
>   */
>  enum xfs_defer_ops_type {
>  	XFS_DEFER_OPS_TYPE_BMAP,
> diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h
> index 22089f1c880a..1c5debe748f0 100644
> --- a/fs/xfs/libxfs/xfs_shared.h
> +++ b/fs/xfs/libxfs/xfs_shared.h
> @@ -64,6 +64,18 @@ void	xfs_log_get_max_trans_res(struct xfs_mount *mp,
>  #define XFS_TRANS_RESERVE	0x20    /* OK to use reserved data blocks */
>  #define XFS_TRANS_NO_WRITECOUNT 0x40	/* do not elevate SB writecount */
>  #define XFS_TRANS_NOFS		0x80	/* pass KM_NOFS to kmem_alloc */
> +/*
> + * LOWMODE is used by the allocator to activate the lowspace algorithm - when
> + * free space is running low the extent allocator may choose to allocate an
> + * extent from an AG without leaving sufficient space for a btree split when
> + * inserting the new extent. In this case the allocator will enable the
> + * lowspace algorithm which is supposed to allow further allocations (such as
> + * btree splits and newroots) to allocate from sequential AGs. In order to
> + * avoid locking AGs out of order the lowspace algorithm will start searching
> + * for free space from AG 0. If the correct transaction reservations have been
> + * made then this algorithm will eventually find all the space it needs.
> + */
> +#define XFS_TRANS_LOWMODE	0x100	/* allocate in low space mode */
>  
>  /*
>   * Field values for xfs_trans_mod_sb.
> diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
> index 212173c62588..182501373af2 100644
> --- a/fs/xfs/xfs_filestream.c
> +++ b/fs/xfs/xfs_filestream.c
> @@ -20,6 +20,7 @@
>  #include "xfs_trace.h"
>  #include "xfs_ag_resv.h"
>  #include "xfs_trans.h"
> +#include "xfs_shared.h"
>  
>  struct xfs_fstrm_item {
>  	struct xfs_mru_cache_elem	mru;
> @@ -378,7 +379,7 @@ xfs_filestream_new_ag(
>  
>  	if (xfs_alloc_is_userdata(ap->datatype))
>  		flags |= XFS_PICK_USERDATA;
> -	if (ap->tp->t_dfops->dop_low)
> +	if (ap->tp->t_flags & XFS_TRANS_LOWMODE)
>  		flags |= XFS_PICK_LOWSPACE;
>  
>  	err = xfs_filestream_pick_ag(pip, startag, agp, flags, minlen);
> diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
> index cc6995cfce66..8807f1bb814a 100644
> --- a/fs/xfs/xfs_trace.h
> +++ b/fs/xfs/xfs_trace.h
> @@ -2223,19 +2223,16 @@ DECLARE_EVENT_CLASS(xfs_defer_class,
>  		__field(dev_t, dev)
>  		__field(void *, dop)
>  		__field(char, committed)
> -		__field(char, low)
>  		__field(unsigned long, caller_ip)
>  	),
>  	TP_fast_assign(
>  		__entry->dev = mp ? mp->m_super->s_dev : 0;
>  		__entry->dop = dop;
> -		__entry->low = dop->dop_low;
>  		__entry->caller_ip = caller_ip;
>  	),
> -	TP_printk("dev %d:%d ops %p low %d, caller %pS",
> +	TP_printk("dev %d:%d ops %p caller %pS",
>  		  MAJOR(__entry->dev), MINOR(__entry->dev),
>  		  __entry->dop,
> -		  __entry->low,
>  		  (char *)__entry->caller_ip)
>  )
>  #define DEFINE_DEFER_EVENT(name) \
> @@ -2251,19 +2248,16 @@ DECLARE_EVENT_CLASS(xfs_defer_error_class,
>  		__field(dev_t, dev)
>  		__field(void *, dop)
>  		__field(char, committed)
> -		__field(char, low)
>  		__field(int, error)
>  	),
>  	TP_fast_assign(
>  		__entry->dev = mp ? mp->m_super->s_dev : 0;
>  		__entry->dop = dop;
> -		__entry->low = dop->dop_low;
>  		__entry->error = error;
>  	),
> -	TP_printk("dev %d:%d ops %p low %d err %d",
> +	TP_printk("dev %d:%d ops %p err %d",
>  		  MAJOR(__entry->dev), MINOR(__entry->dev),
>  		  __entry->dop,
> -		  __entry->low,
>  		  __entry->error)
>  )
>  #define DEFINE_DEFER_ERROR_EVENT(name) \
> diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> index dc79e3c1d3e8..7e493221160e 100644
> --- a/fs/xfs/xfs_trans.h
> +++ b/fs/xfs/xfs_trans.h
> @@ -101,8 +101,6 @@ struct xfs_defer_ops {
>  	/* relog these with each roll */
>  	struct xfs_inode	*dop_inodes[XFS_DEFER_OPS_NR_INODES];
>  	struct xfs_buf		*dop_bufs[XFS_DEFER_OPS_NR_BUFS];
> -
> -	bool			dop_low;	/* alloc in low mode */
>  };
>  
>  /*
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 06/15] xfs: add missing defer ijoins for held inodes
  2018-07-30 16:45 ` [PATCH 06/15] xfs: add missing defer ijoins for held inodes Brian Foster
@ 2018-07-30 20:15   ` Darrick J. Wong
  2018-07-31  8:17   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 20:15 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:11PM -0400, Brian Foster wrote:
> Log items that require relogging during deferred operations
> processing are explicitly joined to the associated dfops via the
> xfs_defer_*join() helpers. These calls imply that the associated
> object is "held" by the transaction such that when rolled, the item
> can be immediately joined to a follow up transaction. For buffers,
> this means the buffer remains locked and held after each roll. For
> inodes, this means that the inode remains locked.
> 
> Failure to join a held item to the dfops structure means the
> associated object pins the tail of the log while dfops processing
> completes, because the item never relogs and is not unlocked or
> released until deferred processing completes.
> 
> Currently, all buffers that are held in transactions (XFS_BLI_HOLD)
> with deferred operations are explicitly joined to the dfops. This is
> not the case for inodes, however, as various contexts defer
> operations to transactions with held inodes without explicit joins
> to the associated dfops (and thus not relogging).
> 
> While this is not a catastrophic problem, it is not ideal. Given
> that we want to eventually relog such items automatically during
> dfops processing, start by explicitly adding these missing
> xfs_defer_ijoin() calls. A call is added everywhere an inode is
> joined to a transaction without transferring lock ownership and
> said transaction runs deferred operations.
> 
> All xfs_defer_ijoin() calls will eventually be replaced by automatic
> dfops inode relogging. This patch essentially implements the
> behavior change that would otherwise occur due to automatic inode
> dfops relogging.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks ok, though I admit I'm a little skeptical of adding the calls only
to replace them with automatic ijoining two patches later... :)

Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/xfs/libxfs/xfs_bmap.c | 1 +
>  fs/xfs/xfs_bmap_util.c   | 1 +
>  fs/xfs/xfs_inode.c       | 1 +
>  fs/xfs/xfs_iomap.c       | 3 +++
>  fs/xfs/xfs_reflink.c     | 1 +
>  5 files changed, 7 insertions(+)
> 
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index 8edf7522aaff..71687d805f79 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -1119,6 +1119,7 @@ xfs_bmap_add_attrfork(
>  			xfs_log_sb(tp);
>  	}
>  
> +	xfs_defer_ijoin(tp->t_dfops, ip);
>  	error = xfs_trans_commit(tp);
>  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
>  	return error;
> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> index 412dc58ae54d..0c58a66b39e5 100644
> --- a/fs/xfs/xfs_bmap_util.c
> +++ b/fs/xfs/xfs_bmap_util.c
> @@ -979,6 +979,7 @@ xfs_alloc_file_space(
>  		/*
>  		 * Complete the transaction
>  		 */
> +		xfs_defer_ijoin(tp->t_dfops, ip);
>  		error = xfs_trans_commit(tp);
>  		xfs_iunlock(ip, XFS_ILOCK_EXCL);
>  		if (error)
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 5fc1815c2b62..441c8593cfd7 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -1810,6 +1810,7 @@ xfs_inactive_ifree(
>  	 * Just ignore errors at this point.  There is nothing we can do except
>  	 * to try to keep going. Make sure it's not a silent error.
>  	 */
> +	xfs_defer_ijoin(tp->t_dfops, ip);
>  	error = xfs_trans_commit(tp);
>  	if (error)
>  		xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index 8e8ca9f03f0e..464b4b3225bb 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -261,6 +261,7 @@ xfs_iomap_write_direct(
>  	/*
>  	 * Complete the transaction
>  	 */
> +	xfs_defer_ijoin(tp->t_dfops, ip);
>  	error = xfs_trans_commit(tp);
>  	if (error)
>  		goto out_unlock;
> @@ -762,6 +763,7 @@ xfs_iomap_write_allocate(
>  			if (error)
>  				goto trans_cancel;
>  
> +			xfs_defer_ijoin(tp->t_dfops, ip);
>  			error = xfs_trans_commit(tp);
>  			if (error)
>  				goto error0;
> @@ -879,6 +881,7 @@ xfs_iomap_write_unwritten(
>  			xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
>  		}
>  
> +		xfs_defer_ijoin(tp->t_dfops, ip);
>  		error = xfs_trans_commit(tp);
>  		xfs_iunlock(ip, XFS_ILOCK_EXCL);
>  		if (error)
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index 9a0a56526266..e986fcf928e5 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -435,6 +435,7 @@ xfs_reflink_allocate_cow(
>  	xfs_inode_set_cowblocks_tag(ip);
>  
>  	/* Finish up. */
> +	xfs_defer_ijoin(tp->t_dfops, ip);
>  	error = xfs_trans_commit(tp);
>  	if (error)
>  		return error;
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 07/15] xfs: automatic dfops buffer relogging
  2018-07-30 16:45 ` [PATCH 07/15] xfs: automatic dfops buffer relogging Brian Foster
@ 2018-07-30 20:20   ` Darrick J. Wong
  2018-07-31 11:48     ` Brian Foster
  2018-07-31  8:19   ` Christoph Hellwig
  1 sibling, 1 reply; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 20:20 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:12PM -0400, Brian Foster wrote:
> Buffers that are held across deferred operations are explicitly
> joined to the dfops structure to ensure appropriate relogging.
> While buffers are currently joined explicitly, we can detect the
> conditions that require relogging at dfops finish time by inspecting
> the transaction item list for held buffers.
> 
> Replace the xfs_defer_bjoin() infrastructure with such detection and
> automatic relogging of held buffers. This eliminates the need for
> the per-dfops buffer list, replaced by an on-stack variant in
> xfs_defer_trans_roll().
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>
> ---
>  fs/xfs/libxfs/xfs_attr.c  |  1 -
>  fs/xfs/libxfs/xfs_defer.c | 55 ++++++++++++++++-----------------------
>  fs/xfs/libxfs/xfs_defer.h |  1 -
>  fs/xfs/xfs_dquot.c        |  1 -
>  fs/xfs/xfs_trans.h        |  1 -
>  5 files changed, 23 insertions(+), 36 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> index 3deb5cdadf08..227887bee00d 100644
> --- a/fs/xfs/libxfs/xfs_attr.c
> +++ b/fs/xfs/libxfs/xfs_attr.c
> @@ -320,7 +320,6 @@ xfs_attr_set(
>  		 * buffer and run into problems with the write verifier.
>  		 */
>  		xfs_trans_bhold(args.trans, leaf_bp);
> -		xfs_defer_bjoin(args.trans->t_dfops, leaf_bp);
>  		xfs_defer_ijoin(args.trans->t_dfops, dp);
>  		error = xfs_defer_finish(&args.trans);
>  		if (error)
> diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> index 0306187b5f56..d0ee55048a7a 100644
> --- a/fs/xfs/libxfs/xfs_defer.c
> +++ b/fs/xfs/libxfs/xfs_defer.c
> @@ -14,6 +14,7 @@
>  #include "xfs_mount.h"
>  #include "xfs_defer.h"
>  #include "xfs_trans.h"
> +#include "xfs_buf_item.h"
>  #include "xfs_trace.h"
>  
>  /*
> @@ -228,6 +229,10 @@ xfs_defer_trans_roll(
>  	struct xfs_trans		**tp)
>  {
>  	struct xfs_defer_ops		*dop = (*tp)->t_dfops;
> +	struct xfs_buf_log_item		*bli;
> +	struct xfs_log_item		*lip;
> +	struct xfs_buf			*bplist[XFS_DEFER_OPS_NR_BUFS];
> +	int				bpcount = 0;
>  	int				i;
>  	int				error;
>  
> @@ -235,9 +240,21 @@ xfs_defer_trans_roll(
>  	for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++)
>  		xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE);
>  
> -	/* Hold the (previously bjoin'd) buffer locked across the roll. */
> -	for (i = 0; i < XFS_DEFER_OPS_NR_BUFS && dop->dop_bufs[i]; i++)
> -		xfs_trans_dirty_buf(*tp, dop->dop_bufs[i]);
> +	list_for_each_entry(lip, &(*tp)->t_items, li_trans) {
> +		switch (lip->li_type) {
> +		case XFS_LI_BUF:
> +			bli = container_of(lip, struct xfs_buf_log_item,
> +					   bli_item);
> +			if (bli->bli_flags & XFS_BLI_HOLD) {
> +				ASSERT(bpcount < XFS_DEFER_OPS_NR_BUFS);

This is a bit of a behavior change -- previously if we oveflowed the
array we'd bail out with -EFSCORRUPTED rather than go corrupting
whatever came after dop_bufs.  Granted, we were pretty terrible about
checking the return values, but I think this ought to be:

if (bpcount >= XFS_DEFER_OPS_NR_BUFS) {
	ASSERT(0);
	return -EFSCORRUPTED;
}

rather than corrupting the on-stack array if we happen to bhold too many
buffers to the transaction.

--D

> +				xfs_trans_dirty_buf(*tp, bli->bli_buf);
> +				bplist[bpcount++] = bli->bli_buf;
> +			}
> +			break;
> +		default:
> +			break;
> +		}
> +	}
>  
>  	trace_xfs_defer_trans_roll((*tp)->t_mountp, dop, _RET_IP_);
>  
> @@ -255,9 +272,9 @@ xfs_defer_trans_roll(
>  		xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0);
>  
>  	/* Rejoin the buffers and dirty them so the log moves forward. */
> -	for (i = 0; i < XFS_DEFER_OPS_NR_BUFS && dop->dop_bufs[i]; i++) {
> -		xfs_trans_bjoin(*tp, dop->dop_bufs[i]);
> -		xfs_trans_bhold(*tp, dop->dop_bufs[i]);
> +	for (i = 0; i < bpcount; i++) {
> +		xfs_trans_bjoin(*tp, bplist[i]);
> +		xfs_trans_bhold(*tp, bplist[i]);
>  	}
>  
>  	return error;
> @@ -295,30 +312,6 @@ xfs_defer_ijoin(
>  	return -EFSCORRUPTED;
>  }
>  
> -/*
> - * Add this buffer to the deferred op.  Each joined buffer is relogged
> - * each time we roll the transaction.
> - */
> -int
> -xfs_defer_bjoin(
> -	struct xfs_defer_ops		*dop,
> -	struct xfs_buf			*bp)
> -{
> -	int				i;
> -
> -	for (i = 0; i < XFS_DEFER_OPS_NR_BUFS; i++) {
> -		if (dop->dop_bufs[i] == bp)
> -			return 0;
> -		else if (dop->dop_bufs[i] == NULL) {
> -			dop->dop_bufs[i] = bp;
> -			return 0;
> -		}
> -	}
> -
> -	ASSERT(0);
> -	return -EFSCORRUPTED;
> -}
> -
>  /*
>   * Reset an already used dfops after finish.
>   */
> @@ -331,7 +324,6 @@ xfs_defer_reset(
>  	ASSERT(!xfs_defer_has_unfinished_work(dop));
>  
>  	memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes));
> -	memset(dop->dop_bufs, 0, sizeof(dop->dop_bufs));
>  
>  	/*
>  	 * Low mode state transfers across transaction rolls to mirror dfops
> @@ -594,7 +586,6 @@ xfs_defer_move(
>  	list_splice_init(&src->dop_pending, &dst->dop_pending);
>  
>  	memcpy(dst->dop_inodes, src->dop_inodes, sizeof(dst->dop_inodes));
> -	memcpy(dst->dop_bufs, src->dop_bufs, sizeof(dst->dop_bufs));
>  
>  	/*
>  	 * Low free space mode was historically controlled by a dfops field.
> diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
> index 8908a2716774..4a8bb838adf2 100644
> --- a/fs/xfs/libxfs/xfs_defer.h
> +++ b/fs/xfs/libxfs/xfs_defer.h
> @@ -43,7 +43,6 @@ void xfs_defer_cancel(struct xfs_trans *);
>  void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
>  bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);
>  int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip);
> -int xfs_defer_bjoin(struct xfs_defer_ops *dop, struct xfs_buf *bp);
>  void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
>  
>  /* Description of a deferred type. */
> diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
> index da5c55cec966..e1196854dbcd 100644
> --- a/fs/xfs/xfs_dquot.c
> +++ b/fs/xfs/xfs_dquot.c
> @@ -362,7 +362,6 @@ xfs_dquot_disk_alloc(
>  	 * manually or by committing the transaction.
>  	 */
>  	xfs_trans_bhold(tp, bp);
> -	error = xfs_defer_bjoin(tp->t_dfops, bp);
>  	if (error) {
>  		xfs_trans_bhold_release(tp, bp);
>  		xfs_trans_brelse(tp, bp);
> diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> index 7e493221160e..581456c79197 100644
> --- a/fs/xfs/xfs_trans.h
> +++ b/fs/xfs/xfs_trans.h
> @@ -100,7 +100,6 @@ struct xfs_defer_ops {
>  
>  	/* relog these with each roll */
>  	struct xfs_inode	*dop_inodes[XFS_DEFER_OPS_NR_INODES];
> -	struct xfs_buf		*dop_bufs[XFS_DEFER_OPS_NR_BUFS];
>  };
>  
>  /*
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 08/15] xfs: automatic dfops inode relogging
  2018-07-30 16:45 ` [PATCH 08/15] xfs: automatic dfops inode relogging Brian Foster
@ 2018-07-30 20:22   ` Darrick J. Wong
  2018-07-31  8:19   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 20:22 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:13PM -0400, Brian Foster wrote:
> Inodes that are held across deferred operations are explicitly
> joined to the dfops structure to ensure appropriate relogging.
> While inodes are currently joined explicitly, we can detect the
> conditions that require relogging at dfops finish time by inspecting
> the transaction item list for inodes with ili_lock_flags == 0.
> 
> Replace the xfs_defer_ijoin() infrastructure with such detection and
> automatic relogging of held inodes. This eliminates the need for the
> per-dfops inode list, replaced by an on-stack variant in
> xfs_defer_trans_roll().
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>
> ---
>  fs/xfs/libxfs/xfs_attr.c        |  9 ------
>  fs/xfs/libxfs/xfs_attr_remote.c |  2 --
>  fs/xfs/libxfs/xfs_bmap.c        |  8 -----
>  fs/xfs/libxfs/xfs_defer.c       | 56 +++++++++++----------------------
>  fs/xfs/libxfs/xfs_defer.h       |  1 -
>  fs/xfs/xfs_bmap_util.c          |  4 ---
>  fs/xfs/xfs_inode.c              |  2 --
>  fs/xfs/xfs_iomap.c              |  3 --
>  fs/xfs/xfs_reflink.c            |  4 ---
>  fs/xfs/xfs_symlink.c            |  1 -
>  fs/xfs/xfs_trans.h              |  3 --
>  11 files changed, 18 insertions(+), 75 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> index 227887bee00d..3190dfc21b60 100644
> --- a/fs/xfs/libxfs/xfs_attr.c
> +++ b/fs/xfs/libxfs/xfs_attr.c
> @@ -320,7 +320,6 @@ xfs_attr_set(
>  		 * buffer and run into problems with the write verifier.
>  		 */
>  		xfs_trans_bhold(args.trans, leaf_bp);
> -		xfs_defer_ijoin(args.trans->t_dfops, dp);
>  		error = xfs_defer_finish(&args.trans);
>  		if (error)
>  			goto out;
> @@ -589,7 +588,6 @@ xfs_attr_leaf_addname(
>  		error = xfs_attr3_leaf_to_node(args);
>  		if (error)
>  			goto out_defer_cancel;
> -		xfs_defer_ijoin(args->trans->t_dfops, dp);
>  		error = xfs_defer_finish(&args->trans);
>  		if (error)
>  			goto out_defer_cancel;
> @@ -678,7 +676,6 @@ xfs_attr_leaf_addname(
>  			/* bp is gone due to xfs_da_shrink_inode */
>  			if (error)
>  				goto out_defer_cancel;
> -			xfs_defer_ijoin(args->trans->t_dfops, dp);
>  			error = xfs_defer_finish(&args->trans);
>  			if (error)
>  				goto out_defer_cancel;
> @@ -742,7 +739,6 @@ xfs_attr_leaf_removename(
>  		/* bp is gone due to xfs_da_shrink_inode */
>  		if (error)
>  			goto out_defer_cancel;
> -		xfs_defer_ijoin(args->trans->t_dfops, dp);
>  		error = xfs_defer_finish(&args->trans);
>  		if (error)
>  			goto out_defer_cancel;
> @@ -869,7 +865,6 @@ xfs_attr_node_addname(
>  			error = xfs_attr3_leaf_to_node(args);
>  			if (error)
>  				goto out_defer_cancel;
> -			xfs_defer_ijoin(args->trans->t_dfops, dp);
>  			error = xfs_defer_finish(&args->trans);
>  			if (error)
>  				goto out_defer_cancel;
> @@ -894,7 +889,6 @@ xfs_attr_node_addname(
>  		error = xfs_da3_split(state);
>  		if (error)
>  			goto out_defer_cancel;
> -		xfs_defer_ijoin(args->trans->t_dfops, dp);
>  		error = xfs_defer_finish(&args->trans);
>  		if (error)
>  			goto out_defer_cancel;
> @@ -991,7 +985,6 @@ xfs_attr_node_addname(
>  			error = xfs_da3_join(state);
>  			if (error)
>  				goto out_defer_cancel;
> -			xfs_defer_ijoin(args->trans->t_dfops, dp);
>  			error = xfs_defer_finish(&args->trans);
>  			if (error)
>  				goto out_defer_cancel;
> @@ -1115,7 +1108,6 @@ xfs_attr_node_removename(
>  		error = xfs_da3_join(state);
>  		if (error)
>  			goto out_defer_cancel;
> -		xfs_defer_ijoin(args->trans->t_dfops, dp);
>  		error = xfs_defer_finish(&args->trans);
>  		if (error)
>  			goto out_defer_cancel;
> @@ -1147,7 +1139,6 @@ xfs_attr_node_removename(
>  			/* bp is gone due to xfs_da_shrink_inode */
>  			if (error)
>  				goto out_defer_cancel;
> -			xfs_defer_ijoin(args->trans->t_dfops, dp);
>  			error = xfs_defer_finish(&args->trans);
>  			if (error)
>  				goto out_defer_cancel;
> diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c
> index 77ca38586913..f52552313773 100644
> --- a/fs/xfs/libxfs/xfs_attr_remote.c
> +++ b/fs/xfs/libxfs/xfs_attr_remote.c
> @@ -486,7 +486,6 @@ xfs_attr_rmtval_set(
>  				  &nmap);
>  		if (error)
>  			goto out_defer_cancel;
> -		xfs_defer_ijoin(args->trans->t_dfops, dp);
>  		error = xfs_defer_finish(&args->trans);
>  		if (error)
>  			goto out_defer_cancel;
> @@ -627,7 +626,6 @@ xfs_attr_rmtval_remove(
>  				    XFS_BMAPI_ATTRFORK, 1, &done);
>  		if (error)
>  			goto out_defer_cancel;
> -		xfs_defer_ijoin(args->trans->t_dfops, args->dp);
>  		error = xfs_defer_finish(&args->trans);
>  		if (error)
>  			goto out_defer_cancel;
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index 71687d805f79..5cd490dc891a 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -1119,7 +1119,6 @@ xfs_bmap_add_attrfork(
>  			xfs_log_sb(tp);
>  	}
>  
> -	xfs_defer_ijoin(tp->t_dfops, ip);
>  	error = xfs_trans_commit(tp);
>  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
>  	return error;
> @@ -5987,7 +5986,6 @@ __xfs_bmap_add(
>  	int				whichfork,
>  	struct xfs_bmbt_irec		*bmap)
>  {
> -	int				error;
>  	struct xfs_bmap_intent		*bi;
>  
>  	trace_xfs_bmap_defer(mp,
> @@ -6006,12 +6004,6 @@ __xfs_bmap_add(
>  	bi->bi_whichfork = whichfork;
>  	bi->bi_bmap = *bmap;
>  
> -	error = xfs_defer_ijoin(dfops, bi->bi_owner);
> -	if (error) {
> -		kmem_free(bi);
> -		return error;
> -	}
> -
>  	xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_BMAP, &bi->bi_list);
>  	return 0;
>  }
> diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> index d0ee55048a7a..6230e74163ac 100644
> --- a/fs/xfs/libxfs/xfs_defer.c
> +++ b/fs/xfs/libxfs/xfs_defer.c
> @@ -15,6 +15,8 @@
>  #include "xfs_defer.h"
>  #include "xfs_trans.h"
>  #include "xfs_buf_item.h"
> +#include "xfs_inode.h"
> +#include "xfs_inode_item.h"
>  #include "xfs_trace.h"
>  
>  /*
> @@ -230,16 +232,14 @@ xfs_defer_trans_roll(
>  {
>  	struct xfs_defer_ops		*dop = (*tp)->t_dfops;
>  	struct xfs_buf_log_item		*bli;
> +	struct xfs_inode_log_item	*ili;
>  	struct xfs_log_item		*lip;
>  	struct xfs_buf			*bplist[XFS_DEFER_OPS_NR_BUFS];
> -	int				bpcount = 0;
> +	struct xfs_inode		*iplist[XFS_DEFER_OPS_NR_INODES];
> +	int				bpcount = 0, ipcount = 0;
>  	int				i;
>  	int				error;
>  
> -	/* Log all the joined inodes. */
> -	for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++)
> -		xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE);
> -
>  	list_for_each_entry(lip, &(*tp)->t_items, li_trans) {
>  		switch (lip->li_type) {
>  		case XFS_LI_BUF:
> @@ -251,6 +251,16 @@ xfs_defer_trans_roll(
>  				bplist[bpcount++] = bli->bli_buf;
>  			}
>  			break;
> +		case XFS_LI_INODE:
> +			ili = container_of(lip, struct xfs_inode_log_item,
> +					   ili_item);
> +			if (ili->ili_lock_flags == 0) {
> +				ASSERT(ipcount < XFS_DEFER_OPS_NR_INODES);

Same complaint here as in the previous patch about the behavior change
in the overflow check.  I admit I sucked at consistently checking the
_defer_ijoin return value, sorry about that.  :(

--D

> +				xfs_trans_log_inode(*tp, ili->ili_inode,
> +						    XFS_ILOG_CORE);
> +				iplist[ipcount++] = ili->ili_inode;
> +			}
> +			break;
>  		default:
>  			break;
>  		}
> @@ -268,8 +278,8 @@ xfs_defer_trans_roll(
>  	}
>  
>  	/* Rejoin the joined inodes. */
> -	for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++)
> -		xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0);
> +	for (i = 0; i < ipcount; i++)
> +		xfs_trans_ijoin(*tp, iplist[i], 0);
>  
>  	/* Rejoin the buffers and dirty them so the log moves forward. */
>  	for (i = 0; i < bpcount; i++) {
> @@ -288,30 +298,6 @@ xfs_defer_has_unfinished_work(
>  	return !list_empty(&dop->dop_pending) || !list_empty(&dop->dop_intake);
>  }
>  
> -/*
> - * Add this inode to the deferred op.  Each joined inode is relogged
> - * each time we roll the transaction.
> - */
> -int
> -xfs_defer_ijoin(
> -	struct xfs_defer_ops		*dop,
> -	struct xfs_inode		*ip)
> -{
> -	int				i;
> -
> -	for (i = 0; i < XFS_DEFER_OPS_NR_INODES; i++) {
> -		if (dop->dop_inodes[i] == ip)
> -			return 0;
> -		else if (dop->dop_inodes[i] == NULL) {
> -			dop->dop_inodes[i] = ip;
> -			return 0;
> -		}
> -	}
> -
> -	ASSERT(0);
> -	return -EFSCORRUPTED;
> -}
> -
>  /*
>   * Reset an already used dfops after finish.
>   */
> @@ -319,11 +305,7 @@ static void
>  xfs_defer_reset(
>  	struct xfs_trans	*tp)
>  {
> -	struct xfs_defer_ops	*dop = tp->t_dfops;
> -
> -	ASSERT(!xfs_defer_has_unfinished_work(dop));
> -
> -	memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes));
> +	ASSERT(!xfs_defer_has_unfinished_work(tp->t_dfops));
>  
>  	/*
>  	 * Low mode state transfers across transaction rolls to mirror dfops
> @@ -585,8 +567,6 @@ xfs_defer_move(
>  	list_splice_init(&src->dop_intake, &dst->dop_intake);
>  	list_splice_init(&src->dop_pending, &dst->dop_pending);
>  
> -	memcpy(dst->dop_inodes, src->dop_inodes, sizeof(dst->dop_inodes));
> -
>  	/*
>  	 * Low free space mode was historically controlled by a dfops field.
>  	 * This meant that low mode state potentially carried across multiple
> diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
> index 4a8bb838adf2..bf1e9f78561e 100644
> --- a/fs/xfs/libxfs/xfs_defer.h
> +++ b/fs/xfs/libxfs/xfs_defer.h
> @@ -42,7 +42,6 @@ int xfs_defer_finish(struct xfs_trans **tp);
>  void xfs_defer_cancel(struct xfs_trans *);
>  void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
>  bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);
> -int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip);
>  void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
>  
>  /* Description of a deferred type. */
> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> index 0c58a66b39e5..30ac1300dc49 100644
> --- a/fs/xfs/xfs_bmap_util.c
> +++ b/fs/xfs/xfs_bmap_util.c
> @@ -979,7 +979,6 @@ xfs_alloc_file_space(
>  		/*
>  		 * Complete the transaction
>  		 */
> -		xfs_defer_ijoin(tp->t_dfops, ip);
>  		error = xfs_trans_commit(tp);
>  		xfs_iunlock(ip, XFS_ILOCK_EXCL);
>  		if (error)
> @@ -1037,8 +1036,6 @@ xfs_unmap_extent(
>  	if (error)
>  		goto out_trans_cancel;
>  
> -	xfs_defer_ijoin(tp->t_dfops, ip);
> -
>  	error = xfs_trans_commit(tp);
>  out_unlock:
>  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
> @@ -1624,7 +1621,6 @@ xfs_swap_extent_rmap(
>  			if (error)
>  				goto out_defer;
>  
> -			xfs_defer_ijoin(tp->t_dfops, ip);
>  			error = xfs_defer_finish(tpp);
>  			tp = *tpp;
>  			if (error)
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 441c8593cfd7..7bb46a0eecfc 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -1569,7 +1569,6 @@ xfs_itruncate_extents_flags(
>  		 * Duplicate the transaction that has the permanent
>  		 * reservation and commit the old transaction.
>  		 */
> -		xfs_defer_ijoin(tp->t_dfops, ip);
>  		error = xfs_defer_finish(&tp);
>  		if (error)
>  			goto out_bmap_cancel;
> @@ -1810,7 +1809,6 @@ xfs_inactive_ifree(
>  	 * Just ignore errors at this point.  There is nothing we can do except
>  	 * to try to keep going. Make sure it's not a silent error.
>  	 */
> -	xfs_defer_ijoin(tp->t_dfops, ip);
>  	error = xfs_trans_commit(tp);
>  	if (error)
>  		xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index 464b4b3225bb..8e8ca9f03f0e 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -261,7 +261,6 @@ xfs_iomap_write_direct(
>  	/*
>  	 * Complete the transaction
>  	 */
> -	xfs_defer_ijoin(tp->t_dfops, ip);
>  	error = xfs_trans_commit(tp);
>  	if (error)
>  		goto out_unlock;
> @@ -763,7 +762,6 @@ xfs_iomap_write_allocate(
>  			if (error)
>  				goto trans_cancel;
>  
> -			xfs_defer_ijoin(tp->t_dfops, ip);
>  			error = xfs_trans_commit(tp);
>  			if (error)
>  				goto error0;
> @@ -881,7 +879,6 @@ xfs_iomap_write_unwritten(
>  			xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
>  		}
>  
> -		xfs_defer_ijoin(tp->t_dfops, ip);
>  		error = xfs_trans_commit(tp);
>  		xfs_iunlock(ip, XFS_ILOCK_EXCL);
>  		if (error)
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index e986fcf928e5..dce8ba8ab681 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -435,7 +435,6 @@ xfs_reflink_allocate_cow(
>  	xfs_inode_set_cowblocks_tag(ip);
>  
>  	/* Finish up. */
> -	xfs_defer_ijoin(tp->t_dfops, ip);
>  	error = xfs_trans_commit(tp);
>  	if (error)
>  		return error;
> @@ -518,7 +517,6 @@ xfs_reflink_cancel_cow_blocks(
>  					NULL);
>  
>  			/* Roll the transaction */
> -			xfs_defer_ijoin((*tpp)->t_dfops, ip);
>  			error = xfs_defer_finish(tpp);
>  			if (error) {
>  				xfs_defer_cancel(*tpp);
> @@ -716,7 +714,6 @@ xfs_reflink_end_cow(
>  		/* Remove the mapping from the CoW fork. */
>  		xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
>  
> -		xfs_defer_ijoin(tp->t_dfops, ip);
>  		error = xfs_defer_finish(&tp);
>  		if (error)
>  			goto out_cancel;
> @@ -1077,7 +1074,6 @@ xfs_reflink_remap_extent(
>  
>  next_extent:
>  		/* Process all the deferred stuff. */
> -		xfs_defer_ijoin(tp->t_dfops, ip);
>  		error = xfs_defer_finish(&tp);
>  		if (error)
>  			goto out_cancel;
> diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
> index 2bfe7fbbedb2..a3e98c64b6e3 100644
> --- a/fs/xfs/xfs_symlink.c
> +++ b/fs/xfs/xfs_symlink.c
> @@ -454,7 +454,6 @@ xfs_inactive_symlink_rmt(
>  	 * Commit the transaction. This first logs the EFI and the inode, then
>  	 * rolls and commits the transaction that frees the extents.
>  	 */
> -	xfs_defer_ijoin(tp->t_dfops, ip);
>  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
>  	error = xfs_trans_commit(tp);
>  	if (error) {
> diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> index 581456c79197..8665d45b82c6 100644
> --- a/fs/xfs/xfs_trans.h
> +++ b/fs/xfs/xfs_trans.h
> @@ -97,9 +97,6 @@ void	xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item,
>  struct xfs_defer_ops {
>  	struct list_head	dop_intake;	/* unlogged pending work */
>  	struct list_head	dop_pending;	/* logged pending work */
> -
> -	/* relog these with each roll */
> -	struct xfs_inode	*dop_inodes[XFS_DEFER_OPS_NR_INODES];
>  };
>  
>  /*
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 09/15] xfs: drop dop param from xfs_defer_op_type ->finish_item() callback
  2018-07-30 16:45 ` [PATCH 09/15] xfs: drop dop param from xfs_defer_op_type ->finish_item() callback Brian Foster
@ 2018-07-30 20:23   ` Darrick J. Wong
  2018-07-31  8:20   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 20:23 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:14PM -0400, Brian Foster wrote:
> The dfops infrastructure ->finish_item() callback passes the
> transaction and dfops as separate parameters. Since dfops is always
> part of a transaction, the latter parameter is no longer necessary.
> Remove it from the various callbacks.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks ok,
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/xfs/libxfs/xfs_bmap.c     |  2 --
>  fs/xfs/libxfs/xfs_bmap.h     |  6 +++---
>  fs/xfs/libxfs/xfs_defer.c    |  2 +-
>  fs/xfs/libxfs/xfs_defer.h    |  4 ++--
>  fs/xfs/libxfs/xfs_refcount.c |  2 +-
>  fs/xfs/libxfs/xfs_refcount.h |  7 +++----
>  fs/xfs/xfs_bmap_item.c       |  5 ++---
>  fs/xfs/xfs_refcount_item.c   |  4 ++--
>  fs/xfs/xfs_trans.h           | 10 +++++-----
>  fs/xfs/xfs_trans_bmap.c      |  6 ++----
>  fs/xfs/xfs_trans_extfree.c   |  2 --
>  fs/xfs/xfs_trans_refcount.c  |  6 ++----
>  fs/xfs/xfs_trans_rmap.c      |  1 -
>  13 files changed, 23 insertions(+), 34 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index 5cd490dc891a..d20f541b7061 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -6045,7 +6045,6 @@ xfs_bmap_unmap_extent(
>  int
>  xfs_bmap_finish_one(
>  	struct xfs_trans		*tp,
> -	struct xfs_defer_ops		*dfops,
>  	struct xfs_inode		*ip,
>  	enum xfs_bmap_intent_type	type,
>  	int				whichfork,
> @@ -6072,7 +6071,6 @@ xfs_bmap_finish_one(
>  
>  	switch (type) {
>  	case XFS_BMAP_MAP:
> -		ASSERT(dfops == tp->t_dfops);
>  		error = xfs_bmapi_remap(tp, ip, startoff, *blockcount,
>  				startblock, 0);
>  		*blockcount = 0;
> diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
> index 2e8555c1229a..9165a878edcd 100644
> --- a/fs/xfs/libxfs/xfs_bmap.h
> +++ b/fs/xfs/libxfs/xfs_bmap.h
> @@ -252,9 +252,9 @@ struct xfs_bmap_intent {
>  	struct xfs_bmbt_irec			bi_bmap;
>  };
>  
> -int	xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_defer_ops *dfops,
> -		struct xfs_inode *ip, enum xfs_bmap_intent_type type,
> -		int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock,
> +int	xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_inode *ip,
> +		enum xfs_bmap_intent_type type, int whichfork,
> +		xfs_fileoff_t startoff, xfs_fsblock_t startblock,
>  		xfs_filblks_t *blockcount, xfs_exntst_t state);
>  int	xfs_bmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
>  		struct xfs_inode *ip, struct xfs_bmbt_irec *imap);
> diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> index 6230e74163ac..7fb7edd5d63e 100644
> --- a/fs/xfs/libxfs/xfs_defer.c
> +++ b/fs/xfs/libxfs/xfs_defer.c
> @@ -365,7 +365,7 @@ xfs_defer_finish_noroll(
>  		list_for_each_safe(li, n, &dfp->dfp_work) {
>  			list_del(li);
>  			dfp->dfp_count--;
> -			error = dfp->dfp_type->finish_item(*tp, dop, li,
> +			error = dfp->dfp_type->finish_item(*tp, li,
>  					dfp->dfp_done, &state);
>  			if (error == -EAGAIN) {
>  				/*
> diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
> index bf1e9f78561e..0de7504e5651 100644
> --- a/fs/xfs/libxfs/xfs_defer.h
> +++ b/fs/xfs/libxfs/xfs_defer.h
> @@ -50,8 +50,8 @@ struct xfs_defer_op_type {
>  	unsigned int		max_items;
>  	void (*abort_intent)(void *);
>  	void *(*create_done)(struct xfs_trans *, void *, unsigned int);
> -	int (*finish_item)(struct xfs_trans *, struct xfs_defer_ops *,
> -			struct list_head *, void *, void **);
> +	int (*finish_item)(struct xfs_trans *, struct list_head *, void *,
> +			void **);
>  	void (*finish_cleanup)(struct xfs_trans *, void *, int);
>  	void (*cancel_item)(struct list_head *);
>  	int (*diff_items)(void *, struct list_head *, struct list_head *);
> diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c
> index 4cbc2efb099e..86f297ca90cd 100644
> --- a/fs/xfs/libxfs/xfs_refcount.c
> +++ b/fs/xfs/libxfs/xfs_refcount.c
> @@ -1082,7 +1082,6 @@ xfs_refcount_finish_one_cleanup(
>  int
>  xfs_refcount_finish_one(
>  	struct xfs_trans		*tp,
> -	struct xfs_defer_ops		*dfops,
>  	enum xfs_refcount_intent_type	type,
>  	xfs_fsblock_t			startblock,
>  	xfs_extlen_t			blockcount,
> @@ -1091,6 +1090,7 @@ xfs_refcount_finish_one(
>  	struct xfs_btree_cur		**pcur)
>  {
>  	struct xfs_mount		*mp = tp->t_mountp;
> +	struct xfs_defer_ops		*dfops = tp->t_dfops;
>  	struct xfs_btree_cur		*rcur;
>  	struct xfs_buf			*agbp = NULL;
>  	int				error = 0;
> diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h
> index 5fef74412727..3b72c6dbf6ad 100644
> --- a/fs/xfs/libxfs/xfs_refcount.h
> +++ b/fs/xfs/libxfs/xfs_refcount.h
> @@ -37,10 +37,9 @@ extern int xfs_refcount_decrease_extent(struct xfs_mount *mp,
>  extern void xfs_refcount_finish_one_cleanup(struct xfs_trans *tp,
>  		struct xfs_btree_cur *rcur, int error);
>  extern int xfs_refcount_finish_one(struct xfs_trans *tp,
> -		struct xfs_defer_ops *dfops, enum xfs_refcount_intent_type type,
> -		xfs_fsblock_t startblock, xfs_extlen_t blockcount,
> -		xfs_fsblock_t *new_fsb, xfs_extlen_t *new_len,
> -		struct xfs_btree_cur **pcur);
> +		enum xfs_refcount_intent_type type, xfs_fsblock_t startblock,
> +		xfs_extlen_t blockcount, xfs_fsblock_t *new_fsb,
> +		xfs_extlen_t *new_len, struct xfs_btree_cur **pcur);
>  
>  extern int xfs_refcount_find_shared(struct xfs_btree_cur *cur,
>  		xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno,
> diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
> index 4b4318ea4b76..328a5c60000b 100644
> --- a/fs/xfs/xfs_bmap_item.c
> +++ b/fs/xfs/xfs_bmap_item.c
> @@ -475,9 +475,8 @@ xfs_bui_recover(
>  	xfs_trans_ijoin(tp, ip, 0);
>  
>  	count = bmap->me_len;
> -	error = xfs_trans_log_finish_bmap_update(tp, budp, tp->t_dfops, type,
> -			ip, whichfork, bmap->me_startoff,
> -			bmap->me_startblock, &count, state);
> +	error = xfs_trans_log_finish_bmap_update(tp, budp, type, ip, whichfork,
> +			bmap->me_startoff, bmap->me_startblock, &count, state);
>  	if (error)
>  		goto err_inode;
>  
> diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
> index 829b7a5bc707..f6a3249aa2d4 100644
> --- a/fs/xfs/xfs_refcount_item.c
> +++ b/fs/xfs/xfs_refcount_item.c
> @@ -479,8 +479,8 @@ xfs_cui_recover(
>  			new_len = refc->pe_len;
>  		} else
>  			error = xfs_trans_log_finish_refcount_update(tp, cudp,
> -				tp->t_dfops, type, refc->pe_startblock,
> -				refc->pe_len, &new_fsb, &new_len, &rcur);
> +				type, refc->pe_startblock, refc->pe_len,
> +				&new_fsb, &new_len, &rcur);
>  		if (error)
>  			goto abort_error;
>  
> diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> index 8665d45b82c6..299656dbf324 100644
> --- a/fs/xfs/xfs_trans.h
> +++ b/fs/xfs/xfs_trans.h
> @@ -268,7 +268,7 @@ void xfs_refcount_update_init_defer_op(void);
>  struct xfs_cud_log_item *xfs_trans_get_cud(struct xfs_trans *tp,
>  		struct xfs_cui_log_item *cuip);
>  int xfs_trans_log_finish_refcount_update(struct xfs_trans *tp,
> -		struct xfs_cud_log_item *cudp, struct xfs_defer_ops *dfops,
> +		struct xfs_cud_log_item *cudp,
>  		enum xfs_refcount_intent_type type, xfs_fsblock_t startblock,
>  		xfs_extlen_t blockcount, xfs_fsblock_t *new_fsb,
>  		xfs_extlen_t *new_len, struct xfs_btree_cur **pcur);
> @@ -280,9 +280,9 @@ void xfs_bmap_update_init_defer_op(void);
>  struct xfs_bud_log_item *xfs_trans_get_bud(struct xfs_trans *tp,
>  		struct xfs_bui_log_item *buip);
>  int xfs_trans_log_finish_bmap_update(struct xfs_trans *tp,
> -		struct xfs_bud_log_item *rudp, struct xfs_defer_ops *dfops,
> -		enum xfs_bmap_intent_type type, struct xfs_inode *ip,
> -		int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock,
> -		xfs_filblks_t *blockcount, xfs_exntst_t state);
> +		struct xfs_bud_log_item *rudp, enum xfs_bmap_intent_type type,
> +		struct xfs_inode *ip, int whichfork, xfs_fileoff_t startoff,
> +		xfs_fsblock_t startblock, xfs_filblks_t *blockcount,
> +		xfs_exntst_t state);
>  
>  #endif	/* __XFS_TRANS_H__ */
> diff --git a/fs/xfs/xfs_trans_bmap.c b/fs/xfs/xfs_trans_bmap.c
> index a15a5cd867f9..741c558b2179 100644
> --- a/fs/xfs/xfs_trans_bmap.c
> +++ b/fs/xfs/xfs_trans_bmap.c
> @@ -43,7 +43,6 @@ int
>  xfs_trans_log_finish_bmap_update(
>  	struct xfs_trans		*tp,
>  	struct xfs_bud_log_item		*budp,
> -	struct xfs_defer_ops		*dop,
>  	enum xfs_bmap_intent_type	type,
>  	struct xfs_inode		*ip,
>  	int				whichfork,
> @@ -54,7 +53,7 @@ xfs_trans_log_finish_bmap_update(
>  {
>  	int				error;
>  
> -	error = xfs_bmap_finish_one(tp, dop, ip, type, whichfork, startoff,
> +	error = xfs_bmap_finish_one(tp, ip, type, whichfork, startoff,
>  			startblock, blockcount, state);
>  
>  	/*
> @@ -176,7 +175,6 @@ xfs_bmap_update_create_done(
>  STATIC int
>  xfs_bmap_update_finish_item(
>  	struct xfs_trans		*tp,
> -	struct xfs_defer_ops		*dop,
>  	struct list_head		*item,
>  	void				*done_item,
>  	void				**state)
> @@ -187,7 +185,7 @@ xfs_bmap_update_finish_item(
>  
>  	bmap = container_of(item, struct xfs_bmap_intent, bi_list);
>  	count = bmap->bi_bmap.br_blockcount;
> -	error = xfs_trans_log_finish_bmap_update(tp, done_item, dop,
> +	error = xfs_trans_log_finish_bmap_update(tp, done_item,
>  			bmap->bi_type,
>  			bmap->bi_owner, bmap->bi_whichfork,
>  			bmap->bi_bmap.br_startoff,
> diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c
> index bd66c76f55e6..855c0b651fd4 100644
> --- a/fs/xfs/xfs_trans_extfree.c
> +++ b/fs/xfs/xfs_trans_extfree.c
> @@ -171,7 +171,6 @@ xfs_extent_free_create_done(
>  STATIC int
>  xfs_extent_free_finish_item(
>  	struct xfs_trans		*tp,
> -	struct xfs_defer_ops		*dop,
>  	struct list_head		*item,
>  	void				*done_item,
>  	void				**state)
> @@ -226,7 +225,6 @@ static const struct xfs_defer_op_type xfs_extent_free_defer_type = {
>  STATIC int
>  xfs_agfl_free_finish_item(
>  	struct xfs_trans		*tp,
> -	struct xfs_defer_ops		*dop,
>  	struct list_head		*item,
>  	void				*done_item,
>  	void				**state)
> diff --git a/fs/xfs/xfs_trans_refcount.c b/fs/xfs/xfs_trans_refcount.c
> index 46dd4fca8aa7..523c55663954 100644
> --- a/fs/xfs/xfs_trans_refcount.c
> +++ b/fs/xfs/xfs_trans_refcount.c
> @@ -42,7 +42,6 @@ int
>  xfs_trans_log_finish_refcount_update(
>  	struct xfs_trans		*tp,
>  	struct xfs_cud_log_item		*cudp,
> -	struct xfs_defer_ops		*dop,
>  	enum xfs_refcount_intent_type	type,
>  	xfs_fsblock_t			startblock,
>  	xfs_extlen_t			blockcount,
> @@ -52,7 +51,7 @@ xfs_trans_log_finish_refcount_update(
>  {
>  	int				error;
>  
> -	error = xfs_refcount_finish_one(tp, dop, type, startblock,
> +	error = xfs_refcount_finish_one(tp, type, startblock,
>  			blockcount, new_fsb, new_len, pcur);
>  
>  	/*
> @@ -169,7 +168,6 @@ xfs_refcount_update_create_done(
>  STATIC int
>  xfs_refcount_update_finish_item(
>  	struct xfs_trans		*tp,
> -	struct xfs_defer_ops		*dop,
>  	struct list_head		*item,
>  	void				*done_item,
>  	void				**state)
> @@ -180,7 +178,7 @@ xfs_refcount_update_finish_item(
>  	int				error;
>  
>  	refc = container_of(item, struct xfs_refcount_intent, ri_list);
> -	error = xfs_trans_log_finish_refcount_update(tp, done_item, dop,
> +	error = xfs_trans_log_finish_refcount_update(tp, done_item,
>  			refc->ri_type,
>  			refc->ri_startblock,
>  			refc->ri_blockcount,
> diff --git a/fs/xfs/xfs_trans_rmap.c b/fs/xfs/xfs_trans_rmap.c
> index 726d8e2c0558..05b00e40251f 100644
> --- a/fs/xfs/xfs_trans_rmap.c
> +++ b/fs/xfs/xfs_trans_rmap.c
> @@ -193,7 +193,6 @@ xfs_rmap_update_create_done(
>  STATIC int
>  xfs_rmap_update_finish_item(
>  	struct xfs_trans		*tp,
> -	struct xfs_defer_ops		*dop,
>  	struct list_head		*item,
>  	void				*done_item,
>  	void				**state)
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 10/15] xfs: clean out superfluous dfops dop params/vars
  2018-07-30 16:45 ` [PATCH 10/15] xfs: clean out superfluous dfops dop params/vars Brian Foster
@ 2018-07-30 20:24   ` Darrick J. Wong
  2018-07-31  8:20   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 20:24 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:15PM -0400, Brian Foster wrote:
> The dfops code still passes around the xfs_defer_ops pointer
> superfluously in a few places. Clean this up wherever the
> transaction will suffice.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks ok,
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/xfs/libxfs/xfs_defer.c | 43 +++++++++++++++++++--------------------
>  fs/xfs/libxfs/xfs_defer.h |  2 +-
>  2 files changed, 22 insertions(+), 23 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> index 7fb7edd5d63e..7b84e3a4b7f3 100644
> --- a/fs/xfs/libxfs/xfs_defer.c
> +++ b/fs/xfs/libxfs/xfs_defer.c
> @@ -181,9 +181,9 @@ static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX];
>   */
>  STATIC void
>  xfs_defer_intake_work(
> -	struct xfs_trans		*tp,
> -	struct xfs_defer_ops		*dop)
> +	struct xfs_trans		*tp)
>  {
> +	struct xfs_defer_ops		*dop = tp->t_dfops;
>  	struct list_head		*li;
>  	struct xfs_defer_pending	*dfp;
>  
> @@ -204,9 +204,9 @@ xfs_defer_intake_work(
>  STATIC void
>  xfs_defer_trans_abort(
>  	struct xfs_trans		*tp,
> -	struct xfs_defer_ops		*dop,
>  	int				error)
>  {
> +	struct xfs_defer_ops		*dop = tp->t_dfops;
>  	struct xfs_defer_pending	*dfp;
>  
>  	trace_xfs_defer_trans_abort(tp->t_mountp, dop, _RET_IP_);
> @@ -230,7 +230,6 @@ STATIC int
>  xfs_defer_trans_roll(
>  	struct xfs_trans		**tp)
>  {
> -	struct xfs_defer_ops		*dop = (*tp)->t_dfops;
>  	struct xfs_buf_log_item		*bli;
>  	struct xfs_inode_log_item	*ili;
>  	struct xfs_log_item		*lip;
> @@ -266,14 +265,14 @@ xfs_defer_trans_roll(
>  		}
>  	}
>  
> -	trace_xfs_defer_trans_roll((*tp)->t_mountp, dop, _RET_IP_);
> +	trace_xfs_defer_trans_roll((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_);
>  
>  	/* Roll the transaction. */
>  	error = xfs_trans_roll(tp);
> -	dop = (*tp)->t_dfops;
>  	if (error) {
> -		trace_xfs_defer_trans_roll_error((*tp)->t_mountp, dop, error);
> -		xfs_defer_trans_abort(*tp, dop, error);
> +		trace_xfs_defer_trans_roll_error((*tp)->t_mountp,
> +						 (*tp)->t_dfops, error);
> +		xfs_defer_trans_abort(*tp,  error);
>  		return error;
>  	}
>  
> @@ -293,9 +292,10 @@ xfs_defer_trans_roll(
>  /* Do we have any work items to finish? */
>  bool
>  xfs_defer_has_unfinished_work(
> -	struct xfs_defer_ops		*dop)
> +	struct xfs_trans		*tp)
>  {
> -	return !list_empty(&dop->dop_pending) || !list_empty(&dop->dop_intake);
> +	return !list_empty(&tp->t_dfops->dop_pending) ||
> +		!list_empty(&tp->t_dfops->dop_intake);
>  }
>  
>  /*
> @@ -305,7 +305,7 @@ static void
>  xfs_defer_reset(
>  	struct xfs_trans	*tp)
>  {
> -	ASSERT(!xfs_defer_has_unfinished_work(tp->t_dfops));
> +	ASSERT(!xfs_defer_has_unfinished_work(tp));
>  
>  	/*
>  	 * Low mode state transfers across transaction rolls to mirror dfops
> @@ -326,7 +326,6 @@ int
>  xfs_defer_finish_noroll(
>  	struct xfs_trans		**tp)
>  {
> -	struct xfs_defer_ops		*dop = (*tp)->t_dfops;
>  	struct xfs_defer_pending	*dfp;
>  	struct list_head		*li;
>  	struct list_head		*n;
> @@ -336,24 +335,22 @@ xfs_defer_finish_noroll(
>  
>  	ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
>  
> -	trace_xfs_defer_finish((*tp)->t_mountp, dop, _RET_IP_);
> +	trace_xfs_defer_finish((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_);
>  
>  	/* Until we run out of pending work to finish... */
> -	while (xfs_defer_has_unfinished_work(dop)) {
> +	while (xfs_defer_has_unfinished_work(*tp)) {
>  		/* Log intents for work items sitting in the intake. */
> -		xfs_defer_intake_work(*tp, dop);
> +		xfs_defer_intake_work(*tp);
>  
>  		/*
> -		 * Roll the transaction and update dop in case dfops was
> -		 * embedded in the transaction.
> +		 * Roll the transaction.
>  		 */
>  		error = xfs_defer_trans_roll(tp);
>  		if (error)
>  			goto out;
> -		dop = (*tp)->t_dfops;
>  
>  		/* Log an intent-done item for the first pending item. */
> -		dfp = list_first_entry(&dop->dop_pending,
> +		dfp = list_first_entry(&(*tp)->t_dfops->dop_pending,
>  				struct xfs_defer_pending, dfp_list);
>  		trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp);
>  		dfp->dfp_done = dfp->dfp_type->create_done(*tp, dfp->dfp_intent,
> @@ -384,7 +381,7 @@ xfs_defer_finish_noroll(
>  				 */
>  				if (cleanup_fn)
>  					cleanup_fn(*tp, state, error);
> -				xfs_defer_trans_abort(*tp, dop, error);
> +				xfs_defer_trans_abort(*tp, error);
>  				goto out;
>  			}
>  		}
> @@ -414,9 +411,11 @@ xfs_defer_finish_noroll(
>  
>  out:
>  	if (error)
> -		trace_xfs_defer_finish_error((*tp)->t_mountp, dop, error);
> +		trace_xfs_defer_finish_error((*tp)->t_mountp, (*tp)->t_dfops,
> +					     error);
>  	 else
> -		trace_xfs_defer_finish_done((*tp)->t_mountp, dop, _RET_IP_);
> +		trace_xfs_defer_finish_done((*tp)->t_mountp, (*tp)->t_dfops,
> +					    _RET_IP_);
>  
>  	return error;
>  }
> diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
> index 0de7504e5651..f051c8056141 100644
> --- a/fs/xfs/libxfs/xfs_defer.h
> +++ b/fs/xfs/libxfs/xfs_defer.h
> @@ -41,7 +41,7 @@ int xfs_defer_finish_noroll(struct xfs_trans **tp);
>  int xfs_defer_finish(struct xfs_trans **tp);
>  void xfs_defer_cancel(struct xfs_trans *);
>  void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
> -bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);
> +bool xfs_defer_has_unfinished_work(struct xfs_trans *tp);
>  void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
>  
>  /* Description of a deferred type. */
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 11/15] xfs: cancel dfops on xfs_defer_finish() error
  2018-07-30 16:45 ` [PATCH 11/15] xfs: cancel dfops on xfs_defer_finish() error Brian Foster
@ 2018-07-30 20:27   ` Darrick J. Wong
  2018-07-31  8:21   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 20:27 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:16PM -0400, Brian Foster wrote:
> The current semantics of xfs_defer_finish() require the caller to
> call xfs_defer_cancel() on error. This is slightly inconsistent with
> transaction commit error handling where a failed commit cleans up
> the transaction before returning.
> 
> More significantly, the only requirement for exposure of
> ->dop_pending outside of xfs_defer_finish() is so that
> xfs_defer_cancel() can drain it on error. Since the only recourse of
> xfs_defer_finish() errors is cancellation, mirror the transaction
> logic and cancel remaining dfops before returning from
> xfs_defer_finish() with an error.
> 
> Beside simplifying xfs_defer_finish() semantics, this ensures that
> xfs_defer_finish() always returns with an empty ->dop_pending and
> thus facilitates removal of the list from xfs_defer_ops.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks ok,
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/xfs/libxfs/xfs_attr.c        | 16 ++++++++--------
>  fs/xfs/libxfs/xfs_attr_remote.c |  4 ++--
>  fs/xfs/libxfs/xfs_defer.c       | 11 ++++++-----
>  fs/xfs/xfs_bmap_util.c          |  2 +-
>  fs/xfs/xfs_dquot.c              |  2 +-
>  fs/xfs/xfs_inode.c              |  2 +-
>  fs/xfs/xfs_reflink.c            |  4 +---
>  fs/xfs/xfs_trans.c              |  4 +---
>  8 files changed, 21 insertions(+), 24 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> index 3190dfc21b60..1e671d4eb6fa 100644
> --- a/fs/xfs/libxfs/xfs_attr.c
> +++ b/fs/xfs/libxfs/xfs_attr.c
> @@ -590,7 +590,7 @@ xfs_attr_leaf_addname(
>  			goto out_defer_cancel;
>  		error = xfs_defer_finish(&args->trans);
>  		if (error)
> -			goto out_defer_cancel;
> +			return error;
>  
>  		/*
>  		 * Commit the current trans (including the inode) and start
> @@ -678,7 +678,7 @@ xfs_attr_leaf_addname(
>  				goto out_defer_cancel;
>  			error = xfs_defer_finish(&args->trans);
>  			if (error)
> -				goto out_defer_cancel;
> +				return error;
>  		}
>  
>  		/*
> @@ -741,7 +741,7 @@ xfs_attr_leaf_removename(
>  			goto out_defer_cancel;
>  		error = xfs_defer_finish(&args->trans);
>  		if (error)
> -			goto out_defer_cancel;
> +			return error;
>  	}
>  	return 0;
>  out_defer_cancel:
> @@ -867,7 +867,7 @@ xfs_attr_node_addname(
>  				goto out_defer_cancel;
>  			error = xfs_defer_finish(&args->trans);
>  			if (error)
> -				goto out_defer_cancel;
> +				goto out;
>  
>  			/*
>  			 * Commit the node conversion and start the next
> @@ -891,7 +891,7 @@ xfs_attr_node_addname(
>  			goto out_defer_cancel;
>  		error = xfs_defer_finish(&args->trans);
>  		if (error)
> -			goto out_defer_cancel;
> +			goto out;
>  	} else {
>  		/*
>  		 * Addition succeeded, update Btree hashvals.
> @@ -987,7 +987,7 @@ xfs_attr_node_addname(
>  				goto out_defer_cancel;
>  			error = xfs_defer_finish(&args->trans);
>  			if (error)
> -				goto out_defer_cancel;
> +				goto out;
>  		}
>  
>  		/*
> @@ -1110,7 +1110,7 @@ xfs_attr_node_removename(
>  			goto out_defer_cancel;
>  		error = xfs_defer_finish(&args->trans);
>  		if (error)
> -			goto out_defer_cancel;
> +			goto out;
>  		/*
>  		 * Commit the Btree join operation and start a new trans.
>  		 */
> @@ -1141,7 +1141,7 @@ xfs_attr_node_removename(
>  				goto out_defer_cancel;
>  			error = xfs_defer_finish(&args->trans);
>  			if (error)
> -				goto out_defer_cancel;
> +				goto out;
>  		} else
>  			xfs_trans_brelse(args->trans, bp);
>  	}
> diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c
> index f52552313773..af094063e402 100644
> --- a/fs/xfs/libxfs/xfs_attr_remote.c
> +++ b/fs/xfs/libxfs/xfs_attr_remote.c
> @@ -488,7 +488,7 @@ xfs_attr_rmtval_set(
>  			goto out_defer_cancel;
>  		error = xfs_defer_finish(&args->trans);
>  		if (error)
> -			goto out_defer_cancel;
> +			return error;
>  
>  		ASSERT(nmap == 1);
>  		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
> @@ -628,7 +628,7 @@ xfs_attr_rmtval_remove(
>  			goto out_defer_cancel;
>  		error = xfs_defer_finish(&args->trans);
>  		if (error)
> -			goto out_defer_cancel;
> +			return error;
>  
>  		/*
>  		 * Close out trans and start the next one in the chain.
> diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> index 7b84e3a4b7f3..66848ede62c0 100644
> --- a/fs/xfs/libxfs/xfs_defer.c
> +++ b/fs/xfs/libxfs/xfs_defer.c
> @@ -410,14 +410,15 @@ xfs_defer_finish_noroll(
>  	}
>  
>  out:
> -	if (error)
> +	if (error) {
>  		trace_xfs_defer_finish_error((*tp)->t_mountp, (*tp)->t_dfops,
>  					     error);
> -	 else
> -		trace_xfs_defer_finish_done((*tp)->t_mountp, (*tp)->t_dfops,
> -					    _RET_IP_);
> +		xfs_defer_cancel(*tp);
> +		return error;
> +	}
>  
> -	return error;
> +	trace_xfs_defer_finish_done((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_);
> +	return 0;
>  }
>  
>  int
> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> index 30ac1300dc49..d9dad399440a 100644
> --- a/fs/xfs/xfs_bmap_util.c
> +++ b/fs/xfs/xfs_bmap_util.c
> @@ -1624,7 +1624,7 @@ xfs_swap_extent_rmap(
>  			error = xfs_defer_finish(tpp);
>  			tp = *tpp;
>  			if (error)
> -				goto out_defer;
> +				goto out;
>  
>  			tirec.br_startoff += rlen;
>  			if (tirec.br_startblock != HOLESTARTBLOCK &&
> diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
> index e1196854dbcd..70a76ac41f01 100644
> --- a/fs/xfs/xfs_dquot.c
> +++ b/fs/xfs/xfs_dquot.c
> @@ -371,7 +371,7 @@ xfs_dquot_disk_alloc(
>  	tp = *tpp;
>  	if (error) {
>  		xfs_buf_relse(bp);
> -		goto error1;
> +		goto error0;
>  	}
>  	*bpp = bp;
>  	return 0;
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 7bb46a0eecfc..d957a46dc1cb 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -1571,7 +1571,7 @@ xfs_itruncate_extents_flags(
>  		 */
>  		error = xfs_defer_finish(&tp);
>  		if (error)
> -			goto out_bmap_cancel;
> +			goto out;
>  
>  		error = xfs_trans_roll_inode(&tp, ip);
>  		if (error)
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index dce8ba8ab681..2ec562d75494 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -518,10 +518,8 @@ xfs_reflink_cancel_cow_blocks(
>  
>  			/* Roll the transaction */
>  			error = xfs_defer_finish(tpp);
> -			if (error) {
> -				xfs_defer_cancel(*tpp);
> +			if (error)
>  				break;
> -			}
>  
>  			/* Remove the mapping from the CoW fork. */
>  			xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index 8c088568b05d..20750cd9c9e7 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -928,10 +928,8 @@ __xfs_trans_commit(
>  	/* finish deferred items on final commit */
>  	if (!regrant && (tp->t_flags & XFS_TRANS_PERM_LOG_RES)) {
>  		error = xfs_defer_finish_noroll(&tp);
> -		if (error) {
> -			xfs_defer_cancel(tp);
> +		if (error)
>  			goto out_unreserve;
> -		}
>  	}
>  
>  	/*
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 12/15] xfs: replace xfs_defer_ops ->dop_pending with on-stack list
  2018-07-30 16:45 ` [PATCH 12/15] xfs: replace xfs_defer_ops ->dop_pending with on-stack list Brian Foster
@ 2018-07-30 20:47   ` Darrick J. Wong
  2018-07-31 11:50     ` Brian Foster
  2018-07-31  8:30   ` Christoph Hellwig
  1 sibling, 1 reply; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 20:47 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:17PM -0400, Brian Foster wrote:
> The xfs_defer_ops ->dop_pending list is used to track active
> deferred operations once intents are logged. These items must be
> aborted in the event of an error. The list is populated as intents
> are logged and items are removed as they complete (or are aborted).
> 
> Now that xfs_defer_finish() cancels on error, there is no need to
> ever access ->dop_pending outside of xfs_defer_finish(). The list is
> only ever populated after xfs_defer_finish() begins and is either
> completed or cancelled before it returns.
> 
> Remove ->dop_pending from xfs_defer_ops and replace it with a local
> list in the xfs_defer_finish() path. Pass the local list to the
> various helpers now that it is not accessible via dfops. Note that
> we have to check for NULL in the abort case as the final tx roll
> occurs outside of the scope of the new local list (once the dfops
> has completed and thus drained the list).
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>
> ---
>  fs/xfs/libxfs/xfs_defer.c | 80 ++++++++++++++++++++-------------------
>  fs/xfs/libxfs/xfs_defer.h |  3 +-
>  fs/xfs/xfs_trace.h        |  1 -
>  fs/xfs/xfs_trans.h        |  1 -
>  4 files changed, 43 insertions(+), 42 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> index 66848ede62c0..6bf792e2d61b 100644
> --- a/fs/xfs/libxfs/xfs_defer.c
> +++ b/fs/xfs/libxfs/xfs_defer.c
> @@ -174,6 +174,8 @@
>  
>  static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX];
>  
> +static void __xfs_defer_cancel(struct list_head *);
> +
>  /*
>   * For each pending item in the intake list, log its intent item and the
>   * associated extents, then add the entire intake list to the end of
> @@ -181,7 +183,8 @@ static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX];
>   */
>  STATIC void
>  xfs_defer_intake_work(
> -	struct xfs_trans		*tp)
> +	struct xfs_trans		*tp,
> +	struct list_head		*dop_pending)
>  {
>  	struct xfs_defer_ops		*dop = tp->t_dfops;
>  	struct list_head		*li;
> @@ -197,13 +200,14 @@ xfs_defer_intake_work(
>  			dfp->dfp_type->log_item(tp, dfp->dfp_intent, li);
>  	}
>  
> -	list_splice_tail_init(&dop->dop_intake, &dop->dop_pending);
> +	list_splice_tail_init(&dop->dop_intake, dop_pending);
>  }
>  
>  /* Abort all the intents that were committed. */
>  STATIC void
>  xfs_defer_trans_abort(
>  	struct xfs_trans		*tp,
> +	struct list_head		*dop_pending,
>  	int				error)
>  {
>  	struct xfs_defer_ops		*dop = tp->t_dfops;
> @@ -212,11 +216,13 @@ xfs_defer_trans_abort(
>  	trace_xfs_defer_trans_abort(tp->t_mountp, dop, _RET_IP_);
>  
>  	/* Abort intent items that don't have a done item. */
> -	list_for_each_entry(dfp, &dop->dop_pending, dfp_list) {
> -		trace_xfs_defer_pending_abort(tp->t_mountp, dfp);
> -		if (dfp->dfp_intent && !dfp->dfp_done) {
> -			dfp->dfp_type->abort_intent(dfp->dfp_intent);
> -			dfp->dfp_intent = NULL;
> +	if (dop_pending) {

/me kinda wonders if you could just make xfs_defer_finish pass an empty
list_head into xfs_defer_trans_roll to avoid this extra indent, but I
don't care all that much and maybe we should save the stack space. :)

> +		list_for_each_entry(dfp, dop_pending, dfp_list) {
> +			trace_xfs_defer_pending_abort(tp->t_mountp, dfp);
> +			if (dfp->dfp_intent && !dfp->dfp_done) {
> +				dfp->dfp_type->abort_intent(dfp->dfp_intent);
> +				dfp->dfp_intent = NULL;
> +			}
>  		}
>  	}
>  
> @@ -228,7 +234,8 @@ xfs_defer_trans_abort(
>  /* Roll a transaction so we can do some deferred op processing. */
>  STATIC int
>  xfs_defer_trans_roll(
> -	struct xfs_trans		**tp)
> +	struct xfs_trans		**tp,
> +	struct list_head		*dop_pending)
>  {
>  	struct xfs_buf_log_item		*bli;
>  	struct xfs_inode_log_item	*ili;
> @@ -272,7 +279,7 @@ xfs_defer_trans_roll(
>  	if (error) {
>  		trace_xfs_defer_trans_roll_error((*tp)->t_mountp,
>  						 (*tp)->t_dfops, error);
> -		xfs_defer_trans_abort(*tp,  error);
> +		xfs_defer_trans_abort(*tp,  dop_pending, error);
>  		return error;
>  	}
>  
> @@ -292,9 +299,10 @@ xfs_defer_trans_roll(
>  /* Do we have any work items to finish? */
>  bool
>  xfs_defer_has_unfinished_work(
> -	struct xfs_trans		*tp)
> +	struct xfs_trans		*tp,
> +	struct list_head		*dop_pending)
>  {
> -	return !list_empty(&tp->t_dfops->dop_pending) ||
> +	return !list_empty(dop_pending) ||
>  		!list_empty(&tp->t_dfops->dop_intake);
>  }
>  
> @@ -305,7 +313,7 @@ static void
>  xfs_defer_reset(
>  	struct xfs_trans	*tp)
>  {
> -	ASSERT(!xfs_defer_has_unfinished_work(tp));
> +	ASSERT(list_empty(&tp->t_dfops->dop_intake));
>  
>  	/*
>  	 * Low mode state transfers across transaction rolls to mirror dfops
> @@ -332,26 +340,27 @@ xfs_defer_finish_noroll(
>  	void				*state;
>  	int				error = 0;
>  	void				(*cleanup_fn)(struct xfs_trans *, void *, int);
> +	LIST_HEAD(dop_pending);
>  
>  	ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
>  
>  	trace_xfs_defer_finish((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_);
>  
>  	/* Until we run out of pending work to finish... */
> -	while (xfs_defer_has_unfinished_work(*tp)) {
> +	while (xfs_defer_has_unfinished_work(*tp, &dop_pending)) {

<urk> see discussion below.

>  		/* Log intents for work items sitting in the intake. */
> -		xfs_defer_intake_work(*tp);
> +		xfs_defer_intake_work(*tp, &dop_pending);
>  
>  		/*
>  		 * Roll the transaction.
>  		 */
> -		error = xfs_defer_trans_roll(tp);
> +		error = xfs_defer_trans_roll(tp, &dop_pending);
>  		if (error)
>  			goto out;
>  
>  		/* Log an intent-done item for the first pending item. */
> -		dfp = list_first_entry(&(*tp)->t_dfops->dop_pending,
> -				struct xfs_defer_pending, dfp_list);
> +		dfp = list_first_entry(&dop_pending, struct xfs_defer_pending,
> +				       dfp_list);
>  		trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp);
>  		dfp->dfp_done = dfp->dfp_type->create_done(*tp, dfp->dfp_intent,
>  				dfp->dfp_count);
> @@ -381,7 +390,7 @@ xfs_defer_finish_noroll(
>  				 */
>  				if (cleanup_fn)
>  					cleanup_fn(*tp, state, error);
> -				xfs_defer_trans_abort(*tp, error);
> +				xfs_defer_trans_abort(*tp, &dop_pending, error);
>  				goto out;
>  			}
>  		}
> @@ -413,6 +422,7 @@ xfs_defer_finish_noroll(
>  	if (error) {
>  		trace_xfs_defer_finish_error((*tp)->t_mountp, (*tp)->t_dfops,
>  					     error);
> +		__xfs_defer_cancel(&dop_pending);
>  		xfs_defer_cancel(*tp);
>  		return error;
>  	}
> @@ -435,7 +445,7 @@ xfs_defer_finish(
>  	if (error)
>  		return error;
>  	if ((*tp)->t_flags & XFS_TRANS_DIRTY) {
> -		error = xfs_defer_trans_roll(tp);
> +		error = xfs_defer_trans_roll(tp, NULL);
>  		if (error)
>  			return error;
>  	}
> @@ -446,34 +456,20 @@ xfs_defer_finish(
>  /*
>   * Free up any items left in the list.
>   */
> -void
> -xfs_defer_cancel(
> -	struct xfs_trans		*tp)
> +static void
> +__xfs_defer_cancel(

Maybe this should be xfs_defer_cancel_list?

> +	struct list_head		*dop_list)
>  {
> -	struct xfs_defer_ops		*dop = tp->t_dfops;
>  	struct xfs_defer_pending	*dfp;
>  	struct xfs_defer_pending	*pli;
>  	struct list_head		*pwi;
>  	struct list_head		*n;
>  
> -	trace_xfs_defer_cancel(NULL, dop, _RET_IP_);
> -
>  	/*
>  	 * Free the pending items.  Caller should already have arranged
>  	 * for the intent items to be released.
>  	 */
> -	list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) {
> -		trace_xfs_defer_intake_cancel(NULL, dfp);
> -		list_del(&dfp->dfp_list);
> -		list_for_each_safe(pwi, n, &dfp->dfp_work) {
> -			list_del(pwi);
> -			dfp->dfp_count--;
> -			dfp->dfp_type->cancel_item(pwi);
> -		}
> -		ASSERT(dfp->dfp_count == 0);
> -		kmem_free(dfp);
> -	}
> -	list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) {
> +	list_for_each_entry_safe(dfp, pli, dop_list, dfp_list) {
>  		trace_xfs_defer_pending_cancel(NULL, dfp);

trace_xfs_defer_cancel_list?

Maybe it's worth passing a *mp into this function so we can pass it to
the tracepoint?

>  		list_del(&dfp->dfp_list);
>  		list_for_each_safe(pwi, n, &dfp->dfp_work) {
> @@ -486,6 +482,14 @@ xfs_defer_cancel(
>  	}
>  }
>  
> +void
> +xfs_defer_cancel(
> +	struct xfs_trans	*tp)
> +{
> +	trace_xfs_defer_cancel(NULL, tp->t_dfops, _RET_IP_);

That NULL can be tp->t_mountp, right?  Since tp should never be NULL?

> +	__xfs_defer_cancel(&tp->t_dfops->dop_intake);
> +}
> +
>  /* Add an item for later deferred processing. */
>  void
>  xfs_defer_add(
> @@ -541,7 +545,6 @@ xfs_defer_init(
>  
>  	memset(dop, 0, sizeof(struct xfs_defer_ops));
>  	INIT_LIST_HEAD(&dop->dop_intake);
> -	INIT_LIST_HEAD(&dop->dop_pending);
>  	if (tp) {
>  		ASSERT(tp->t_firstblock == NULLFSBLOCK);
>  		tp->t_dfops = dop;
> @@ -565,7 +568,6 @@ xfs_defer_move(
>  	ASSERT(dst != src);
>  
>  	list_splice_init(&src->dop_intake, &dst->dop_intake);
> -	list_splice_init(&src->dop_pending, &dst->dop_pending);
>  
>  	/*
>  	 * Low free space mode was historically controlled by a dfops field.
> diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
> index f051c8056141..363af16328cb 100644
> --- a/fs/xfs/libxfs/xfs_defer.h
> +++ b/fs/xfs/libxfs/xfs_defer.h
> @@ -41,7 +41,8 @@ int xfs_defer_finish_noroll(struct xfs_trans **tp);
>  int xfs_defer_finish(struct xfs_trans **tp);
>  void xfs_defer_cancel(struct xfs_trans *);
>  void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
> -bool xfs_defer_has_unfinished_work(struct xfs_trans *tp);
> +bool xfs_defer_has_unfinished_work(struct xfs_trans *tp,
> +		struct list_head *dop_pending);

Eww, I dislike exposing this implementation detail in a public
interface.  Assuming you take my suggestion in patch 1 to ASSERT if
xfs_trans_{cancel,commit} encounter unfinished deferred work and a
transaction we can't roll, there will be only three callers of this
function, and only one of them knows about the pending item list.
Perhaps the list_empty(dop_pending) check can be open-coded in
xfs_defer_finish_noroll?

--D

>  void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
>  
>  /* Description of a deferred type. */
> diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
> index 8807f1bb814a..6b55bbc09578 100644
> --- a/fs/xfs/xfs_trace.h
> +++ b/fs/xfs/xfs_trace.h
> @@ -2393,7 +2393,6 @@ DEFINE_DEFER_ERROR_EVENT(xfs_defer_trans_roll_error);
>  DEFINE_DEFER_ERROR_EVENT(xfs_defer_finish_error);
>  
>  DEFINE_DEFER_PENDING_EVENT(xfs_defer_intake_work);
> -DEFINE_DEFER_PENDING_EVENT(xfs_defer_intake_cancel);
>  DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_cancel);
>  DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_finish);
>  DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_abort);
> diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> index 299656dbf324..1cdc7c0ebeac 100644
> --- a/fs/xfs/xfs_trans.h
> +++ b/fs/xfs/xfs_trans.h
> @@ -96,7 +96,6 @@ void	xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item,
>  #define XFS_DEFER_OPS_NR_BUFS	2	/* join up to two buffers */
>  struct xfs_defer_ops {
>  	struct list_head	dop_intake;	/* unlogged pending work */
> -	struct list_head	dop_pending;	/* logged pending work */
>  };
>  
>  /*
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 13/15] xfs: pass transaction to xfs_defer_add()
  2018-07-30 16:45 ` [PATCH 13/15] xfs: pass transaction to xfs_defer_add() Brian Foster
@ 2018-07-30 20:49   ` Darrick J. Wong
  2018-07-31  8:31   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 20:49 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:18PM -0400, Brian Foster wrote:
> The majority of remaining references to struct xfs_defer_ops in XFS
> are associated with xfs_defer_add(). At this point, there are no
> more external xfs_defer_ops users left. All instances of
> xfs_defer_ops are embedded in the transaction, which means we can
> safely pass the transaction down to the dfops add interface.
> 
> Update xfs_defer_add() to receive the transaction as a parameter.
> Various subsystems implement wrappers to allocate and construct the
> context specific data structures for the associated deferred
> operation type. Update these to also carry the transaction down as
> needed and clean up unused dfops parameters along the way.
> 
> This removes most of the remaining references to struct
> xfs_defer_ops throughout the code and facilitates removal of the
> structure.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks ok,
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/xfs/libxfs/xfs_alloc.c      |  9 ++--
>  fs/xfs/libxfs/xfs_bmap.c       | 75 +++++++++++++++------------------
>  fs/xfs/libxfs/xfs_bmap.h       | 19 ++++-----
>  fs/xfs/libxfs/xfs_bmap_btree.c |  2 +-
>  fs/xfs/libxfs/xfs_defer.c      |  3 +-
>  fs/xfs/libxfs/xfs_defer.h      |  2 +-
>  fs/xfs/libxfs/xfs_ialloc.c     | 25 +++++------
>  fs/xfs/libxfs/xfs_refcount.c   | 76 ++++++++++++++--------------------
>  fs/xfs/libxfs/xfs_refcount.h   | 18 ++++----
>  fs/xfs/libxfs/xfs_rmap.c       | 53 ++++++++++++------------
>  fs/xfs/libxfs/xfs_rmap.h       | 22 ++++------
>  fs/xfs/xfs_bmap_item.c         |  3 +-
>  fs/xfs/xfs_bmap_util.c         | 13 ++----
>  fs/xfs/xfs_refcount_item.c     | 14 ++-----
>  fs/xfs/xfs_reflink.c           | 21 ++++------
>  15 files changed, 156 insertions(+), 199 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
> index 3c3f2d5119ea..6bacdc31a439 100644
> --- a/fs/xfs/libxfs/xfs_alloc.c
> +++ b/fs/xfs/libxfs/xfs_alloc.c
> @@ -2198,12 +2198,12 @@ xfs_agfl_reset(
>   */
>  STATIC void
>  xfs_defer_agfl_block(
> -	struct xfs_mount		*mp,
> -	struct xfs_defer_ops		*dfops,
> +	struct xfs_trans		*tp,
>  	xfs_agnumber_t			agno,
>  	xfs_fsblock_t			agbno,
>  	struct xfs_owner_info		*oinfo)
>  {
> +	struct xfs_mount		*mp = tp->t_mountp;
>  	struct xfs_extent_free_item	*new;		/* new element */
>  
>  	ASSERT(xfs_bmap_free_item_zone != NULL);
> @@ -2216,7 +2216,7 @@ xfs_defer_agfl_block(
>  
>  	trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1);
>  
> -	xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_AGFL_FREE, &new->xefi_list);
> +	xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_AGFL_FREE, &new->xefi_list);
>  }
>  
>  /*
> @@ -2325,8 +2325,7 @@ xfs_alloc_fix_freelist(
>  
>  		/* defer agfl frees if dfops is provided */
>  		if (tp->t_dfops) {
> -			xfs_defer_agfl_block(mp, tp->t_dfops, args->agno,
> -					     bno, &targs.oinfo);
> +			xfs_defer_agfl_block(tp, args->agno, bno, &targs.oinfo);
>  		} else {
>  			error = xfs_free_agfl_block(tp, args->agno, bno, agbp,
>  						    &targs.oinfo);
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index d20f541b7061..f5f1fc47923e 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -533,13 +533,13 @@ xfs_bmap_validate_ret(
>   */
>  void
>  __xfs_bmap_add_free(
> -	struct xfs_mount		*mp,
> -	struct xfs_defer_ops		*dfops,
> +	struct xfs_trans		*tp,
>  	xfs_fsblock_t			bno,
>  	xfs_filblks_t			len,
>  	struct xfs_owner_info		*oinfo,
>  	bool				skip_discard)
>  {
> +	struct xfs_mount		*mp = tp->t_mountp;
>  	struct xfs_extent_free_item	*new;		/* new element */
>  #ifdef DEBUG
>  	xfs_agnumber_t		agno;
> @@ -568,7 +568,7 @@ __xfs_bmap_add_free(
>  	new->xefi_skip_discard = skip_discard;
>  	trace_xfs_bmap_free_defer(mp, XFS_FSB_TO_AGNO(mp, bno), 0,
>  			XFS_FSB_TO_AGBNO(mp, bno), len);
> -	xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list);
> +	xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list);
>  }
>  
>  /*
> @@ -624,7 +624,7 @@ xfs_bmap_btree_to_extents(
>  	if ((error = xfs_btree_check_block(cur, cblock, 0, cbp)))
>  		return error;
>  	xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork);
> -	xfs_bmap_add_free(mp, cur->bc_tp->t_dfops, cbno, 1, &oinfo);
> +	xfs_bmap_add_free(cur->bc_tp, cbno, 1, &oinfo);
>  	ip->i_d.di_nblocks--;
>  	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
>  	xfs_trans_binval(tp, cbp);
> @@ -1961,8 +1961,7 @@ xfs_bmap_add_extent_delay_real(
>  
>  	/* add reverse mapping unless caller opted out */
>  	if (!(bma->flags & XFS_BMAPI_NORMAP)) {
> -		error = xfs_rmap_map_extent(mp, bma->tp->t_dfops, bma->ip,
> -				whichfork, new);
> +		error = xfs_rmap_map_extent(bma->tp, bma->ip, whichfork, new);
>  		if (error)
>  			goto done;
>  	}
> @@ -2026,7 +2025,6 @@ xfs_bmap_add_extent_unwritten_real(
>  	int			state = xfs_bmap_fork_to_state(whichfork);
>  	struct xfs_mount	*mp = ip->i_mount;
>  	struct xfs_bmbt_irec	old;
> -	struct xfs_defer_ops	*dfops = tp ? tp->t_dfops : NULL;
>  
>  	*logflagsp = 0;
>  
> @@ -2445,7 +2443,7 @@ xfs_bmap_add_extent_unwritten_real(
>  	}
>  
>  	/* update reverse mappings */
> -	error = xfs_rmap_convert_extent(mp, dfops, ip, whichfork, new);
> +	error = xfs_rmap_convert_extent(mp, tp, ip, whichfork, new);
>  	if (error)
>  		goto done;
>  
> @@ -2806,8 +2804,7 @@ xfs_bmap_add_extent_hole_real(
>  
>  	/* add reverse mapping unless caller opted out */
>  	if (!(flags & XFS_BMAPI_NORMAP)) {
> -		error = xfs_rmap_map_extent(mp, tp->t_dfops, ip, whichfork,
> -				new);
> +		error = xfs_rmap_map_extent(tp, ip, whichfork, new);
>  		if (error)
>  			goto done;
>  	}
> @@ -4364,9 +4361,8 @@ xfs_bmapi_write(
>  			 * the refcount btree for orphan recovery.
>  			 */
>  			if (whichfork == XFS_COW_FORK) {
> -				error = xfs_refcount_alloc_cow_extent(mp,
> -						tp->t_dfops, bma.blkno,
> -						bma.length);
> +				error = xfs_refcount_alloc_cow_extent(tp,
> +						bma.blkno, bma.length);
>  				if (error)
>  					goto error0;
>  			}
> @@ -4852,7 +4848,6 @@ xfs_bmap_del_extent_real(
>  	uint			qfield;	/* quota field to update */
>  	int			state = xfs_bmap_fork_to_state(whichfork);
>  	struct xfs_bmbt_irec	old;
> -	struct xfs_defer_ops	*dfops = tp ? tp->t_dfops : NULL;
>  
>  	mp = ip->i_mount;
>  	XFS_STATS_INC(mp, xs_del_exlist);
> @@ -5036,7 +5031,7 @@ xfs_bmap_del_extent_real(
>  	}
>  
>  	/* remove reverse mapping */
> -	error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, del);
> +	error = xfs_rmap_unmap_extent(tp, ip, whichfork, del);
>  	if (error)
>  		goto done;
>  
> @@ -5045,11 +5040,11 @@ xfs_bmap_del_extent_real(
>  	 */
>  	if (do_fx && !(bflags & XFS_BMAPI_REMAP)) {
>  		if (xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK) {
> -			error = xfs_refcount_decrease_extent(mp, dfops, del);
> +			error = xfs_refcount_decrease_extent(tp, del);
>  			if (error)
>  				goto done;
>  		} else {
> -			__xfs_bmap_add_free(mp, dfops, del->br_startblock,
> +			__xfs_bmap_add_free(tp, del->br_startblock,
>  					del->br_blockcount, NULL,
>  					(bflags & XFS_BMAPI_NODISCARD) ||
>  					del->br_state == XFS_EXT_UNWRITTEN);
> @@ -5489,6 +5484,7 @@ xfs_bmse_can_merge(
>   */
>  STATIC int
>  xfs_bmse_merge(
> +	struct xfs_trans		*tp,
>  	struct xfs_inode		*ip,
>  	int				whichfork,
>  	xfs_fileoff_t			shift,		/* shift fsb */
> @@ -5496,8 +5492,7 @@ xfs_bmse_merge(
>  	struct xfs_bmbt_irec		*got,		/* extent to shift */
>  	struct xfs_bmbt_irec		*left,		/* preceding extent */
>  	struct xfs_btree_cur		*cur,
> -	int				*logflags,	/* output */
> -	struct xfs_defer_ops		*dfops)
> +	int				*logflags)	/* output */
>  {
>  	struct xfs_bmbt_irec		new;
>  	xfs_filblks_t			blockcount;
> @@ -5553,23 +5548,23 @@ xfs_bmse_merge(
>  			&new);
>  
>  	/* update reverse mapping. rmap functions merge the rmaps for us */
> -	error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, got);
> +	error = xfs_rmap_unmap_extent(tp, ip, whichfork, got);
>  	if (error)
>  		return error;
>  	memcpy(&new, got, sizeof(new));
>  	new.br_startoff = left->br_startoff + left->br_blockcount;
> -	return xfs_rmap_map_extent(mp, dfops, ip, whichfork, &new);
> +	return xfs_rmap_map_extent(tp, ip, whichfork, &new);
>  }
>  
>  static int
>  xfs_bmap_shift_update_extent(
> +	struct xfs_trans	*tp,
>  	struct xfs_inode	*ip,
>  	int			whichfork,
>  	struct xfs_iext_cursor	*icur,
>  	struct xfs_bmbt_irec	*got,
>  	struct xfs_btree_cur	*cur,
>  	int			*logflags,
> -	struct xfs_defer_ops	*dfops,
>  	xfs_fileoff_t		startoff)
>  {
>  	struct xfs_mount	*mp = ip->i_mount;
> @@ -5597,10 +5592,10 @@ xfs_bmap_shift_update_extent(
>  			got);
>  
>  	/* update reverse mapping */
> -	error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, &prev);
> +	error = xfs_rmap_unmap_extent(tp, ip, whichfork, &prev);
>  	if (error)
>  		return error;
> -	return xfs_rmap_map_extent(mp, dfops, ip, whichfork, got);
> +	return xfs_rmap_map_extent(tp, ip, whichfork, got);
>  }
>  
>  int
> @@ -5660,9 +5655,9 @@ xfs_bmap_collapse_extents(
>  		}
>  
>  		if (xfs_bmse_can_merge(&prev, &got, offset_shift_fsb)) {
> -			error = xfs_bmse_merge(ip, whichfork, offset_shift_fsb,
> -					&icur, &got, &prev, cur, &logflags,
> -					tp->t_dfops);
> +			error = xfs_bmse_merge(tp, ip, whichfork,
> +					offset_shift_fsb, &icur, &got, &prev,
> +					cur, &logflags);
>  			if (error)
>  				goto del_cursor;
>  			goto done;
> @@ -5674,8 +5669,8 @@ xfs_bmap_collapse_extents(
>  		}
>  	}
>  
> -	error = xfs_bmap_shift_update_extent(ip, whichfork, &icur, &got, cur,
> -			&logflags, tp->t_dfops, new_startoff);
> +	error = xfs_bmap_shift_update_extent(tp, ip, whichfork, &icur, &got,
> +			cur, &logflags, new_startoff);
>  	if (error)
>  		goto del_cursor;
>  
> @@ -5801,8 +5796,8 @@ xfs_bmap_insert_extents(
>  			WARN_ON_ONCE(1);
>  	}
>  
> -	error = xfs_bmap_shift_update_extent(ip, whichfork, &icur, &got, cur,
> -			&logflags, tp->t_dfops, new_startoff);
> +	error = xfs_bmap_shift_update_extent(tp, ip, whichfork, &icur, &got,
> +			cur, &logflags, new_startoff);
>  	if (error)
>  		goto del_cursor;
>  
> @@ -5979,13 +5974,13 @@ xfs_bmap_is_update_needed(
>  /* Record a bmap intent. */
>  static int
>  __xfs_bmap_add(
> -	struct xfs_mount		*mp,
> -	struct xfs_defer_ops		*dfops,
> +	struct xfs_trans		*tp,
>  	enum xfs_bmap_intent_type	type,
>  	struct xfs_inode		*ip,
>  	int				whichfork,
>  	struct xfs_bmbt_irec		*bmap)
>  {
> +	struct xfs_mount		*mp = tp->t_mountp;
>  	struct xfs_bmap_intent		*bi;
>  
>  	trace_xfs_bmap_defer(mp,
> @@ -6004,38 +5999,34 @@ __xfs_bmap_add(
>  	bi->bi_whichfork = whichfork;
>  	bi->bi_bmap = *bmap;
>  
> -	xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_BMAP, &bi->bi_list);
> +	xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_BMAP, &bi->bi_list);
>  	return 0;
>  }
>  
>  /* Map an extent into a file. */
>  int
>  xfs_bmap_map_extent(
> -	struct xfs_mount	*mp,
> -	struct xfs_defer_ops	*dfops,
> +	struct xfs_trans	*tp,
>  	struct xfs_inode	*ip,
>  	struct xfs_bmbt_irec	*PREV)
>  {
>  	if (!xfs_bmap_is_update_needed(PREV))
>  		return 0;
>  
> -	return __xfs_bmap_add(mp, dfops, XFS_BMAP_MAP, ip,
> -			XFS_DATA_FORK, PREV);
> +	return __xfs_bmap_add(tp, XFS_BMAP_MAP, ip, XFS_DATA_FORK, PREV);
>  }
>  
>  /* Unmap an extent out of a file. */
>  int
>  xfs_bmap_unmap_extent(
> -	struct xfs_mount	*mp,
> -	struct xfs_defer_ops	*dfops,
> +	struct xfs_trans	*tp,
>  	struct xfs_inode	*ip,
>  	struct xfs_bmbt_irec	*PREV)
>  {
>  	if (!xfs_bmap_is_update_needed(PREV))
>  		return 0;
>  
> -	return __xfs_bmap_add(mp, dfops, XFS_BMAP_UNMAP, ip,
> -			XFS_DATA_FORK, PREV);
> +	return __xfs_bmap_add(tp, XFS_BMAP_UNMAP, ip, XFS_DATA_FORK, PREV);
>  }
>  
>  /*
> diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
> index 9165a878edcd..b6e9b639e731 100644
> --- a/fs/xfs/libxfs/xfs_bmap.h
> +++ b/fs/xfs/libxfs/xfs_bmap.h
> @@ -184,9 +184,9 @@ void	xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno,
>  void	xfs_trim_extent_eof(struct xfs_bmbt_irec *, struct xfs_inode *);
>  int	xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
>  void	xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
> -void	__xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
> -			  xfs_fsblock_t bno, xfs_filblks_t len,
> -			  struct xfs_owner_info *oinfo, bool skip_discard);
> +void	__xfs_bmap_add_free(struct xfs_trans *tp, xfs_fsblock_t bno,
> +		xfs_filblks_t len, struct xfs_owner_info *oinfo,
> +		bool skip_discard);
>  void	xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork);
>  int	xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip,
>  		xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork);
> @@ -230,13 +230,12 @@ int	xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork,
>  
>  static inline void
>  xfs_bmap_add_free(
> -	struct xfs_mount		*mp,
> -	struct xfs_defer_ops		*dfops,
> +	struct xfs_trans		*tp,
>  	xfs_fsblock_t			bno,
>  	xfs_filblks_t			len,
>  	struct xfs_owner_info		*oinfo)
>  {
> -	__xfs_bmap_add_free(mp, dfops, bno, len, oinfo, false);
> +	__xfs_bmap_add_free(tp, bno, len, oinfo, false);
>  }
>  
>  enum xfs_bmap_intent_type {
> @@ -256,10 +255,10 @@ int	xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_inode *ip,
>  		enum xfs_bmap_intent_type type, int whichfork,
>  		xfs_fileoff_t startoff, xfs_fsblock_t startblock,
>  		xfs_filblks_t *blockcount, xfs_exntst_t state);
> -int	xfs_bmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
> -		struct xfs_inode *ip, struct xfs_bmbt_irec *imap);
> -int	xfs_bmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
> -		struct xfs_inode *ip, struct xfs_bmbt_irec *imap);
> +int	xfs_bmap_map_extent(struct xfs_trans *tp, struct xfs_inode *ip,
> +		struct xfs_bmbt_irec *imap);
> +int	xfs_bmap_unmap_extent(struct xfs_trans *tp, struct xfs_inode *ip,
> +		struct xfs_bmbt_irec *imap);
>  
>  static inline int xfs_bmap_fork_to_state(int whichfork)
>  {
> diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
> index 955e29de8cae..cdb74d2e2a43 100644
> --- a/fs/xfs/libxfs/xfs_bmap_btree.c
> +++ b/fs/xfs/libxfs/xfs_bmap_btree.c
> @@ -289,7 +289,7 @@ xfs_bmbt_free_block(
>  	struct xfs_owner_info	oinfo;
>  
>  	xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_private.b.whichfork);
> -	xfs_bmap_add_free(mp, cur->bc_tp->t_dfops, fsbno, 1, &oinfo);
> +	xfs_bmap_add_free(cur->bc_tp, fsbno, 1, &oinfo);
>  	ip->i_d.di_nblocks--;
>  
>  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
> diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> index 6bf792e2d61b..152190a69432 100644
> --- a/fs/xfs/libxfs/xfs_defer.c
> +++ b/fs/xfs/libxfs/xfs_defer.c
> @@ -493,10 +493,11 @@ xfs_defer_cancel(
>  /* Add an item for later deferred processing. */
>  void
>  xfs_defer_add(
> -	struct xfs_defer_ops		*dop,
> +	struct xfs_trans		*tp,
>  	enum xfs_defer_ops_type		type,
>  	struct list_head		*li)
>  {
> +	struct xfs_defer_ops		*dop = tp->t_dfops;
>  	struct xfs_defer_pending	*dfp = NULL;
>  
>  	/*
> diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
> index 363af16328cb..295703737272 100644
> --- a/fs/xfs/libxfs/xfs_defer.h
> +++ b/fs/xfs/libxfs/xfs_defer.h
> @@ -35,7 +35,7 @@ enum xfs_defer_ops_type {
>  	XFS_DEFER_OPS_TYPE_MAX,
>  };
>  
> -void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type,
> +void xfs_defer_add(struct xfs_trans *tp, enum xfs_defer_ops_type type,
>  		struct list_head *h);
>  int xfs_defer_finish_noroll(struct xfs_trans **tp);
>  int xfs_defer_finish(struct xfs_trans **tp);
> diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
> index 295304ad1bc1..a8f6db735d5d 100644
> --- a/fs/xfs/libxfs/xfs_ialloc.c
> +++ b/fs/xfs/libxfs/xfs_ialloc.c
> @@ -1838,23 +1838,24 @@ xfs_dialloc(
>   */
>  STATIC void
>  xfs_difree_inode_chunk(
> -	struct xfs_mount		*mp,
> +	struct xfs_trans		*tp,
>  	xfs_agnumber_t			agno,
> -	struct xfs_inobt_rec_incore	*rec,
> -	struct xfs_defer_ops		*dfops)
> +	struct xfs_inobt_rec_incore	*rec)
>  {
> -	xfs_agblock_t	sagbno = XFS_AGINO_TO_AGBNO(mp, rec->ir_startino);
> -	int		startidx, endidx;
> -	int		nextbit;
> -	xfs_agblock_t	agbno;
> -	int		contigblk;
> -	struct xfs_owner_info	oinfo;
> +	struct xfs_mount		*mp = tp->t_mountp;
> +	xfs_agblock_t			sagbno = XFS_AGINO_TO_AGBNO(mp,
> +							rec->ir_startino);
> +	int				startidx, endidx;
> +	int				nextbit;
> +	xfs_agblock_t			agbno;
> +	int				contigblk;
> +	struct xfs_owner_info		oinfo;
>  	DECLARE_BITMAP(holemask, XFS_INOBT_HOLEMASK_BITS);
>  	xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES);
>  
>  	if (!xfs_inobt_issparse(rec->ir_holemask)) {
>  		/* not sparse, calculate extent info directly */
> -		xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, sagbno),
> +		xfs_bmap_add_free(tp, XFS_AGB_TO_FSB(mp, agno, sagbno),
>  				  mp->m_ialloc_blks, &oinfo);
>  		return;
>  	}
> @@ -1898,7 +1899,7 @@ xfs_difree_inode_chunk(
>  
>  		ASSERT(agbno % mp->m_sb.sb_spino_align == 0);
>  		ASSERT(contigblk % mp->m_sb.sb_spino_align == 0);
> -		xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, agbno),
> +		xfs_bmap_add_free(tp, XFS_AGB_TO_FSB(mp, agno, agbno),
>  				  contigblk, &oinfo);
>  
>  		/* reset range to current bit and carry on... */
> @@ -2002,7 +2003,7 @@ xfs_difree_inobt(
>  			goto error0;
>  		}
>  
> -		xfs_difree_inode_chunk(mp, agno, &rec, tp->t_dfops);
> +		xfs_difree_inode_chunk(tp, agno, &rec);
>  	} else {
>  		xic->deleted = false;
>  
> diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c
> index 86f297ca90cd..c713c49200d3 100644
> --- a/fs/xfs/libxfs/xfs_refcount.c
> +++ b/fs/xfs/libxfs/xfs_refcount.c
> @@ -34,11 +34,9 @@ enum xfs_refc_adjust_op {
>  };
>  
>  STATIC int __xfs_refcount_cow_alloc(struct xfs_btree_cur *rcur,
> -		xfs_agblock_t agbno, xfs_extlen_t aglen,
> -		struct xfs_defer_ops *dfops);
> +		xfs_agblock_t agbno, xfs_extlen_t aglen);
>  STATIC int __xfs_refcount_cow_free(struct xfs_btree_cur *rcur,
> -		xfs_agblock_t agbno, xfs_extlen_t aglen,
> -		struct xfs_defer_ops *dfops);
> +		xfs_agblock_t agbno, xfs_extlen_t aglen);
>  
>  /*
>   * Look up the first record less than or equal to [bno, len] in the btree
> @@ -870,7 +868,6 @@ xfs_refcount_adjust_extents(
>  	xfs_agblock_t		*agbno,
>  	xfs_extlen_t		*aglen,
>  	enum xfs_refc_adjust_op	adj,
> -	struct xfs_defer_ops	*dfops,
>  	struct xfs_owner_info	*oinfo)
>  {
>  	struct xfs_refcount_irec	ext, tmp;
> @@ -925,8 +922,8 @@ xfs_refcount_adjust_extents(
>  				fsbno = XFS_AGB_TO_FSB(cur->bc_mp,
>  						cur->bc_private.a.agno,
>  						tmp.rc_startblock);
> -				xfs_bmap_add_free(cur->bc_mp, dfops, fsbno,
> -						tmp.rc_blockcount, oinfo);
> +				xfs_bmap_add_free(cur->bc_tp, fsbno,
> +						  tmp.rc_blockcount, oinfo);
>  			}
>  
>  			(*agbno) += tmp.rc_blockcount;
> @@ -968,8 +965,8 @@ xfs_refcount_adjust_extents(
>  			fsbno = XFS_AGB_TO_FSB(cur->bc_mp,
>  					cur->bc_private.a.agno,
>  					ext.rc_startblock);
> -			xfs_bmap_add_free(cur->bc_mp, dfops, fsbno,
> -					ext.rc_blockcount, oinfo);
> +			xfs_bmap_add_free(cur->bc_tp, fsbno, ext.rc_blockcount,
> +					  oinfo);
>  		}
>  
>  skip:
> @@ -998,7 +995,6 @@ xfs_refcount_adjust(
>  	xfs_agblock_t		*new_agbno,
>  	xfs_extlen_t		*new_aglen,
>  	enum xfs_refc_adjust_op	adj,
> -	struct xfs_defer_ops	*dfops,
>  	struct xfs_owner_info	*oinfo)
>  {
>  	bool			shape_changed;
> @@ -1043,7 +1039,7 @@ xfs_refcount_adjust(
>  
>  	/* Now that we've taken care of the ends, adjust the middle extents */
>  	error = xfs_refcount_adjust_extents(cur, new_agbno, new_aglen,
> -			adj, dfops, oinfo);
> +			adj, oinfo);
>  	if (error)
>  		goto out_error;
>  
> @@ -1090,7 +1086,6 @@ xfs_refcount_finish_one(
>  	struct xfs_btree_cur		**pcur)
>  {
>  	struct xfs_mount		*mp = tp->t_mountp;
> -	struct xfs_defer_ops		*dfops = tp->t_dfops;
>  	struct xfs_btree_cur		*rcur;
>  	struct xfs_buf			*agbp = NULL;
>  	int				error = 0;
> @@ -1145,23 +1140,23 @@ xfs_refcount_finish_one(
>  	switch (type) {
>  	case XFS_REFCOUNT_INCREASE:
>  		error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno,
> -			new_len, XFS_REFCOUNT_ADJUST_INCREASE, dfops, NULL);
> +			new_len, XFS_REFCOUNT_ADJUST_INCREASE, NULL);
>  		*new_fsb = XFS_AGB_TO_FSB(mp, agno, new_agbno);
>  		break;
>  	case XFS_REFCOUNT_DECREASE:
>  		error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno,
> -			new_len, XFS_REFCOUNT_ADJUST_DECREASE, dfops, NULL);
> +			new_len, XFS_REFCOUNT_ADJUST_DECREASE, NULL);
>  		*new_fsb = XFS_AGB_TO_FSB(mp, agno, new_agbno);
>  		break;
>  	case XFS_REFCOUNT_ALLOC_COW:
>  		*new_fsb = startblock + blockcount;
>  		*new_len = 0;
> -		error = __xfs_refcount_cow_alloc(rcur, bno, blockcount, dfops);
> +		error = __xfs_refcount_cow_alloc(rcur, bno, blockcount);
>  		break;
>  	case XFS_REFCOUNT_FREE_COW:
>  		*new_fsb = startblock + blockcount;
>  		*new_len = 0;
> -		error = __xfs_refcount_cow_free(rcur, bno, blockcount, dfops);
> +		error = __xfs_refcount_cow_free(rcur, bno, blockcount);
>  		break;
>  	default:
>  		ASSERT(0);
> @@ -1183,12 +1178,12 @@ xfs_refcount_finish_one(
>   */
>  static int
>  __xfs_refcount_add(
> -	struct xfs_mount		*mp,
> -	struct xfs_defer_ops		*dfops,
> +	struct xfs_trans		*tp,
>  	enum xfs_refcount_intent_type	type,
>  	xfs_fsblock_t			startblock,
>  	xfs_extlen_t			blockcount)
>  {
> +	struct xfs_mount		*mp = tp->t_mountp;
>  	struct xfs_refcount_intent	*ri;
>  
>  	trace_xfs_refcount_defer(mp, XFS_FSB_TO_AGNO(mp, startblock),
> @@ -1202,7 +1197,7 @@ __xfs_refcount_add(
>  	ri->ri_startblock = startblock;
>  	ri->ri_blockcount = blockcount;
>  
> -	xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_REFCOUNT, &ri->ri_list);
> +	xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_REFCOUNT, &ri->ri_list);
>  	return 0;
>  }
>  
> @@ -1211,14 +1206,13 @@ __xfs_refcount_add(
>   */
>  int
>  xfs_refcount_increase_extent(
> -	struct xfs_mount		*mp,
> -	struct xfs_defer_ops		*dfops,
> +	struct xfs_trans		*tp,
>  	struct xfs_bmbt_irec		*PREV)
>  {
> -	if (!xfs_sb_version_hasreflink(&mp->m_sb))
> +	if (!xfs_sb_version_hasreflink(&tp->t_mountp->m_sb))
>  		return 0;
>  
> -	return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_INCREASE,
> +	return __xfs_refcount_add(tp, XFS_REFCOUNT_INCREASE,
>  			PREV->br_startblock, PREV->br_blockcount);
>  }
>  
> @@ -1227,14 +1221,13 @@ xfs_refcount_increase_extent(
>   */
>  int
>  xfs_refcount_decrease_extent(
> -	struct xfs_mount		*mp,
> -	struct xfs_defer_ops		*dfops,
> +	struct xfs_trans		*tp,
>  	struct xfs_bmbt_irec		*PREV)
>  {
> -	if (!xfs_sb_version_hasreflink(&mp->m_sb))
> +	if (!xfs_sb_version_hasreflink(&tp->t_mountp->m_sb))
>  		return 0;
>  
> -	return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_DECREASE,
> +	return __xfs_refcount_add(tp, XFS_REFCOUNT_DECREASE,
>  			PREV->br_startblock, PREV->br_blockcount);
>  }
>  
> @@ -1522,8 +1515,7 @@ STATIC int
>  __xfs_refcount_cow_alloc(
>  	struct xfs_btree_cur	*rcur,
>  	xfs_agblock_t		agbno,
> -	xfs_extlen_t		aglen,
> -	struct xfs_defer_ops	*dfops)
> +	xfs_extlen_t		aglen)
>  {
>  	trace_xfs_refcount_cow_increase(rcur->bc_mp, rcur->bc_private.a.agno,
>  			agbno, aglen);
> @@ -1540,8 +1532,7 @@ STATIC int
>  __xfs_refcount_cow_free(
>  	struct xfs_btree_cur	*rcur,
>  	xfs_agblock_t		agbno,
> -	xfs_extlen_t		aglen,
> -	struct xfs_defer_ops	*dfops)
> +	xfs_extlen_t		aglen)
>  {
>  	trace_xfs_refcount_cow_decrease(rcur->bc_mp, rcur->bc_private.a.agno,
>  			agbno, aglen);
> @@ -1554,47 +1545,45 @@ __xfs_refcount_cow_free(
>  /* Record a CoW staging extent in the refcount btree. */
>  int
>  xfs_refcount_alloc_cow_extent(
> -	struct xfs_mount		*mp,
> -	struct xfs_defer_ops		*dfops,
> +	struct xfs_trans		*tp,
>  	xfs_fsblock_t			fsb,
>  	xfs_extlen_t			len)
>  {
> +	struct xfs_mount		*mp = tp->t_mountp;
>  	int				error;
>  
>  	if (!xfs_sb_version_hasreflink(&mp->m_sb))
>  		return 0;
>  
> -	error = __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_ALLOC_COW,
> -			fsb, len);
> +	error = __xfs_refcount_add(tp, XFS_REFCOUNT_ALLOC_COW, fsb, len);
>  	if (error)
>  		return error;
>  
>  	/* Add rmap entry */
> -	return xfs_rmap_alloc_extent(mp, dfops, XFS_FSB_TO_AGNO(mp, fsb),
> +	return xfs_rmap_alloc_extent(tp, XFS_FSB_TO_AGNO(mp, fsb),
>  			XFS_FSB_TO_AGBNO(mp, fsb), len, XFS_RMAP_OWN_COW);
>  }
>  
>  /* Forget a CoW staging event in the refcount btree. */
>  int
>  xfs_refcount_free_cow_extent(
> -	struct xfs_mount		*mp,
> -	struct xfs_defer_ops		*dfops,
> +	struct xfs_trans		*tp,
>  	xfs_fsblock_t			fsb,
>  	xfs_extlen_t			len)
>  {
> +	struct xfs_mount		*mp = tp->t_mountp;
>  	int				error;
>  
>  	if (!xfs_sb_version_hasreflink(&mp->m_sb))
>  		return 0;
>  
>  	/* Remove rmap entry */
> -	error = xfs_rmap_free_extent(mp, dfops, XFS_FSB_TO_AGNO(mp, fsb),
> +	error = xfs_rmap_free_extent(tp, XFS_FSB_TO_AGNO(mp, fsb),
>  			XFS_FSB_TO_AGBNO(mp, fsb), len, XFS_RMAP_OWN_COW);
>  	if (error)
>  		return error;
>  
> -	return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_FREE_COW,
> -			fsb, len);
> +	return __xfs_refcount_add(tp, XFS_REFCOUNT_FREE_COW, fsb, len);
>  }
>  
>  struct xfs_refcount_recovery {
> @@ -1692,14 +1681,13 @@ xfs_refcount_recover_cow_leftovers(
>  		/* Free the orphan record */
>  		agbno = rr->rr_rrec.rc_startblock - XFS_REFC_COW_START;
>  		fsb = XFS_AGB_TO_FSB(mp, agno, agbno);
> -		error = xfs_refcount_free_cow_extent(mp, tp->t_dfops, fsb,
> +		error = xfs_refcount_free_cow_extent(tp, fsb,
>  				rr->rr_rrec.rc_blockcount);
>  		if (error)
>  			goto out_trans;
>  
>  		/* Free the block. */
> -		xfs_bmap_add_free(mp, tp->t_dfops, fsb,
> -				rr->rr_rrec.rc_blockcount, NULL);
> +		xfs_bmap_add_free(tp, fsb, rr->rr_rrec.rc_blockcount, NULL);
>  
>  		error = xfs_trans_commit(tp);
>  		if (error)
> diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h
> index 3b72c6dbf6ad..1d9c518575e7 100644
> --- a/fs/xfs/libxfs/xfs_refcount.h
> +++ b/fs/xfs/libxfs/xfs_refcount.h
> @@ -29,10 +29,10 @@ struct xfs_refcount_intent {
>  	xfs_extlen_t				ri_blockcount;
>  };
>  
> -extern int xfs_refcount_increase_extent(struct xfs_mount *mp,
> -		struct xfs_defer_ops *dfops, struct xfs_bmbt_irec *irec);
> -extern int xfs_refcount_decrease_extent(struct xfs_mount *mp,
> -		struct xfs_defer_ops *dfops, struct xfs_bmbt_irec *irec);
> +extern int xfs_refcount_increase_extent(struct xfs_trans *tp,
> +		struct xfs_bmbt_irec *irec);
> +extern int xfs_refcount_decrease_extent(struct xfs_trans *tp,
> +		struct xfs_bmbt_irec *irec);
>  
>  extern void xfs_refcount_finish_one_cleanup(struct xfs_trans *tp,
>  		struct xfs_btree_cur *rcur, int error);
> @@ -45,12 +45,10 @@ extern int xfs_refcount_find_shared(struct xfs_btree_cur *cur,
>  		xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno,
>  		xfs_extlen_t *flen, bool find_end_of_shared);
>  
> -extern int xfs_refcount_alloc_cow_extent(struct xfs_mount *mp,
> -		struct xfs_defer_ops *dfops, xfs_fsblock_t fsb,
> -		xfs_extlen_t len);
> -extern int xfs_refcount_free_cow_extent(struct xfs_mount *mp,
> -		struct xfs_defer_ops *dfops, xfs_fsblock_t fsb,
> -		xfs_extlen_t len);
> +extern int xfs_refcount_alloc_cow_extent(struct xfs_trans *tp,
> +		xfs_fsblock_t fsb, xfs_extlen_t len);
> +extern int xfs_refcount_free_cow_extent(struct xfs_trans *tp,
> +		xfs_fsblock_t fsb, xfs_extlen_t len);
>  extern int xfs_refcount_recover_cow_leftovers(struct xfs_mount *mp,
>  		xfs_agnumber_t agno);
>  
> diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
> index fb266fa2cc45..aa683eda6b70 100644
> --- a/fs/xfs/libxfs/xfs_rmap.c
> +++ b/fs/xfs/libxfs/xfs_rmap.c
> @@ -2277,14 +2277,14 @@ xfs_rmap_update_is_needed(
>   */
>  static int
>  __xfs_rmap_add(
> -	struct xfs_mount		*mp,
> -	struct xfs_defer_ops		*dfops,
> +	struct xfs_trans		*tp,
>  	enum xfs_rmap_intent_type	type,
>  	uint64_t			owner,
>  	int				whichfork,
>  	struct xfs_bmbt_irec		*bmap)
>  {
> -	struct xfs_rmap_intent	*ri;
> +	struct xfs_mount		*mp = tp->t_mountp;
> +	struct xfs_rmap_intent		*ri;
>  
>  	trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
>  			type,
> @@ -2301,23 +2301,22 @@ __xfs_rmap_add(
>  	ri->ri_whichfork = whichfork;
>  	ri->ri_bmap = *bmap;
>  
> -	xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
> +	xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
>  	return 0;
>  }
>  
>  /* Map an extent into a file. */
>  int
>  xfs_rmap_map_extent(
> -	struct xfs_mount	*mp,
> -	struct xfs_defer_ops	*dfops,
> +	struct xfs_trans	*tp,
>  	struct xfs_inode	*ip,
>  	int			whichfork,
>  	struct xfs_bmbt_irec	*PREV)
>  {
> -	if (!xfs_rmap_update_is_needed(mp, whichfork))
> +	if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
>  		return 0;
>  
> -	return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
> +	return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
>  			XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
>  			whichfork, PREV);
>  }
> @@ -2325,25 +2324,29 @@ xfs_rmap_map_extent(
>  /* Unmap an extent out of a file. */
>  int
>  xfs_rmap_unmap_extent(
> -	struct xfs_mount	*mp,
> -	struct xfs_defer_ops	*dfops,
> +	struct xfs_trans	*tp,
>  	struct xfs_inode	*ip,
>  	int			whichfork,
>  	struct xfs_bmbt_irec	*PREV)
>  {
> -	if (!xfs_rmap_update_is_needed(mp, whichfork))
> +	if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
>  		return 0;
>  
> -	return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
> +	return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
>  			XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
>  			whichfork, PREV);
>  }
>  
> -/* Convert a data fork extent from unwritten to real or vice versa. */
> +/*
> + * Convert a data fork extent from unwritten to real or vice versa.
> + *
> + * Note that tp can be NULL here as no transaction is used for COW fork
> + * unwritten conversion.
> + */
>  int
>  xfs_rmap_convert_extent(
>  	struct xfs_mount	*mp,
> -	struct xfs_defer_ops	*dfops,
> +	struct xfs_trans	*tp,
>  	struct xfs_inode	*ip,
>  	int			whichfork,
>  	struct xfs_bmbt_irec	*PREV)
> @@ -2351,7 +2354,7 @@ xfs_rmap_convert_extent(
>  	if (!xfs_rmap_update_is_needed(mp, whichfork))
>  		return 0;
>  
> -	return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
> +	return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ?
>  			XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
>  			whichfork, PREV);
>  }
> @@ -2359,8 +2362,7 @@ xfs_rmap_convert_extent(
>  /* Schedule the creation of an rmap for non-file data. */
>  int
>  xfs_rmap_alloc_extent(
> -	struct xfs_mount	*mp,
> -	struct xfs_defer_ops	*dfops,
> +	struct xfs_trans	*tp,
>  	xfs_agnumber_t		agno,
>  	xfs_agblock_t		bno,
>  	xfs_extlen_t		len,
> @@ -2368,23 +2370,21 @@ xfs_rmap_alloc_extent(
>  {
>  	struct xfs_bmbt_irec	bmap;
>  
> -	if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
> +	if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
>  		return 0;
>  
> -	bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
> +	bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
>  	bmap.br_blockcount = len;
>  	bmap.br_startoff = 0;
>  	bmap.br_state = XFS_EXT_NORM;
>  
> -	return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner,
> -			XFS_DATA_FORK, &bmap);
> +	return __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
>  }
>  
>  /* Schedule the deletion of an rmap for non-file data. */
>  int
>  xfs_rmap_free_extent(
> -	struct xfs_mount	*mp,
> -	struct xfs_defer_ops	*dfops,
> +	struct xfs_trans	*tp,
>  	xfs_agnumber_t		agno,
>  	xfs_agblock_t		bno,
>  	xfs_extlen_t		len,
> @@ -2392,16 +2392,15 @@ xfs_rmap_free_extent(
>  {
>  	struct xfs_bmbt_irec	bmap;
>  
> -	if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
> +	if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
>  		return 0;
>  
> -	bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
> +	bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
>  	bmap.br_blockcount = len;
>  	bmap.br_startoff = 0;
>  	bmap.br_state = XFS_EXT_NORM;
>  
> -	return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner,
> -			XFS_DATA_FORK, &bmap);
> +	return __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
>  }
>  
>  /* Compare rmap records.  Returns -1 if a < b, 1 if a > b, and 0 if equal. */
> diff --git a/fs/xfs/libxfs/xfs_rmap.h b/fs/xfs/libxfs/xfs_rmap.h
> index 9f19454768b2..157dc722ad35 100644
> --- a/fs/xfs/libxfs/xfs_rmap.h
> +++ b/fs/xfs/libxfs/xfs_rmap.h
> @@ -185,21 +185,17 @@ struct xfs_rmap_intent {
>  };
>  
>  /* functions for updating the rmapbt based on bmbt map/unmap operations */
> -int xfs_rmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
> +int xfs_rmap_map_extent(struct xfs_trans *tp, struct xfs_inode *ip,
> +		int whichfork, struct xfs_bmbt_irec *imap);
> +int xfs_rmap_unmap_extent(struct xfs_trans *tp, struct xfs_inode *ip,
> +		int whichfork, struct xfs_bmbt_irec *imap);
> +int xfs_rmap_convert_extent(struct xfs_mount *mp, struct xfs_trans *tp,
>  		struct xfs_inode *ip, int whichfork,
>  		struct xfs_bmbt_irec *imap);
> -int xfs_rmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
> -		struct xfs_inode *ip, int whichfork,
> -		struct xfs_bmbt_irec *imap);
> -int xfs_rmap_convert_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
> -		struct xfs_inode *ip, int whichfork,
> -		struct xfs_bmbt_irec *imap);
> -int xfs_rmap_alloc_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
> -		xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
> -		uint64_t owner);
> -int xfs_rmap_free_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
> -		xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
> -		uint64_t owner);
> +int xfs_rmap_alloc_extent(struct xfs_trans *tp, xfs_agnumber_t agno,
> +		xfs_agblock_t bno, xfs_extlen_t len, uint64_t owner);
> +int xfs_rmap_free_extent(struct xfs_trans *tp, xfs_agnumber_t agno,
> +		xfs_agblock_t bno, xfs_extlen_t len, uint64_t owner);
>  
>  void xfs_rmap_finish_one_cleanup(struct xfs_trans *tp,
>  		struct xfs_btree_cur *rcur, int error);
> diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
> index 328a5c60000b..ffe42147a032 100644
> --- a/fs/xfs/xfs_bmap_item.c
> +++ b/fs/xfs/xfs_bmap_item.c
> @@ -486,8 +486,7 @@ xfs_bui_recover(
>  		irec.br_blockcount = count;
>  		irec.br_startoff = bmap->me_startoff;
>  		irec.br_state = state;
> -		error = xfs_bmap_unmap_extent(tp->t_mountp, tp->t_dfops, ip,
> -					      &irec);
> +		error = xfs_bmap_unmap_extent(tp, ip, &irec);
>  		if (error)
>  			goto err_inode;
>  	}
> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> index d9dad399440a..addbd74ecd8e 100644
> --- a/fs/xfs/xfs_bmap_util.c
> +++ b/fs/xfs/xfs_bmap_util.c
> @@ -1534,7 +1534,6 @@ xfs_swap_extent_rmap(
>  	struct xfs_inode		*tip)
>  {
>  	struct xfs_trans		*tp = *tpp;
> -	struct xfs_mount		*mp = tp->t_mountp;
>  	struct xfs_bmbt_irec		irec;
>  	struct xfs_bmbt_irec		uirec;
>  	struct xfs_bmbt_irec		tirec;
> @@ -1598,26 +1597,22 @@ xfs_swap_extent_rmap(
>  			trace_xfs_swap_extent_rmap_remap_piece(tip, &uirec);
>  
>  			/* Remove the mapping from the donor file. */
> -			error = xfs_bmap_unmap_extent(mp, tp->t_dfops, tip,
> -					&uirec);
> +			error = xfs_bmap_unmap_extent(tp, tip, &uirec);
>  			if (error)
>  				goto out_defer;
>  
>  			/* Remove the mapping from the source file. */
> -			error = xfs_bmap_unmap_extent(mp, tp->t_dfops, ip,
> -					&irec);
> +			error = xfs_bmap_unmap_extent(tp, ip, &irec);
>  			if (error)
>  				goto out_defer;
>  
>  			/* Map the donor file's blocks into the source file. */
> -			error = xfs_bmap_map_extent(mp, tp->t_dfops, ip,
> -					&uirec);
> +			error = xfs_bmap_map_extent(tp, ip, &uirec);
>  			if (error)
>  				goto out_defer;
>  
>  			/* Map the source file's blocks into the donor file. */
> -			error = xfs_bmap_map_extent(mp, tp->t_dfops, tip,
> -					&irec);
> +			error = xfs_bmap_map_extent(tp, tip, &irec);
>  			if (error)
>  				goto out_defer;
>  
> diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
> index f6a3249aa2d4..c626fc5d3464 100644
> --- a/fs/xfs/xfs_refcount_item.c
> +++ b/fs/xfs/xfs_refcount_item.c
> @@ -490,24 +490,18 @@ xfs_cui_recover(
>  			irec.br_blockcount = new_len;
>  			switch (type) {
>  			case XFS_REFCOUNT_INCREASE:
> -				error = xfs_refcount_increase_extent(
> -						tp->t_mountp, tp->t_dfops,
> -						&irec);
> +				error = xfs_refcount_increase_extent(tp, &irec);
>  				break;
>  			case XFS_REFCOUNT_DECREASE:
> -				error = xfs_refcount_decrease_extent(
> -						tp->t_mountp, tp->t_dfops,
> -						&irec);
> +				error = xfs_refcount_decrease_extent(tp, &irec);
>  				break;
>  			case XFS_REFCOUNT_ALLOC_COW:
> -				error = xfs_refcount_alloc_cow_extent(
> -						tp->t_mountp, tp->t_dfops,
> +				error = xfs_refcount_alloc_cow_extent(tp,
>  						irec.br_startblock,
>  						irec.br_blockcount);
>  				break;
>  			case XFS_REFCOUNT_FREE_COW:
> -				error = xfs_refcount_free_cow_extent(
> -						tp->t_mountp, tp->t_dfops,
> +				error = xfs_refcount_free_cow_extent(tp,
>  						irec.br_startblock,
>  						irec.br_blockcount);
>  				break;
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index 2ec562d75494..cbceb320a2e7 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -506,15 +506,13 @@ xfs_reflink_cancel_cow_blocks(
>  			ASSERT((*tpp)->t_firstblock == NULLFSBLOCK);
>  
>  			/* Free the CoW orphan record. */
> -			error = xfs_refcount_free_cow_extent(ip->i_mount,
> -					(*tpp)->t_dfops, del.br_startblock,
> -					del.br_blockcount);
> +			error = xfs_refcount_free_cow_extent(*tpp,
> +					del.br_startblock, del.br_blockcount);
>  			if (error)
>  				break;
>  
> -			xfs_bmap_add_free(ip->i_mount, (*tpp)->t_dfops,
> -					del.br_startblock, del.br_blockcount,
> -					NULL);
> +			xfs_bmap_add_free(*tpp, del.br_startblock,
> +					  del.br_blockcount, NULL);
>  
>  			/* Roll the transaction */
>  			error = xfs_defer_finish(tpp);
> @@ -694,14 +692,13 @@ xfs_reflink_end_cow(
>  		trace_xfs_reflink_cow_remap(ip, &del);
>  
>  		/* Free the CoW orphan record. */
> -		error = xfs_refcount_free_cow_extent(tp->t_mountp, tp->t_dfops,
> -				del.br_startblock, del.br_blockcount);
> +		error = xfs_refcount_free_cow_extent(tp, del.br_startblock,
> +				del.br_blockcount);
>  		if (error)
>  			goto out_cancel;
>  
>  		/* Map the new blocks into the data fork. */
> -		error = xfs_bmap_map_extent(tp->t_mountp, tp->t_dfops, ip,
> -					    &del);
> +		error = xfs_bmap_map_extent(tp, ip, &del);
>  		if (error)
>  			goto out_cancel;
>  
> @@ -1046,12 +1043,12 @@ xfs_reflink_remap_extent(
>  				uirec.br_blockcount, uirec.br_startblock);
>  
>  		/* Update the refcount tree */
> -		error = xfs_refcount_increase_extent(mp, tp->t_dfops, &uirec);
> +		error = xfs_refcount_increase_extent(tp, &uirec);
>  		if (error)
>  			goto out_cancel;
>  
>  		/* Map the new blocks into the data fork. */
> -		error = xfs_bmap_map_extent(mp, tp->t_dfops, ip, &uirec);
> +		error = xfs_bmap_map_extent(tp, ip, &uirec);
>  		if (error)
>  			goto out_cancel;
>  
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 14/15] xfs: always defer agfl block frees
  2018-07-30 16:45 ` [PATCH 14/15] xfs: always defer agfl block frees Brian Foster
@ 2018-07-30 20:49   ` Darrick J. Wong
  2018-07-31  8:32   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 20:49 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:19PM -0400, Brian Foster wrote:
> The AGFL fixup code conditionally defers block frees from the free
> list based on whether the current transaction has an associated
> xfs_defer_ops structure. Now that dfops is embedded in the
> transaction and the internal dfops is used unconditionally, this
> invariant is always true.
> 
> Remove the now dead logic to check for ->t_dfops in
> xfs_alloc_fix_freelist() and unconditionally defer AGFL block frees.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks ok,
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/xfs/libxfs/xfs_alloc.c | 11 ++---------
>  1 file changed, 2 insertions(+), 9 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
> index 6bacdc31a439..32a370665d71 100644
> --- a/fs/xfs/libxfs/xfs_alloc.c
> +++ b/fs/xfs/libxfs/xfs_alloc.c
> @@ -2323,15 +2323,8 @@ xfs_alloc_fix_freelist(
>  		if (error)
>  			goto out_agbp_relse;
>  
> -		/* defer agfl frees if dfops is provided */
> -		if (tp->t_dfops) {
> -			xfs_defer_agfl_block(tp, args->agno, bno, &targs.oinfo);
> -		} else {
> -			error = xfs_free_agfl_block(tp, args->agno, bno, agbp,
> -						    &targs.oinfo);
> -			if (error)
> -				goto out_agbp_relse;
> -		}
> +		/* defer agfl frees */
> +		xfs_defer_agfl_block(tp, args->agno, bno, &targs.oinfo);
>  	}
>  
>  	targs.tp = tp;
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 15/15] xfs: fold dfops into the transaction
  2018-07-30 16:45 ` [PATCH 15/15] xfs: fold dfops into the transaction Brian Foster
@ 2018-07-30 20:51   ` Darrick J. Wong
  2018-07-31  8:36   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-30 20:51 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:20PM -0400, Brian Foster wrote:
> struct xfs_defer_ops has now been reduced to a single list_head. The
> external dfops mechanism is unused and thus everywhere a (permanent)
> transaction is accessible the associated dfops structure is as well.
> 
> Remove the xfs_defer_ops structure and fold the list_head into the
> transaction. Also remove the last remnant of external dfops in
> xfs_trans_dup().
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks ok, I'll give it a spin to see how it does...
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/xfs/libxfs/xfs_bmap.c     |  1 -
>  fs/xfs/libxfs/xfs_btree.h    |  1 -
>  fs/xfs/libxfs/xfs_da_btree.h |  1 -
>  fs/xfs/libxfs/xfs_defer.c    | 65 +++++++++++-------------------------
>  fs/xfs/libxfs/xfs_defer.h    |  2 --
>  fs/xfs/libxfs/xfs_dir2.c     |  2 --
>  fs/xfs/libxfs/xfs_dir2.h     |  1 -
>  fs/xfs/xfs_inode.h           |  1 -
>  fs/xfs/xfs_reflink.c         |  5 ++-
>  fs/xfs/xfs_trace.h           | 33 +++++++++---------
>  fs/xfs/xfs_trans.c           | 11 +++---
>  fs/xfs/xfs_trans.h           |  8 ++---
>  12 files changed, 43 insertions(+), 88 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index f5f1fc47923e..0f9f522ab792 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -4285,7 +4285,6 @@ xfs_bmapi_write(
>  	bma.ip = ip;
>  	bma.total = total;
>  	bma.datatype = 0;
> -	ASSERT(!tp || tp->t_dfops);
>  
>  	while (bno < end && n < *nmap) {
>  		bool			need_alloc = false, wasdelay = false;
> diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
> index 503615f4d729..e3b3e9dce5da 100644
> --- a/fs/xfs/libxfs/xfs_btree.h
> +++ b/fs/xfs/libxfs/xfs_btree.h
> @@ -7,7 +7,6 @@
>  #define	__XFS_BTREE_H__
>  
>  struct xfs_buf;
> -struct xfs_defer_ops;
>  struct xfs_inode;
>  struct xfs_mount;
>  struct xfs_trans;
> diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h
> index 59e290ef334f..84dd865b6c3d 100644
> --- a/fs/xfs/libxfs/xfs_da_btree.h
> +++ b/fs/xfs/libxfs/xfs_da_btree.h
> @@ -7,7 +7,6 @@
>  #ifndef __XFS_DA_BTREE_H__
>  #define	__XFS_DA_BTREE_H__
>  
> -struct xfs_defer_ops;
>  struct xfs_inode;
>  struct xfs_trans;
>  struct zone;
> diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> index 152190a69432..9ce9e1c75e23 100644
> --- a/fs/xfs/libxfs/xfs_defer.c
> +++ b/fs/xfs/libxfs/xfs_defer.c
> @@ -186,11 +186,10 @@ xfs_defer_intake_work(
>  	struct xfs_trans		*tp,
>  	struct list_head		*dop_pending)
>  {
> -	struct xfs_defer_ops		*dop = tp->t_dfops;
>  	struct list_head		*li;
>  	struct xfs_defer_pending	*dfp;
>  
> -	list_for_each_entry(dfp, &dop->dop_intake, dfp_list) {
> +	list_for_each_entry(dfp, &tp->t_dfops, dfp_list) {
>  		dfp->dfp_intent = dfp->dfp_type->create_intent(tp,
>  				dfp->dfp_count);
>  		trace_xfs_defer_intake_work(tp->t_mountp, dfp);
> @@ -200,7 +199,7 @@ xfs_defer_intake_work(
>  			dfp->dfp_type->log_item(tp, dfp->dfp_intent, li);
>  	}
>  
> -	list_splice_tail_init(&dop->dop_intake, dop_pending);
> +	list_splice_tail_init(&tp->t_dfops, dop_pending);
>  }
>  
>  /* Abort all the intents that were committed. */
> @@ -210,10 +209,9 @@ xfs_defer_trans_abort(
>  	struct list_head		*dop_pending,
>  	int				error)
>  {
> -	struct xfs_defer_ops		*dop = tp->t_dfops;
>  	struct xfs_defer_pending	*dfp;
>  
> -	trace_xfs_defer_trans_abort(tp->t_mountp, dop, _RET_IP_);
> +	trace_xfs_defer_trans_abort(tp->t_mountp, tp, _RET_IP_);
>  
>  	/* Abort intent items that don't have a done item. */
>  	if (dop_pending) {
> @@ -272,13 +270,12 @@ xfs_defer_trans_roll(
>  		}
>  	}
>  
> -	trace_xfs_defer_trans_roll((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_);
> +	trace_xfs_defer_trans_roll((*tp)->t_mountp, *tp, _RET_IP_);
>  
>  	/* Roll the transaction. */
>  	error = xfs_trans_roll(tp);
>  	if (error) {
> -		trace_xfs_defer_trans_roll_error((*tp)->t_mountp,
> -						 (*tp)->t_dfops, error);
> +		trace_xfs_defer_trans_roll_error((*tp)->t_mountp, *tp, error);
>  		xfs_defer_trans_abort(*tp,  dop_pending, error);
>  		return error;
>  	}
> @@ -303,7 +300,7 @@ xfs_defer_has_unfinished_work(
>  	struct list_head		*dop_pending)
>  {
>  	return !list_empty(dop_pending) ||
> -		!list_empty(&tp->t_dfops->dop_intake);
> +		!list_empty(&tp->t_dfops);
>  }
>  
>  /*
> @@ -313,7 +310,7 @@ static void
>  xfs_defer_reset(
>  	struct xfs_trans	*tp)
>  {
> -	ASSERT(list_empty(&tp->t_dfops->dop_intake));
> +	ASSERT(list_empty(&tp->t_dfops));
>  
>  	/*
>  	 * Low mode state transfers across transaction rolls to mirror dfops
> @@ -344,7 +341,7 @@ xfs_defer_finish_noroll(
>  
>  	ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
>  
> -	trace_xfs_defer_finish((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_);
> +	trace_xfs_defer_finish((*tp)->t_mountp, *tp, _RET_IP_);
>  
>  	/* Until we run out of pending work to finish... */
>  	while (xfs_defer_has_unfinished_work(*tp, &dop_pending)) {
> @@ -420,14 +417,13 @@ xfs_defer_finish_noroll(
>  
>  out:
>  	if (error) {
> -		trace_xfs_defer_finish_error((*tp)->t_mountp, (*tp)->t_dfops,
> -					     error);
> +		trace_xfs_defer_finish_error((*tp)->t_mountp, *tp, error);
>  		__xfs_defer_cancel(&dop_pending);
>  		xfs_defer_cancel(*tp);
>  		return error;
>  	}
>  
> -	trace_xfs_defer_finish_done((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_);
> +	trace_xfs_defer_finish_done((*tp)->t_mountp, *tp, _RET_IP_);
>  	return 0;
>  }
>  
> @@ -486,8 +482,8 @@ void
>  xfs_defer_cancel(
>  	struct xfs_trans	*tp)
>  {
> -	trace_xfs_defer_cancel(NULL, tp->t_dfops, _RET_IP_);
> -	__xfs_defer_cancel(&tp->t_dfops->dop_intake);
> +	trace_xfs_defer_cancel(NULL, tp, _RET_IP_);
> +	__xfs_defer_cancel(&tp->t_dfops);
>  }
>  
>  /* Add an item for later deferred processing. */
> @@ -497,7 +493,6 @@ xfs_defer_add(
>  	enum xfs_defer_ops_type		type,
>  	struct list_head		*li)
>  {
> -	struct xfs_defer_ops		*dop = tp->t_dfops;
>  	struct xfs_defer_pending	*dfp = NULL;
>  
>  	/*
> @@ -505,8 +500,8 @@ xfs_defer_add(
>  	 * If the last pending item has the same type, reuse it.  Else,
>  	 * create a new pending item at the end of the intake list.
>  	 */
> -	if (!list_empty(&dop->dop_intake)) {
> -		dfp = list_last_entry(&dop->dop_intake,
> +	if (!list_empty(&tp->t_dfops)) {
> +		dfp = list_last_entry(&tp->t_dfops,
>  				struct xfs_defer_pending, dfp_list);
>  		if (dfp->dfp_type->type != type ||
>  		    (dfp->dfp_type->max_items &&
> @@ -521,7 +516,7 @@ xfs_defer_add(
>  		dfp->dfp_done = NULL;
>  		dfp->dfp_count = 0;
>  		INIT_LIST_HEAD(&dfp->dfp_work);
> -		list_add_tail(&dfp->dfp_list, &dop->dop_intake);
> +		list_add_tail(&dfp->dfp_list, &tp->t_dfops);
>  	}
>  
>  	list_add_tail(li, &dfp->dfp_work);
> @@ -536,39 +531,17 @@ xfs_defer_init_op_type(
>  	defer_op_types[type->type] = type;
>  }
>  
> -/* Initialize a deferred operation. */
> -void
> -xfs_defer_init(
> -	struct xfs_trans		*tp,
> -	struct xfs_defer_ops		*dop)
> -{
> -	struct xfs_mount		*mp = NULL;
> -
> -	memset(dop, 0, sizeof(struct xfs_defer_ops));
> -	INIT_LIST_HEAD(&dop->dop_intake);
> -	if (tp) {
> -		ASSERT(tp->t_firstblock == NULLFSBLOCK);
> -		tp->t_dfops = dop;
> -		mp = tp->t_mountp;
> -	}
> -	trace_xfs_defer_init(mp, dop, _RET_IP_);
> -}
> -
>  /*
> - * Move state from one xfs_defer_ops to another and reset the source to initial
> - * state. This is primarily used to carry state forward across transaction rolls
> - * with internal dfops.
> + * Move deferred ops from one transaction to another and reset the source to
> + * initial state. This is primarily used to carry state forward across
> + * transaction rolls with pending dfops.
>   */
>  void
>  xfs_defer_move(
>  	struct xfs_trans	*dtp,
>  	struct xfs_trans	*stp)
>  {
> -	struct xfs_defer_ops	*dst = dtp->t_dfops;
> -	struct xfs_defer_ops	*src = stp->t_dfops;
> -	ASSERT(dst != src);
> -
> -	list_splice_init(&src->dop_intake, &dst->dop_intake);
> +	list_splice_init(&stp->t_dfops, &dtp->t_dfops);
>  
>  	/*
>  	 * Low free space mode was historically controlled by a dfops field.
> diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
> index 295703737272..9ea37a8c464a 100644
> --- a/fs/xfs/libxfs/xfs_defer.h
> +++ b/fs/xfs/libxfs/xfs_defer.h
> @@ -7,7 +7,6 @@
>  #define	__XFS_DEFER_H__
>  
>  struct xfs_defer_op_type;
> -struct xfs_defer_ops;
>  
>  /*
>   * Save a log intent item and a list of extents, so that we can replay
> @@ -40,7 +39,6 @@ void xfs_defer_add(struct xfs_trans *tp, enum xfs_defer_ops_type type,
>  int xfs_defer_finish_noroll(struct xfs_trans **tp);
>  int xfs_defer_finish(struct xfs_trans **tp);
>  void xfs_defer_cancel(struct xfs_trans *);
> -void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
>  bool xfs_defer_has_unfinished_work(struct xfs_trans *tp,
>  		struct list_head *dop_pending);
>  void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
> diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c
> index 4ea1fddb126f..229152cd1a24 100644
> --- a/fs/xfs/libxfs/xfs_dir2.c
> +++ b/fs/xfs/libxfs/xfs_dir2.c
> @@ -424,7 +424,6 @@ xfs_dir_removename(
>  	int			v;		/* type-checking value */
>  
>  	ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
> -	ASSERT(tp->t_dfops);
>  	XFS_STATS_INC(dp->i_mount, xs_dir_remove);
>  
>  	args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
> @@ -483,7 +482,6 @@ xfs_dir_replace(
>  	int			v;		/* type-checking value */
>  
>  	ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
> -	ASSERT(tp->t_dfops);
>  
>  	rval = xfs_dir_ino_validate(tp->t_mountp, inum);
>  	if (rval)
> diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h
> index ba5acd03de94..c3e3f6b813d8 100644
> --- a/fs/xfs/libxfs/xfs_dir2.h
> +++ b/fs/xfs/libxfs/xfs_dir2.h
> @@ -9,7 +9,6 @@
>  #include "xfs_da_format.h"
>  #include "xfs_da_btree.h"
>  
> -struct xfs_defer_ops;
>  struct xfs_da_args;
>  struct xfs_inode;
>  struct xfs_mount;
> diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
> index 79a3e61a6991..be2014520155 100644
> --- a/fs/xfs/xfs_inode.h
> +++ b/fs/xfs/xfs_inode.h
> @@ -15,7 +15,6 @@
>  struct xfs_dinode;
>  struct xfs_inode;
>  struct xfs_buf;
> -struct xfs_defer_ops;
>  struct xfs_bmbt_irec;
>  struct xfs_inode_log_item;
>  struct xfs_mount;
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index cbceb320a2e7..38f405415b88 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -502,7 +502,6 @@ xfs_reflink_cancel_cow_blocks(
>  			if (error)
>  				break;
>  		} else if (del.br_state == XFS_EXT_UNWRITTEN || cancel_real) {
> -			ASSERT((*tpp)->t_dfops);
>  			ASSERT((*tpp)->t_firstblock == NULLFSBLOCK);
>  
>  			/* Free the CoW orphan record. */
> @@ -678,7 +677,7 @@ xfs_reflink_end_cow(
>  			goto prev_extent;
>  
>  		/* Unmap the old blocks in the data fork. */
> -		ASSERT(tp->t_dfops && tp->t_firstblock == NULLFSBLOCK);
> +		ASSERT(tp->t_firstblock == NULLFSBLOCK);
>  		rlen = del.br_blockcount;
>  		error = __xfs_bunmapi(tp, ip, del.br_startoff, &rlen, 0, 1);
>  		if (error)
> @@ -1021,7 +1020,7 @@ xfs_reflink_remap_extent(
>  	/* Unmap the old blocks in the data fork. */
>  	rlen = unmap_len;
>  	while (rlen) {
> -		ASSERT(tp->t_dfops && tp->t_firstblock == NULLFSBLOCK);
> +		ASSERT(tp->t_firstblock == NULLFSBLOCK);
>  		error = __xfs_bunmapi(tp, ip, destoff, &rlen, 0, 1);
>  		if (error)
>  			goto out_cancel;
> diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
> index 6b55bbc09578..023c0445a231 100644
> --- a/fs/xfs/xfs_trace.h
> +++ b/fs/xfs/xfs_trace.h
> @@ -2213,57 +2213,56 @@ DEFINE_BTREE_CUR_EVENT(xfs_btree_overlapped_query_range);
>  
>  /* deferred ops */
>  struct xfs_defer_pending;
> -struct xfs_defer_ops;
>  
>  DECLARE_EVENT_CLASS(xfs_defer_class,
> -	TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop,
> +	TP_PROTO(struct xfs_mount *mp, struct xfs_trans *tp,
>  		 unsigned long caller_ip),
> -	TP_ARGS(mp, dop, caller_ip),
> +	TP_ARGS(mp, tp, caller_ip),
>  	TP_STRUCT__entry(
>  		__field(dev_t, dev)
> -		__field(void *, dop)
> +		__field(void *, tp)
>  		__field(char, committed)
>  		__field(unsigned long, caller_ip)
>  	),
>  	TP_fast_assign(
>  		__entry->dev = mp ? mp->m_super->s_dev : 0;
> -		__entry->dop = dop;
> +		__entry->tp = tp;
>  		__entry->caller_ip = caller_ip;
>  	),
> -	TP_printk("dev %d:%d ops %p caller %pS",
> +	TP_printk("dev %d:%d tp %p caller %pS",
>  		  MAJOR(__entry->dev), MINOR(__entry->dev),
> -		  __entry->dop,
> +		  __entry->tp,
>  		  (char *)__entry->caller_ip)
>  )
>  #define DEFINE_DEFER_EVENT(name) \
>  DEFINE_EVENT(xfs_defer_class, name, \
> -	TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, \
> +	TP_PROTO(struct xfs_mount *mp, struct xfs_trans *tp, \
>  		 unsigned long caller_ip), \
> -	TP_ARGS(mp, dop, caller_ip))
> +	TP_ARGS(mp, tp, caller_ip))
>  
>  DECLARE_EVENT_CLASS(xfs_defer_error_class,
> -	TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, int error),
> -	TP_ARGS(mp, dop, error),
> +	TP_PROTO(struct xfs_mount *mp, struct xfs_trans *tp, int error),
> +	TP_ARGS(mp, tp, error),
>  	TP_STRUCT__entry(
>  		__field(dev_t, dev)
> -		__field(void *, dop)
> +		__field(void *, tp)
>  		__field(char, committed)
>  		__field(int, error)
>  	),
>  	TP_fast_assign(
>  		__entry->dev = mp ? mp->m_super->s_dev : 0;
> -		__entry->dop = dop;
> +		__entry->tp = tp;
>  		__entry->error = error;
>  	),
> -	TP_printk("dev %d:%d ops %p err %d",
> +	TP_printk("dev %d:%d tp %p err %d",
>  		  MAJOR(__entry->dev), MINOR(__entry->dev),
> -		  __entry->dop,
> +		  __entry->tp,
>  		  __entry->error)
>  )
>  #define DEFINE_DEFER_ERROR_EVENT(name) \
>  DEFINE_EVENT(xfs_defer_error_class, name, \
> -	TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, int error), \
> -	TP_ARGS(mp, dop, error))
> +	TP_PROTO(struct xfs_mount *mp, struct xfs_trans *tp, int error), \
> +	TP_ARGS(mp, tp, error))
>  
>  DECLARE_EVENT_CLASS(xfs_defer_pending_class,
>  	TP_PROTO(struct xfs_mount *mp, struct xfs_defer_pending *dfp),
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index 20750cd9c9e7..d4faa0414927 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -100,6 +100,7 @@ xfs_trans_dup(
>  	ntp->t_mountp = tp->t_mountp;
>  	INIT_LIST_HEAD(&ntp->t_items);
>  	INIT_LIST_HEAD(&ntp->t_busy);
> +	INIT_LIST_HEAD(&ntp->t_dfops);
>  	ntp->t_firstblock = NULLFSBLOCK;
>  
>  	ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
> @@ -120,12 +121,8 @@ xfs_trans_dup(
>  	tp->t_rtx_res = tp->t_rtx_res_used;
>  	ntp->t_pflags = tp->t_pflags;
>  
> -	/* copy the dfops pointer if it's external, otherwise move it */
> -	xfs_defer_init(ntp, &ntp->t_dfops_internal);
> -	if (tp->t_dfops != &tp->t_dfops_internal)
> -		ntp->t_dfops = tp->t_dfops;
> -	else
> -		xfs_defer_move(ntp, tp);
> +	/* move deferred ops over to the new tp */
> +	xfs_defer_move(ntp, tp);
>  
>  	xfs_trans_dup_dqinfo(tp, ntp);
>  
> @@ -280,8 +277,8 @@ xfs_trans_alloc(
>  	tp->t_mountp = mp;
>  	INIT_LIST_HEAD(&tp->t_items);
>  	INIT_LIST_HEAD(&tp->t_busy);
> +	INIT_LIST_HEAD(&tp->t_dfops);
>  	tp->t_firstblock = NULLFSBLOCK;
> -	xfs_defer_init(tp, &tp->t_dfops_internal);
>  
>  	error = xfs_trans_reserve(tp, resp, blocks, rtextents);
>  	if (error) {
> diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> index 1cdc7c0ebeac..c3d278e96ad1 100644
> --- a/fs/xfs/xfs_trans.h
> +++ b/fs/xfs/xfs_trans.h
> @@ -90,13 +90,10 @@ void	xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item,
>  #define XFS_ITEM_FLUSHING	3
>  
>  /*
> - * Deferred operations tracking structure.
> + * Deferred operation item relogging limits.
>   */
>  #define XFS_DEFER_OPS_NR_INODES	2	/* join up to two inodes */
>  #define XFS_DEFER_OPS_NR_BUFS	2	/* join up to two buffers */
> -struct xfs_defer_ops {
> -	struct list_head	dop_intake;	/* unlogged pending work */
> -};
>  
>  /*
>   * This is the structure maintained for every active transaction.
> @@ -114,7 +111,6 @@ typedef struct xfs_trans {
>  	struct xlog_ticket	*t_ticket;	/* log mgr ticket */
>  	struct xfs_mount	*t_mountp;	/* ptr to fs mount struct */
>  	struct xfs_dquot_acct   *t_dqinfo;	/* acctg info for dquots */
> -	struct xfs_defer_ops	*t_dfops;	/* dfops reference */
>  	int64_t			t_icount_delta;	/* superblock icount change */
>  	int64_t			t_ifree_delta;	/* superblock ifree change */
>  	int64_t			t_fdblocks_delta; /* superblock fdblocks chg */
> @@ -136,8 +132,8 @@ typedef struct xfs_trans {
>  	int64_t			t_rextslog_delta;/* superblocks rextslog chg */
>  	struct list_head	t_items;	/* log item descriptors */
>  	struct list_head	t_busy;		/* list of busy extents */
> +	struct list_head	t_dfops;	/* deferred operations */
>  	unsigned long		t_pflags;	/* saved process flags state */
> -	struct xfs_defer_ops	t_dfops_internal;
>  } xfs_trans_t;
>  
>  /*
> -- 
> 2.17.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 01/15] xfs: refactor internal dfops initialization
  2018-07-30 19:30   ` Darrick J. Wong
@ 2018-07-31  8:10     ` Christoph Hellwig
  2018-07-31 11:47     ` Brian Foster
  1 sibling, 0 replies; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:10 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Brian Foster, linux-xfs

On Mon, Jul 30, 2018 at 12:30:48PM -0700, Darrick J. Wong wrote:
> >  	trace_xfs_trans_commit(tp, _RET_IP_);
> >  
> >  	/* finish deferred items on final commit */
> > -	if (!regrant && tp->t_dfops) {
> > +	if (!regrant && (tp->t_flags & XFS_TRANS_PERM_LOG_RES)) {
> 
> The usage model of deferred ops is that one has to create a transaction
> with a permanent reservation, and only then start attaching deferred ops
> to the dfops inside the transaction.  It's a programming error if a
> caller tries to finish deferred ops using a non-permanent transaction,
> and prior to this patch t_dfops would be NULL and we'd blow up
> immediately in xfs_defer_add(..., tp->t_dfops, ...);
> 
> However, now that we initialize t_dfops unconditionally, won't this
> cause the above programming mistake to leak silently any incorrectly
> queued defer ops?

I guess we'll just need an assert for a perment reservation in
xfs_defer_add, although that'll have to wait for the patch that
actually passes a transaction to it.

Except for that this patch looks fine to me:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 02/15] xfs: use transaction for intent recovery instead of raw dfops
  2018-07-30 20:09   ` Darrick J. Wong
@ 2018-07-31  8:12     ` Christoph Hellwig
  2018-07-31 11:47     ` Brian Foster
  1 sibling, 0 replies; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:12 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Brian Foster, linux-xfs

On Mon, Jul 30, 2018 at 01:09:09PM -0700, Darrick J. Wong wrote:
> > -	struct xfs_mount		*mp,
> > -	struct xfs_bui_log_item		*buip,
> > -	struct xfs_defer_ops		*dfops)
> > +	struct xfs_trans		*itp,
> 
> "itp"?
> 
> Oh, the intent-holder transaction...

Maybe we should just call it parent_tp which would be a little
less confusing?

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 02/15] xfs: use transaction for intent recovery instead of raw dfops
  2018-07-30 16:45 ` [PATCH 02/15] xfs: use transaction for intent recovery instead of raw dfops Brian Foster
  2018-07-30 20:09   ` Darrick J. Wong
@ 2018-07-31  8:13   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:13 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

>  
> +	error = xfs_trans_alloc_empty(log->l_mp, &tp);
> +	if (error)
> +		return error;
> +

I think we need a big comment explaining the use of this transaction
here.  Except for that and any naming issues:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 03/15] xfs: remove unused __xfs_defer_cancel() internal helper
  2018-07-30 16:45 ` [PATCH 03/15] xfs: remove unused __xfs_defer_cancel() internal helper Brian Foster
  2018-07-30 20:09   ` Darrick J. Wong
@ 2018-07-31  8:13   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:13 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:08PM -0400, Brian Foster wrote:
> With no more external dfops users, there is no need for an
> xfs_defer_ops cancel wrapper.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 04/15] xfs: pass transaction to dfops reset/move helpers
  2018-07-30 16:45 ` [PATCH 04/15] xfs: pass transaction to dfops reset/move helpers Brian Foster
  2018-07-30 20:10   ` Darrick J. Wong
@ 2018-07-31  8:14   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:14 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:09PM -0400, Brian Foster wrote:
> All callers pass ->t_dfops of the associated transactions. Refactor
> the helpers to receive the transactions and facilitate further
> cleanups between xfs_defer_ops and xfs_trans.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 05/15] xfs: replace dop_low with transaction flag
  2018-07-30 16:45 ` [PATCH 05/15] xfs: replace dop_low with transaction flag Brian Foster
  2018-07-30 20:11   ` Darrick J. Wong
@ 2018-07-31  8:16   ` Christoph Hellwig
  2018-07-31 11:47     ` Brian Foster
  1 sibling, 1 reply; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:16 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

> +	/*
> +	 * Low free space mode was historically controlled by a dfops field.
> +	 * This meant that low mode state potentially carried across multiple
> +	 * transaction rolls. Transfer low mode on a dfops move to preserve
> +	 * that behavior.
> +	 */
> +	dtp->t_flags |= stp->t_flags & XFS_TRANS_LOWMODE;

Maybe add parentheses here for clarity.

Except for that:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 06/15] xfs: add missing defer ijoins for held inodes
  2018-07-30 16:45 ` [PATCH 06/15] xfs: add missing defer ijoins for held inodes Brian Foster
  2018-07-30 20:15   ` Darrick J. Wong
@ 2018-07-31  8:17   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:17 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

Looks fine,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 07/15] xfs: automatic dfops buffer relogging
  2018-07-30 16:45 ` [PATCH 07/15] xfs: automatic dfops buffer relogging Brian Foster
  2018-07-30 20:20   ` Darrick J. Wong
@ 2018-07-31  8:19   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:19 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:12PM -0400, Brian Foster wrote:
> Buffers that are held across deferred operations are explicitly
> joined to the dfops structure to ensure appropriate relogging.
> While buffers are currently joined explicitly, we can detect the
> conditions that require relogging at dfops finish time by inspecting
> the transaction item list for held buffers.
> 
> Replace the xfs_defer_bjoin() infrastructure with such detection and
> automatic relogging of held buffers. This eliminates the need for
> the per-dfops buffer list, replaced by an on-stack variant in
> xfs_defer_trans_roll().

Looks good modulo added error checking as noted by Darrick:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 08/15] xfs: automatic dfops inode relogging
  2018-07-30 16:45 ` [PATCH 08/15] xfs: automatic dfops inode relogging Brian Foster
  2018-07-30 20:22   ` Darrick J. Wong
@ 2018-07-31  8:19   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:19 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:13PM -0400, Brian Foster wrote:
> Inodes that are held across deferred operations are explicitly
> joined to the dfops structure to ensure appropriate relogging.
> While inodes are currently joined explicitly, we can detect the
> conditions that require relogging at dfops finish time by inspecting
> the transaction item list for inodes with ili_lock_flags == 0.
> 
> Replace the xfs_defer_ijoin() infrastructure with such detection and
> automatic relogging of held inodes. This eliminates the need for the
> per-dfops inode list, replaced by an on-stack variant in
> xfs_defer_trans_roll().

Looks good modulo additional error checking:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 09/15] xfs: drop dop param from xfs_defer_op_type ->finish_item() callback
  2018-07-30 16:45 ` [PATCH 09/15] xfs: drop dop param from xfs_defer_op_type ->finish_item() callback Brian Foster
  2018-07-30 20:23   ` Darrick J. Wong
@ 2018-07-31  8:20   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:20 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:14PM -0400, Brian Foster wrote:
> The dfops infrastructure ->finish_item() callback passes the
> transaction and dfops as separate parameters. Since dfops is always
> part of a transaction, the latter parameter is no longer necessary.
> Remove it from the various callbacks.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 10/15] xfs: clean out superfluous dfops dop params/vars
  2018-07-30 16:45 ` [PATCH 10/15] xfs: clean out superfluous dfops dop params/vars Brian Foster
  2018-07-30 20:24   ` Darrick J. Wong
@ 2018-07-31  8:20   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:20 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:15PM -0400, Brian Foster wrote:
> The dfops code still passes around the xfs_defer_ops pointer
> superfluously in a few places. Clean this up wherever the
> transaction will suffice.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 11/15] xfs: cancel dfops on xfs_defer_finish() error
  2018-07-30 16:45 ` [PATCH 11/15] xfs: cancel dfops on xfs_defer_finish() error Brian Foster
  2018-07-30 20:27   ` Darrick J. Wong
@ 2018-07-31  8:21   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:21 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 12/15] xfs: replace xfs_defer_ops ->dop_pending with on-stack list
  2018-07-30 16:45 ` [PATCH 12/15] xfs: replace xfs_defer_ops ->dop_pending with on-stack list Brian Foster
  2018-07-30 20:47   ` Darrick J. Wong
@ 2018-07-31  8:30   ` Christoph Hellwig
  2018-07-31 11:50     ` Brian Foster
  1 sibling, 1 reply; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:30 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:17PM -0400, Brian Foster wrote:
> The xfs_defer_ops ->dop_pending list is used to track active
> deferred operations once intents are logged. These items must be
> aborted in the event of an error. The list is populated as intents
> are logged and items are removed as they complete (or are aborted).
> 
> Now that xfs_defer_finish() cancels on error, there is no need to
> ever access ->dop_pending outside of xfs_defer_finish(). The list is
> only ever populated after xfs_defer_finish() begins and is either
> completed or cancelled before it returns.
> 
> Remove ->dop_pending from xfs_defer_ops and replace it with a local
> list in the xfs_defer_finish() path. Pass the local list to the
> various helpers now that it is not accessible via dfops. Note that
> we have to check for NULL in the abort case as the final tx roll
> occurs outside of the scope of the new local list (once the dfops
> has completed and thus drained the list).
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>
> ---
>  fs/xfs/libxfs/xfs_defer.c | 80 ++++++++++++++++++++-------------------
>  fs/xfs/libxfs/xfs_defer.h |  3 +-
>  fs/xfs/xfs_trace.h        |  1 -
>  fs/xfs/xfs_trans.h        |  1 -
>  4 files changed, 43 insertions(+), 42 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> index 66848ede62c0..6bf792e2d61b 100644
> --- a/fs/xfs/libxfs/xfs_defer.c
> +++ b/fs/xfs/libxfs/xfs_defer.c
> @@ -174,6 +174,8 @@
>  
>  static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX];
>  
> +static void __xfs_defer_cancel(struct list_head *);

Can you just move __xfs_defer_cancel up to here to avoid the
forward declaration?

> +
>  /*
>   * For each pending item in the intake list, log its intent item and the
>   * associated extents, then add the entire intake list to the end of
> @@ -181,7 +183,8 @@ static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX];
>   */
>  STATIC void
>  xfs_defer_intake_work(
> -	struct xfs_trans		*tp)
> +	struct xfs_trans		*tp,
> +	struct list_head		*dop_pending)
>  {
>  	struct xfs_defer_ops		*dop = tp->t_dfops;
>  	struct list_head		*li;
> @@ -197,13 +200,14 @@ xfs_defer_intake_work(
>  			dfp->dfp_type->log_item(tp, dfp->dfp_intent, li);
>  	}
>  
> -	list_splice_tail_init(&dop->dop_intake, &dop->dop_pending);
> +	list_splice_tail_init(&dop->dop_intake, dop_pending);

It almost seems simpler to just move the list_splice_tail_init to the
(only) caller.

> @@ -292,9 +299,10 @@ xfs_defer_trans_roll(
>  /* Do we have any work items to finish? */
>  bool
>  xfs_defer_has_unfinished_work(
> -	struct xfs_trans		*tp)
> +	struct xfs_trans		*tp,
> +	struct list_head		*dop_pending)
>  {
> -	return !list_empty(&tp->t_dfops->dop_pending) ||
> +	return !list_empty(dop_pending) ||
>  		!list_empty(&tp->t_dfops->dop_intake);
>  }

I'd just opencode this in the only caller that is left.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 13/15] xfs: pass transaction to xfs_defer_add()
  2018-07-30 16:45 ` [PATCH 13/15] xfs: pass transaction to xfs_defer_add() Brian Foster
  2018-07-30 20:49   ` Darrick J. Wong
@ 2018-07-31  8:31   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:31 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

This is the right patch to add an assert for a permanent transaction
in xfs_defer_add.

Except for that this looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 14/15] xfs: always defer agfl block frees
  2018-07-30 16:45 ` [PATCH 14/15] xfs: always defer agfl block frees Brian Foster
  2018-07-30 20:49   ` Darrick J. Wong
@ 2018-07-31  8:32   ` Christoph Hellwig
  1 sibling, 0 replies; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:32 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:45:19PM -0400, Brian Foster wrote:
> The AGFL fixup code conditionally defers block frees from the free
> list based on whether the current transaction has an associated
> xfs_defer_ops structure. Now that dfops is embedded in the
> transaction and the internal dfops is used unconditionally, this
> invariant is always true.
> 
> Remove the now dead logic to check for ->t_dfops in
> xfs_alloc_fix_freelist() and unconditionally defer AGFL block frees.
> 
> Signed-off-by: Brian Foster <bfoster@redhat.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 15/15] xfs: fold dfops into the transaction
  2018-07-30 16:45 ` [PATCH 15/15] xfs: fold dfops into the transaction Brian Foster
  2018-07-30 20:51   ` Darrick J. Wong
@ 2018-07-31  8:36   ` Christoph Hellwig
  2018-07-31 11:49     ` Brian Foster
  1 sibling, 1 reply; 56+ messages in thread
From: Christoph Hellwig @ 2018-07-31  8:36 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

> -	trace_xfs_defer_trans_abort(tp->t_mountp, dop, _RET_IP_);
> +	trace_xfs_defer_trans_abort(tp->t_mountp, tp, _RET_IP_);

Can't we stop passing the explicit xfs_mount to these tracepoints now?

Otherwise looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 01/15] xfs: refactor internal dfops initialization
  2018-07-30 19:30   ` Darrick J. Wong
  2018-07-31  8:10     ` Christoph Hellwig
@ 2018-07-31 11:47     ` Brian Foster
  2018-07-31 14:08       ` Darrick J. Wong
  1 sibling, 1 reply; 56+ messages in thread
From: Brian Foster @ 2018-07-31 11:47 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 12:30:48PM -0700, Darrick J. Wong wrote:
> On Mon, Jul 30, 2018 at 12:45:06PM -0400, Brian Foster wrote:
> > The current transaction allocation code conditionally initializes
> > the ->t_dfops indirection pointer. Transaction commit/cancel check
> > the validity of the pointer to determine whether to finish/cancel
> > the internal dfops.
> > 
> > This disallows the ability to use the internal dfops list as a
> > temporary container (via xfs_trans_alloc_empty()). Refactor
> > transaction allocation to always initialize ->t_dfops and check
> > permanent reservation state on transaction commit/cancel.
> > 
> > Signed-off-by: Brian Foster <bfoster@redhat.com>
> > ---
> >  fs/xfs/xfs_trans.c | 12 +++---------
> >  1 file changed, 3 insertions(+), 9 deletions(-)
> > 
> > diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> > index 7bf5c1202719..8d3b7f28b193 100644
> > --- a/fs/xfs/xfs_trans.c
> > +++ b/fs/xfs/xfs_trans.c
> > @@ -281,13 +281,7 @@ xfs_trans_alloc(
> >  	INIT_LIST_HEAD(&tp->t_items);
> >  	INIT_LIST_HEAD(&tp->t_busy);
> >  	tp->t_firstblock = NULLFSBLOCK;
> > -	/*
> > -	 * We only roll transactions with permanent log reservation. Don't init
> > -	 * ->t_dfops to skip attempts to finish or cancel an empty dfops with a
> > -	 * non-permanent res.
> > -	 */
> > -	if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES)
> > -		xfs_defer_init(tp, &tp->t_dfops_internal);
> > +	xfs_defer_init(tp, &tp->t_dfops_internal);
> >  
> >  	error = xfs_trans_reserve(tp, resp, blocks, rtextents);
> >  	if (error) {
> > @@ -932,7 +926,7 @@ __xfs_trans_commit(
> >  	trace_xfs_trans_commit(tp, _RET_IP_);
> >  
> >  	/* finish deferred items on final commit */
> > -	if (!regrant && tp->t_dfops) {
> > +	if (!regrant && (tp->t_flags & XFS_TRANS_PERM_LOG_RES)) {
> 
> The usage model of deferred ops is that one has to create a transaction
> with a permanent reservation, and only then start attaching deferred ops
> to the dfops inside the transaction.  It's a programming error if a
> caller tries to finish deferred ops using a non-permanent transaction,
> and prior to this patch t_dfops would be NULL and we'd blow up
> immediately in xfs_defer_add(..., tp->t_dfops, ...);
> 
> However, now that we initialize t_dfops unconditionally, won't this
> cause the above programming mistake to leak silently any incorrectly
> queued defer ops?
> 

Yeah, I'm not sure the previous behavior was really appropriate in that
regard either. I'll add the xfs_defer_add() assert suggested by
Christoph. We could also add a WARN_ON_ONCE() or something in the commit
path to make sure we never see a !perm transaction with dfops, if you
think that's useful..?

Brian

> --D
> 
> >  		error = xfs_defer_finish_noroll(&tp);
> >  		if (error) {
> >  			xfs_defer_cancel(tp);
> > @@ -1029,7 +1023,7 @@ xfs_trans_cancel(
> >  
> >  	trace_xfs_trans_cancel(tp, _RET_IP_);
> >  
> > -	if (tp->t_dfops)
> > +	if (tp->t_flags & XFS_TRANS_PERM_LOG_RES)
> >  		xfs_defer_cancel(tp);
> >  
> >  	/*
> > -- 
> > 2.17.1
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 02/15] xfs: use transaction for intent recovery instead of raw dfops
  2018-07-30 20:09   ` Darrick J. Wong
  2018-07-31  8:12     ` Christoph Hellwig
@ 2018-07-31 11:47     ` Brian Foster
  2018-07-31 14:18       ` Darrick J. Wong
  1 sibling, 1 reply; 56+ messages in thread
From: Brian Foster @ 2018-07-31 11:47 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 01:09:09PM -0700, Darrick J. Wong wrote:
> On Mon, Jul 30, 2018 at 12:45:07PM -0400, Brian Foster wrote:
> > Log intent recovery is the last user of an external (on-stack)
> > dfops. The pattern exists because the dfops is used to collect
> > additional deferred operations queued during the whole recovery
> > sequence. The dfops is finished with a new transaction after intent
> > recovery completes.
> > 
> > We already have a mechanism to create an empty, container-like
> > transaction to support the scrub infrastructure. We can reuse that
> > mechanism here to drop the final user of external dfops. This
> > facilitates folding dfops state (i.e., dop_low) into the
> > transaction, the elimination of now unused external dfops support
> > and also eliminates the only caller of __xfs_defer_cancel().
> > 
> > Replace the on-stack dfops with an empty transaction and pass it
> > around to the various helpers that queue and finish deferred
> > operations during intent recovery.
> > 
> > Signed-off-by: Brian Foster <bfoster@redhat.com>
> > ---
> >  fs/xfs/xfs_bmap_item.c     | 12 +++++------
> >  fs/xfs/xfs_bmap_item.h     |  3 +--
> >  fs/xfs/xfs_log_recover.c   | 42 ++++++++++++++++++--------------------
> >  fs/xfs/xfs_refcount_item.c | 12 +++++------
> >  fs/xfs/xfs_refcount_item.h |  3 +--
> >  5 files changed, 34 insertions(+), 38 deletions(-)
> > 
> > diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
> > index e1d6c127b07d..992235e7c761 100644
> > --- a/fs/xfs/xfs_bmap_item.c
> > +++ b/fs/xfs/xfs_bmap_item.c
> > @@ -375,9 +375,8 @@ xfs_bud_init(
> >   */
> >  int
> >  xfs_bui_recover(
> > -	struct xfs_mount		*mp,
> > -	struct xfs_bui_log_item		*buip,
> > -	struct xfs_defer_ops		*dfops)
> > +	struct xfs_trans		*itp,
> 
> "itp"?
> 
> Oh, the intent-holder transaction...
> 

Yeah..

> > +	struct xfs_bui_log_item		*buip)
> >  {
> >  	int				error = 0;
> >  	unsigned int			bui_type;
...
> > diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
> > index 7776fde9430c..6650b790e43b 100644
> > --- a/fs/xfs/xfs_log_recover.c
> > +++ b/fs/xfs/xfs_log_recover.c
...
> > @@ -4880,22 +4878,25 @@ STATIC int
> >  xlog_recover_process_intents(
> >  	struct xlog		*log)
> >  {
> > -	struct xfs_defer_ops	dfops;
> > +	struct xfs_trans	*tp;
> >  	struct xfs_ail_cursor	cur;
> >  	struct xfs_log_item	*lip;
> >  	struct xfs_ail		*ailp;
> > -	int			error = 0;
> > +	int			error;
> >  #if defined(DEBUG) || defined(XFS_WARN)
> >  	xfs_lsn_t		last_lsn;
> >  #endif
> >  
> > +	error = xfs_trans_alloc_empty(log->l_mp, &tp);
> 
> Here's where we allocate the intent-placeholder transaction, so why
> isn't this named "itp" as well?
> 

I only used itp where tp conflicted with a local transaction (the
contexts where we have to transfer state back and forth between two
transactions).

> I think I have a handle on what this patch does, though the variable
> naming itp/tp is a little confusing.
> 

I have no real preference on the naming. I can call it parent_tp as
Christoph suggests and use that up and down the chain rather than only
in the contexts where both transactions exist if you think that is more
clear..?

Brian

> --D
> 
> > +	if (error)
> > +		return error;
> > +
> >  	ailp = log->l_ailp;
> >  	spin_lock(&ailp->ail_lock);
> >  	lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
> >  #if defined(DEBUG) || defined(XFS_WARN)
> >  	last_lsn = xlog_assign_lsn(log->l_curr_cycle, log->l_curr_block);
> >  #endif
> > -	xfs_defer_init(NULL, &dfops);
> >  	while (lip != NULL) {
> >  		/*
> >  		 * We're done when we see something other than an intent.
> > @@ -4930,12 +4931,10 @@ xlog_recover_process_intents(
> >  			error = xlog_recover_process_rui(log->l_mp, ailp, lip);
> >  			break;
> >  		case XFS_LI_CUI:
> > -			error = xlog_recover_process_cui(log->l_mp, ailp, lip,
> > -					&dfops);
> > +			error = xlog_recover_process_cui(tp, ailp, lip);
> >  			break;
> >  		case XFS_LI_BUI:
> > -			error = xlog_recover_process_bui(log->l_mp, ailp, lip,
> > -					&dfops);
> > +			error = xlog_recover_process_bui(tp, ailp, lip);
> >  			break;
> >  		}
> >  		if (error)
> > @@ -4945,10 +4944,9 @@ xlog_recover_process_intents(
> >  out:
> >  	xfs_trans_ail_cursor_done(&cur);
> >  	spin_unlock(&ailp->ail_lock);
> > -	if (error)
> > -		__xfs_defer_cancel(&dfops);
> > -	else
> > -		error = xlog_finish_defer_ops(log->l_mp, &dfops);
> > +	if (!error)
> > +		error = xlog_finish_defer_ops(tp);
> > +	xfs_trans_cancel(tp);
> >  
> >  	return error;
> >  }
> > diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
> > index d3582a06626f..d663ea1f4076 100644
> > --- a/fs/xfs/xfs_refcount_item.c
> > +++ b/fs/xfs/xfs_refcount_item.c
> > @@ -380,9 +380,8 @@ xfs_cud_init(
> >   */
> >  int
> >  xfs_cui_recover(
> > -	struct xfs_mount		*mp,
> > -	struct xfs_cui_log_item		*cuip,
> > -	struct xfs_defer_ops		*dfops)
> > +	struct xfs_trans		*itp,
> > +	struct xfs_cui_log_item		*cuip)
> >  {
> >  	int				i;
> >  	int				error = 0;
> > @@ -398,6 +397,7 @@ xfs_cui_recover(
> >  	xfs_extlen_t			new_len;
> >  	struct xfs_bmbt_irec		irec;
> >  	bool				requeue_only = false;
> > +	struct xfs_mount		*mp = itp->t_mountp;
> >  
> >  	ASSERT(!test_bit(XFS_CUI_RECOVERED, &cuip->cui_flags));
> >  
> > @@ -457,7 +457,7 @@ xfs_cui_recover(
> >  	 * finishes them on completion. Transfer current dfops state to this
> >  	 * transaction and transfer the result back before we return.
> >  	 */
> > -	xfs_defer_move(tp->t_dfops, dfops);
> > +	xfs_defer_move(tp->t_dfops, itp->t_dfops);
> >  	cudp = xfs_trans_get_cud(tp, cuip);
> >  
> >  	for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
> > @@ -522,13 +522,13 @@ xfs_cui_recover(
> >  
> >  	xfs_refcount_finish_one_cleanup(tp, rcur, error);
> >  	set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags);
> > -	xfs_defer_move(dfops, tp->t_dfops);
> > +	xfs_defer_move(itp->t_dfops, tp->t_dfops);
> >  	error = xfs_trans_commit(tp);
> >  	return error;
> >  
> >  abort_error:
> >  	xfs_refcount_finish_one_cleanup(tp, rcur, error);
> > -	xfs_defer_move(dfops, tp->t_dfops);
> > +	xfs_defer_move(itp->t_dfops, tp->t_dfops);
> >  	xfs_trans_cancel(tp);
> >  	return error;
> >  }
> > diff --git a/fs/xfs/xfs_refcount_item.h b/fs/xfs/xfs_refcount_item.h
> > index dd830b69cd1e..98895da52c1f 100644
> > --- a/fs/xfs/xfs_refcount_item.h
> > +++ b/fs/xfs/xfs_refcount_item.h
> > @@ -82,7 +82,6 @@ struct xfs_cud_log_item *xfs_cud_init(struct xfs_mount *,
> >  		struct xfs_cui_log_item *);
> >  void xfs_cui_item_free(struct xfs_cui_log_item *);
> >  void xfs_cui_release(struct xfs_cui_log_item *);
> > -int xfs_cui_recover(struct xfs_mount *mp, struct xfs_cui_log_item *cuip,
> > -		struct xfs_defer_ops *dfops);
> > +int xfs_cui_recover(struct xfs_trans *itp, struct xfs_cui_log_item *cuip);
> >  
> >  #endif	/* __XFS_REFCOUNT_ITEM_H__ */
> > -- 
> > 2.17.1
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 05/15] xfs: replace dop_low with transaction flag
  2018-07-31  8:16   ` Christoph Hellwig
@ 2018-07-31 11:47     ` Brian Foster
  0 siblings, 0 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-31 11:47 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Tue, Jul 31, 2018 at 01:16:59AM -0700, Christoph Hellwig wrote:
> > +	/*
> > +	 * Low free space mode was historically controlled by a dfops field.
> > +	 * This meant that low mode state potentially carried across multiple
> > +	 * transaction rolls. Transfer low mode on a dfops move to preserve
> > +	 * that behavior.
> > +	 */
> > +	dtp->t_flags |= stp->t_flags & XFS_TRANS_LOWMODE;
> 
> Maybe add parentheses here for clarity.
> 

Added, thanks.

Brian

> Except for that:
> 
> Reviewed-by: Christoph Hellwig <hch@lst.de>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 07/15] xfs: automatic dfops buffer relogging
  2018-07-30 20:20   ` Darrick J. Wong
@ 2018-07-31 11:48     ` Brian Foster
  0 siblings, 0 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-31 11:48 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 01:20:37PM -0700, Darrick J. Wong wrote:
> On Mon, Jul 30, 2018 at 12:45:12PM -0400, Brian Foster wrote:
> > Buffers that are held across deferred operations are explicitly
> > joined to the dfops structure to ensure appropriate relogging.
> > While buffers are currently joined explicitly, we can detect the
> > conditions that require relogging at dfops finish time by inspecting
> > the transaction item list for held buffers.
> > 
> > Replace the xfs_defer_bjoin() infrastructure with such detection and
> > automatic relogging of held buffers. This eliminates the need for
> > the per-dfops buffer list, replaced by an on-stack variant in
> > xfs_defer_trans_roll().
> > 
> > Signed-off-by: Brian Foster <bfoster@redhat.com>
> > ---
> >  fs/xfs/libxfs/xfs_attr.c  |  1 -
> >  fs/xfs/libxfs/xfs_defer.c | 55 ++++++++++++++++-----------------------
> >  fs/xfs/libxfs/xfs_defer.h |  1 -
> >  fs/xfs/xfs_dquot.c        |  1 -
> >  fs/xfs/xfs_trans.h        |  1 -
> >  5 files changed, 23 insertions(+), 36 deletions(-)
> > 
...
> > diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> > index 0306187b5f56..d0ee55048a7a 100644
> > --- a/fs/xfs/libxfs/xfs_defer.c
> > +++ b/fs/xfs/libxfs/xfs_defer.c
...
> > @@ -235,9 +240,21 @@ xfs_defer_trans_roll(
> >  	for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++)
> >  		xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE);
> >  
> > -	/* Hold the (previously bjoin'd) buffer locked across the roll. */
> > -	for (i = 0; i < XFS_DEFER_OPS_NR_BUFS && dop->dop_bufs[i]; i++)
> > -		xfs_trans_dirty_buf(*tp, dop->dop_bufs[i]);
> > +	list_for_each_entry(lip, &(*tp)->t_items, li_trans) {
> > +		switch (lip->li_type) {
> > +		case XFS_LI_BUF:
> > +			bli = container_of(lip, struct xfs_buf_log_item,
> > +					   bli_item);
> > +			if (bli->bli_flags & XFS_BLI_HOLD) {
> > +				ASSERT(bpcount < XFS_DEFER_OPS_NR_BUFS);
> 
> This is a bit of a behavior change -- previously if we oveflowed the
> array we'd bail out with -EFSCORRUPTED rather than go corrupting
> whatever came after dop_bufs.  Granted, we were pretty terrible about
> checking the return values, but I think this ought to be:
> 
> if (bpcount >= XFS_DEFER_OPS_NR_BUFS) {
> 	ASSERT(0);
> 	return -EFSCORRUPTED;
> }
> 
> rather than corrupting the on-stack array if we happen to bhold too many
> buffers to the transaction.
> 

Yup, good point. I'll fix up the error checking in both of these
patches.

Brian

> --D
> 
> > +				xfs_trans_dirty_buf(*tp, bli->bli_buf);
> > +				bplist[bpcount++] = bli->bli_buf;
> > +			}
> > +			break;
> > +		default:
> > +			break;
> > +		}
> > +	}
> >  
> >  	trace_xfs_defer_trans_roll((*tp)->t_mountp, dop, _RET_IP_);
> >  
> > @@ -255,9 +272,9 @@ xfs_defer_trans_roll(
> >  		xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0);
> >  
> >  	/* Rejoin the buffers and dirty them so the log moves forward. */
> > -	for (i = 0; i < XFS_DEFER_OPS_NR_BUFS && dop->dop_bufs[i]; i++) {
> > -		xfs_trans_bjoin(*tp, dop->dop_bufs[i]);
> > -		xfs_trans_bhold(*tp, dop->dop_bufs[i]);
> > +	for (i = 0; i < bpcount; i++) {
> > +		xfs_trans_bjoin(*tp, bplist[i]);
> > +		xfs_trans_bhold(*tp, bplist[i]);
> >  	}
> >  
> >  	return error;
> > @@ -295,30 +312,6 @@ xfs_defer_ijoin(
> >  	return -EFSCORRUPTED;
> >  }
> >  
> > -/*
> > - * Add this buffer to the deferred op.  Each joined buffer is relogged
> > - * each time we roll the transaction.
> > - */
> > -int
> > -xfs_defer_bjoin(
> > -	struct xfs_defer_ops		*dop,
> > -	struct xfs_buf			*bp)
> > -{
> > -	int				i;
> > -
> > -	for (i = 0; i < XFS_DEFER_OPS_NR_BUFS; i++) {
> > -		if (dop->dop_bufs[i] == bp)
> > -			return 0;
> > -		else if (dop->dop_bufs[i] == NULL) {
> > -			dop->dop_bufs[i] = bp;
> > -			return 0;
> > -		}
> > -	}
> > -
> > -	ASSERT(0);
> > -	return -EFSCORRUPTED;
> > -}
> > -
> >  /*
> >   * Reset an already used dfops after finish.
> >   */
> > @@ -331,7 +324,6 @@ xfs_defer_reset(
> >  	ASSERT(!xfs_defer_has_unfinished_work(dop));
> >  
> >  	memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes));
> > -	memset(dop->dop_bufs, 0, sizeof(dop->dop_bufs));
> >  
> >  	/*
> >  	 * Low mode state transfers across transaction rolls to mirror dfops
> > @@ -594,7 +586,6 @@ xfs_defer_move(
> >  	list_splice_init(&src->dop_pending, &dst->dop_pending);
> >  
> >  	memcpy(dst->dop_inodes, src->dop_inodes, sizeof(dst->dop_inodes));
> > -	memcpy(dst->dop_bufs, src->dop_bufs, sizeof(dst->dop_bufs));
> >  
> >  	/*
> >  	 * Low free space mode was historically controlled by a dfops field.
> > diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
> > index 8908a2716774..4a8bb838adf2 100644
> > --- a/fs/xfs/libxfs/xfs_defer.h
> > +++ b/fs/xfs/libxfs/xfs_defer.h
> > @@ -43,7 +43,6 @@ void xfs_defer_cancel(struct xfs_trans *);
> >  void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
> >  bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);
> >  int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip);
> > -int xfs_defer_bjoin(struct xfs_defer_ops *dop, struct xfs_buf *bp);
> >  void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
> >  
> >  /* Description of a deferred type. */
> > diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
> > index da5c55cec966..e1196854dbcd 100644
> > --- a/fs/xfs/xfs_dquot.c
> > +++ b/fs/xfs/xfs_dquot.c
> > @@ -362,7 +362,6 @@ xfs_dquot_disk_alloc(
> >  	 * manually or by committing the transaction.
> >  	 */
> >  	xfs_trans_bhold(tp, bp);
> > -	error = xfs_defer_bjoin(tp->t_dfops, bp);
> >  	if (error) {
> >  		xfs_trans_bhold_release(tp, bp);
> >  		xfs_trans_brelse(tp, bp);
> > diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> > index 7e493221160e..581456c79197 100644
> > --- a/fs/xfs/xfs_trans.h
> > +++ b/fs/xfs/xfs_trans.h
> > @@ -100,7 +100,6 @@ struct xfs_defer_ops {
> >  
> >  	/* relog these with each roll */
> >  	struct xfs_inode	*dop_inodes[XFS_DEFER_OPS_NR_INODES];
> > -	struct xfs_buf		*dop_bufs[XFS_DEFER_OPS_NR_BUFS];
> >  };
> >  
> >  /*
> > -- 
> > 2.17.1
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 15/15] xfs: fold dfops into the transaction
  2018-07-31  8:36   ` Christoph Hellwig
@ 2018-07-31 11:49     ` Brian Foster
  0 siblings, 0 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-31 11:49 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Tue, Jul 31, 2018 at 01:36:03AM -0700, Christoph Hellwig wrote:
> > -	trace_xfs_defer_trans_abort(tp->t_mountp, dop, _RET_IP_);
> > +	trace_xfs_defer_trans_abort(tp->t_mountp, tp, _RET_IP_);
> 
> Can't we stop passing the explicit xfs_mount to these tracepoints now?
> 

I thought I tried that and ran into xfs_trans definition issues. Looking
again, I see that we're using ->t_mountp in other tracepoints so perhaps
something else was going on. I don't recall exactly so I'll make another
pass and try to clean these up wherever we have a transaction.

Brian

> Otherwise looks good:
> 
> Reviewed-by: Christoph Hellwig <hch@lst.de>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 12/15] xfs: replace xfs_defer_ops ->dop_pending with on-stack list
  2018-07-30 20:47   ` Darrick J. Wong
@ 2018-07-31 11:50     ` Brian Foster
  0 siblings, 0 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-31 11:50 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs

On Mon, Jul 30, 2018 at 01:47:02PM -0700, Darrick J. Wong wrote:
> On Mon, Jul 30, 2018 at 12:45:17PM -0400, Brian Foster wrote:
> > The xfs_defer_ops ->dop_pending list is used to track active
> > deferred operations once intents are logged. These items must be
> > aborted in the event of an error. The list is populated as intents
> > are logged and items are removed as they complete (or are aborted).
> > 
> > Now that xfs_defer_finish() cancels on error, there is no need to
> > ever access ->dop_pending outside of xfs_defer_finish(). The list is
> > only ever populated after xfs_defer_finish() begins and is either
> > completed or cancelled before it returns.
> > 
> > Remove ->dop_pending from xfs_defer_ops and replace it with a local
> > list in the xfs_defer_finish() path. Pass the local list to the
> > various helpers now that it is not accessible via dfops. Note that
> > we have to check for NULL in the abort case as the final tx roll
> > occurs outside of the scope of the new local list (once the dfops
> > has completed and thus drained the list).
> > 
> > Signed-off-by: Brian Foster <bfoster@redhat.com>
> > ---
> >  fs/xfs/libxfs/xfs_defer.c | 80 ++++++++++++++++++++-------------------
> >  fs/xfs/libxfs/xfs_defer.h |  3 +-
> >  fs/xfs/xfs_trace.h        |  1 -
> >  fs/xfs/xfs_trans.h        |  1 -
> >  4 files changed, 43 insertions(+), 42 deletions(-)
> > 
> > diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> > index 66848ede62c0..6bf792e2d61b 100644
> > --- a/fs/xfs/libxfs/xfs_defer.c
> > +++ b/fs/xfs/libxfs/xfs_defer.c
...
> > @@ -212,11 +216,13 @@ xfs_defer_trans_abort(
> >  	trace_xfs_defer_trans_abort(tp->t_mountp, dop, _RET_IP_);
> >  
> >  	/* Abort intent items that don't have a done item. */
> > -	list_for_each_entry(dfp, &dop->dop_pending, dfp_list) {
> > -		trace_xfs_defer_pending_abort(tp->t_mountp, dfp);
> > -		if (dfp->dfp_intent && !dfp->dfp_done) {
> > -			dfp->dfp_type->abort_intent(dfp->dfp_intent);
> > -			dfp->dfp_intent = NULL;
> > +	if (dop_pending) {
> 
> /me kinda wonders if you could just make xfs_defer_finish pass an empty
> list_head into xfs_defer_trans_roll to avoid this extra indent, but I
> don't care all that much and maybe we should save the stack space. :)
> 

I started with something like that when hacking this up and eventually
replaced it because the indent didn't actually create any long lines.

> > +		list_for_each_entry(dfp, dop_pending, dfp_list) {
> > +			trace_xfs_defer_pending_abort(tp->t_mountp, dfp);
> > +			if (dfp->dfp_intent && !dfp->dfp_done) {
> > +				dfp->dfp_type->abort_intent(dfp->dfp_intent);
> > +				dfp->dfp_intent = NULL;
> > +			}
> >  		}
> >  	}
> >  
...
> > @@ -446,34 +456,20 @@ xfs_defer_finish(
> >  /*
> >   * Free up any items left in the list.
> >   */
> > -void
> > -xfs_defer_cancel(
> > -	struct xfs_trans		*tp)
> > +static void
> > +__xfs_defer_cancel(
> 
> Maybe this should be xfs_defer_cancel_list?
> 

Sure.

> > +	struct list_head		*dop_list)
> >  {
> > -	struct xfs_defer_ops		*dop = tp->t_dfops;
> >  	struct xfs_defer_pending	*dfp;
> >  	struct xfs_defer_pending	*pli;
> >  	struct list_head		*pwi;
> >  	struct list_head		*n;
> >  
> > -	trace_xfs_defer_cancel(NULL, dop, _RET_IP_);
> > -
> >  	/*
> >  	 * Free the pending items.  Caller should already have arranged
> >  	 * for the intent items to be released.
> >  	 */
> > -	list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) {
> > -		trace_xfs_defer_intake_cancel(NULL, dfp);
> > -		list_del(&dfp->dfp_list);
> > -		list_for_each_safe(pwi, n, &dfp->dfp_work) {
> > -			list_del(pwi);
> > -			dfp->dfp_count--;
> > -			dfp->dfp_type->cancel_item(pwi);
> > -		}
> > -		ASSERT(dfp->dfp_count == 0);
> > -		kmem_free(dfp);
> > -	}
> > -	list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) {
> > +	list_for_each_entry_safe(dfp, pli, dop_list, dfp_list) {
> >  		trace_xfs_defer_pending_cancel(NULL, dfp);
> 
> trace_xfs_defer_cancel_list?
> 
> Maybe it's worth passing a *mp into this function so we can pass it to
> the tracepoint?
> 

Ok.

> >  		list_del(&dfp->dfp_list);
> >  		list_for_each_safe(pwi, n, &dfp->dfp_work) {
> > @@ -486,6 +482,14 @@ xfs_defer_cancel(
> >  	}
> >  }
> >  
> > +void
> > +xfs_defer_cancel(
> > +	struct xfs_trans	*tp)
> > +{
> > +	trace_xfs_defer_cancel(NULL, tp->t_dfops, _RET_IP_);
> 
> That NULL can be tp->t_mountp, right?  Since tp should never be NULL?
> 

Yeah, this will hopefully be replaced with the transaction reference so
that makes sense.

> > +	__xfs_defer_cancel(&tp->t_dfops->dop_intake);
> > +}
> > +
> >  /* Add an item for later deferred processing. */
> >  void
> >  xfs_defer_add(
...
> > diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
> > index f051c8056141..363af16328cb 100644
> > --- a/fs/xfs/libxfs/xfs_defer.h
> > +++ b/fs/xfs/libxfs/xfs_defer.h
> > @@ -41,7 +41,8 @@ int xfs_defer_finish_noroll(struct xfs_trans **tp);
> >  int xfs_defer_finish(struct xfs_trans **tp);
> >  void xfs_defer_cancel(struct xfs_trans *);
> >  void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop);
> > -bool xfs_defer_has_unfinished_work(struct xfs_trans *tp);
> > +bool xfs_defer_has_unfinished_work(struct xfs_trans *tp,
> > +		struct list_head *dop_pending);
> 
> Eww, I dislike exposing this implementation detail in a public
> interface.  Assuming you take my suggestion in patch 1 to ASSERT if
> xfs_trans_{cancel,commit} encounter unfinished deferred work and a
> transaction we can't roll, there will be only three callers of this
> function, and only one of them knows about the pending item list.
> Perhaps the list_empty(dop_pending) check can be open-coded in
> xfs_defer_finish_noroll?
> 

Christoph points out there's only one caller left so I'll probably just
kill this off entirely.

Brian

> --D
> 
> >  void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
> >  
> >  /* Description of a deferred type. */
> > diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
> > index 8807f1bb814a..6b55bbc09578 100644
> > --- a/fs/xfs/xfs_trace.h
> > +++ b/fs/xfs/xfs_trace.h
> > @@ -2393,7 +2393,6 @@ DEFINE_DEFER_ERROR_EVENT(xfs_defer_trans_roll_error);
> >  DEFINE_DEFER_ERROR_EVENT(xfs_defer_finish_error);
> >  
> >  DEFINE_DEFER_PENDING_EVENT(xfs_defer_intake_work);
> > -DEFINE_DEFER_PENDING_EVENT(xfs_defer_intake_cancel);
> >  DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_cancel);
> >  DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_finish);
> >  DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_abort);
> > diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> > index 299656dbf324..1cdc7c0ebeac 100644
> > --- a/fs/xfs/xfs_trans.h
> > +++ b/fs/xfs/xfs_trans.h
> > @@ -96,7 +96,6 @@ void	xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item,
> >  #define XFS_DEFER_OPS_NR_BUFS	2	/* join up to two buffers */
> >  struct xfs_defer_ops {
> >  	struct list_head	dop_intake;	/* unlogged pending work */
> > -	struct list_head	dop_pending;	/* logged pending work */
> >  };
> >  
> >  /*
> > -- 
> > 2.17.1
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 12/15] xfs: replace xfs_defer_ops ->dop_pending with on-stack list
  2018-07-31  8:30   ` Christoph Hellwig
@ 2018-07-31 11:50     ` Brian Foster
  0 siblings, 0 replies; 56+ messages in thread
From: Brian Foster @ 2018-07-31 11:50 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs

On Tue, Jul 31, 2018 at 01:30:02AM -0700, Christoph Hellwig wrote:
> On Mon, Jul 30, 2018 at 12:45:17PM -0400, Brian Foster wrote:
> > The xfs_defer_ops ->dop_pending list is used to track active
> > deferred operations once intents are logged. These items must be
> > aborted in the event of an error. The list is populated as intents
> > are logged and items are removed as they complete (or are aborted).
> > 
> > Now that xfs_defer_finish() cancels on error, there is no need to
> > ever access ->dop_pending outside of xfs_defer_finish(). The list is
> > only ever populated after xfs_defer_finish() begins and is either
> > completed or cancelled before it returns.
> > 
> > Remove ->dop_pending from xfs_defer_ops and replace it with a local
> > list in the xfs_defer_finish() path. Pass the local list to the
> > various helpers now that it is not accessible via dfops. Note that
> > we have to check for NULL in the abort case as the final tx roll
> > occurs outside of the scope of the new local list (once the dfops
> > has completed and thus drained the list).
> > 
> > Signed-off-by: Brian Foster <bfoster@redhat.com>
> > ---
> >  fs/xfs/libxfs/xfs_defer.c | 80 ++++++++++++++++++++-------------------
> >  fs/xfs/libxfs/xfs_defer.h |  3 +-
> >  fs/xfs/xfs_trace.h        |  1 -
> >  fs/xfs/xfs_trans.h        |  1 -
> >  4 files changed, 43 insertions(+), 42 deletions(-)
> > 
> > diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
> > index 66848ede62c0..6bf792e2d61b 100644
> > --- a/fs/xfs/libxfs/xfs_defer.c
> > +++ b/fs/xfs/libxfs/xfs_defer.c
> > @@ -174,6 +174,8 @@
> >  
> >  static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX];
> >  
> > +static void __xfs_defer_cancel(struct list_head *);
> 
> Can you just move __xfs_defer_cancel up to here to avoid the
> forward declaration?
> 

I think so, I'll give it a try.

> > +
> >  /*
> >   * For each pending item in the intake list, log its intent item and the
> >   * associated extents, then add the entire intake list to the end of
> > @@ -181,7 +183,8 @@ static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX];
> >   */
> >  STATIC void
> >  xfs_defer_intake_work(
> > -	struct xfs_trans		*tp)
> > +	struct xfs_trans		*tp,
> > +	struct list_head		*dop_pending)
> >  {
> >  	struct xfs_defer_ops		*dop = tp->t_dfops;
> >  	struct list_head		*li;
> > @@ -197,13 +200,14 @@ xfs_defer_intake_work(
> >  			dfp->dfp_type->log_item(tp, dfp->dfp_intent, li);
> >  	}
> >  
> > -	list_splice_tail_init(&dop->dop_intake, &dop->dop_pending);
> > +	list_splice_tail_init(&dop->dop_intake, dop_pending);
> 
> It almost seems simpler to just move the list_splice_tail_init to the
> (only) caller.
> 

Hm, yeah. I guess that changes the semantics of the function a bit. I
could rename it (and the tracepoint) to something like
xfs_defer_create_intents(), drop the dop_pending param and lift the
splice into the caller if nobody objects..?

> > @@ -292,9 +299,10 @@ xfs_defer_trans_roll(
> >  /* Do we have any work items to finish? */
> >  bool
> >  xfs_defer_has_unfinished_work(
> > -	struct xfs_trans		*tp)
> > +	struct xfs_trans		*tp,
> > +	struct list_head		*dop_pending)
> >  {
> > -	return !list_empty(&tp->t_dfops->dop_pending) ||
> > +	return !list_empty(dop_pending) ||
> >  		!list_empty(&tp->t_dfops->dop_intake);
> >  }
> 
> I'd just opencode this in the only caller that is left.

Yep, thanks.

Brian

> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 01/15] xfs: refactor internal dfops initialization
  2018-07-31 11:47     ` Brian Foster
@ 2018-07-31 14:08       ` Darrick J. Wong
  0 siblings, 0 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-31 14:08 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Tue, Jul 31, 2018 at 07:47:36AM -0400, Brian Foster wrote:
> On Mon, Jul 30, 2018 at 12:30:48PM -0700, Darrick J. Wong wrote:
> > On Mon, Jul 30, 2018 at 12:45:06PM -0400, Brian Foster wrote:
> > > The current transaction allocation code conditionally initializes
> > > the ->t_dfops indirection pointer. Transaction commit/cancel check
> > > the validity of the pointer to determine whether to finish/cancel
> > > the internal dfops.
> > > 
> > > This disallows the ability to use the internal dfops list as a
> > > temporary container (via xfs_trans_alloc_empty()). Refactor
> > > transaction allocation to always initialize ->t_dfops and check
> > > permanent reservation state on transaction commit/cancel.
> > > 
> > > Signed-off-by: Brian Foster <bfoster@redhat.com>
> > > ---
> > >  fs/xfs/xfs_trans.c | 12 +++---------
> > >  1 file changed, 3 insertions(+), 9 deletions(-)
> > > 
> > > diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> > > index 7bf5c1202719..8d3b7f28b193 100644
> > > --- a/fs/xfs/xfs_trans.c
> > > +++ b/fs/xfs/xfs_trans.c
> > > @@ -281,13 +281,7 @@ xfs_trans_alloc(
> > >  	INIT_LIST_HEAD(&tp->t_items);
> > >  	INIT_LIST_HEAD(&tp->t_busy);
> > >  	tp->t_firstblock = NULLFSBLOCK;
> > > -	/*
> > > -	 * We only roll transactions with permanent log reservation. Don't init
> > > -	 * ->t_dfops to skip attempts to finish or cancel an empty dfops with a
> > > -	 * non-permanent res.
> > > -	 */
> > > -	if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES)
> > > -		xfs_defer_init(tp, &tp->t_dfops_internal);
> > > +	xfs_defer_init(tp, &tp->t_dfops_internal);
> > >  
> > >  	error = xfs_trans_reserve(tp, resp, blocks, rtextents);
> > >  	if (error) {
> > > @@ -932,7 +926,7 @@ __xfs_trans_commit(
> > >  	trace_xfs_trans_commit(tp, _RET_IP_);
> > >  
> > >  	/* finish deferred items on final commit */
> > > -	if (!regrant && tp->t_dfops) {
> > > +	if (!regrant && (tp->t_flags & XFS_TRANS_PERM_LOG_RES)) {
> > 
> > The usage model of deferred ops is that one has to create a transaction
> > with a permanent reservation, and only then start attaching deferred ops
> > to the dfops inside the transaction.  It's a programming error if a
> > caller tries to finish deferred ops using a non-permanent transaction,
> > and prior to this patch t_dfops would be NULL and we'd blow up
> > immediately in xfs_defer_add(..., tp->t_dfops, ...);
> > 
> > However, now that we initialize t_dfops unconditionally, won't this
> > cause the above programming mistake to leak silently any incorrectly
> > queued defer ops?
> > 
> 
> Yeah, I'm not sure the previous behavior was really appropriate in that
> regard either. I'll add the xfs_defer_add() assert suggested by
> Christoph. We could also add a WARN_ON_ONCE() or something in the commit
> path to make sure we never see a !perm transaction with dfops, if you
> think that's useful..?

Yes -- some sort of warning that will help us catch programming mistakes
even if !DEBUG. :)

--D

> Brian
> 
> > --D
> > 
> > >  		error = xfs_defer_finish_noroll(&tp);
> > >  		if (error) {
> > >  			xfs_defer_cancel(tp);
> > > @@ -1029,7 +1023,7 @@ xfs_trans_cancel(
> > >  
> > >  	trace_xfs_trans_cancel(tp, _RET_IP_);
> > >  
> > > -	if (tp->t_dfops)
> > > +	if (tp->t_flags & XFS_TRANS_PERM_LOG_RES)
> > >  		xfs_defer_cancel(tp);
> > >  
> > >  	/*
> > > -- 
> > > 2.17.1
> > > 
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 02/15] xfs: use transaction for intent recovery instead of raw dfops
  2018-07-31 11:47     ` Brian Foster
@ 2018-07-31 14:18       ` Darrick J. Wong
  0 siblings, 0 replies; 56+ messages in thread
From: Darrick J. Wong @ 2018-07-31 14:18 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs

On Tue, Jul 31, 2018 at 07:47:51AM -0400, Brian Foster wrote:
> On Mon, Jul 30, 2018 at 01:09:09PM -0700, Darrick J. Wong wrote:
> > On Mon, Jul 30, 2018 at 12:45:07PM -0400, Brian Foster wrote:
> > > Log intent recovery is the last user of an external (on-stack)
> > > dfops. The pattern exists because the dfops is used to collect
> > > additional deferred operations queued during the whole recovery
> > > sequence. The dfops is finished with a new transaction after intent
> > > recovery completes.
> > > 
> > > We already have a mechanism to create an empty, container-like
> > > transaction to support the scrub infrastructure. We can reuse that
> > > mechanism here to drop the final user of external dfops. This
> > > facilitates folding dfops state (i.e., dop_low) into the
> > > transaction, the elimination of now unused external dfops support
> > > and also eliminates the only caller of __xfs_defer_cancel().
> > > 
> > > Replace the on-stack dfops with an empty transaction and pass it
> > > around to the various helpers that queue and finish deferred
> > > operations during intent recovery.
> > > 
> > > Signed-off-by: Brian Foster <bfoster@redhat.com>
> > > ---
> > >  fs/xfs/xfs_bmap_item.c     | 12 +++++------
> > >  fs/xfs/xfs_bmap_item.h     |  3 +--
> > >  fs/xfs/xfs_log_recover.c   | 42 ++++++++++++++++++--------------------
> > >  fs/xfs/xfs_refcount_item.c | 12 +++++------
> > >  fs/xfs/xfs_refcount_item.h |  3 +--
> > >  5 files changed, 34 insertions(+), 38 deletions(-)
> > > 
> > > diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
> > > index e1d6c127b07d..992235e7c761 100644
> > > --- a/fs/xfs/xfs_bmap_item.c
> > > +++ b/fs/xfs/xfs_bmap_item.c
> > > @@ -375,9 +375,8 @@ xfs_bud_init(
> > >   */
> > >  int
> > >  xfs_bui_recover(
> > > -	struct xfs_mount		*mp,
> > > -	struct xfs_bui_log_item		*buip,
> > > -	struct xfs_defer_ops		*dfops)
> > > +	struct xfs_trans		*itp,
> > 
> > "itp"?
> > 
> > Oh, the intent-holder transaction...
> > 
> 
> Yeah..
> 
> > > +	struct xfs_bui_log_item		*buip)
> > >  {
> > >  	int				error = 0;
> > >  	unsigned int			bui_type;
> ...
> > > diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
> > > index 7776fde9430c..6650b790e43b 100644
> > > --- a/fs/xfs/xfs_log_recover.c
> > > +++ b/fs/xfs/xfs_log_recover.c
> ...
> > > @@ -4880,22 +4878,25 @@ STATIC int
> > >  xlog_recover_process_intents(
> > >  	struct xlog		*log)
> > >  {
> > > -	struct xfs_defer_ops	dfops;
> > > +	struct xfs_trans	*tp;
> > >  	struct xfs_ail_cursor	cur;
> > >  	struct xfs_log_item	*lip;
> > >  	struct xfs_ail		*ailp;
> > > -	int			error = 0;
> > > +	int			error;
> > >  #if defined(DEBUG) || defined(XFS_WARN)
> > >  	xfs_lsn_t		last_lsn;
> > >  #endif
> > >  
> > > +	error = xfs_trans_alloc_empty(log->l_mp, &tp);
> > 
> > Here's where we allocate the intent-placeholder transaction, so why
> > isn't this named "itp" as well?
> > 
> 
> I only used itp where tp conflicted with a local transaction (the
> contexts where we have to transfer state back and forth between two
> transactions).
> 
> > I think I have a handle on what this patch does, though the variable
> > naming itp/tp is a little confusing.
> > 
> 
> I have no real preference on the naming. I can call it parent_tp as
> Christoph suggests and use that up and down the chain rather than only
> in the contexts where both transactions exist if you think that is more
> clear..?

Yes, please.  The 'parent_tp' transaction is really just a holder for a
dfops list that will eventually get finished with a non-empty
transaction, so we should make it as clear as possible in the source
code that the parent_tp is not for logging real work. :)

--D

> Brian
> 
> > --D
> > 
> > > +	if (error)
> > > +		return error;
> > > +
> > >  	ailp = log->l_ailp;
> > >  	spin_lock(&ailp->ail_lock);
> > >  	lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
> > >  #if defined(DEBUG) || defined(XFS_WARN)
> > >  	last_lsn = xlog_assign_lsn(log->l_curr_cycle, log->l_curr_block);
> > >  #endif
> > > -	xfs_defer_init(NULL, &dfops);
> > >  	while (lip != NULL) {
> > >  		/*
> > >  		 * We're done when we see something other than an intent.
> > > @@ -4930,12 +4931,10 @@ xlog_recover_process_intents(
> > >  			error = xlog_recover_process_rui(log->l_mp, ailp, lip);
> > >  			break;
> > >  		case XFS_LI_CUI:
> > > -			error = xlog_recover_process_cui(log->l_mp, ailp, lip,
> > > -					&dfops);
> > > +			error = xlog_recover_process_cui(tp, ailp, lip);
> > >  			break;
> > >  		case XFS_LI_BUI:
> > > -			error = xlog_recover_process_bui(log->l_mp, ailp, lip,
> > > -					&dfops);
> > > +			error = xlog_recover_process_bui(tp, ailp, lip);
> > >  			break;
> > >  		}
> > >  		if (error)
> > > @@ -4945,10 +4944,9 @@ xlog_recover_process_intents(
> > >  out:
> > >  	xfs_trans_ail_cursor_done(&cur);
> > >  	spin_unlock(&ailp->ail_lock);
> > > -	if (error)
> > > -		__xfs_defer_cancel(&dfops);
> > > -	else
> > > -		error = xlog_finish_defer_ops(log->l_mp, &dfops);
> > > +	if (!error)
> > > +		error = xlog_finish_defer_ops(tp);
> > > +	xfs_trans_cancel(tp);
> > >  
> > >  	return error;
> > >  }
> > > diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
> > > index d3582a06626f..d663ea1f4076 100644
> > > --- a/fs/xfs/xfs_refcount_item.c
> > > +++ b/fs/xfs/xfs_refcount_item.c
> > > @@ -380,9 +380,8 @@ xfs_cud_init(
> > >   */
> > >  int
> > >  xfs_cui_recover(
> > > -	struct xfs_mount		*mp,
> > > -	struct xfs_cui_log_item		*cuip,
> > > -	struct xfs_defer_ops		*dfops)
> > > +	struct xfs_trans		*itp,
> > > +	struct xfs_cui_log_item		*cuip)
> > >  {
> > >  	int				i;
> > >  	int				error = 0;
> > > @@ -398,6 +397,7 @@ xfs_cui_recover(
> > >  	xfs_extlen_t			new_len;
> > >  	struct xfs_bmbt_irec		irec;
> > >  	bool				requeue_only = false;
> > > +	struct xfs_mount		*mp = itp->t_mountp;
> > >  
> > >  	ASSERT(!test_bit(XFS_CUI_RECOVERED, &cuip->cui_flags));
> > >  
> > > @@ -457,7 +457,7 @@ xfs_cui_recover(
> > >  	 * finishes them on completion. Transfer current dfops state to this
> > >  	 * transaction and transfer the result back before we return.
> > >  	 */
> > > -	xfs_defer_move(tp->t_dfops, dfops);
> > > +	xfs_defer_move(tp->t_dfops, itp->t_dfops);
> > >  	cudp = xfs_trans_get_cud(tp, cuip);
> > >  
> > >  	for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
> > > @@ -522,13 +522,13 @@ xfs_cui_recover(
> > >  
> > >  	xfs_refcount_finish_one_cleanup(tp, rcur, error);
> > >  	set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags);
> > > -	xfs_defer_move(dfops, tp->t_dfops);
> > > +	xfs_defer_move(itp->t_dfops, tp->t_dfops);
> > >  	error = xfs_trans_commit(tp);
> > >  	return error;
> > >  
> > >  abort_error:
> > >  	xfs_refcount_finish_one_cleanup(tp, rcur, error);
> > > -	xfs_defer_move(dfops, tp->t_dfops);
> > > +	xfs_defer_move(itp->t_dfops, tp->t_dfops);
> > >  	xfs_trans_cancel(tp);
> > >  	return error;
> > >  }
> > > diff --git a/fs/xfs/xfs_refcount_item.h b/fs/xfs/xfs_refcount_item.h
> > > index dd830b69cd1e..98895da52c1f 100644
> > > --- a/fs/xfs/xfs_refcount_item.h
> > > +++ b/fs/xfs/xfs_refcount_item.h
> > > @@ -82,7 +82,6 @@ struct xfs_cud_log_item *xfs_cud_init(struct xfs_mount *,
> > >  		struct xfs_cui_log_item *);
> > >  void xfs_cui_item_free(struct xfs_cui_log_item *);
> > >  void xfs_cui_release(struct xfs_cui_log_item *);
> > > -int xfs_cui_recover(struct xfs_mount *mp, struct xfs_cui_log_item *cuip,
> > > -		struct xfs_defer_ops *dfops);
> > > +int xfs_cui_recover(struct xfs_trans *itp, struct xfs_cui_log_item *cuip);
> > >  
> > >  #endif	/* __XFS_REFCOUNT_ITEM_H__ */
> > > -- 
> > > 2.17.1
> > > 
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2018-07-31 15:58 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-30 16:45 [PATCH 00/15] xfs: condense dfops and automatic relogging Brian Foster
2018-07-30 16:45 ` [PATCH 01/15] xfs: refactor internal dfops initialization Brian Foster
2018-07-30 19:30   ` Darrick J. Wong
2018-07-31  8:10     ` Christoph Hellwig
2018-07-31 11:47     ` Brian Foster
2018-07-31 14:08       ` Darrick J. Wong
2018-07-30 16:45 ` [PATCH 02/15] xfs: use transaction for intent recovery instead of raw dfops Brian Foster
2018-07-30 20:09   ` Darrick J. Wong
2018-07-31  8:12     ` Christoph Hellwig
2018-07-31 11:47     ` Brian Foster
2018-07-31 14:18       ` Darrick J. Wong
2018-07-31  8:13   ` Christoph Hellwig
2018-07-30 16:45 ` [PATCH 03/15] xfs: remove unused __xfs_defer_cancel() internal helper Brian Foster
2018-07-30 20:09   ` Darrick J. Wong
2018-07-31  8:13   ` Christoph Hellwig
2018-07-30 16:45 ` [PATCH 04/15] xfs: pass transaction to dfops reset/move helpers Brian Foster
2018-07-30 20:10   ` Darrick J. Wong
2018-07-31  8:14   ` Christoph Hellwig
2018-07-30 16:45 ` [PATCH 05/15] xfs: replace dop_low with transaction flag Brian Foster
2018-07-30 20:11   ` Darrick J. Wong
2018-07-31  8:16   ` Christoph Hellwig
2018-07-31 11:47     ` Brian Foster
2018-07-30 16:45 ` [PATCH 06/15] xfs: add missing defer ijoins for held inodes Brian Foster
2018-07-30 20:15   ` Darrick J. Wong
2018-07-31  8:17   ` Christoph Hellwig
2018-07-30 16:45 ` [PATCH 07/15] xfs: automatic dfops buffer relogging Brian Foster
2018-07-30 20:20   ` Darrick J. Wong
2018-07-31 11:48     ` Brian Foster
2018-07-31  8:19   ` Christoph Hellwig
2018-07-30 16:45 ` [PATCH 08/15] xfs: automatic dfops inode relogging Brian Foster
2018-07-30 20:22   ` Darrick J. Wong
2018-07-31  8:19   ` Christoph Hellwig
2018-07-30 16:45 ` [PATCH 09/15] xfs: drop dop param from xfs_defer_op_type ->finish_item() callback Brian Foster
2018-07-30 20:23   ` Darrick J. Wong
2018-07-31  8:20   ` Christoph Hellwig
2018-07-30 16:45 ` [PATCH 10/15] xfs: clean out superfluous dfops dop params/vars Brian Foster
2018-07-30 20:24   ` Darrick J. Wong
2018-07-31  8:20   ` Christoph Hellwig
2018-07-30 16:45 ` [PATCH 11/15] xfs: cancel dfops on xfs_defer_finish() error Brian Foster
2018-07-30 20:27   ` Darrick J. Wong
2018-07-31  8:21   ` Christoph Hellwig
2018-07-30 16:45 ` [PATCH 12/15] xfs: replace xfs_defer_ops ->dop_pending with on-stack list Brian Foster
2018-07-30 20:47   ` Darrick J. Wong
2018-07-31 11:50     ` Brian Foster
2018-07-31  8:30   ` Christoph Hellwig
2018-07-31 11:50     ` Brian Foster
2018-07-30 16:45 ` [PATCH 13/15] xfs: pass transaction to xfs_defer_add() Brian Foster
2018-07-30 20:49   ` Darrick J. Wong
2018-07-31  8:31   ` Christoph Hellwig
2018-07-30 16:45 ` [PATCH 14/15] xfs: always defer agfl block frees Brian Foster
2018-07-30 20:49   ` Darrick J. Wong
2018-07-31  8:32   ` Christoph Hellwig
2018-07-30 16:45 ` [PATCH 15/15] xfs: fold dfops into the transaction Brian Foster
2018-07-30 20:51   ` Darrick J. Wong
2018-07-31  8:36   ` Christoph Hellwig
2018-07-31 11:49     ` Brian Foster

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.