mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 10:31:33 -04:00
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:
committed by
Carlos Maiolino
parent
00f40876f4
commit
0241ea5fb0
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user