mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
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 3f6d5e6a46 ("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: 756b1c3433 ("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>
This commit is contained in:
parent
01a2896154
commit
a1ca658d64
2 changed files with 6 additions and 11 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue