mirror of
https://github.com/torvalds/linux.git
synced 2026-09-26 10:02:02 +02:00
fs: don't create the private nullfs mount under namespace_sem
init_mount_tree() mounts the mutable rootfs on top of nullfs via
LOCK_MOUNT_EXACT(). That declares a pinned mountpoint with a cleanup
attribute in the scope of the whole function so the nullfs root inode
lock and namespace_sem are only dropped when init_mount_tree() returns.
This became a problem when the private nullfs instance for kthreads was
added. kern_mount() allocates a new superblock and alloc_super() takes
the new s_umount with SINGLE_DEPTH_NESTING and then shrinker_mutex via
shrinker_alloc(). Doing that with namespace_sem held teaches lockdep the
dependency
namespace_sem -> s_umount/1 -> shrinker_mutex
With CONFIG_SHRINKER_DEBUG shrinker_debugfs_rename() takes the debugfs
directory inode lock under shrinker_mutex every time a block device is
mounted and lock_mount_exact() takes namespace_sem under the inode lock
of the mountpoint for every mount. So mounting anything on debugfs,
e.g. the tracefs automount on /sys/kernel/debug/tracing, closes the
cycle:
WARNING: possible circular locking dependency detected
7.3.0-rc3+ #17 Not tainted
------------------------------------------------------
rasdaemon/4449 is trying to acquire lock:
(namespace_sem){++++}-{4:4}, at: lock_mount_exact+0x4c/0x308
but task is already holding lock:
(&sb->s_type->i_mutex_key#17){++++}-{4:4}, at: lock_mount_exact+0x3c/0x308
which lock already depends on the new lock.
...
Chain exists of:
namespace_sem --> shrinker_mutex --> &sb->s_type->i_mutex_key#17
This can't actually deadlock. init_mount_tree() runs single-threaded
during early boot before any other task exists and nothing allocates a
superblock under namespace_sem after that. But lockdep can't know that
and disables itself for the rest of the boot.
Move mounting the rootfs on top of nullfs into a helper so the locks
are dropped when it returns.
Fixes: 32750c77e8 ("fs: start all kthreads in nullfs")
Reported-by: Zenghui Yu <yuzenghui@huawei.com>
Closes: https://lore.kernel.org/15174353-3f4a-a1ca-5bd1-ea2a4c77828e@huawei.com
Link: https://patch.msgid.link/20260917-atemtechnik-bleichen-befassen-9a57db01baf0@brauner
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
parent
f6988c9067
commit
5179241521
|
|
@ -6184,6 +6184,21 @@ struct mnt_namespace init_mnt_ns = {
|
|||
.poll = __WAIT_QUEUE_HEAD_INITIALIZER(init_mnt_ns.poll),
|
||||
};
|
||||
|
||||
static void __init mount_rootfs_on_nullfs(struct vfsmount *mnt,
|
||||
struct vfsmount *nullfs_mnt)
|
||||
{
|
||||
struct path root = {
|
||||
.mnt = nullfs_mnt,
|
||||
.dentry = nullfs_mnt->mnt_root,
|
||||
};
|
||||
|
||||
LOCK_MOUNT_EXACT(mp, &root);
|
||||
if (unlikely(IS_ERR(mp.parent)))
|
||||
panic("VFS: Failed to mount rootfs on nullfs");
|
||||
scoped_guard(mount_writer)
|
||||
attach_mnt(real_mount(mnt), mp.parent, mp.mp);
|
||||
}
|
||||
|
||||
static void __init init_mount_tree(void)
|
||||
{
|
||||
struct vfsmount *mnt, *nullfs_mnt;
|
||||
|
|
@ -6215,15 +6230,7 @@ static void __init init_mount_tree(void)
|
|||
mnt_root = real_mount(nullfs_mnt);
|
||||
init_mnt_ns.root = mnt_root;
|
||||
|
||||
/* Mount mutable rootfs on top of nullfs. */
|
||||
root.mnt = nullfs_mnt;
|
||||
root.dentry = nullfs_mnt->mnt_root;
|
||||
|
||||
LOCK_MOUNT_EXACT(mp, &root);
|
||||
if (unlikely(IS_ERR(mp.parent)))
|
||||
panic("VFS: Failed to mount rootfs on nullfs");
|
||||
scoped_guard(mount_writer)
|
||||
attach_mnt(real_mount(mnt), mp.parent, mp.mp);
|
||||
mount_rootfs_on_nullfs(mnt, nullfs_mnt);
|
||||
|
||||
pr_info("VFS: Finished mounting rootfs on nullfs\n");
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user