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: stop reclaim before pushing AIL during unmount

The unmount sequence in xfs_unmount_flush_inodes() pushed the AIL while
background reclaim and inodegc are still running. This is broken
independently of any use-after-free issues - background reclaim and
inodegc should not be running while the AIL is being pushed during
unmount, as inodegc can dirty and insert inodes into the AIL during the
flush, and background reclaim can race to abort and free dirty inodes.

Reorder xfs_unmount_flush_inodes() to stop inodegc and cancel background
reclaim before pushing the AIL. Stop inodegc before cancelling
m_reclaim_work because the inodegc worker can re-queue m_reclaim_work
via xfs_inodegc_set_reclaimable.

Reported-by: syzbot+652af2b3c5569c4ab63c@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=652af2b3c5569c4ab63c
Fixes: 90c60e164012 ("xfs: xfs_iflush() is no longer necessary")
Cc: stable@vger.kernel.org # v5.9
Signed-off-by: Yuto Ohnuki <ytohnuki@amazon.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>

authored by

Yuto Ohnuki and committed by
Carlos Maiolino
4f24a767 362c4909

+4 -3
+4 -3
fs/xfs/xfs_mount.c
··· 608 608 * have been retrying in the background. This will prevent never-ending 609 609 * retries in AIL pushing from hanging the unmount. 610 610 * 611 - * Finally, we can push the AIL to clean all the remaining dirty objects, then 612 - * reclaim the remaining inodes that are still in memory at this point in time. 611 + * Stop inodegc and background reclaim before pushing the AIL so that they 612 + * are not running while the AIL is being flushed. Then push the AIL to 613 + * clean all the remaining dirty objects and reclaim the remaining inodes. 613 614 */ 614 615 static void 615 616 xfs_unmount_flush_inodes( ··· 622 621 623 622 xfs_set_unmounting(mp); 624 623 625 - xfs_ail_push_all_sync(mp->m_ail); 626 624 xfs_inodegc_stop(mp); 627 625 cancel_delayed_work_sync(&mp->m_reclaim_work); 626 + xfs_ail_push_all_sync(mp->m_ail); 628 627 xfs_reclaim_inodes(mp); 629 628 xfs_health_unmount(mp); 630 629 xfs_healthmon_unmount(mp);