summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2025-02-07 11:26:33 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-02-17 10:05:44 +0100
commitee93e08d4c8be850e5283098e428663684c9a6c1 (patch)
tree4f29e14d42fe54b3cca1e9c6765d61e0a04b6711 /fs
parent9be0b25adeb2e2383351fdd9f8c9ec75dddcc4e0 (diff)
downloadlinux-ee93e08d4c8be850e5283098e428663684c9a6c1.tar.gz
linux-ee93e08d4c8be850e5283098e428663684c9a6c1.tar.bz2
linux-ee93e08d4c8be850e5283098e428663684c9a6c1.zip
xfs: avoid nested calls to __xfs_trans_commit
commit e96c1e2f262e0993859e266e751977bfad3ca98a upstream Currently, __xfs_trans_commit calls xfs_defer_finish_noroll, which calls __xfs_trans_commit again on the same transaction. In other words, there's function recursion that has caused minor amounts of confusion in the past. There's no reason to keep this around, since there's only one place where we actually want the xfs_defer_finish_noroll, and that is in the top level xfs_trans_commit call. Fixes: 98719051e75ccf ("xfs: refactor internal dfops initialization") Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_trans.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 30e03342287a..001d9bec4ed5 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -834,18 +834,6 @@ __xfs_trans_commit(
trace_xfs_trans_commit(tp, _RET_IP_);
- /*
- * Finish deferred items on final commit. Only permanent transactions
- * should ever have deferred ops.
- */
- WARN_ON_ONCE(!list_empty(&tp->t_dfops) &&
- !(tp->t_flags & XFS_TRANS_PERM_LOG_RES));
- if (!regrant && (tp->t_flags & XFS_TRANS_PERM_LOG_RES)) {
- error = xfs_defer_finish_noroll(&tp);
- if (error)
- goto out_unreserve;
- }
-
error = xfs_trans_run_precommits(tp);
if (error)
goto out_unreserve;
@@ -924,6 +912,20 @@ int
xfs_trans_commit(
struct xfs_trans *tp)
{
+ /*
+ * Finish deferred items on final commit. Only permanent transactions
+ * should ever have deferred ops.
+ */
+ WARN_ON_ONCE(!list_empty(&tp->t_dfops) &&
+ !(tp->t_flags & XFS_TRANS_PERM_LOG_RES));
+ if (tp->t_flags & XFS_TRANS_PERM_LOG_RES) {
+ int error = xfs_defer_finish_noroll(&tp);
+ if (error) {
+ xfs_trans_cancel(tp);
+ return error;
+ }
+ }
+
return __xfs_trans_commit(tp, false);
}