xfs: restore nofs context unconditionally in xfs_trans_roll

When __xfs_trans_commit() fails in xfs_trans_roll(), the NOFS context
is cleared but only restored in the success path.  This leaves the
error path without nofs protection, causing a circular lock dependency
between xfs_nondir_ilock_class and fs_reclaim:

       CPU0                    CPU1
       ----                    ----
  lock(&xfs_nondir_ilock_class);
                               lock(fs_reclaim);
                               lock(&xfs_nondir_ilock_class);
  lock(fs_reclaim);

Fix this by moving xfs_trans_set_context() before the error check so
that nofs context is always restored on the new transaction.

Reported-by: syzbot+59178abfeb0ea3f0ab20@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=59178abfeb0ea3f0ab20
Fixes: a1ca658d64 ("xfs: fix incorrect context handling in xfs_trans_roll")
Cc: stable@vger.kernel.org
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
This commit is contained in:
Yun Zhou
2026-07-30 17:30:02 +08:00
committed by Carlos Maiolino
parent 00f40876f4
commit 0241ea5fb0

View File

@@ -1029,6 +1029,15 @@ xfs_trans_roll(
* duplicate transaction that gets returned.
*/
error = __xfs_trans_commit(tp, true);
tp = *tpp;
/*
* __xfs_trans_commit cleared the NOFS flag by calling into
* xfs_trans_free. Set it again here before doing memory
* allocations.
*/
xfs_trans_set_context(tp);
if (error)
return error;
@@ -1040,13 +1049,6 @@ xfs_trans_roll(
* either nothing be locked across this call, or that anything that is
* locked be logged in the prior and the next transactions.
*/
tp = *tpp;
/*
* __xfs_trans_commit cleared the NOFS flag by calling into
* xfs_trans_free. Set it again here before doing memory
* allocations.
*/
xfs_trans_set_context(tp);
error = xfs_log_regrant(tp->t_mountp, tp->t_ticket);
if (error)
return error;