From: Wenwu Hou Date: Sat, 17 Jan 2026 06:52:43 +0000 (+0800) Subject: xfs: fix incorrect context handling in xfs_trans_roll X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a1ca658d649a4d8972e2e21ac2625b633217e327;p=thirdparty%2Flinux.git xfs: fix incorrect context handling in xfs_trans_roll The memalloc_nofs_save() and memalloc_nofs_restore() calls are incorrectly paired in xfs_trans_roll. Call path: xfs_trans_alloc() __xfs_trans_alloc() // tp->t_pflags = memalloc_nofs_save(); xfs_trans_set_context() ... xfs_defer_trans_roll() xfs_trans_roll() xfs_trans_dup() // old_tp->t_pflags = 0; xfs_trans_switch_context() __xfs_trans_commit() xfs_trans_free() // memalloc_nofs_restore(tp->t_pflags); xfs_trans_clear_context() The code passes 0 to memalloc_nofs_restore() when committing the original transaction, but memalloc_nofs_restore() should always receive the flags returned from the paired memalloc_nofs_save() call. Before commit 3f6d5e6a468d ("mm: introduce memalloc_flags_{save,restore}"), calling memalloc_nofs_restore(0) would unset the PF_MEMALLOC_NOFS flag, which could cause memory allocation deadlocks[1]. Fortunately, after that commit, memalloc_nofs_restore(0) does nothing, so this issue is currently harmless. Fixes: 756b1c343333 ("xfs: use current->journal_info for detecting transaction recursion") Link: https://lore.kernel.org/linux-xfs/20251104131857.1587584-1-leo.lilong@huawei.com [1] Signed-off-by: Wenwu Hou Reviewed-by: Christoph Hellwig Signed-off-by: Carlos Maiolino --- diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 2c3c29d0d4a08..bcc470f56e466 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -124,8 +124,6 @@ xfs_trans_dup( ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used; tp->t_rtx_res = tp->t_rtx_res_used; - xfs_trans_switch_context(tp, ntp); - /* move deferred ops over to the new tp */ xfs_defer_move(ntp, tp); @@ -1043,6 +1041,12 @@ xfs_trans_roll( * 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; diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 8830600b3e729..eb83c5dac0320 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -280,13 +280,4 @@ xfs_trans_clear_context( memalloc_nofs_restore(tp->t_pflags); } -static inline void -xfs_trans_switch_context( - struct xfs_trans *old_tp, - struct xfs_trans *new_tp) -{ - new_tp->t_pflags = old_tp->t_pflags; - old_tp->t_pflags = 0; -} - #endif /* __XFS_TRANS_H__ */