Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <hwenwur@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>

authored by

Wenwu Hou and committed by
Carlos Maiolino
a1ca658d 01a28961

+6 -11
+6 -2
fs/xfs/xfs_trans.c
··· 124 124 ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used; 125 125 tp->t_rtx_res = tp->t_rtx_res_used; 126 126 127 - xfs_trans_switch_context(tp, ntp); 128 - 129 127 /* move deferred ops over to the new tp */ 130 128 xfs_defer_move(ntp, tp); 131 129 ··· 1041 1043 * locked be logged in the prior and the next transactions. 1042 1044 */ 1043 1045 tp = *tpp; 1046 + /* 1047 + * __xfs_trans_commit cleared the NOFS flag by calling into 1048 + * xfs_trans_free. Set it again here before doing memory 1049 + * allocations. 1050 + */ 1051 + xfs_trans_set_context(tp); 1044 1052 error = xfs_log_regrant(tp->t_mountp, tp->t_ticket); 1045 1053 if (error) 1046 1054 return error;
-9
fs/xfs/xfs_trans.h
··· 280 280 memalloc_nofs_restore(tp->t_pflags); 281 281 } 282 282 283 - static inline void 284 - xfs_trans_switch_context( 285 - struct xfs_trans *old_tp, 286 - struct xfs_trans *new_tp) 287 - { 288 - new_tp->t_pflags = old_tp->t_pflags; 289 - old_tp->t_pflags = 0; 290 - } 291 - 292 283 #endif /* __XFS_TRANS_H__ */