* cleanup transaction allocation
@ 2025-07-15 12:25 Christoph Hellwig
2025-07-15 12:25 ` [PATCH 1/8] xfs: use xfs_trans_reserve_more in xfs_trans_reserve_more_inode Christoph Hellwig
` (7 more replies)
0 siblings, 8 replies; 22+ messages in thread
From: Christoph Hellwig @ 2025-07-15 12:25 UTC (permalink / raw)
To: Carlos Maiolino; +Cc: linux-xfs
Hi all,
this series cleans up the xfs_trans_alloc* and xfs_trans_reserve*
interfaces by keeping different code paths more separate and thus
removing redundant arguments and error returns.
A git tree is also available here:
git://git.infradead.org/users/hch/xfs.git xfs-trans-cleanups
Gitweb:
https://git.infradead.org/?p=users/hch/xfs.git;a=shortlog;h=refs/heads/xfs-trans-cleanups
Diffstat:
libxfs/xfs_refcount.c | 4 -
scrub/common.c | 7 +
scrub/common.h | 2
scrub/dir_repair.c | 8 --
scrub/fscounters.c | 3
scrub/metapath.c | 4 -
scrub/nlinks.c | 8 --
scrub/nlinks_repair.c | 4 -
scrub/parent_repair.c | 12 ---
scrub/quotacheck.c | 4 -
scrub/repair.c | 16 ----
scrub/repair.h | 4 -
scrub/rmap_repair.c | 9 --
scrub/rtrmap_repair.c | 9 --
scrub/scrub.c | 5 -
xfs_attr_item.c | 5 -
xfs_discard.c | 12 ---
xfs_fsmap.c | 4 -
xfs_icache.c | 5 -
xfs_inode.c | 5 -
xfs_itable.c | 18 ----
xfs_iwalk.c | 11 --
xfs_log.c | 6 -
xfs_log_priv.h | 4 -
xfs_notify_failure.c | 5 -
xfs_qm.c | 10 --
xfs_rtalloc.c | 13 ---
xfs_trans.c | 196 +++++++++++++++++++++++---------------------------
xfs_trans.h | 3
xfs_zone_gc.c | 5 -
30 files changed, 147 insertions(+), 254 deletions(-)
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 1/8] xfs: use xfs_trans_reserve_more in xfs_trans_reserve_more_inode
2025-07-15 12:25 cleanup transaction allocation Christoph Hellwig
@ 2025-07-15 12:25 ` Christoph Hellwig
2025-07-15 14:47 ` Darrick J. Wong
2025-07-15 12:25 ` [PATCH 2/8] xfs: don't use xfs_trans_reserve in xfs_trans_reserve_more Christoph Hellwig
` (6 subsequent siblings)
7 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2025-07-15 12:25 UTC (permalink / raw)
To: Carlos Maiolino; +Cc: linux-xfs
Instead of duplicating the empty transacaction reservation
definition.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/xfs_trans.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index b4a07af513ba..8b15bfe68774 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -1163,14 +1163,13 @@ xfs_trans_reserve_more_inode(
unsigned int rblocks,
bool force_quota)
{
- struct xfs_trans_res resv = { };
struct xfs_mount *mp = ip->i_mount;
unsigned int rtx = xfs_extlen_to_rtxlen(mp, rblocks);
int error;
xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);
- error = xfs_trans_reserve(tp, &resv, dblocks, rtx);
+ error = xfs_trans_reserve_more(tp, dblocks, rtx);
if (error)
return error;
--
2.47.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 2/8] xfs: don't use xfs_trans_reserve in xfs_trans_reserve_more
2025-07-15 12:25 cleanup transaction allocation Christoph Hellwig
2025-07-15 12:25 ` [PATCH 1/8] xfs: use xfs_trans_reserve_more in xfs_trans_reserve_more_inode Christoph Hellwig
@ 2025-07-15 12:25 ` Christoph Hellwig
2025-07-15 14:49 ` Darrick J. Wong
2025-07-15 12:25 ` [PATCH 3/8] xfs: decouple xfs_trans_alloc_empty from xfs_trans_alloc Christoph Hellwig
` (5 subsequent siblings)
7 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2025-07-15 12:25 UTC (permalink / raw)
To: Carlos Maiolino; +Cc: linux-xfs
xfs_trans_reserve_more just tries to allocate additional blocks and/or
rtextents and is otherwise unrelated to the transaction reservation
logic. Open code the block and rtextent reservation in
xfs_trans_reserve_more to prepare for simplifying xfs_trans_reserve.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/xfs_trans.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 8b15bfe68774..1fddea8d761a 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -1146,9 +1146,18 @@ xfs_trans_reserve_more(
unsigned int blocks,
unsigned int rtextents)
{
- struct xfs_trans_res resv = { };
-
- return xfs_trans_reserve(tp, &resv, blocks, rtextents);
+ bool rsvd = tp->t_flags & XFS_TRANS_RESERVE;
+
+ if (blocks && xfs_dec_fdblocks(tp->t_mountp, blocks, rsvd))
+ return -ENOSPC;
+ if (rtextents && xfs_dec_frextents(tp->t_mountp, rtextents) < 0) {
+ if (blocks)
+ xfs_add_fdblocks(tp->t_mountp, blocks);
+ return -ENOSPC;
+ }
+ tp->t_blk_res += blocks;
+ tp->t_rtx_res += rtextents;
+ return 0;
}
/*
--
2.47.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 3/8] xfs: decouple xfs_trans_alloc_empty from xfs_trans_alloc
2025-07-15 12:25 cleanup transaction allocation Christoph Hellwig
2025-07-15 12:25 ` [PATCH 1/8] xfs: use xfs_trans_reserve_more in xfs_trans_reserve_more_inode Christoph Hellwig
2025-07-15 12:25 ` [PATCH 2/8] xfs: don't use xfs_trans_reserve in xfs_trans_reserve_more Christoph Hellwig
@ 2025-07-15 12:25 ` Christoph Hellwig
2025-07-15 14:54 ` Darrick J. Wong
2025-07-15 12:25 ` [PATCH 4/8] xfs: don't use xfs_trans_reserve in xfs_trans_roll Christoph Hellwig
` (4 subsequent siblings)
7 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2025-07-15 12:25 UTC (permalink / raw)
To: Carlos Maiolino; +Cc: linux-xfs
xfs_trans_alloc_empty only shares the very basic transaction structure
allocation and initialization with xfs_trans_alloc.
Split out a new __xfs_trans_alloc helper for that and otherwise decouple
xfs_trans_alloc_empty from xfs_trans_alloc.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/xfs_trans.c | 52 +++++++++++++++++++++++++---------------------
1 file changed, 28 insertions(+), 24 deletions(-)
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 1fddea8d761a..e43f44f62c5f 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -241,6 +241,28 @@ xfs_trans_reserve(
return error;
}
+static struct xfs_trans *
+__xfs_trans_alloc(
+ struct xfs_mount *mp,
+ uint flags)
+{
+ struct xfs_trans *tp;
+
+ ASSERT(!(flags & XFS_TRANS_RES_FDBLKS) || xfs_has_lazysbcount(mp));
+
+ tp = kmem_cache_zalloc(xfs_trans_cache, GFP_KERNEL | __GFP_NOFAIL);
+ if (!(flags & XFS_TRANS_NO_WRITECOUNT))
+ sb_start_intwrite(mp->m_super);
+ xfs_trans_set_context(tp);
+ tp->t_flags = flags;
+ tp->t_mountp = mp;
+ INIT_LIST_HEAD(&tp->t_items);
+ INIT_LIST_HEAD(&tp->t_busy);
+ INIT_LIST_HEAD(&tp->t_dfops);
+ tp->t_highest_agno = NULLAGNUMBER;
+ return tp;
+}
+
int
xfs_trans_alloc(
struct xfs_mount *mp,
@@ -254,33 +276,16 @@ xfs_trans_alloc(
bool want_retry = true;
int error;
+ ASSERT(resp->tr_logres > 0);
+
/*
* Allocate the handle before we do our freeze accounting and setting up
* GFP_NOFS allocation context so that we avoid lockdep false positives
* by doing GFP_KERNEL allocations inside sb_start_intwrite().
*/
retry:
- tp = kmem_cache_zalloc(xfs_trans_cache, GFP_KERNEL | __GFP_NOFAIL);
- if (!(flags & XFS_TRANS_NO_WRITECOUNT))
- sb_start_intwrite(mp->m_super);
- xfs_trans_set_context(tp);
-
- /*
- * Zero-reservation ("empty") transactions can't modify anything, so
- * they're allowed to run while we're frozen.
- */
- WARN_ON(resp->tr_logres > 0 &&
- mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE);
- ASSERT(!(flags & XFS_TRANS_RES_FDBLKS) ||
- xfs_has_lazysbcount(mp));
-
- tp->t_flags = flags;
- tp->t_mountp = mp;
- INIT_LIST_HEAD(&tp->t_items);
- INIT_LIST_HEAD(&tp->t_busy);
- INIT_LIST_HEAD(&tp->t_dfops);
- tp->t_highest_agno = NULLAGNUMBER;
-
+ WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE);
+ tp = __xfs_trans_alloc(mp, flags);
error = xfs_trans_reserve(tp, resp, blocks, rtextents);
if (error == -ENOSPC && want_retry) {
xfs_trans_cancel(tp);
@@ -329,9 +334,8 @@ xfs_trans_alloc_empty(
struct xfs_mount *mp,
struct xfs_trans **tpp)
{
- struct xfs_trans_res resv = {0};
-
- return xfs_trans_alloc(mp, &resv, 0, 0, XFS_TRANS_NO_WRITECOUNT, tpp);
+ *tpp = __xfs_trans_alloc(mp, XFS_TRANS_NO_WRITECOUNT);
+ return 0;
}
/*
--
2.47.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 4/8] xfs: don't use xfs_trans_reserve in xfs_trans_roll
2025-07-15 12:25 cleanup transaction allocation Christoph Hellwig
` (2 preceding siblings ...)
2025-07-15 12:25 ` [PATCH 3/8] xfs: decouple xfs_trans_alloc_empty from xfs_trans_alloc Christoph Hellwig
@ 2025-07-15 12:25 ` Christoph Hellwig
2025-07-15 14:59 ` Darrick J. Wong
2025-07-15 12:25 ` [PATCH 5/8] xfs: return the allocated transaction from xfs_trans_alloc_empty Christoph Hellwig
` (3 subsequent siblings)
7 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2025-07-15 12:25 UTC (permalink / raw)
To: Carlos Maiolino; +Cc: linux-xfs
xfs_trans_roll uses xfs_trans_reserve to basically just call into
xfs_log_regrant while bypassing the reset of xfs_trans_reserve.
Open code the call to xfs_log_regrant in xfs_trans_roll and simplify
xfs_trans_reserve now that it never regrants and always asks for a log
reservation.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/xfs_trans.c | 122 +++++++++++++++++++--------------------------
1 file changed, 51 insertions(+), 71 deletions(-)
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index e43f44f62c5f..553128b7f86a 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -134,18 +134,14 @@ xfs_trans_dup(
}
/*
- * This is called to reserve free disk blocks and log space for the
- * given transaction. This must be done before allocating any resources
- * within the transaction.
+ * This is called to reserve free disk blocks and log space for the given
+ * transaction before allocating any resources within the transaction.
*
* This will return ENOSPC if there are not enough blocks available.
* It will sleep waiting for available log space.
- * The only valid value for the flags parameter is XFS_RES_LOG_PERM, which
- * is used by long running transactions. If any one of the reservations
- * fails then they will all be backed out.
*
- * This does not do quota reservations. That typically is done by the
- * caller afterwards.
+ * This does not do quota reservations. That typically is done by the caller
+ * afterwards.
*/
static int
xfs_trans_reserve(
@@ -158,10 +154,12 @@ xfs_trans_reserve(
int error = 0;
bool rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
+ ASSERT(resp->tr_logres > 0);
+
/*
- * Attempt to reserve the needed disk blocks by decrementing
- * the number needed from the number available. This will
- * fail if the count would go below zero.
+ * Attempt to reserve the needed disk blocks by decrementing the number
+ * needed from the number available. This will fail if the count would
+ * go below zero.
*/
if (blocks > 0) {
error = xfs_dec_fdblocks(mp, blocks, rsvd);
@@ -173,42 +171,20 @@ xfs_trans_reserve(
/*
* Reserve the log space needed for this transaction.
*/
- if (resp->tr_logres > 0) {
- bool permanent = false;
-
- ASSERT(tp->t_log_res == 0 ||
- tp->t_log_res == resp->tr_logres);
- ASSERT(tp->t_log_count == 0 ||
- tp->t_log_count == resp->tr_logcount);
-
- if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES) {
- tp->t_flags |= XFS_TRANS_PERM_LOG_RES;
- permanent = true;
- } else {
- ASSERT(tp->t_ticket == NULL);
- ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES));
- }
-
- if (tp->t_ticket != NULL) {
- ASSERT(resp->tr_logflags & XFS_TRANS_PERM_LOG_RES);
- error = xfs_log_regrant(mp, tp->t_ticket);
- } else {
- error = xfs_log_reserve(mp, resp->tr_logres,
- resp->tr_logcount,
- &tp->t_ticket, permanent);
- }
-
- if (error)
- goto undo_blocks;
+ if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES)
+ tp->t_flags |= XFS_TRANS_PERM_LOG_RES;
+ error = xfs_log_reserve(mp, resp->tr_logres, resp->tr_logcount,
+ &tp->t_ticket, (tp->t_flags & XFS_TRANS_PERM_LOG_RES));
+ if (error)
+ goto undo_blocks;
- tp->t_log_res = resp->tr_logres;
- tp->t_log_count = resp->tr_logcount;
- }
+ tp->t_log_res = resp->tr_logres;
+ tp->t_log_count = resp->tr_logcount;
/*
- * Attempt to reserve the needed realtime extents by decrementing
- * the number needed from the number available. This will
- * fail if the count would go below zero.
+ * Attempt to reserve the needed realtime extents by decrementing the
+ * number needed from the number available. This will fail if the
+ * count would go below zero.
*/
if (rtextents > 0) {
error = xfs_dec_frextents(mp, rtextents);
@@ -221,18 +197,11 @@ xfs_trans_reserve(
return 0;
- /*
- * Error cases jump to one of these labels to undo any
- * reservations which have already been performed.
- */
undo_log:
- if (resp->tr_logres > 0) {
- xfs_log_ticket_ungrant(mp->m_log, tp->t_ticket);
- tp->t_ticket = NULL;
- tp->t_log_res = 0;
- tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES;
- }
-
+ xfs_log_ticket_ungrant(mp->m_log, tp->t_ticket);
+ tp->t_ticket = NULL;
+ tp->t_log_res = 0;
+ tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES;
undo_blocks:
if (blocks > 0) {
xfs_add_fdblocks(mp, blocks);
@@ -1030,36 +999,41 @@ xfs_trans_cancel(
}
/*
- * Roll from one trans in the sequence of PERMANENT transactions to
- * the next: permanent transactions are only flushed out when
- * committed with xfs_trans_commit(), but we still want as soon
- * as possible to let chunks of it go to the log. So we commit the
- * chunk we've been working on and get a new transaction to continue.
+ * Roll from one trans in the sequence of PERMANENT transactions to the next:
+ * permanent transactions are only flushed out when committed with
+ * xfs_trans_commit(), but we still want as soon as possible to let chunks of it
+ * go to the log. So we commit the chunk we've been working on and get a new
+ * transaction to continue.
*/
int
xfs_trans_roll(
struct xfs_trans **tpp)
{
struct xfs_trans *trans = *tpp;
+ struct xfs_mount *mp = trans->t_mountp;
struct xfs_trans_res tres;
int error;
trace_xfs_trans_roll(trans, _RET_IP_);
+ ASSERT(trans->t_log_res > 0);
+
/*
* Copy the critical parameters from one trans to the next.
*/
tres.tr_logres = trans->t_log_res;
tres.tr_logcount = trans->t_log_count;
+ tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
*tpp = xfs_trans_dup(trans);
/*
* Commit the current transaction.
- * If this commit failed, then it'd just unlock those items that
- * are not marked ihold. That also means that a filesystem shutdown
- * is in progress. The caller takes the responsibility to cancel
- * the duplicate transaction that gets returned.
+ *
+ * If this commit failed, then it'd just unlock those items that are not
+ * marked ihold. That also means that a filesystem shutdown is in
+ * progress. The caller takes the responsibility to cancel the
+ * duplicate transaction that gets returned.
*/
error = __xfs_trans_commit(trans, true);
if (error)
@@ -1067,14 +1041,20 @@ xfs_trans_roll(
/*
* Reserve space in the log for the next transaction.
- * This also pushes items in the "AIL", the list of logged items,
- * out to disk if they are taking up space at the tail of the log
- * that we want to use. This requires that either nothing be locked
- * across this call, or that anything that is locked be logged in
- * the prior and the next transactions.
+ *
+ * This also pushes items in the AIL out to disk if they are taking up
+ * space at the tail of the log that we want to use. This requires that
+ * either nothing be locked across this call, or that anything that is
+ * locked be logged in the prior and the next transactions.
*/
- tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
- return xfs_trans_reserve(*tpp, &tres, 0, 0);
+ trans = *tpp;
+ trans->t_flags |= XFS_TRANS_PERM_LOG_RES;
+ error = xfs_log_regrant(mp, trans->t_ticket);
+ if (error)
+ return error;
+ trans->t_log_res = tres.tr_logres;
+ trans->t_log_count = tres.tr_logcount;
+ return 0;
}
/*
--
2.47.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 5/8] xfs: return the allocated transaction from xfs_trans_alloc_empty
2025-07-15 12:25 cleanup transaction allocation Christoph Hellwig
` (3 preceding siblings ...)
2025-07-15 12:25 ` [PATCH 4/8] xfs: don't use xfs_trans_reserve in xfs_trans_roll Christoph Hellwig
@ 2025-07-15 12:25 ` Christoph Hellwig
2025-07-15 14:59 ` Darrick J. Wong
2025-07-15 12:25 ` [PATCH 6/8] xfs: return the allocated transaction from xchk_trans_alloc_empty Christoph Hellwig
` (2 subsequent siblings)
7 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2025-07-15 12:25 UTC (permalink / raw)
To: Carlos Maiolino; +Cc: linux-xfs
xfs_trans_alloc_empty can't return errors, so return the allocated
transaction directly instead of an output double pointer argument.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/libxfs/xfs_refcount.c | 4 +---
fs/xfs/scrub/common.c | 3 ++-
fs/xfs/scrub/repair.c | 12 ++----------
fs/xfs/scrub/scrub.c | 5 +----
fs/xfs/xfs_attr_item.c | 5 +----
fs/xfs/xfs_discard.c | 12 +++---------
fs/xfs/xfs_fsmap.c | 4 +---
fs/xfs/xfs_icache.c | 5 +----
fs/xfs/xfs_inode.c | 5 +----
fs/xfs/xfs_itable.c | 18 +++---------------
fs/xfs/xfs_iwalk.c | 11 +++--------
fs/xfs/xfs_notify_failure.c | 5 +----
fs/xfs/xfs_qm.c | 10 ++--------
fs/xfs/xfs_rtalloc.c | 13 +++----------
fs/xfs/xfs_trans.c | 8 +++-----
fs/xfs/xfs_trans.h | 3 +--
fs/xfs/xfs_zone_gc.c | 5 +----
17 files changed, 30 insertions(+), 98 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c
index cebe83f7842a..897784037483 100644
--- a/fs/xfs/libxfs/xfs_refcount.c
+++ b/fs/xfs/libxfs/xfs_refcount.c
@@ -2099,9 +2099,7 @@ xfs_refcount_recover_cow_leftovers(
* recording the CoW debris we cancel the (empty) transaction
* and everything goes away cleanly.
*/
- error = xfs_trans_alloc_empty(mp, &tp);
- if (error)
- return error;
+ tp = xfs_trans_alloc_empty(mp);
if (isrt) {
xfs_rtgroup_lock(to_rtg(xg), XFS_RTGLOCK_REFCOUNT);
diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c
index 28ad341df8ee..d080f4e6e9d8 100644
--- a/fs/xfs/scrub/common.c
+++ b/fs/xfs/scrub/common.c
@@ -870,7 +870,8 @@ int
xchk_trans_alloc_empty(
struct xfs_scrub *sc)
{
- return xfs_trans_alloc_empty(sc->mp, &sc->tp);
+ sc->tp = xfs_trans_alloc_empty(sc->mp);
+ return 0;
}
/*
diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c
index f8f9ed30f56b..f7f80ff32afc 100644
--- a/fs/xfs/scrub/repair.c
+++ b/fs/xfs/scrub/repair.c
@@ -1279,18 +1279,10 @@ xrep_trans_alloc_hook_dummy(
void **cookiep,
struct xfs_trans **tpp)
{
- int error;
-
*cookiep = current->journal_info;
current->journal_info = NULL;
-
- error = xfs_trans_alloc_empty(mp, tpp);
- if (!error)
- return 0;
-
- current->journal_info = *cookiep;
- *cookiep = NULL;
- return error;
+ *tpp = xfs_trans_alloc_empty(mp);
+ return 0;
}
/* Cancel a dummy transaction used by a live update hook function. */
diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c
index 76e24032e99a..3c3b0d25006f 100644
--- a/fs/xfs/scrub/scrub.c
+++ b/fs/xfs/scrub/scrub.c
@@ -876,10 +876,7 @@ xchk_scrubv_open_by_handle(
struct xfs_inode *ip;
int error;
- error = xfs_trans_alloc_empty(mp, &tp);
- if (error)
- return NULL;
-
+ tp = xfs_trans_alloc_empty(mp);
error = xfs_iget(mp, tp, head->svh_ino, XCHK_IGET_FLAGS, 0, &ip);
xfs_trans_cancel(tp);
if (error)
diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c
index f683b7a9323f..da1e11f38eb0 100644
--- a/fs/xfs/xfs_attr_item.c
+++ b/fs/xfs/xfs_attr_item.c
@@ -616,10 +616,7 @@ xfs_attri_iread_extents(
struct xfs_trans *tp;
int error;
- error = xfs_trans_alloc_empty(ip->i_mount, &tp);
- if (error)
- return error;
-
+ tp = xfs_trans_alloc_empty(ip->i_mount);
xfs_ilock(ip, XFS_ILOCK_EXCL);
error = xfs_iread_extents(tp, ip, XFS_ATTR_FORK);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c
index 603d51365645..ee49f20875af 100644
--- a/fs/xfs/xfs_discard.c
+++ b/fs/xfs/xfs_discard.c
@@ -189,9 +189,7 @@ xfs_trim_gather_extents(
*/
xfs_log_force(mp, XFS_LOG_SYNC);
- error = xfs_trans_alloc_empty(mp, &tp);
- if (error)
- return error;
+ tp = xfs_trans_alloc_empty(mp);
error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
if (error)
@@ -583,9 +581,7 @@ xfs_trim_rtextents(
struct xfs_trans *tp;
int error;
- error = xfs_trans_alloc_empty(mp, &tp);
- if (error)
- return error;
+ tp = xfs_trans_alloc_empty(mp);
/*
* Walk the free ranges between low and high. The query_range function
@@ -701,9 +697,7 @@ xfs_trim_rtgroup_extents(
struct xfs_trans *tp;
int error;
- error = xfs_trans_alloc_empty(mp, &tp);
- if (error)
- return error;
+ tp = xfs_trans_alloc_empty(mp);
/*
* Walk the free ranges between low and high. The query_range function
diff --git a/fs/xfs/xfs_fsmap.c b/fs/xfs/xfs_fsmap.c
index 414b27a86458..af68c7de8ee8 100644
--- a/fs/xfs/xfs_fsmap.c
+++ b/fs/xfs/xfs_fsmap.c
@@ -1270,9 +1270,7 @@ xfs_getfsmap(
* buffer locking abilities to detect cycles in the rmapbt
* without deadlocking.
*/
- error = xfs_trans_alloc_empty(mp, &tp);
- if (error)
- break;
+ tp = xfs_trans_alloc_empty(mp);
info.dev = handlers[i].dev;
info.last = false;
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index bbc2f2973dcc..4cf7abe50143 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -893,10 +893,7 @@ xfs_metafile_iget(
struct xfs_trans *tp;
int error;
- error = xfs_trans_alloc_empty(mp, &tp);
- if (error)
- return error;
-
+ tp = xfs_trans_alloc_empty(mp);
error = xfs_trans_metafile_iget(tp, ino, metafile_type, ipp);
xfs_trans_cancel(tp);
return error;
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 761a996a857c..4264f8c92e53 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2934,10 +2934,7 @@ xfs_inode_reload_unlinked(
struct xfs_trans *tp;
int error;
- error = xfs_trans_alloc_empty(ip->i_mount, &tp);
- if (error)
- return error;
-
+ tp = xfs_trans_alloc_empty(ip->i_mount);
xfs_ilock(ip, XFS_ILOCK_SHARED);
if (xfs_inode_unlinked_incomplete(ip))
error = xfs_inode_reload_unlinked_bucket(tp, ip);
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 1fa1c0564b0c..c8c9b8d8309f 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -239,14 +239,10 @@ xfs_bulkstat_one(
* Grab an empty transaction so that we can use its recursive buffer
* locking abilities to detect cycles in the inobt without deadlocking.
*/
- error = xfs_trans_alloc_empty(breq->mp, &tp);
- if (error)
- goto out;
-
+ tp = xfs_trans_alloc_empty(breq->mp);
error = xfs_bulkstat_one_int(breq->mp, breq->idmap, tp,
breq->startino, &bc);
xfs_trans_cancel(tp);
-out:
kfree(bc.buf);
/*
@@ -331,17 +327,13 @@ xfs_bulkstat(
* Grab an empty transaction so that we can use its recursive buffer
* locking abilities to detect cycles in the inobt without deadlocking.
*/
- error = xfs_trans_alloc_empty(breq->mp, &tp);
- if (error)
- goto out;
-
+ tp = xfs_trans_alloc_empty(breq->mp);
if (breq->flags & XFS_IBULK_SAME_AG)
iwalk_flags |= XFS_IWALK_SAME_AG;
error = xfs_iwalk(breq->mp, tp, breq->startino, iwalk_flags,
xfs_bulkstat_iwalk, breq->icount, &bc);
xfs_trans_cancel(tp);
-out:
kfree(bc.buf);
/*
@@ -464,14 +456,10 @@ xfs_inumbers(
* Grab an empty transaction so that we can use its recursive buffer
* locking abilities to detect cycles in the inobt without deadlocking.
*/
- error = xfs_trans_alloc_empty(breq->mp, &tp);
- if (error)
- goto out;
-
+ tp = xfs_trans_alloc_empty(breq->mp);
error = xfs_inobt_walk(breq->mp, tp, breq->startino, breq->flags,
xfs_inumbers_walk, breq->icount, &ic);
xfs_trans_cancel(tp);
-out:
/*
* We found some inode groups, so clear the error status and return
diff --git a/fs/xfs/xfs_iwalk.c b/fs/xfs/xfs_iwalk.c
index 7db3ece370b1..c1c31d1a8e21 100644
--- a/fs/xfs/xfs_iwalk.c
+++ b/fs/xfs/xfs_iwalk.c
@@ -377,11 +377,8 @@ xfs_iwalk_run_callbacks(
if (!has_more)
return 0;
- if (iwag->drop_trans) {
- error = xfs_trans_alloc_empty(mp, &iwag->tp);
- if (error)
- return error;
- }
+ if (iwag->drop_trans)
+ iwag->tp = xfs_trans_alloc_empty(mp);
/* ...and recreate the cursor just past where we left off. */
error = xfs_ialloc_read_agi(iwag->pag, iwag->tp, 0, agi_bpp);
@@ -617,9 +614,7 @@ xfs_iwalk_ag_work(
* Grab an empty transaction so that we can use its recursive buffer
* locking abilities to detect cycles in the inobt without deadlocking.
*/
- error = xfs_trans_alloc_empty(mp, &iwag->tp);
- if (error)
- goto out;
+ iwag->tp = xfs_trans_alloc_empty(mp);
iwag->drop_trans = 1;
error = xfs_iwalk_ag(iwag);
diff --git a/fs/xfs/xfs_notify_failure.c b/fs/xfs/xfs_notify_failure.c
index 42e9c72b85c0..fbd521f89874 100644
--- a/fs/xfs/xfs_notify_failure.c
+++ b/fs/xfs/xfs_notify_failure.c
@@ -279,10 +279,7 @@ xfs_dax_notify_dev_failure(
kernel_frozen = xfs_dax_notify_failure_freeze(mp) == 0;
}
- error = xfs_trans_alloc_empty(mp, &tp);
- if (error)
- goto out;
-
+ tp = xfs_trans_alloc_empty(mp);
start_gno = xfs_fsb_to_gno(mp, start_bno, type);
end_gno = xfs_fsb_to_gno(mp, end_bno, type);
while ((xg = xfs_group_next_range(mp, xg, start_gno, end_gno, type))) {
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index fa135ac26471..23ba84ec919a 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -660,10 +660,7 @@ xfs_qm_load_metadir_qinos(
struct xfs_trans *tp;
int error;
- error = xfs_trans_alloc_empty(mp, &tp);
- if (error)
- return error;
-
+ tp = xfs_trans_alloc_empty(mp);
error = xfs_dqinode_load_parent(tp, &qi->qi_dirip);
if (error == -ENOENT) {
/* no quota dir directory, but we'll create one later */
@@ -1755,10 +1752,7 @@ xfs_qm_qino_load(
struct xfs_inode *dp = NULL;
int error;
- error = xfs_trans_alloc_empty(mp, &tp);
- if (error)
- return error;
-
+ tp = xfs_trans_alloc_empty(mp);
if (xfs_has_metadir(mp)) {
error = xfs_dqinode_load_parent(tp, &dp);
if (error)
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 736eb0924573..6907e871fa15 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -729,9 +729,7 @@ xfs_rtginode_ensure(
if (rtg->rtg_inodes[type])
return 0;
- error = xfs_trans_alloc_empty(rtg_mount(rtg), &tp);
- if (error)
- return error;
+ tp = xfs_trans_alloc_empty(rtg_mount(rtg));
error = xfs_rtginode_load(rtg, type, tp);
xfs_trans_cancel(tp);
@@ -1305,9 +1303,7 @@ xfs_growfs_rt_prep_groups(
if (!mp->m_rtdirip) {
struct xfs_trans *tp;
- error = xfs_trans_alloc_empty(mp, &tp);
- if (error)
- return error;
+ tp = xfs_trans_alloc_empty(mp);
error = xfs_rtginode_load_parent(tp);
xfs_trans_cancel(tp);
@@ -1674,10 +1670,7 @@ xfs_rtmount_inodes(
struct xfs_rtgroup *rtg = NULL;
int error;
- error = xfs_trans_alloc_empty(mp, &tp);
- if (error)
- return error;
-
+ tp = xfs_trans_alloc_empty(mp);
if (xfs_has_rtgroups(mp) && mp->m_sb.sb_rgcount > 0) {
error = xfs_rtginode_load_parent(tp);
if (error)
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 553128b7f86a..dc7199c81a78 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -298,13 +298,11 @@ xfs_trans_alloc(
* where we can be grabbing buffers at the same time that freeze is trying to
* drain the buffer LRU list.
*/
-int
+struct xfs_trans *
xfs_trans_alloc_empty(
- struct xfs_mount *mp,
- struct xfs_trans **tpp)
+ struct xfs_mount *mp)
{
- *tpp = __xfs_trans_alloc(mp, XFS_TRANS_NO_WRITECOUNT);
- return 0;
+ return __xfs_trans_alloc(mp, XFS_TRANS_NO_WRITECOUNT);
}
/*
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 2b366851e9a4..a6b10aaeb1f1 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -168,8 +168,7 @@ int xfs_trans_alloc(struct xfs_mount *mp, struct xfs_trans_res *resp,
struct xfs_trans **tpp);
int xfs_trans_reserve_more(struct xfs_trans *tp,
unsigned int blocks, unsigned int rtextents);
-int xfs_trans_alloc_empty(struct xfs_mount *mp,
- struct xfs_trans **tpp);
+struct xfs_trans *xfs_trans_alloc_empty(struct xfs_mount *mp);
void xfs_trans_mod_sb(xfs_trans_t *, uint, int64_t);
int xfs_trans_get_buf_map(struct xfs_trans *tp, struct xfs_buftarg *target,
diff --git a/fs/xfs/xfs_zone_gc.c b/fs/xfs/xfs_zone_gc.c
index 9c00fc5baa30..e1954b0e6021 100644
--- a/fs/xfs/xfs_zone_gc.c
+++ b/fs/xfs/xfs_zone_gc.c
@@ -328,10 +328,7 @@ xfs_zone_gc_query(
iter->rec_idx = 0;
iter->rec_count = 0;
- error = xfs_trans_alloc_empty(mp, &tp);
- if (error)
- return error;
-
+ tp = xfs_trans_alloc_empty(mp);
xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP);
cur = xfs_rtrmapbt_init_cursor(tp, rtg);
error = xfs_rmap_query_range(cur, &ri_low, &ri_high,
--
2.47.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 6/8] xfs: return the allocated transaction from xchk_trans_alloc_empty
2025-07-15 12:25 cleanup transaction allocation Christoph Hellwig
` (4 preceding siblings ...)
2025-07-15 12:25 ` [PATCH 5/8] xfs: return the allocated transaction from xfs_trans_alloc_empty Christoph Hellwig
@ 2025-07-15 12:25 ` Christoph Hellwig
2025-07-15 14:59 ` Darrick J. Wong
2025-07-15 12:25 ` [PATCH 7/8] xfs: return the allocated transaction from xrep_trans_alloc_hook_dummy Christoph Hellwig
2025-07-15 12:25 ` [PATCH 8/8] xfs: remove the xlog_ticket_t typedef Christoph Hellwig
7 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2025-07-15 12:25 UTC (permalink / raw)
To: Carlos Maiolino; +Cc: linux-xfs
xchk_trans_alloc_empty can't return errors, so return the allocated
transaction directly instead of an output double pointer argument.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/scrub/common.c | 6 +++---
fs/xfs/scrub/common.h | 2 +-
fs/xfs/scrub/dir_repair.c | 8 ++------
fs/xfs/scrub/fscounters.c | 3 ++-
fs/xfs/scrub/metapath.c | 4 +---
fs/xfs/scrub/nlinks.c | 8 ++------
fs/xfs/scrub/nlinks_repair.c | 4 +---
fs/xfs/scrub/parent_repair.c | 12 +++---------
fs/xfs/scrub/quotacheck.c | 4 +---
fs/xfs/scrub/rmap_repair.c | 4 +---
fs/xfs/scrub/rtrmap_repair.c | 4 +---
11 files changed, 18 insertions(+), 41 deletions(-)
diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c
index d080f4e6e9d8..2ef7742be7d3 100644
--- a/fs/xfs/scrub/common.c
+++ b/fs/xfs/scrub/common.c
@@ -866,12 +866,11 @@ xchk_trans_cancel(
sc->tp = NULL;
}
-int
+void
xchk_trans_alloc_empty(
struct xfs_scrub *sc)
{
sc->tp = xfs_trans_alloc_empty(sc->mp);
- return 0;
}
/*
@@ -893,7 +892,8 @@ xchk_trans_alloc(
return xfs_trans_alloc(sc->mp, &M_RES(sc->mp)->tr_itruncate,
resblks, 0, 0, &sc->tp);
- return xchk_trans_alloc_empty(sc);
+ xchk_trans_alloc_empty(sc);
+ return 0;
}
/* Set us up with a transaction and an empty context. */
diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h
index 19877d99f255..ddbc065c798c 100644
--- a/fs/xfs/scrub/common.h
+++ b/fs/xfs/scrub/common.h
@@ -7,7 +7,7 @@
#define __XFS_SCRUB_COMMON_H__
int xchk_trans_alloc(struct xfs_scrub *sc, uint resblks);
-int xchk_trans_alloc_empty(struct xfs_scrub *sc);
+void xchk_trans_alloc_empty(struct xfs_scrub *sc);
void xchk_trans_cancel(struct xfs_scrub *sc);
bool xchk_process_error(struct xfs_scrub *sc, xfs_agnumber_t agno,
diff --git a/fs/xfs/scrub/dir_repair.c b/fs/xfs/scrub/dir_repair.c
index 249313882108..8d3b550990b5 100644
--- a/fs/xfs/scrub/dir_repair.c
+++ b/fs/xfs/scrub/dir_repair.c
@@ -1289,9 +1289,7 @@ xrep_dir_scan_dirtree(
if (sc->ilock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL))
xchk_iunlock(sc, sc->ilock_flags & (XFS_ILOCK_SHARED |
XFS_ILOCK_EXCL));
- error = xchk_trans_alloc_empty(sc);
- if (error)
- return error;
+ xchk_trans_alloc_empty(sc);
while ((error = xchk_iscan_iter(&rd->pscan.iscan, &ip)) == 1) {
bool flush;
@@ -1317,9 +1315,7 @@ xrep_dir_scan_dirtree(
if (error)
break;
- error = xchk_trans_alloc_empty(sc);
- if (error)
- break;
+ xchk_trans_alloc_empty(sc);
}
if (xchk_should_terminate(sc, &error))
diff --git a/fs/xfs/scrub/fscounters.c b/fs/xfs/scrub/fscounters.c
index 9b598c5790ad..cebd0d526926 100644
--- a/fs/xfs/scrub/fscounters.c
+++ b/fs/xfs/scrub/fscounters.c
@@ -237,7 +237,8 @@ xchk_setup_fscounters(
return error;
}
- return xchk_trans_alloc_empty(sc);
+ xchk_trans_alloc_empty(sc);
+ return 0;
}
/*
diff --git a/fs/xfs/scrub/metapath.c b/fs/xfs/scrub/metapath.c
index e21c16fbd15d..14939d7de349 100644
--- a/fs/xfs/scrub/metapath.c
+++ b/fs/xfs/scrub/metapath.c
@@ -318,9 +318,7 @@ xchk_metapath(
return 0;
}
- error = xchk_trans_alloc_empty(sc);
- if (error)
- return error;
+ xchk_trans_alloc_empty(sc);
error = xchk_metapath_ilock_both(mpath);
if (error)
diff --git a/fs/xfs/scrub/nlinks.c b/fs/xfs/scrub/nlinks.c
index 4a47d0aabf73..26721fab5cab 100644
--- a/fs/xfs/scrub/nlinks.c
+++ b/fs/xfs/scrub/nlinks.c
@@ -555,9 +555,7 @@ xchk_nlinks_collect(
* do not take sb_internal.
*/
xchk_trans_cancel(sc);
- error = xchk_trans_alloc_empty(sc);
- if (error)
- return error;
+ xchk_trans_alloc_empty(sc);
while ((error = xchk_iscan_iter(&xnc->collect_iscan, &ip)) == 1) {
if (S_ISDIR(VFS_I(ip)->i_mode))
@@ -880,9 +878,7 @@ xchk_nlinks_compare(
* inactivation workqueue.
*/
xchk_trans_cancel(sc);
- error = xchk_trans_alloc_empty(sc);
- if (error)
- return error;
+ xchk_trans_alloc_empty(sc);
/*
* Use the inobt to walk all allocated inodes to compare the link
diff --git a/fs/xfs/scrub/nlinks_repair.c b/fs/xfs/scrub/nlinks_repair.c
index 4ebdee095428..6ef2ee9c3814 100644
--- a/fs/xfs/scrub/nlinks_repair.c
+++ b/fs/xfs/scrub/nlinks_repair.c
@@ -340,9 +340,7 @@ xrep_nlinks(
* We can only push the inactivation workqueues with an empty
* transaction.
*/
- error = xchk_trans_alloc_empty(sc);
- if (error)
- break;
+ xchk_trans_alloc_empty(sc);
}
xchk_iscan_iter_finish(&xnc->compare_iscan);
xchk_iscan_teardown(&xnc->compare_iscan);
diff --git a/fs/xfs/scrub/parent_repair.c b/fs/xfs/scrub/parent_repair.c
index 31bfe10be22a..2949feda6271 100644
--- a/fs/xfs/scrub/parent_repair.c
+++ b/fs/xfs/scrub/parent_repair.c
@@ -569,9 +569,7 @@ xrep_parent_scan_dirtree(
if (sc->ilock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL))
xchk_iunlock(sc, sc->ilock_flags & (XFS_ILOCK_SHARED |
XFS_ILOCK_EXCL));
- error = xchk_trans_alloc_empty(sc);
- if (error)
- return error;
+ xchk_trans_alloc_empty(sc);
while ((error = xchk_iscan_iter(&rp->pscan.iscan, &ip)) == 1) {
bool flush;
@@ -597,9 +595,7 @@ xrep_parent_scan_dirtree(
if (error)
break;
- error = xchk_trans_alloc_empty(sc);
- if (error)
- break;
+ xchk_trans_alloc_empty(sc);
}
if (xchk_should_terminate(sc, &error))
@@ -1099,9 +1095,7 @@ xrep_parent_flush_xattrs(
xrep_tempfile_iounlock(rp->sc);
/* Recreate the empty transaction and relock the inode. */
- error = xchk_trans_alloc_empty(rp->sc);
- if (error)
- return error;
+ xchk_trans_alloc_empty(rp->sc);
xchk_ilock(rp->sc, XFS_ILOCK_EXCL);
return 0;
}
diff --git a/fs/xfs/scrub/quotacheck.c b/fs/xfs/scrub/quotacheck.c
index dc4033b91e44..e4105aaafe84 100644
--- a/fs/xfs/scrub/quotacheck.c
+++ b/fs/xfs/scrub/quotacheck.c
@@ -505,9 +505,7 @@ xqcheck_collect_counts(
* transactions do not take sb_internal.
*/
xchk_trans_cancel(sc);
- error = xchk_trans_alloc_empty(sc);
- if (error)
- return error;
+ xchk_trans_alloc_empty(sc);
while ((error = xchk_iscan_iter(&xqc->iscan, &ip)) == 1) {
error = xqcheck_collect_inode(xqc, ip);
diff --git a/fs/xfs/scrub/rmap_repair.c b/fs/xfs/scrub/rmap_repair.c
index f5f73078ffe2..bf1e632b449a 100644
--- a/fs/xfs/scrub/rmap_repair.c
+++ b/fs/xfs/scrub/rmap_repair.c
@@ -951,9 +951,7 @@ xrep_rmap_find_rmaps(
sa->agf_bp = NULL;
sa->agi_bp = NULL;
xchk_trans_cancel(sc);
- error = xchk_trans_alloc_empty(sc);
- if (error)
- return error;
+ xchk_trans_alloc_empty(sc);
/* Iterate all AGs for inodes rmaps. */
while ((error = xchk_iscan_iter(&rr->iscan, &ip)) == 1) {
diff --git a/fs/xfs/scrub/rtrmap_repair.c b/fs/xfs/scrub/rtrmap_repair.c
index fc2592c53af5..4a56726d9952 100644
--- a/fs/xfs/scrub/rtrmap_repair.c
+++ b/fs/xfs/scrub/rtrmap_repair.c
@@ -580,9 +580,7 @@ xrep_rtrmap_find_rmaps(
*/
xchk_trans_cancel(sc);
xchk_rtgroup_unlock(&sc->sr);
- error = xchk_trans_alloc_empty(sc);
- if (error)
- return error;
+ xchk_trans_alloc_empty(sc);
while ((error = xchk_iscan_iter(&rr->iscan, &ip)) == 1) {
error = xrep_rtrmap_scan_inode(rr, ip);
--
2.47.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 7/8] xfs: return the allocated transaction from xrep_trans_alloc_hook_dummy
2025-07-15 12:25 cleanup transaction allocation Christoph Hellwig
` (5 preceding siblings ...)
2025-07-15 12:25 ` [PATCH 6/8] xfs: return the allocated transaction from xchk_trans_alloc_empty Christoph Hellwig
@ 2025-07-15 12:25 ` Christoph Hellwig
2025-07-15 15:18 ` Darrick J. Wong
2025-07-15 12:25 ` [PATCH 8/8] xfs: remove the xlog_ticket_t typedef Christoph Hellwig
7 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2025-07-15 12:25 UTC (permalink / raw)
To: Carlos Maiolino; +Cc: linux-xfs
xrep_trans_alloc_hook_dummy can't return errors, so return the allocated
transaction directly instead of an output double pointer argument.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/scrub/repair.c | 8 +++-----
fs/xfs/scrub/repair.h | 4 ++--
fs/xfs/scrub/rmap_repair.c | 5 +----
fs/xfs/scrub/rtrmap_repair.c | 5 +----
4 files changed, 7 insertions(+), 15 deletions(-)
diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c
index f7f80ff32afc..79251c595e18 100644
--- a/fs/xfs/scrub/repair.c
+++ b/fs/xfs/scrub/repair.c
@@ -1273,16 +1273,14 @@ xrep_setup_xfbtree(
* function MUST NOT be called from regular repair code because the current
* process' transaction is saved via the cookie.
*/
-int
+struct xfs_trans *
xrep_trans_alloc_hook_dummy(
struct xfs_mount *mp,
- void **cookiep,
- struct xfs_trans **tpp)
+ void **cookiep)
{
*cookiep = current->journal_info;
current->journal_info = NULL;
- *tpp = xfs_trans_alloc_empty(mp);
- return 0;
+ return xfs_trans_alloc_empty(mp);
}
/* Cancel a dummy transaction used by a live update hook function. */
diff --git a/fs/xfs/scrub/repair.h b/fs/xfs/scrub/repair.h
index af0a3a9e5ed9..0a808e903cf5 100644
--- a/fs/xfs/scrub/repair.h
+++ b/fs/xfs/scrub/repair.h
@@ -180,8 +180,8 @@ int xrep_quotacheck(struct xfs_scrub *sc);
int xrep_reinit_pagf(struct xfs_scrub *sc);
int xrep_reinit_pagi(struct xfs_scrub *sc);
-int xrep_trans_alloc_hook_dummy(struct xfs_mount *mp, void **cookiep,
- struct xfs_trans **tpp);
+struct xfs_trans *xrep_trans_alloc_hook_dummy(struct xfs_mount *mp,
+ void **cookiep);
void xrep_trans_cancel_hook_dummy(void **cookiep, struct xfs_trans *tp);
bool xrep_buf_verify_struct(struct xfs_buf *bp, const struct xfs_buf_ops *ops);
diff --git a/fs/xfs/scrub/rmap_repair.c b/fs/xfs/scrub/rmap_repair.c
index bf1e632b449a..6024872a17e5 100644
--- a/fs/xfs/scrub/rmap_repair.c
+++ b/fs/xfs/scrub/rmap_repair.c
@@ -1621,9 +1621,7 @@ xrep_rmapbt_live_update(
trace_xrep_rmap_live_update(pag_group(rr->sc->sa.pag), action, p);
- error = xrep_trans_alloc_hook_dummy(mp, &txcookie, &tp);
- if (error)
- goto out_abort;
+ tp = xrep_trans_alloc_hook_dummy(mp, &txcookie);
mutex_lock(&rr->lock);
mcur = xfs_rmapbt_mem_cursor(rr->sc->sa.pag, tp, &rr->rmap_btree);
@@ -1644,7 +1642,6 @@ xrep_rmapbt_live_update(
out_cancel:
xfbtree_trans_cancel(&rr->rmap_btree, tp);
xrep_trans_cancel_hook_dummy(&txcookie, tp);
-out_abort:
mutex_unlock(&rr->lock);
xchk_iscan_abort(&rr->iscan);
out_unlock:
diff --git a/fs/xfs/scrub/rtrmap_repair.c b/fs/xfs/scrub/rtrmap_repair.c
index 4a56726d9952..5b8155c87873 100644
--- a/fs/xfs/scrub/rtrmap_repair.c
+++ b/fs/xfs/scrub/rtrmap_repair.c
@@ -855,9 +855,7 @@ xrep_rtrmapbt_live_update(
trace_xrep_rmap_live_update(rtg_group(rr->sc->sr.rtg), action, p);
- error = xrep_trans_alloc_hook_dummy(mp, &txcookie, &tp);
- if (error)
- goto out_abort;
+ tp = xrep_trans_alloc_hook_dummy(mp, &txcookie);
mutex_lock(&rr->lock);
mcur = xfs_rtrmapbt_mem_cursor(rr->sc->sr.rtg, tp, &rr->rtrmap_btree);
@@ -878,7 +876,6 @@ xrep_rtrmapbt_live_update(
out_cancel:
xfbtree_trans_cancel(&rr->rtrmap_btree, tp);
xrep_trans_cancel_hook_dummy(&txcookie, tp);
-out_abort:
xchk_iscan_abort(&rr->iscan);
mutex_unlock(&rr->lock);
out_unlock:
--
2.47.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 8/8] xfs: remove the xlog_ticket_t typedef
2025-07-15 12:25 cleanup transaction allocation Christoph Hellwig
` (6 preceding siblings ...)
2025-07-15 12:25 ` [PATCH 7/8] xfs: return the allocated transaction from xrep_trans_alloc_hook_dummy Christoph Hellwig
@ 2025-07-15 12:25 ` Christoph Hellwig
2025-07-15 15:18 ` Darrick J. Wong
7 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2025-07-15 12:25 UTC (permalink / raw)
To: Carlos Maiolino; +Cc: linux-xfs
Almost no users of the typedef left, kill it and switch the remaining
users to use the underlying struct.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/xfs_log.c | 6 +++---
fs/xfs/xfs_log_priv.h | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 793468b4d30d..bc3297da2143 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -3092,16 +3092,16 @@ xfs_log_force_seq(
*/
void
xfs_log_ticket_put(
- xlog_ticket_t *ticket)
+ struct xlog_ticket *ticket)
{
ASSERT(atomic_read(&ticket->t_ref) > 0);
if (atomic_dec_and_test(&ticket->t_ref))
kmem_cache_free(xfs_log_ticket_cache, ticket);
}
-xlog_ticket_t *
+struct xlog_ticket *
xfs_log_ticket_get(
- xlog_ticket_t *ticket)
+ struct xlog_ticket *ticket)
{
ASSERT(atomic_read(&ticket->t_ref) > 0);
atomic_inc(&ticket->t_ref);
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 39a102cc1b43..a9a7a271c15b 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -144,7 +144,7 @@ enum xlog_iclog_state {
#define XLOG_COVER_OPS 5
-typedef struct xlog_ticket {
+struct xlog_ticket {
struct list_head t_queue; /* reserve/write queue */
struct task_struct *t_task; /* task that owns this ticket */
xlog_tid_t t_tid; /* transaction identifier */
@@ -155,7 +155,7 @@ typedef struct xlog_ticket {
char t_cnt; /* current unit count */
uint8_t t_flags; /* properties of reservation */
int t_iclog_hdrs; /* iclog hdrs in t_curr_res */
-} xlog_ticket_t;
+};
/*
* - A log record header is 512 bytes. There is plenty of room to grow the
--
2.47.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH 1/8] xfs: use xfs_trans_reserve_more in xfs_trans_reserve_more_inode
2025-07-15 12:25 ` [PATCH 1/8] xfs: use xfs_trans_reserve_more in xfs_trans_reserve_more_inode Christoph Hellwig
@ 2025-07-15 14:47 ` Darrick J. Wong
0 siblings, 0 replies; 22+ messages in thread
From: Darrick J. Wong @ 2025-07-15 14:47 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-xfs
On Tue, Jul 15, 2025 at 02:25:34PM +0200, Christoph Hellwig wrote:
> Instead of duplicating the empty transacaction reservation
> definition.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Nice cleanup
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
--D
> ---
> fs/xfs/xfs_trans.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index b4a07af513ba..8b15bfe68774 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -1163,14 +1163,13 @@ xfs_trans_reserve_more_inode(
> unsigned int rblocks,
> bool force_quota)
> {
> - struct xfs_trans_res resv = { };
> struct xfs_mount *mp = ip->i_mount;
> unsigned int rtx = xfs_extlen_to_rtxlen(mp, rblocks);
> int error;
>
> xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);
>
> - error = xfs_trans_reserve(tp, &resv, dblocks, rtx);
> + error = xfs_trans_reserve_more(tp, dblocks, rtx);
> if (error)
> return error;
>
> --
> 2.47.2
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 2/8] xfs: don't use xfs_trans_reserve in xfs_trans_reserve_more
2025-07-15 12:25 ` [PATCH 2/8] xfs: don't use xfs_trans_reserve in xfs_trans_reserve_more Christoph Hellwig
@ 2025-07-15 14:49 ` Darrick J. Wong
2025-07-15 15:35 ` Christoph Hellwig
0 siblings, 1 reply; 22+ messages in thread
From: Darrick J. Wong @ 2025-07-15 14:49 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-xfs
On Tue, Jul 15, 2025 at 02:25:35PM +0200, Christoph Hellwig wrote:
> xfs_trans_reserve_more just tries to allocate additional blocks and/or
> rtextents and is otherwise unrelated to the transaction reservation
> logic. Open code the block and rtextent reservation in
> xfs_trans_reserve_more to prepare for simplifying xfs_trans_reserve.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> fs/xfs/xfs_trans.c | 15 ++++++++++++---
> 1 file changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index 8b15bfe68774..1fddea8d761a 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -1146,9 +1146,18 @@ xfs_trans_reserve_more(
> unsigned int blocks,
> unsigned int rtextents)
> {
> - struct xfs_trans_res resv = { };
> -
> - return xfs_trans_reserve(tp, &resv, blocks, rtextents);
> + bool rsvd = tp->t_flags & XFS_TRANS_RESERVE;
> +
> + if (blocks && xfs_dec_fdblocks(tp->t_mountp, blocks, rsvd))
> + return -ENOSPC;
> + if (rtextents && xfs_dec_frextents(tp->t_mountp, rtextents) < 0) {
xfs_dec_frextents is checked for a negative return value, then why isn't
xfs_dec_fdblocks given the same treatment? Or, since IIRC both return 0
or -ENOSPC you could omit the "< 0" ?
I like how this eliminates the pointless empty resv object though.
--D
> + if (blocks)
> + xfs_add_fdblocks(tp->t_mountp, blocks);
> + return -ENOSPC;
> + }
> + tp->t_blk_res += blocks;
> + tp->t_rtx_res += rtextents;
> + return 0;
> }
>
> /*
> --
> 2.47.2
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 3/8] xfs: decouple xfs_trans_alloc_empty from xfs_trans_alloc
2025-07-15 12:25 ` [PATCH 3/8] xfs: decouple xfs_trans_alloc_empty from xfs_trans_alloc Christoph Hellwig
@ 2025-07-15 14:54 ` Darrick J. Wong
0 siblings, 0 replies; 22+ messages in thread
From: Darrick J. Wong @ 2025-07-15 14:54 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-xfs
On Tue, Jul 15, 2025 at 02:25:36PM +0200, Christoph Hellwig wrote:
> xfs_trans_alloc_empty only shares the very basic transaction structure
> allocation and initialization with xfs_trans_alloc.
>
> Split out a new __xfs_trans_alloc helper for that and otherwise decouple
> xfs_trans_alloc_empty from xfs_trans_alloc.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
That makes sense, especially because all the _empty callsites become so
much cleaner later on...
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
--D
> ---
> fs/xfs/xfs_trans.c | 52 +++++++++++++++++++++++++---------------------
> 1 file changed, 28 insertions(+), 24 deletions(-)
>
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index 1fddea8d761a..e43f44f62c5f 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -241,6 +241,28 @@ xfs_trans_reserve(
> return error;
> }
>
> +static struct xfs_trans *
> +__xfs_trans_alloc(
> + struct xfs_mount *mp,
> + uint flags)
> +{
> + struct xfs_trans *tp;
> +
> + ASSERT(!(flags & XFS_TRANS_RES_FDBLKS) || xfs_has_lazysbcount(mp));
> +
> + tp = kmem_cache_zalloc(xfs_trans_cache, GFP_KERNEL | __GFP_NOFAIL);
> + if (!(flags & XFS_TRANS_NO_WRITECOUNT))
> + sb_start_intwrite(mp->m_super);
> + xfs_trans_set_context(tp);
> + tp->t_flags = flags;
> + tp->t_mountp = mp;
> + INIT_LIST_HEAD(&tp->t_items);
> + INIT_LIST_HEAD(&tp->t_busy);
> + INIT_LIST_HEAD(&tp->t_dfops);
> + tp->t_highest_agno = NULLAGNUMBER;
> + return tp;
> +}
> +
> int
> xfs_trans_alloc(
> struct xfs_mount *mp,
> @@ -254,33 +276,16 @@ xfs_trans_alloc(
> bool want_retry = true;
> int error;
>
> + ASSERT(resp->tr_logres > 0);
> +
> /*
> * Allocate the handle before we do our freeze accounting and setting up
> * GFP_NOFS allocation context so that we avoid lockdep false positives
> * by doing GFP_KERNEL allocations inside sb_start_intwrite().
> */
> retry:
> - tp = kmem_cache_zalloc(xfs_trans_cache, GFP_KERNEL | __GFP_NOFAIL);
> - if (!(flags & XFS_TRANS_NO_WRITECOUNT))
> - sb_start_intwrite(mp->m_super);
> - xfs_trans_set_context(tp);
> -
> - /*
> - * Zero-reservation ("empty") transactions can't modify anything, so
> - * they're allowed to run while we're frozen.
> - */
> - WARN_ON(resp->tr_logres > 0 &&
> - mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE);
> - ASSERT(!(flags & XFS_TRANS_RES_FDBLKS) ||
> - xfs_has_lazysbcount(mp));
> -
> - tp->t_flags = flags;
> - tp->t_mountp = mp;
> - INIT_LIST_HEAD(&tp->t_items);
> - INIT_LIST_HEAD(&tp->t_busy);
> - INIT_LIST_HEAD(&tp->t_dfops);
> - tp->t_highest_agno = NULLAGNUMBER;
> -
> + WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE);
> + tp = __xfs_trans_alloc(mp, flags);
> error = xfs_trans_reserve(tp, resp, blocks, rtextents);
> if (error == -ENOSPC && want_retry) {
> xfs_trans_cancel(tp);
> @@ -329,9 +334,8 @@ xfs_trans_alloc_empty(
> struct xfs_mount *mp,
> struct xfs_trans **tpp)
> {
> - struct xfs_trans_res resv = {0};
> -
> - return xfs_trans_alloc(mp, &resv, 0, 0, XFS_TRANS_NO_WRITECOUNT, tpp);
> + *tpp = __xfs_trans_alloc(mp, XFS_TRANS_NO_WRITECOUNT);
> + return 0;
> }
>
> /*
> --
> 2.47.2
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 4/8] xfs: don't use xfs_trans_reserve in xfs_trans_roll
2025-07-15 12:25 ` [PATCH 4/8] xfs: don't use xfs_trans_reserve in xfs_trans_roll Christoph Hellwig
@ 2025-07-15 14:59 ` Darrick J. Wong
0 siblings, 0 replies; 22+ messages in thread
From: Darrick J. Wong @ 2025-07-15 14:59 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-xfs
On Tue, Jul 15, 2025 at 02:25:37PM +0200, Christoph Hellwig wrote:
> xfs_trans_roll uses xfs_trans_reserve to basically just call into
> xfs_log_regrant while bypassing the reset of xfs_trans_reserve.
>
> Open code the call to xfs_log_regrant in xfs_trans_roll and simplify
> xfs_trans_reserve now that it never regrants and always asks for a log
> reservation.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> fs/xfs/xfs_trans.c | 122 +++++++++++++++++++--------------------------
> 1 file changed, 51 insertions(+), 71 deletions(-)
>
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index e43f44f62c5f..553128b7f86a 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -134,18 +134,14 @@ xfs_trans_dup(
> }
>
> /*
> - * This is called to reserve free disk blocks and log space for the
> - * given transaction. This must be done before allocating any resources
> - * within the transaction.
> + * This is called to reserve free disk blocks and log space for the given
> + * transaction before allocating any resources within the transaction.
> *
> * This will return ENOSPC if there are not enough blocks available.
> * It will sleep waiting for available log space.
> - * The only valid value for the flags parameter is XFS_RES_LOG_PERM, which
> - * is used by long running transactions. If any one of the reservations
> - * fails then they will all be backed out.
> *
> - * This does not do quota reservations. That typically is done by the
> - * caller afterwards.
> + * This does not do quota reservations. That typically is done by the caller
> + * afterwards.
> */
> static int
> xfs_trans_reserve(
> @@ -158,10 +154,12 @@ xfs_trans_reserve(
> int error = 0;
> bool rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
>
> + ASSERT(resp->tr_logres > 0);
> +
> /*
> - * Attempt to reserve the needed disk blocks by decrementing
> - * the number needed from the number available. This will
> - * fail if the count would go below zero.
> + * Attempt to reserve the needed disk blocks by decrementing the number
> + * needed from the number available. This will fail if the count would
> + * go below zero.
> */
> if (blocks > 0) {
> error = xfs_dec_fdblocks(mp, blocks, rsvd);
> @@ -173,42 +171,20 @@ xfs_trans_reserve(
> /*
> * Reserve the log space needed for this transaction.
> */
> - if (resp->tr_logres > 0) {
> - bool permanent = false;
> -
> - ASSERT(tp->t_log_res == 0 ||
> - tp->t_log_res == resp->tr_logres);
> - ASSERT(tp->t_log_count == 0 ||
> - tp->t_log_count == resp->tr_logcount);
> -
> - if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES) {
> - tp->t_flags |= XFS_TRANS_PERM_LOG_RES;
> - permanent = true;
> - } else {
> - ASSERT(tp->t_ticket == NULL);
> - ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES));
> - }
> -
> - if (tp->t_ticket != NULL) {
> - ASSERT(resp->tr_logflags & XFS_TRANS_PERM_LOG_RES);
> - error = xfs_log_regrant(mp, tp->t_ticket);
> - } else {
> - error = xfs_log_reserve(mp, resp->tr_logres,
> - resp->tr_logcount,
> - &tp->t_ticket, permanent);
> - }
> -
> - if (error)
> - goto undo_blocks;
> + if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES)
> + tp->t_flags |= XFS_TRANS_PERM_LOG_RES;
> + error = xfs_log_reserve(mp, resp->tr_logres, resp->tr_logcount,
> + &tp->t_ticket, (tp->t_flags & XFS_TRANS_PERM_LOG_RES));
> + if (error)
> + goto undo_blocks;
>
> - tp->t_log_res = resp->tr_logres;
> - tp->t_log_count = resp->tr_logcount;
> - }
> + tp->t_log_res = resp->tr_logres;
> + tp->t_log_count = resp->tr_logcount;
>
> /*
> - * Attempt to reserve the needed realtime extents by decrementing
> - * the number needed from the number available. This will
> - * fail if the count would go below zero.
> + * Attempt to reserve the needed realtime extents by decrementing the
> + * number needed from the number available. This will fail if the
> + * count would go below zero.
> */
> if (rtextents > 0) {
> error = xfs_dec_frextents(mp, rtextents);
> @@ -221,18 +197,11 @@ xfs_trans_reserve(
>
> return 0;
>
> - /*
> - * Error cases jump to one of these labels to undo any
> - * reservations which have already been performed.
> - */
> undo_log:
> - if (resp->tr_logres > 0) {
> - xfs_log_ticket_ungrant(mp->m_log, tp->t_ticket);
> - tp->t_ticket = NULL;
> - tp->t_log_res = 0;
> - tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES;
> - }
> -
> + xfs_log_ticket_ungrant(mp->m_log, tp->t_ticket);
> + tp->t_ticket = NULL;
> + tp->t_log_res = 0;
> + tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES;
> undo_blocks:
> if (blocks > 0) {
> xfs_add_fdblocks(mp, blocks);
> @@ -1030,36 +999,41 @@ xfs_trans_cancel(
> }
>
> /*
> - * Roll from one trans in the sequence of PERMANENT transactions to
> - * the next: permanent transactions are only flushed out when
> - * committed with xfs_trans_commit(), but we still want as soon
> - * as possible to let chunks of it go to the log. So we commit the
> - * chunk we've been working on and get a new transaction to continue.
> + * Roll from one trans in the sequence of PERMANENT transactions to the next:
> + * permanent transactions are only flushed out when committed with
> + * xfs_trans_commit(), but we still want as soon as possible to let chunks of it
> + * go to the log. So we commit the chunk we've been working on and get a new
> + * transaction to continue.
> */
> int
> xfs_trans_roll(
> struct xfs_trans **tpp)
> {
> struct xfs_trans *trans = *tpp;
> + struct xfs_mount *mp = trans->t_mountp;
> struct xfs_trans_res tres;
> int error;
>
> trace_xfs_trans_roll(trans, _RET_IP_);
>
> + ASSERT(trans->t_log_res > 0);
> +
> /*
> * Copy the critical parameters from one trans to the next.
> */
> tres.tr_logres = trans->t_log_res;
> tres.tr_logcount = trans->t_log_count;
> + tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
As a dumb optimization, you could initialize tres at declaration time
instead of down here.
Other than that minor nitpicking, this does make it easier for me to
figure out what xfs_trans_roll does because now I don't have to go
picking through the _reserve logic so on those grounds
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
--D
>
> *tpp = xfs_trans_dup(trans);
>
> /*
> * Commit the current transaction.
> - * If this commit failed, then it'd just unlock those items that
> - * are not marked ihold. That also means that a filesystem shutdown
> - * is in progress. The caller takes the responsibility to cancel
> - * the duplicate transaction that gets returned.
> + *
> + * If this commit failed, then it'd just unlock those items that are not
> + * marked ihold. That also means that a filesystem shutdown is in
> + * progress. The caller takes the responsibility to cancel the
> + * duplicate transaction that gets returned.
> */
> error = __xfs_trans_commit(trans, true);
> if (error)
> @@ -1067,14 +1041,20 @@ xfs_trans_roll(
>
> /*
> * Reserve space in the log for the next transaction.
> - * This also pushes items in the "AIL", the list of logged items,
> - * out to disk if they are taking up space at the tail of the log
> - * that we want to use. This requires that either nothing be locked
> - * across this call, or that anything that is locked be logged in
> - * the prior and the next transactions.
> + *
> + * This also pushes items in the AIL out to disk if they are taking up
> + * space at the tail of the log that we want to use. This requires that
> + * either nothing be locked across this call, or that anything that is
> + * locked be logged in the prior and the next transactions.
> */
> - tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
> - return xfs_trans_reserve(*tpp, &tres, 0, 0);
> + trans = *tpp;
> + trans->t_flags |= XFS_TRANS_PERM_LOG_RES;
> + error = xfs_log_regrant(mp, trans->t_ticket);
> + if (error)
> + return error;
> + trans->t_log_res = tres.tr_logres;
> + trans->t_log_count = tres.tr_logcount;
> + return 0;
> }
>
> /*
> --
> 2.47.2
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 5/8] xfs: return the allocated transaction from xfs_trans_alloc_empty
2025-07-15 12:25 ` [PATCH 5/8] xfs: return the allocated transaction from xfs_trans_alloc_empty Christoph Hellwig
@ 2025-07-15 14:59 ` Darrick J. Wong
0 siblings, 0 replies; 22+ messages in thread
From: Darrick J. Wong @ 2025-07-15 14:59 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-xfs
On Tue, Jul 15, 2025 at 02:25:38PM +0200, Christoph Hellwig wrote:
> xfs_trans_alloc_empty can't return errors, so return the allocated
> transaction directly instead of an output double pointer argument.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> fs/xfs/libxfs/xfs_refcount.c | 4 +---
> fs/xfs/scrub/common.c | 3 ++-
> fs/xfs/scrub/repair.c | 12 ++----------
> fs/xfs/scrub/scrub.c | 5 +----
> fs/xfs/xfs_attr_item.c | 5 +----
> fs/xfs/xfs_discard.c | 12 +++---------
> fs/xfs/xfs_fsmap.c | 4 +---
> fs/xfs/xfs_icache.c | 5 +----
> fs/xfs/xfs_inode.c | 5 +----
> fs/xfs/xfs_itable.c | 18 +++---------------
> fs/xfs/xfs_iwalk.c | 11 +++--------
> fs/xfs/xfs_notify_failure.c | 5 +----
> fs/xfs/xfs_qm.c | 10 ++--------
> fs/xfs/xfs_rtalloc.c | 13 +++----------
> fs/xfs/xfs_trans.c | 8 +++-----
> fs/xfs/xfs_trans.h | 3 +--
> fs/xfs/xfs_zone_gc.c | 5 +----
> 17 files changed, 30 insertions(+), 98 deletions(-)
Yaaaaaay,
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
--D
>
> diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c
> index cebe83f7842a..897784037483 100644
> --- a/fs/xfs/libxfs/xfs_refcount.c
> +++ b/fs/xfs/libxfs/xfs_refcount.c
> @@ -2099,9 +2099,7 @@ xfs_refcount_recover_cow_leftovers(
> * recording the CoW debris we cancel the (empty) transaction
> * and everything goes away cleanly.
> */
> - error = xfs_trans_alloc_empty(mp, &tp);
> - if (error)
> - return error;
> + tp = xfs_trans_alloc_empty(mp);
>
> if (isrt) {
> xfs_rtgroup_lock(to_rtg(xg), XFS_RTGLOCK_REFCOUNT);
> diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c
> index 28ad341df8ee..d080f4e6e9d8 100644
> --- a/fs/xfs/scrub/common.c
> +++ b/fs/xfs/scrub/common.c
> @@ -870,7 +870,8 @@ int
> xchk_trans_alloc_empty(
> struct xfs_scrub *sc)
> {
> - return xfs_trans_alloc_empty(sc->mp, &sc->tp);
> + sc->tp = xfs_trans_alloc_empty(sc->mp);
> + return 0;
> }
>
> /*
> diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c
> index f8f9ed30f56b..f7f80ff32afc 100644
> --- a/fs/xfs/scrub/repair.c
> +++ b/fs/xfs/scrub/repair.c
> @@ -1279,18 +1279,10 @@ xrep_trans_alloc_hook_dummy(
> void **cookiep,
> struct xfs_trans **tpp)
> {
> - int error;
> -
> *cookiep = current->journal_info;
> current->journal_info = NULL;
> -
> - error = xfs_trans_alloc_empty(mp, tpp);
> - if (!error)
> - return 0;
> -
> - current->journal_info = *cookiep;
> - *cookiep = NULL;
> - return error;
> + *tpp = xfs_trans_alloc_empty(mp);
> + return 0;
> }
>
> /* Cancel a dummy transaction used by a live update hook function. */
> diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c
> index 76e24032e99a..3c3b0d25006f 100644
> --- a/fs/xfs/scrub/scrub.c
> +++ b/fs/xfs/scrub/scrub.c
> @@ -876,10 +876,7 @@ xchk_scrubv_open_by_handle(
> struct xfs_inode *ip;
> int error;
>
> - error = xfs_trans_alloc_empty(mp, &tp);
> - if (error)
> - return NULL;
> -
> + tp = xfs_trans_alloc_empty(mp);
> error = xfs_iget(mp, tp, head->svh_ino, XCHK_IGET_FLAGS, 0, &ip);
> xfs_trans_cancel(tp);
> if (error)
> diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c
> index f683b7a9323f..da1e11f38eb0 100644
> --- a/fs/xfs/xfs_attr_item.c
> +++ b/fs/xfs/xfs_attr_item.c
> @@ -616,10 +616,7 @@ xfs_attri_iread_extents(
> struct xfs_trans *tp;
> int error;
>
> - error = xfs_trans_alloc_empty(ip->i_mount, &tp);
> - if (error)
> - return error;
> -
> + tp = xfs_trans_alloc_empty(ip->i_mount);
> xfs_ilock(ip, XFS_ILOCK_EXCL);
> error = xfs_iread_extents(tp, ip, XFS_ATTR_FORK);
> xfs_iunlock(ip, XFS_ILOCK_EXCL);
> diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c
> index 603d51365645..ee49f20875af 100644
> --- a/fs/xfs/xfs_discard.c
> +++ b/fs/xfs/xfs_discard.c
> @@ -189,9 +189,7 @@ xfs_trim_gather_extents(
> */
> xfs_log_force(mp, XFS_LOG_SYNC);
>
> - error = xfs_trans_alloc_empty(mp, &tp);
> - if (error)
> - return error;
> + tp = xfs_trans_alloc_empty(mp);
>
> error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
> if (error)
> @@ -583,9 +581,7 @@ xfs_trim_rtextents(
> struct xfs_trans *tp;
> int error;
>
> - error = xfs_trans_alloc_empty(mp, &tp);
> - if (error)
> - return error;
> + tp = xfs_trans_alloc_empty(mp);
>
> /*
> * Walk the free ranges between low and high. The query_range function
> @@ -701,9 +697,7 @@ xfs_trim_rtgroup_extents(
> struct xfs_trans *tp;
> int error;
>
> - error = xfs_trans_alloc_empty(mp, &tp);
> - if (error)
> - return error;
> + tp = xfs_trans_alloc_empty(mp);
>
> /*
> * Walk the free ranges between low and high. The query_range function
> diff --git a/fs/xfs/xfs_fsmap.c b/fs/xfs/xfs_fsmap.c
> index 414b27a86458..af68c7de8ee8 100644
> --- a/fs/xfs/xfs_fsmap.c
> +++ b/fs/xfs/xfs_fsmap.c
> @@ -1270,9 +1270,7 @@ xfs_getfsmap(
> * buffer locking abilities to detect cycles in the rmapbt
> * without deadlocking.
> */
> - error = xfs_trans_alloc_empty(mp, &tp);
> - if (error)
> - break;
> + tp = xfs_trans_alloc_empty(mp);
>
> info.dev = handlers[i].dev;
> info.last = false;
> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> index bbc2f2973dcc..4cf7abe50143 100644
> --- a/fs/xfs/xfs_icache.c
> +++ b/fs/xfs/xfs_icache.c
> @@ -893,10 +893,7 @@ xfs_metafile_iget(
> struct xfs_trans *tp;
> int error;
>
> - error = xfs_trans_alloc_empty(mp, &tp);
> - if (error)
> - return error;
> -
> + tp = xfs_trans_alloc_empty(mp);
> error = xfs_trans_metafile_iget(tp, ino, metafile_type, ipp);
> xfs_trans_cancel(tp);
> return error;
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 761a996a857c..4264f8c92e53 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -2934,10 +2934,7 @@ xfs_inode_reload_unlinked(
> struct xfs_trans *tp;
> int error;
>
> - error = xfs_trans_alloc_empty(ip->i_mount, &tp);
> - if (error)
> - return error;
> -
> + tp = xfs_trans_alloc_empty(ip->i_mount);
> xfs_ilock(ip, XFS_ILOCK_SHARED);
> if (xfs_inode_unlinked_incomplete(ip))
> error = xfs_inode_reload_unlinked_bucket(tp, ip);
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index 1fa1c0564b0c..c8c9b8d8309f 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
> @@ -239,14 +239,10 @@ xfs_bulkstat_one(
> * Grab an empty transaction so that we can use its recursive buffer
> * locking abilities to detect cycles in the inobt without deadlocking.
> */
> - error = xfs_trans_alloc_empty(breq->mp, &tp);
> - if (error)
> - goto out;
> -
> + tp = xfs_trans_alloc_empty(breq->mp);
> error = xfs_bulkstat_one_int(breq->mp, breq->idmap, tp,
> breq->startino, &bc);
> xfs_trans_cancel(tp);
> -out:
> kfree(bc.buf);
>
> /*
> @@ -331,17 +327,13 @@ xfs_bulkstat(
> * Grab an empty transaction so that we can use its recursive buffer
> * locking abilities to detect cycles in the inobt without deadlocking.
> */
> - error = xfs_trans_alloc_empty(breq->mp, &tp);
> - if (error)
> - goto out;
> -
> + tp = xfs_trans_alloc_empty(breq->mp);
> if (breq->flags & XFS_IBULK_SAME_AG)
> iwalk_flags |= XFS_IWALK_SAME_AG;
>
> error = xfs_iwalk(breq->mp, tp, breq->startino, iwalk_flags,
> xfs_bulkstat_iwalk, breq->icount, &bc);
> xfs_trans_cancel(tp);
> -out:
> kfree(bc.buf);
>
> /*
> @@ -464,14 +456,10 @@ xfs_inumbers(
> * Grab an empty transaction so that we can use its recursive buffer
> * locking abilities to detect cycles in the inobt without deadlocking.
> */
> - error = xfs_trans_alloc_empty(breq->mp, &tp);
> - if (error)
> - goto out;
> -
> + tp = xfs_trans_alloc_empty(breq->mp);
> error = xfs_inobt_walk(breq->mp, tp, breq->startino, breq->flags,
> xfs_inumbers_walk, breq->icount, &ic);
> xfs_trans_cancel(tp);
> -out:
>
> /*
> * We found some inode groups, so clear the error status and return
> diff --git a/fs/xfs/xfs_iwalk.c b/fs/xfs/xfs_iwalk.c
> index 7db3ece370b1..c1c31d1a8e21 100644
> --- a/fs/xfs/xfs_iwalk.c
> +++ b/fs/xfs/xfs_iwalk.c
> @@ -377,11 +377,8 @@ xfs_iwalk_run_callbacks(
> if (!has_more)
> return 0;
>
> - if (iwag->drop_trans) {
> - error = xfs_trans_alloc_empty(mp, &iwag->tp);
> - if (error)
> - return error;
> - }
> + if (iwag->drop_trans)
> + iwag->tp = xfs_trans_alloc_empty(mp);
>
> /* ...and recreate the cursor just past where we left off. */
> error = xfs_ialloc_read_agi(iwag->pag, iwag->tp, 0, agi_bpp);
> @@ -617,9 +614,7 @@ xfs_iwalk_ag_work(
> * Grab an empty transaction so that we can use its recursive buffer
> * locking abilities to detect cycles in the inobt without deadlocking.
> */
> - error = xfs_trans_alloc_empty(mp, &iwag->tp);
> - if (error)
> - goto out;
> + iwag->tp = xfs_trans_alloc_empty(mp);
> iwag->drop_trans = 1;
>
> error = xfs_iwalk_ag(iwag);
> diff --git a/fs/xfs/xfs_notify_failure.c b/fs/xfs/xfs_notify_failure.c
> index 42e9c72b85c0..fbd521f89874 100644
> --- a/fs/xfs/xfs_notify_failure.c
> +++ b/fs/xfs/xfs_notify_failure.c
> @@ -279,10 +279,7 @@ xfs_dax_notify_dev_failure(
> kernel_frozen = xfs_dax_notify_failure_freeze(mp) == 0;
> }
>
> - error = xfs_trans_alloc_empty(mp, &tp);
> - if (error)
> - goto out;
> -
> + tp = xfs_trans_alloc_empty(mp);
> start_gno = xfs_fsb_to_gno(mp, start_bno, type);
> end_gno = xfs_fsb_to_gno(mp, end_bno, type);
> while ((xg = xfs_group_next_range(mp, xg, start_gno, end_gno, type))) {
> diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
> index fa135ac26471..23ba84ec919a 100644
> --- a/fs/xfs/xfs_qm.c
> +++ b/fs/xfs/xfs_qm.c
> @@ -660,10 +660,7 @@ xfs_qm_load_metadir_qinos(
> struct xfs_trans *tp;
> int error;
>
> - error = xfs_trans_alloc_empty(mp, &tp);
> - if (error)
> - return error;
> -
> + tp = xfs_trans_alloc_empty(mp);
> error = xfs_dqinode_load_parent(tp, &qi->qi_dirip);
> if (error == -ENOENT) {
> /* no quota dir directory, but we'll create one later */
> @@ -1755,10 +1752,7 @@ xfs_qm_qino_load(
> struct xfs_inode *dp = NULL;
> int error;
>
> - error = xfs_trans_alloc_empty(mp, &tp);
> - if (error)
> - return error;
> -
> + tp = xfs_trans_alloc_empty(mp);
> if (xfs_has_metadir(mp)) {
> error = xfs_dqinode_load_parent(tp, &dp);
> if (error)
> diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
> index 736eb0924573..6907e871fa15 100644
> --- a/fs/xfs/xfs_rtalloc.c
> +++ b/fs/xfs/xfs_rtalloc.c
> @@ -729,9 +729,7 @@ xfs_rtginode_ensure(
> if (rtg->rtg_inodes[type])
> return 0;
>
> - error = xfs_trans_alloc_empty(rtg_mount(rtg), &tp);
> - if (error)
> - return error;
> + tp = xfs_trans_alloc_empty(rtg_mount(rtg));
> error = xfs_rtginode_load(rtg, type, tp);
> xfs_trans_cancel(tp);
>
> @@ -1305,9 +1303,7 @@ xfs_growfs_rt_prep_groups(
> if (!mp->m_rtdirip) {
> struct xfs_trans *tp;
>
> - error = xfs_trans_alloc_empty(mp, &tp);
> - if (error)
> - return error;
> + tp = xfs_trans_alloc_empty(mp);
> error = xfs_rtginode_load_parent(tp);
> xfs_trans_cancel(tp);
>
> @@ -1674,10 +1670,7 @@ xfs_rtmount_inodes(
> struct xfs_rtgroup *rtg = NULL;
> int error;
>
> - error = xfs_trans_alloc_empty(mp, &tp);
> - if (error)
> - return error;
> -
> + tp = xfs_trans_alloc_empty(mp);
> if (xfs_has_rtgroups(mp) && mp->m_sb.sb_rgcount > 0) {
> error = xfs_rtginode_load_parent(tp);
> if (error)
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index 553128b7f86a..dc7199c81a78 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -298,13 +298,11 @@ xfs_trans_alloc(
> * where we can be grabbing buffers at the same time that freeze is trying to
> * drain the buffer LRU list.
> */
> -int
> +struct xfs_trans *
> xfs_trans_alloc_empty(
> - struct xfs_mount *mp,
> - struct xfs_trans **tpp)
> + struct xfs_mount *mp)
> {
> - *tpp = __xfs_trans_alloc(mp, XFS_TRANS_NO_WRITECOUNT);
> - return 0;
> + return __xfs_trans_alloc(mp, XFS_TRANS_NO_WRITECOUNT);
> }
>
> /*
> diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> index 2b366851e9a4..a6b10aaeb1f1 100644
> --- a/fs/xfs/xfs_trans.h
> +++ b/fs/xfs/xfs_trans.h
> @@ -168,8 +168,7 @@ int xfs_trans_alloc(struct xfs_mount *mp, struct xfs_trans_res *resp,
> struct xfs_trans **tpp);
> int xfs_trans_reserve_more(struct xfs_trans *tp,
> unsigned int blocks, unsigned int rtextents);
> -int xfs_trans_alloc_empty(struct xfs_mount *mp,
> - struct xfs_trans **tpp);
> +struct xfs_trans *xfs_trans_alloc_empty(struct xfs_mount *mp);
> void xfs_trans_mod_sb(xfs_trans_t *, uint, int64_t);
>
> int xfs_trans_get_buf_map(struct xfs_trans *tp, struct xfs_buftarg *target,
> diff --git a/fs/xfs/xfs_zone_gc.c b/fs/xfs/xfs_zone_gc.c
> index 9c00fc5baa30..e1954b0e6021 100644
> --- a/fs/xfs/xfs_zone_gc.c
> +++ b/fs/xfs/xfs_zone_gc.c
> @@ -328,10 +328,7 @@ xfs_zone_gc_query(
> iter->rec_idx = 0;
> iter->rec_count = 0;
>
> - error = xfs_trans_alloc_empty(mp, &tp);
> - if (error)
> - return error;
> -
> + tp = xfs_trans_alloc_empty(mp);
> xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP);
> cur = xfs_rtrmapbt_init_cursor(tp, rtg);
> error = xfs_rmap_query_range(cur, &ri_low, &ri_high,
> --
> 2.47.2
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 6/8] xfs: return the allocated transaction from xchk_trans_alloc_empty
2025-07-15 12:25 ` [PATCH 6/8] xfs: return the allocated transaction from xchk_trans_alloc_empty Christoph Hellwig
@ 2025-07-15 14:59 ` Darrick J. Wong
0 siblings, 0 replies; 22+ messages in thread
From: Darrick J. Wong @ 2025-07-15 14:59 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-xfs
On Tue, Jul 15, 2025 at 02:25:39PM +0200, Christoph Hellwig wrote:
> xchk_trans_alloc_empty can't return errors, so return the allocated
> transaction directly instead of an output double pointer argument.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> fs/xfs/scrub/common.c | 6 +++---
> fs/xfs/scrub/common.h | 2 +-
> fs/xfs/scrub/dir_repair.c | 8 ++------
> fs/xfs/scrub/fscounters.c | 3 ++-
> fs/xfs/scrub/metapath.c | 4 +---
> fs/xfs/scrub/nlinks.c | 8 ++------
> fs/xfs/scrub/nlinks_repair.c | 4 +---
> fs/xfs/scrub/parent_repair.c | 12 +++---------
> fs/xfs/scrub/quotacheck.c | 4 +---
> fs/xfs/scrub/rmap_repair.c | 4 +---
> fs/xfs/scrub/rtrmap_repair.c | 4 +---
> 11 files changed, 18 insertions(+), 41 deletions(-)
Moar yaaaay,
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
--D
>
> diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c
> index d080f4e6e9d8..2ef7742be7d3 100644
> --- a/fs/xfs/scrub/common.c
> +++ b/fs/xfs/scrub/common.c
> @@ -866,12 +866,11 @@ xchk_trans_cancel(
> sc->tp = NULL;
> }
>
> -int
> +void
> xchk_trans_alloc_empty(
> struct xfs_scrub *sc)
> {
> sc->tp = xfs_trans_alloc_empty(sc->mp);
> - return 0;
> }
>
> /*
> @@ -893,7 +892,8 @@ xchk_trans_alloc(
> return xfs_trans_alloc(sc->mp, &M_RES(sc->mp)->tr_itruncate,
> resblks, 0, 0, &sc->tp);
>
> - return xchk_trans_alloc_empty(sc);
> + xchk_trans_alloc_empty(sc);
> + return 0;
> }
>
> /* Set us up with a transaction and an empty context. */
> diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h
> index 19877d99f255..ddbc065c798c 100644
> --- a/fs/xfs/scrub/common.h
> +++ b/fs/xfs/scrub/common.h
> @@ -7,7 +7,7 @@
> #define __XFS_SCRUB_COMMON_H__
>
> int xchk_trans_alloc(struct xfs_scrub *sc, uint resblks);
> -int xchk_trans_alloc_empty(struct xfs_scrub *sc);
> +void xchk_trans_alloc_empty(struct xfs_scrub *sc);
> void xchk_trans_cancel(struct xfs_scrub *sc);
>
> bool xchk_process_error(struct xfs_scrub *sc, xfs_agnumber_t agno,
> diff --git a/fs/xfs/scrub/dir_repair.c b/fs/xfs/scrub/dir_repair.c
> index 249313882108..8d3b550990b5 100644
> --- a/fs/xfs/scrub/dir_repair.c
> +++ b/fs/xfs/scrub/dir_repair.c
> @@ -1289,9 +1289,7 @@ xrep_dir_scan_dirtree(
> if (sc->ilock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL))
> xchk_iunlock(sc, sc->ilock_flags & (XFS_ILOCK_SHARED |
> XFS_ILOCK_EXCL));
> - error = xchk_trans_alloc_empty(sc);
> - if (error)
> - return error;
> + xchk_trans_alloc_empty(sc);
>
> while ((error = xchk_iscan_iter(&rd->pscan.iscan, &ip)) == 1) {
> bool flush;
> @@ -1317,9 +1315,7 @@ xrep_dir_scan_dirtree(
> if (error)
> break;
>
> - error = xchk_trans_alloc_empty(sc);
> - if (error)
> - break;
> + xchk_trans_alloc_empty(sc);
> }
>
> if (xchk_should_terminate(sc, &error))
> diff --git a/fs/xfs/scrub/fscounters.c b/fs/xfs/scrub/fscounters.c
> index 9b598c5790ad..cebd0d526926 100644
> --- a/fs/xfs/scrub/fscounters.c
> +++ b/fs/xfs/scrub/fscounters.c
> @@ -237,7 +237,8 @@ xchk_setup_fscounters(
> return error;
> }
>
> - return xchk_trans_alloc_empty(sc);
> + xchk_trans_alloc_empty(sc);
> + return 0;
> }
>
> /*
> diff --git a/fs/xfs/scrub/metapath.c b/fs/xfs/scrub/metapath.c
> index e21c16fbd15d..14939d7de349 100644
> --- a/fs/xfs/scrub/metapath.c
> +++ b/fs/xfs/scrub/metapath.c
> @@ -318,9 +318,7 @@ xchk_metapath(
> return 0;
> }
>
> - error = xchk_trans_alloc_empty(sc);
> - if (error)
> - return error;
> + xchk_trans_alloc_empty(sc);
>
> error = xchk_metapath_ilock_both(mpath);
> if (error)
> diff --git a/fs/xfs/scrub/nlinks.c b/fs/xfs/scrub/nlinks.c
> index 4a47d0aabf73..26721fab5cab 100644
> --- a/fs/xfs/scrub/nlinks.c
> +++ b/fs/xfs/scrub/nlinks.c
> @@ -555,9 +555,7 @@ xchk_nlinks_collect(
> * do not take sb_internal.
> */
> xchk_trans_cancel(sc);
> - error = xchk_trans_alloc_empty(sc);
> - if (error)
> - return error;
> + xchk_trans_alloc_empty(sc);
>
> while ((error = xchk_iscan_iter(&xnc->collect_iscan, &ip)) == 1) {
> if (S_ISDIR(VFS_I(ip)->i_mode))
> @@ -880,9 +878,7 @@ xchk_nlinks_compare(
> * inactivation workqueue.
> */
> xchk_trans_cancel(sc);
> - error = xchk_trans_alloc_empty(sc);
> - if (error)
> - return error;
> + xchk_trans_alloc_empty(sc);
>
> /*
> * Use the inobt to walk all allocated inodes to compare the link
> diff --git a/fs/xfs/scrub/nlinks_repair.c b/fs/xfs/scrub/nlinks_repair.c
> index 4ebdee095428..6ef2ee9c3814 100644
> --- a/fs/xfs/scrub/nlinks_repair.c
> +++ b/fs/xfs/scrub/nlinks_repair.c
> @@ -340,9 +340,7 @@ xrep_nlinks(
> * We can only push the inactivation workqueues with an empty
> * transaction.
> */
> - error = xchk_trans_alloc_empty(sc);
> - if (error)
> - break;
> + xchk_trans_alloc_empty(sc);
> }
> xchk_iscan_iter_finish(&xnc->compare_iscan);
> xchk_iscan_teardown(&xnc->compare_iscan);
> diff --git a/fs/xfs/scrub/parent_repair.c b/fs/xfs/scrub/parent_repair.c
> index 31bfe10be22a..2949feda6271 100644
> --- a/fs/xfs/scrub/parent_repair.c
> +++ b/fs/xfs/scrub/parent_repair.c
> @@ -569,9 +569,7 @@ xrep_parent_scan_dirtree(
> if (sc->ilock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL))
> xchk_iunlock(sc, sc->ilock_flags & (XFS_ILOCK_SHARED |
> XFS_ILOCK_EXCL));
> - error = xchk_trans_alloc_empty(sc);
> - if (error)
> - return error;
> + xchk_trans_alloc_empty(sc);
>
> while ((error = xchk_iscan_iter(&rp->pscan.iscan, &ip)) == 1) {
> bool flush;
> @@ -597,9 +595,7 @@ xrep_parent_scan_dirtree(
> if (error)
> break;
>
> - error = xchk_trans_alloc_empty(sc);
> - if (error)
> - break;
> + xchk_trans_alloc_empty(sc);
> }
>
> if (xchk_should_terminate(sc, &error))
> @@ -1099,9 +1095,7 @@ xrep_parent_flush_xattrs(
> xrep_tempfile_iounlock(rp->sc);
>
> /* Recreate the empty transaction and relock the inode. */
> - error = xchk_trans_alloc_empty(rp->sc);
> - if (error)
> - return error;
> + xchk_trans_alloc_empty(rp->sc);
> xchk_ilock(rp->sc, XFS_ILOCK_EXCL);
> return 0;
> }
> diff --git a/fs/xfs/scrub/quotacheck.c b/fs/xfs/scrub/quotacheck.c
> index dc4033b91e44..e4105aaafe84 100644
> --- a/fs/xfs/scrub/quotacheck.c
> +++ b/fs/xfs/scrub/quotacheck.c
> @@ -505,9 +505,7 @@ xqcheck_collect_counts(
> * transactions do not take sb_internal.
> */
> xchk_trans_cancel(sc);
> - error = xchk_trans_alloc_empty(sc);
> - if (error)
> - return error;
> + xchk_trans_alloc_empty(sc);
>
> while ((error = xchk_iscan_iter(&xqc->iscan, &ip)) == 1) {
> error = xqcheck_collect_inode(xqc, ip);
> diff --git a/fs/xfs/scrub/rmap_repair.c b/fs/xfs/scrub/rmap_repair.c
> index f5f73078ffe2..bf1e632b449a 100644
> --- a/fs/xfs/scrub/rmap_repair.c
> +++ b/fs/xfs/scrub/rmap_repair.c
> @@ -951,9 +951,7 @@ xrep_rmap_find_rmaps(
> sa->agf_bp = NULL;
> sa->agi_bp = NULL;
> xchk_trans_cancel(sc);
> - error = xchk_trans_alloc_empty(sc);
> - if (error)
> - return error;
> + xchk_trans_alloc_empty(sc);
>
> /* Iterate all AGs for inodes rmaps. */
> while ((error = xchk_iscan_iter(&rr->iscan, &ip)) == 1) {
> diff --git a/fs/xfs/scrub/rtrmap_repair.c b/fs/xfs/scrub/rtrmap_repair.c
> index fc2592c53af5..4a56726d9952 100644
> --- a/fs/xfs/scrub/rtrmap_repair.c
> +++ b/fs/xfs/scrub/rtrmap_repair.c
> @@ -580,9 +580,7 @@ xrep_rtrmap_find_rmaps(
> */
> xchk_trans_cancel(sc);
> xchk_rtgroup_unlock(&sc->sr);
> - error = xchk_trans_alloc_empty(sc);
> - if (error)
> - return error;
> + xchk_trans_alloc_empty(sc);
>
> while ((error = xchk_iscan_iter(&rr->iscan, &ip)) == 1) {
> error = xrep_rtrmap_scan_inode(rr, ip);
> --
> 2.47.2
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 7/8] xfs: return the allocated transaction from xrep_trans_alloc_hook_dummy
2025-07-15 12:25 ` [PATCH 7/8] xfs: return the allocated transaction from xrep_trans_alloc_hook_dummy Christoph Hellwig
@ 2025-07-15 15:18 ` Darrick J. Wong
2025-07-15 15:36 ` Christoph Hellwig
0 siblings, 1 reply; 22+ messages in thread
From: Darrick J. Wong @ 2025-07-15 15:18 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-xfs
On Tue, Jul 15, 2025 at 02:25:40PM +0200, Christoph Hellwig wrote:
> xrep_trans_alloc_hook_dummy can't return errors, so return the allocated
> transaction directly instead of an output double pointer argument.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> fs/xfs/scrub/repair.c | 8 +++-----
> fs/xfs/scrub/repair.h | 4 ++--
> fs/xfs/scrub/rmap_repair.c | 5 +----
> fs/xfs/scrub/rtrmap_repair.c | 5 +----
> 4 files changed, 7 insertions(+), 15 deletions(-)
>
> diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c
> index f7f80ff32afc..79251c595e18 100644
> --- a/fs/xfs/scrub/repair.c
> +++ b/fs/xfs/scrub/repair.c
> @@ -1273,16 +1273,14 @@ xrep_setup_xfbtree(
> * function MUST NOT be called from regular repair code because the current
> * process' transaction is saved via the cookie.
> */
> -int
> +struct xfs_trans *
> xrep_trans_alloc_hook_dummy(
> struct xfs_mount *mp,
> - void **cookiep,
> - struct xfs_trans **tpp)
> + void **cookiep)
> {
> *cookiep = current->journal_info;
> current->journal_info = NULL;
You could get rid of all this journal_info manipulation because xfs no
longer uses that to track the current transaction.
--D
> - *tpp = xfs_trans_alloc_empty(mp);
> - return 0;
> + return xfs_trans_alloc_empty(mp);
> }
>
> /* Cancel a dummy transaction used by a live update hook function. */
> diff --git a/fs/xfs/scrub/repair.h b/fs/xfs/scrub/repair.h
> index af0a3a9e5ed9..0a808e903cf5 100644
> --- a/fs/xfs/scrub/repair.h
> +++ b/fs/xfs/scrub/repair.h
> @@ -180,8 +180,8 @@ int xrep_quotacheck(struct xfs_scrub *sc);
> int xrep_reinit_pagf(struct xfs_scrub *sc);
> int xrep_reinit_pagi(struct xfs_scrub *sc);
>
> -int xrep_trans_alloc_hook_dummy(struct xfs_mount *mp, void **cookiep,
> - struct xfs_trans **tpp);
> +struct xfs_trans *xrep_trans_alloc_hook_dummy(struct xfs_mount *mp,
> + void **cookiep);
> void xrep_trans_cancel_hook_dummy(void **cookiep, struct xfs_trans *tp);
>
> bool xrep_buf_verify_struct(struct xfs_buf *bp, const struct xfs_buf_ops *ops);
> diff --git a/fs/xfs/scrub/rmap_repair.c b/fs/xfs/scrub/rmap_repair.c
> index bf1e632b449a..6024872a17e5 100644
> --- a/fs/xfs/scrub/rmap_repair.c
> +++ b/fs/xfs/scrub/rmap_repair.c
> @@ -1621,9 +1621,7 @@ xrep_rmapbt_live_update(
>
> trace_xrep_rmap_live_update(pag_group(rr->sc->sa.pag), action, p);
>
> - error = xrep_trans_alloc_hook_dummy(mp, &txcookie, &tp);
> - if (error)
> - goto out_abort;
> + tp = xrep_trans_alloc_hook_dummy(mp, &txcookie);
>
> mutex_lock(&rr->lock);
> mcur = xfs_rmapbt_mem_cursor(rr->sc->sa.pag, tp, &rr->rmap_btree);
> @@ -1644,7 +1642,6 @@ xrep_rmapbt_live_update(
> out_cancel:
> xfbtree_trans_cancel(&rr->rmap_btree, tp);
> xrep_trans_cancel_hook_dummy(&txcookie, tp);
> -out_abort:
> mutex_unlock(&rr->lock);
> xchk_iscan_abort(&rr->iscan);
> out_unlock:
> diff --git a/fs/xfs/scrub/rtrmap_repair.c b/fs/xfs/scrub/rtrmap_repair.c
> index 4a56726d9952..5b8155c87873 100644
> --- a/fs/xfs/scrub/rtrmap_repair.c
> +++ b/fs/xfs/scrub/rtrmap_repair.c
> @@ -855,9 +855,7 @@ xrep_rtrmapbt_live_update(
>
> trace_xrep_rmap_live_update(rtg_group(rr->sc->sr.rtg), action, p);
>
> - error = xrep_trans_alloc_hook_dummy(mp, &txcookie, &tp);
> - if (error)
> - goto out_abort;
> + tp = xrep_trans_alloc_hook_dummy(mp, &txcookie);
>
> mutex_lock(&rr->lock);
> mcur = xfs_rtrmapbt_mem_cursor(rr->sc->sr.rtg, tp, &rr->rtrmap_btree);
> @@ -878,7 +876,6 @@ xrep_rtrmapbt_live_update(
> out_cancel:
> xfbtree_trans_cancel(&rr->rtrmap_btree, tp);
> xrep_trans_cancel_hook_dummy(&txcookie, tp);
> -out_abort:
> xchk_iscan_abort(&rr->iscan);
> mutex_unlock(&rr->lock);
> out_unlock:
> --
> 2.47.2
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 8/8] xfs: remove the xlog_ticket_t typedef
2025-07-15 12:25 ` [PATCH 8/8] xfs: remove the xlog_ticket_t typedef Christoph Hellwig
@ 2025-07-15 15:18 ` Darrick J. Wong
0 siblings, 0 replies; 22+ messages in thread
From: Darrick J. Wong @ 2025-07-15 15:18 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-xfs
On Tue, Jul 15, 2025 at 02:25:41PM +0200, Christoph Hellwig wrote:
> Almost no users of the typedef left, kill it and switch the remaining
> users to use the underlying struct.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Looks good,
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
--D
> ---
> fs/xfs/xfs_log.c | 6 +++---
> fs/xfs/xfs_log_priv.h | 4 ++--
> 2 files changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
> index 793468b4d30d..bc3297da2143 100644
> --- a/fs/xfs/xfs_log.c
> +++ b/fs/xfs/xfs_log.c
> @@ -3092,16 +3092,16 @@ xfs_log_force_seq(
> */
> void
> xfs_log_ticket_put(
> - xlog_ticket_t *ticket)
> + struct xlog_ticket *ticket)
> {
> ASSERT(atomic_read(&ticket->t_ref) > 0);
> if (atomic_dec_and_test(&ticket->t_ref))
> kmem_cache_free(xfs_log_ticket_cache, ticket);
> }
>
> -xlog_ticket_t *
> +struct xlog_ticket *
> xfs_log_ticket_get(
> - xlog_ticket_t *ticket)
> + struct xlog_ticket *ticket)
> {
> ASSERT(atomic_read(&ticket->t_ref) > 0);
> atomic_inc(&ticket->t_ref);
> diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
> index 39a102cc1b43..a9a7a271c15b 100644
> --- a/fs/xfs/xfs_log_priv.h
> +++ b/fs/xfs/xfs_log_priv.h
> @@ -144,7 +144,7 @@ enum xlog_iclog_state {
>
> #define XLOG_COVER_OPS 5
>
> -typedef struct xlog_ticket {
> +struct xlog_ticket {
> struct list_head t_queue; /* reserve/write queue */
> struct task_struct *t_task; /* task that owns this ticket */
> xlog_tid_t t_tid; /* transaction identifier */
> @@ -155,7 +155,7 @@ typedef struct xlog_ticket {
> char t_cnt; /* current unit count */
> uint8_t t_flags; /* properties of reservation */
> int t_iclog_hdrs; /* iclog hdrs in t_curr_res */
> -} xlog_ticket_t;
> +};
>
> /*
> * - A log record header is 512 bytes. There is plenty of room to grow the
> --
> 2.47.2
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 2/8] xfs: don't use xfs_trans_reserve in xfs_trans_reserve_more
2025-07-15 14:49 ` Darrick J. Wong
@ 2025-07-15 15:35 ` Christoph Hellwig
2025-07-15 15:55 ` Darrick J. Wong
0 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2025-07-15 15:35 UTC (permalink / raw)
To: Darrick J. Wong; +Cc: Christoph Hellwig, Carlos Maiolino, linux-xfs
On Tue, Jul 15, 2025 at 07:49:44AM -0700, Darrick J. Wong wrote:
> > + if (blocks && xfs_dec_fdblocks(tp->t_mountp, blocks, rsvd))
> > + return -ENOSPC;
> > + if (rtextents && xfs_dec_frextents(tp->t_mountp, rtextents) < 0) {
>
> xfs_dec_frextents is checked for a negative return value, then why isn't
> xfs_dec_fdblocks given the same treatment? Or, since IIRC both return 0
> or -ENOSPC you could omit the "< 0" ?
No good reason, I'll make sure they use the same scheme. I don't care
which one, so if you prefer the shorter one I'll go for that.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 7/8] xfs: return the allocated transaction from xrep_trans_alloc_hook_dummy
2025-07-15 15:18 ` Darrick J. Wong
@ 2025-07-15 15:36 ` Christoph Hellwig
0 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2025-07-15 15:36 UTC (permalink / raw)
To: Darrick J. Wong; +Cc: Christoph Hellwig, Carlos Maiolino, linux-xfs
On Tue, Jul 15, 2025 at 08:18:11AM -0700, Darrick J. Wong wrote:
> > *cookiep = current->journal_info;
> > current->journal_info = NULL;
>
> You could get rid of all this journal_info manipulation because xfs no
> longer uses that to track the current transaction.
I'll take a look. Probably separately from this series to avoid
scope creep.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 2/8] xfs: don't use xfs_trans_reserve in xfs_trans_reserve_more
2025-07-15 15:35 ` Christoph Hellwig
@ 2025-07-15 15:55 ` Darrick J. Wong
0 siblings, 0 replies; 22+ messages in thread
From: Darrick J. Wong @ 2025-07-15 15:55 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-xfs
On Tue, Jul 15, 2025 at 05:35:00PM +0200, Christoph Hellwig wrote:
> On Tue, Jul 15, 2025 at 07:49:44AM -0700, Darrick J. Wong wrote:
> > > + if (blocks && xfs_dec_fdblocks(tp->t_mountp, blocks, rsvd))
> > > + return -ENOSPC;
> > > + if (rtextents && xfs_dec_frextents(tp->t_mountp, rtextents) < 0) {
> >
> > xfs_dec_frextents is checked for a negative return value, then why isn't
> > xfs_dec_fdblocks given the same treatment? Or, since IIRC both return 0
> > or -ENOSPC you could omit the "< 0" ?
>
> No good reason, I'll make sure they use the same scheme. I don't care
> which one, so if you prefer the shorter one I'll go for that.
I have no particular preference either way.
--D
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 4/8] xfs: don't use xfs_trans_reserve in xfs_trans_roll
2025-07-16 12:43 cleanup transaction allocation v2 Christoph Hellwig
@ 2025-07-16 12:43 ` Christoph Hellwig
2025-07-16 15:32 ` Darrick J. Wong
0 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2025-07-16 12:43 UTC (permalink / raw)
To: Carlos Maiolino; +Cc: linux-xfs
xfs_trans_roll uses xfs_trans_reserve to basically just call into
xfs_log_regrant while bypassing the reset of xfs_trans_reserve.
Open code the call to xfs_log_regrant in xfs_trans_roll and simplify
xfs_trans_reserve now that it never regrants and always asks for a log
reservation.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/xfs_trans.c | 133 ++++++++++++++++++---------------------------
1 file changed, 54 insertions(+), 79 deletions(-)
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index e5edb89909ed..8d0aee747f72 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -134,18 +134,14 @@ xfs_trans_dup(
}
/*
- * This is called to reserve free disk blocks and log space for the
- * given transaction. This must be done before allocating any resources
- * within the transaction.
+ * This is called to reserve free disk blocks and log space for the given
+ * transaction before allocating any resources within the transaction.
*
* This will return ENOSPC if there are not enough blocks available.
* It will sleep waiting for available log space.
- * The only valid value for the flags parameter is XFS_RES_LOG_PERM, which
- * is used by long running transactions. If any one of the reservations
- * fails then they will all be backed out.
*
- * This does not do quota reservations. That typically is done by the
- * caller afterwards.
+ * This does not do quota reservations. That typically is done by the caller
+ * afterwards.
*/
static int
xfs_trans_reserve(
@@ -158,10 +154,12 @@ xfs_trans_reserve(
int error = 0;
bool rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
+ ASSERT(resp->tr_logres > 0);
+
/*
- * Attempt to reserve the needed disk blocks by decrementing
- * the number needed from the number available. This will
- * fail if the count would go below zero.
+ * Attempt to reserve the needed disk blocks by decrementing the number
+ * needed from the number available. This will fail if the count would
+ * go below zero.
*/
if (blocks > 0) {
error = xfs_dec_fdblocks(mp, blocks, rsvd);
@@ -173,42 +171,20 @@ xfs_trans_reserve(
/*
* Reserve the log space needed for this transaction.
*/
- if (resp->tr_logres > 0) {
- bool permanent = false;
-
- ASSERT(tp->t_log_res == 0 ||
- tp->t_log_res == resp->tr_logres);
- ASSERT(tp->t_log_count == 0 ||
- tp->t_log_count == resp->tr_logcount);
-
- if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES) {
- tp->t_flags |= XFS_TRANS_PERM_LOG_RES;
- permanent = true;
- } else {
- ASSERT(tp->t_ticket == NULL);
- ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES));
- }
-
- if (tp->t_ticket != NULL) {
- ASSERT(resp->tr_logflags & XFS_TRANS_PERM_LOG_RES);
- error = xfs_log_regrant(mp, tp->t_ticket);
- } else {
- error = xfs_log_reserve(mp, resp->tr_logres,
- resp->tr_logcount,
- &tp->t_ticket, permanent);
- }
-
- if (error)
- goto undo_blocks;
+ if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES)
+ tp->t_flags |= XFS_TRANS_PERM_LOG_RES;
+ error = xfs_log_reserve(mp, resp->tr_logres, resp->tr_logcount,
+ &tp->t_ticket, (tp->t_flags & XFS_TRANS_PERM_LOG_RES));
+ if (error)
+ goto undo_blocks;
- tp->t_log_res = resp->tr_logres;
- tp->t_log_count = resp->tr_logcount;
- }
+ tp->t_log_res = resp->tr_logres;
+ tp->t_log_count = resp->tr_logcount;
/*
- * Attempt to reserve the needed realtime extents by decrementing
- * the number needed from the number available. This will
- * fail if the count would go below zero.
+ * Attempt to reserve the needed realtime extents by decrementing the
+ * number needed from the number available. This will fail if the
+ * count would go below zero.
*/
if (rtextents > 0) {
error = xfs_dec_frextents(mp, rtextents);
@@ -221,18 +197,11 @@ xfs_trans_reserve(
return 0;
- /*
- * Error cases jump to one of these labels to undo any
- * reservations which have already been performed.
- */
undo_log:
- if (resp->tr_logres > 0) {
- xfs_log_ticket_ungrant(mp->m_log, tp->t_ticket);
- tp->t_ticket = NULL;
- tp->t_log_res = 0;
- tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES;
- }
-
+ xfs_log_ticket_ungrant(mp->m_log, tp->t_ticket);
+ tp->t_ticket = NULL;
+ tp->t_log_res = 0;
+ tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES;
undo_blocks:
if (blocks > 0) {
xfs_add_fdblocks(mp, blocks);
@@ -1030,51 +999,57 @@ xfs_trans_cancel(
}
/*
- * Roll from one trans in the sequence of PERMANENT transactions to
- * the next: permanent transactions are only flushed out when
- * committed with xfs_trans_commit(), but we still want as soon
- * as possible to let chunks of it go to the log. So we commit the
- * chunk we've been working on and get a new transaction to continue.
+ * Roll from one trans in the sequence of PERMANENT transactions to the next:
+ * permanent transactions are only flushed out when committed with
+ * xfs_trans_commit(), but we still want as soon as possible to let chunks of it
+ * go to the log. So we commit the chunk we've been working on and get a new
+ * transaction to continue.
*/
int
xfs_trans_roll(
struct xfs_trans **tpp)
{
- struct xfs_trans *trans = *tpp;
- struct xfs_trans_res tres;
+ struct xfs_trans *tp = *tpp;
+ unsigned int log_res = tp->t_log_res;
+ unsigned int log_count = tp->t_log_count;
int error;
- trace_xfs_trans_roll(trans, _RET_IP_);
+ trace_xfs_trans_roll(tp, _RET_IP_);
+
+ ASSERT(log_res > 0);
/*
* Copy the critical parameters from one trans to the next.
*/
- tres.tr_logres = trans->t_log_res;
- tres.tr_logcount = trans->t_log_count;
-
- *tpp = xfs_trans_dup(trans);
+ *tpp = xfs_trans_dup(tp);
/*
* Commit the current transaction.
- * If this commit failed, then it'd just unlock those items that
- * are not marked ihold. That also means that a filesystem shutdown
- * is in progress. The caller takes the responsibility to cancel
- * the duplicate transaction that gets returned.
+ *
+ * If this commit failed, then it'd just unlock those items that are not
+ * marked ihold. That also means that a filesystem shutdown is in
+ * progress. The caller takes the responsibility to cancel the
+ * duplicate transaction that gets returned.
*/
- error = __xfs_trans_commit(trans, true);
+ error = __xfs_trans_commit(tp, true);
if (error)
return error;
/*
* Reserve space in the log for the next transaction.
- * This also pushes items in the "AIL", the list of logged items,
- * out to disk if they are taking up space at the tail of the log
- * that we want to use. This requires that either nothing be locked
- * across this call, or that anything that is locked be logged in
- * the prior and the next transactions.
+ *
+ * This also pushes items in the AIL out to disk if they are taking up
+ * space at the tail of the log that we want to use. This requires that
+ * either nothing be locked across this call, or that anything that is
+ * locked be logged in the prior and the next transactions.
*/
- tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
- return xfs_trans_reserve(*tpp, &tres, 0, 0);
+ tp = *tpp;
+ error = xfs_log_regrant(tp->t_mountp, tp->t_ticket);
+ if (error)
+ return error;
+ tp->t_log_res = log_res;
+ tp->t_log_count = log_count;
+ return 0;
}
/*
--
2.47.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH 4/8] xfs: don't use xfs_trans_reserve in xfs_trans_roll
2025-07-16 12:43 ` [PATCH 4/8] xfs: don't use xfs_trans_reserve in xfs_trans_roll Christoph Hellwig
@ 2025-07-16 15:32 ` Darrick J. Wong
0 siblings, 0 replies; 22+ messages in thread
From: Darrick J. Wong @ 2025-07-16 15:32 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-xfs
On Wed, Jul 16, 2025 at 02:43:14PM +0200, Christoph Hellwig wrote:
> xfs_trans_roll uses xfs_trans_reserve to basically just call into
> xfs_log_regrant while bypassing the reset of xfs_trans_reserve.
>
> Open code the call to xfs_log_regrant in xfs_trans_roll and simplify
> xfs_trans_reserve now that it never regrants and always asks for a log
> reservation.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Looks good now, and we don't even have the dummy stack resv anymore. :)
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
--D
> ---
> fs/xfs/xfs_trans.c | 133 ++++++++++++++++++---------------------------
> 1 file changed, 54 insertions(+), 79 deletions(-)
>
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index e5edb89909ed..8d0aee747f72 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -134,18 +134,14 @@ xfs_trans_dup(
> }
>
> /*
> - * This is called to reserve free disk blocks and log space for the
> - * given transaction. This must be done before allocating any resources
> - * within the transaction.
> + * This is called to reserve free disk blocks and log space for the given
> + * transaction before allocating any resources within the transaction.
> *
> * This will return ENOSPC if there are not enough blocks available.
> * It will sleep waiting for available log space.
> - * The only valid value for the flags parameter is XFS_RES_LOG_PERM, which
> - * is used by long running transactions. If any one of the reservations
> - * fails then they will all be backed out.
> *
> - * This does not do quota reservations. That typically is done by the
> - * caller afterwards.
> + * This does not do quota reservations. That typically is done by the caller
> + * afterwards.
> */
> static int
> xfs_trans_reserve(
> @@ -158,10 +154,12 @@ xfs_trans_reserve(
> int error = 0;
> bool rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
>
> + ASSERT(resp->tr_logres > 0);
> +
> /*
> - * Attempt to reserve the needed disk blocks by decrementing
> - * the number needed from the number available. This will
> - * fail if the count would go below zero.
> + * Attempt to reserve the needed disk blocks by decrementing the number
> + * needed from the number available. This will fail if the count would
> + * go below zero.
> */
> if (blocks > 0) {
> error = xfs_dec_fdblocks(mp, blocks, rsvd);
> @@ -173,42 +171,20 @@ xfs_trans_reserve(
> /*
> * Reserve the log space needed for this transaction.
> */
> - if (resp->tr_logres > 0) {
> - bool permanent = false;
> -
> - ASSERT(tp->t_log_res == 0 ||
> - tp->t_log_res == resp->tr_logres);
> - ASSERT(tp->t_log_count == 0 ||
> - tp->t_log_count == resp->tr_logcount);
> -
> - if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES) {
> - tp->t_flags |= XFS_TRANS_PERM_LOG_RES;
> - permanent = true;
> - } else {
> - ASSERT(tp->t_ticket == NULL);
> - ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES));
> - }
> -
> - if (tp->t_ticket != NULL) {
> - ASSERT(resp->tr_logflags & XFS_TRANS_PERM_LOG_RES);
> - error = xfs_log_regrant(mp, tp->t_ticket);
> - } else {
> - error = xfs_log_reserve(mp, resp->tr_logres,
> - resp->tr_logcount,
> - &tp->t_ticket, permanent);
> - }
> -
> - if (error)
> - goto undo_blocks;
> + if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES)
> + tp->t_flags |= XFS_TRANS_PERM_LOG_RES;
> + error = xfs_log_reserve(mp, resp->tr_logres, resp->tr_logcount,
> + &tp->t_ticket, (tp->t_flags & XFS_TRANS_PERM_LOG_RES));
> + if (error)
> + goto undo_blocks;
>
> - tp->t_log_res = resp->tr_logres;
> - tp->t_log_count = resp->tr_logcount;
> - }
> + tp->t_log_res = resp->tr_logres;
> + tp->t_log_count = resp->tr_logcount;
>
> /*
> - * Attempt to reserve the needed realtime extents by decrementing
> - * the number needed from the number available. This will
> - * fail if the count would go below zero.
> + * Attempt to reserve the needed realtime extents by decrementing the
> + * number needed from the number available. This will fail if the
> + * count would go below zero.
> */
> if (rtextents > 0) {
> error = xfs_dec_frextents(mp, rtextents);
> @@ -221,18 +197,11 @@ xfs_trans_reserve(
>
> return 0;
>
> - /*
> - * Error cases jump to one of these labels to undo any
> - * reservations which have already been performed.
> - */
> undo_log:
> - if (resp->tr_logres > 0) {
> - xfs_log_ticket_ungrant(mp->m_log, tp->t_ticket);
> - tp->t_ticket = NULL;
> - tp->t_log_res = 0;
> - tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES;
> - }
> -
> + xfs_log_ticket_ungrant(mp->m_log, tp->t_ticket);
> + tp->t_ticket = NULL;
> + tp->t_log_res = 0;
> + tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES;
> undo_blocks:
> if (blocks > 0) {
> xfs_add_fdblocks(mp, blocks);
> @@ -1030,51 +999,57 @@ xfs_trans_cancel(
> }
>
> /*
> - * Roll from one trans in the sequence of PERMANENT transactions to
> - * the next: permanent transactions are only flushed out when
> - * committed with xfs_trans_commit(), but we still want as soon
> - * as possible to let chunks of it go to the log. So we commit the
> - * chunk we've been working on and get a new transaction to continue.
> + * Roll from one trans in the sequence of PERMANENT transactions to the next:
> + * permanent transactions are only flushed out when committed with
> + * xfs_trans_commit(), but we still want as soon as possible to let chunks of it
> + * go to the log. So we commit the chunk we've been working on and get a new
> + * transaction to continue.
> */
> int
> xfs_trans_roll(
> struct xfs_trans **tpp)
> {
> - struct xfs_trans *trans = *tpp;
> - struct xfs_trans_res tres;
> + struct xfs_trans *tp = *tpp;
> + unsigned int log_res = tp->t_log_res;
> + unsigned int log_count = tp->t_log_count;
> int error;
>
> - trace_xfs_trans_roll(trans, _RET_IP_);
> + trace_xfs_trans_roll(tp, _RET_IP_);
> +
> + ASSERT(log_res > 0);
>
> /*
> * Copy the critical parameters from one trans to the next.
> */
> - tres.tr_logres = trans->t_log_res;
> - tres.tr_logcount = trans->t_log_count;
> -
> - *tpp = xfs_trans_dup(trans);
> + *tpp = xfs_trans_dup(tp);
>
> /*
> * Commit the current transaction.
> - * If this commit failed, then it'd just unlock those items that
> - * are not marked ihold. That also means that a filesystem shutdown
> - * is in progress. The caller takes the responsibility to cancel
> - * the duplicate transaction that gets returned.
> + *
> + * If this commit failed, then it'd just unlock those items that are not
> + * marked ihold. That also means that a filesystem shutdown is in
> + * progress. The caller takes the responsibility to cancel the
> + * duplicate transaction that gets returned.
> */
> - error = __xfs_trans_commit(trans, true);
> + error = __xfs_trans_commit(tp, true);
> if (error)
> return error;
>
> /*
> * Reserve space in the log for the next transaction.
> - * This also pushes items in the "AIL", the list of logged items,
> - * out to disk if they are taking up space at the tail of the log
> - * that we want to use. This requires that either nothing be locked
> - * across this call, or that anything that is locked be logged in
> - * the prior and the next transactions.
> + *
> + * This also pushes items in the AIL out to disk if they are taking up
> + * space at the tail of the log that we want to use. This requires that
> + * either nothing be locked across this call, or that anything that is
> + * locked be logged in the prior and the next transactions.
> */
> - tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
> - return xfs_trans_reserve(*tpp, &tres, 0, 0);
> + tp = *tpp;
> + error = xfs_log_regrant(tp->t_mountp, tp->t_ticket);
> + if (error)
> + return error;
> + tp->t_log_res = log_res;
> + tp->t_log_count = log_count;
> + return 0;
> }
>
> /*
> --
> 2.47.2
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2025-07-16 15:32 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-15 12:25 cleanup transaction allocation Christoph Hellwig
2025-07-15 12:25 ` [PATCH 1/8] xfs: use xfs_trans_reserve_more in xfs_trans_reserve_more_inode Christoph Hellwig
2025-07-15 14:47 ` Darrick J. Wong
2025-07-15 12:25 ` [PATCH 2/8] xfs: don't use xfs_trans_reserve in xfs_trans_reserve_more Christoph Hellwig
2025-07-15 14:49 ` Darrick J. Wong
2025-07-15 15:35 ` Christoph Hellwig
2025-07-15 15:55 ` Darrick J. Wong
2025-07-15 12:25 ` [PATCH 3/8] xfs: decouple xfs_trans_alloc_empty from xfs_trans_alloc Christoph Hellwig
2025-07-15 14:54 ` Darrick J. Wong
2025-07-15 12:25 ` [PATCH 4/8] xfs: don't use xfs_trans_reserve in xfs_trans_roll Christoph Hellwig
2025-07-15 14:59 ` Darrick J. Wong
2025-07-15 12:25 ` [PATCH 5/8] xfs: return the allocated transaction from xfs_trans_alloc_empty Christoph Hellwig
2025-07-15 14:59 ` Darrick J. Wong
2025-07-15 12:25 ` [PATCH 6/8] xfs: return the allocated transaction from xchk_trans_alloc_empty Christoph Hellwig
2025-07-15 14:59 ` Darrick J. Wong
2025-07-15 12:25 ` [PATCH 7/8] xfs: return the allocated transaction from xrep_trans_alloc_hook_dummy Christoph Hellwig
2025-07-15 15:18 ` Darrick J. Wong
2025-07-15 15:36 ` Christoph Hellwig
2025-07-15 12:25 ` [PATCH 8/8] xfs: remove the xlog_ticket_t typedef Christoph Hellwig
2025-07-15 15:18 ` Darrick J. Wong
-- strict thread matches above, loose matches on Subject: below --
2025-07-16 12:43 cleanup transaction allocation v2 Christoph Hellwig
2025-07-16 12:43 ` [PATCH 4/8] xfs: don't use xfs_trans_reserve in xfs_trans_roll Christoph Hellwig
2025-07-16 15:32 ` Darrick J. Wong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).