[PATCH 0/5] fs: don't let a stuck unmount take everybody else with it
From: Josef Bacik
Date: Tue Oct 20 2026 - 20:59:09 EST
Hello,
A consistent problem we have in containerized environments is a
misbehaving mount taking out all of the other containers. We hit the
super_lock() while we've got a stuck or slow umount and everything backs
up behind it, and there's no way to kill those things.
This is because we call super_lock(), which waits on the s_umount lock.
This is held throughout the entire umount operation, so anything wanting
to operate on the super block has to wait for the umount to finish.
This is fine for certain things, sync() and fsfreeze and such. They want
to block because they want the work to be finished, it's essentially a
barrier on the cleanliness of the file system.
Other things don't care. In that case we should just skip grabbing the
super block if its s_active count is 0, as it means its going away soon.
In the cases that we do end up in super_lock() and we don't necessarily
care about the barrier behavior of waiting on s_umount, we can wait for
DYING as killable, so that we can at least stop the pile on of other
tasks waiting on the super block.
We set the SB_DYING flag at the end of the sync, right before we drop
the s_umount rwsem, so this is an easy flag to wait on to get the
barrier behavior without taking the lock itself.
This series doesn't really move the needle on keeping the host usable in
the face of a hung file system. It is the first step in a whole long
series of steps needed to make sure misbehaving containers can't effect
the rest of the host.
For testing I put ext4 on a dm-linear device, dirtied 64M, suspended the
device underneath it and unmounted, which leaves the unmount sitting in
sync_filesystem(). Without the series drop_caches, quotactl(Q_SYNC),
ustat(), sync, BLKFLSBUF and a second mount of the device all end up in
super_lock() and ignore SIGKILL. With it the first three come straight
back, the other three wait but go away on SIGKILL, and a sync that isn't
killed still doesn't return until the unmount is done.
Freezing the device (a dm suspend with lockfs) and freezing everything
for suspend (pm_test=freezer with freeze_filesystems=1) wait for the
unmount with and without the series, SIGKILL or not, and leave nothing
frozen behind, and the emergency sync doesn't claim to be complete
before the unmount is. On both kernels the unmount finishes once the
device is resumed and all the data is there, and 200 rounds of
unmounting with sync and drop_caches running against it are fine. This
was with KASAN and lockdep on, neither had anything to say.
fstests ran against ext4 and btrfs, no issues. Thanks,
Josef
---
Josef Bacik (5):
fs: make sync(2) wait for superblocks being shut down explicitly
fs: make freezing for suspend wait for superblocks being shut down
fs: make the block device callbacks wait for superblocks being shut down
fs: don't sleep on s_umount of a superblock being shut down
fs: let a mount waiting for the old superblock to die be killed
fs/internal.h | 1 +
fs/super.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
fs/sync.c | 15 +++----
3 files changed, 117 insertions(+), 23 deletions(-)
---
base-commit: 2c3ba1f1cb416b81d617b92a24a4bcaa48d574e3
change-id: 20261020-b4-super-lock-dying-aad90aeb1984