mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Zenghui Yu <yuzenghui@huawei.com>
To: Christian Brauner <brauner@kernel.org>
Cc: <linux-fsdevel@vger.kernel.org>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	<linux-kernel@vger.kernel.org>,
	Alexander Viro <viro@zeniv.linux.org.uk>, Jan Kara <jack@suse.cz>,
	Jann Horn <jannh@google.com>
Subject: Re: [PATCH RFC v4 23/25] fs: start all kthreads in nullfs
Date: Tue, 15 Sep 2026 20:39:10 +0800	[thread overview]
Message-ID: <15174353-3f4a-a1ca-5bd1-ea2a4c77828e@huawei.com> (raw)
In-Reply-To: <20260601-work-kthread-nullfs-v4-23-77ee053060e0@kernel.org>

Hi Christian,

On 2026/6/1 21:56, Christian Brauner wrote:
> Point init_task's fs_struct (root and pwd) at a private nullfs instance
> instead of the mutable rootfs. All kthreads now start isolated in nullfs
> and must use scoped_with_init_fs() for any path resolution.
> 
> PID 1 is moved from nullfs into the initramfs by init_userspace_fs().
> Usermodehelper threads use userspace_init_fs via the umh flag in
> copy_fs(). All subsystems that need init's filesystem state for path
> resolution already use scoped_with_init_fs() from earlier commits in
> this series.
> 
> This isolates kthreads from userspace filesystem state and makes it
> hard to perform filesystem operations from kthread context.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
> ---
>  fs/namespace.c | 16 ++++++++++------
>  1 file changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/namespace.c b/fs/namespace.c
> index fe919abd2f01..43ca4838d451 100644
> --- a/fs/namespace.c
> +++ b/fs/namespace.c
> @@ -6173,12 +6173,14 @@ static void __init init_mount_tree(void)
>  	struct path root;
>  
>  	/*
> -	 * We create two mounts:
> +	 * We create three mounts:
>  	 *
>  	 * (1) nullfs with mount id 1
>  	 * (2) mutable rootfs with mount id 2
> +	 * (3) private nullfs for kthreads (SB_KERNMOUNT)
>  	 *
> -	 * with (2) mounted on top of (1).
> +	 * with (2) mounted on top of (1). The init_task's root and pwd
> +	 * are pointed at (3) so all kthreads start isolated in nullfs.
>  	 */
>  	nullfs_mnt = vfs_kern_mount(&nullfs_fs_type, 0, "nullfs", NULL);
>  	if (IS_ERR(nullfs_mnt))
> @@ -6218,12 +6220,14 @@ static void __init init_mount_tree(void)
>  		init_mnt_ns.nr_mounts++;
>  	}

|	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);

>  
> +	nullfs_mnt = kern_mount(&nullfs_fs_type);
> +	if (IS_ERR(nullfs_mnt))
> +		panic("VFS: Failed to create private nullfs instance");
> +	root.mnt	= nullfs_mnt;
> +	root.dentry	= nullfs_mnt->mnt_root;

The following lockdep splat can be triggered on mainline, which is built
with arm64's defconfig plus

	CONFIG_SHRINKER_DEBUG
	CONFIG_PROVE_LOCKING
	CONFIG_FTRACE

.  Reverting this patch (as pointed out by AI) makes this warn disappear.
Please have a look :-) .

Thanks,
Zenghui

---8<---

 ======================================================
 WARNING: possible circular locking dependency detected
 7.3.0-rc3+ #17 Not tainted
 ------------------------------------------------------
 rasdaemon/4449 is trying to acquire lock:
 ffff80008246cb78 (namespace_sem){++++}-{4:4}, at: lock_mount_exact+0x4c/0x308

 but task is already holding lock:
 ffff002080496980 (&sb->s_type->i_mutex_key#17){++++}-{4:4}, at: lock_mount_exact+0x3c/0x308

 which lock already depends on the new lock.


 the existing dependency chain (in reverse order) is:

 -> #3 (&sb->s_type->i_mutex_key#17){++++}-{4:4}:
        down_read+0x48/0x164
        lookup_slow+0x30/0x68
        lookup_noperm_unlocked+0x58/0x5c
        debugfs_change_name+0xd4/0x33c
        shrinker_debugfs_rename+0xa8/0x118
        setup_bdev_super+0x130/0x260
        get_tree_bdev_flags+0x12c/0x1ec
        get_tree_bdev+0x14/0x20
        ext4_get_tree+0x18/0x24
        vfs_get_tree+0x28/0xec
        path_mount+0x3ec/0xbb8
        __arm64_sys_mount+0x190/0x2d8
        invoke_syscall+0x54/0x110
        el0_svc_common.constprop.0+0x40/0xe0
        do_el0_svc+0x1c/0x28
        el0_svc+0x4c/0x3a4
        el0t_64_sync_handler+0xa0/0xe4
        el0t_64_sync+0x198/0x19c

 -> #2 (shrinker_mutex){+.+.}-{4:4}:
        __mutex_lock+0x90/0x870
        mutex_lock_nested+0x24/0x30
        shrinker_alloc+0x158/0x4a0
        sget_fc+0x2fc/0x7b8
        get_tree_nodev+0x2c/0xb8
        nullfs_fs_get_tree+0x18/0x24
        vfs_get_tree+0x28/0xec
        vfs_kern_mount.part.0+0xcc/0x130
        mnt_init+0x12c/0x470
        vfs_caches_init+0x120/0x294
        start_kernel+0x824/0x93c
        __primary_switched+0x88/0x90

 -> #1 (&type->s_umount_key#2/1){+.+.}-{4:4}:
        down_write_nested+0x34/0xcc
        sget_fc+0x14c/0x7b8
        get_tree_nodev+0x2c/0xb8
        nullfs_fs_get_tree+0x18/0x24
        vfs_get_tree+0x28/0xec
        vfs_kern_mount.part.0+0xcc/0x130
        mnt_init+0x2b0/0x470			-> kern_mount()
        vfs_caches_init+0x120/0x294
        start_kernel+0x824/0x93c
        __primary_switched+0x88/0x90

 -> #0 (namespace_sem){++++}-{4:4}:
        __lock_acquire+0x1490/0x21b8
        lock_acquire+0x1d8/0x404
        down_write+0x38/0xd0
        lock_mount_exact+0x4c/0x308
        finish_automount+0x70/0x134
        __traverse_mounts+0xd4/0x22c
        step_into_slowpath+0x2ec/0x390
        path_openat+0x2b0/0x8d4
        do_file_open+0x98/0x158
        do_sys_openat2+0x78/0xfc
        __arm64_sys_openat+0x70/0xbc
        invoke_syscall+0x54/0x110
        el0_svc_common.constprop.0+0x40/0xe0
        do_el0_svc+0x1c/0x28
        el0_svc+0x4c/0x3a4
        el0t_64_sync_handler+0xa0/0xe4
        el0t_64_sync+0x198/0x19c

 other info that might help us debug this:

 Chain exists of:
   namespace_sem --> shrinker_mutex --> &sb->s_type->i_mutex_key#17

  Possible unsafe locking scenario:

        CPU0                    CPU1
        ----                    ----
   lock(&sb->s_type->i_mutex_key#17);
                                lock(shrinker_mutex);
                                lock(&sb->s_type->i_mutex_key#17);
   lock(namespace_sem);

  *** DEADLOCK ***

 locks held by rasdaemon/4449: 1, last CPU#95:
  #0: ffff002080496980 (&sb->s_type->i_mutex_key#17){++++}-{4:4}, at: lock_mount_exact+0x3c/0x308

 stack backtrace:
 CPU: 95 UID: 0 PID: 4449 Comm: rasdaemon Not tainted 7.3.0-rc3+ #17 PREEMPT
 Hardware name: Huawei TaiShan 2280 V2/BC82AMDDA, BIOS 1.05 09/18/2019
 Call trace:
  show_stack+0x18/0x24 (C)
  dump_stack_lvl+0x90/0xd0
  dump_stack+0x18/0x24
  print_circular_bug+0x294/0x378
  check_noncircular+0x164/0x178
  __lock_acquire+0x1490/0x21b8
  lock_acquire+0x1d8/0x404
  down_write+0x38/0xd0
  lock_mount_exact+0x4c/0x308
  finish_automount+0x70/0x134
  __traverse_mounts+0xd4/0x22c
  step_into_slowpath+0x2ec/0x390
  path_openat+0x2b0/0x8d4
  do_file_open+0x98/0x158
  do_sys_openat2+0x78/0xfc
  __arm64_sys_openat+0x70/0xbc
  invoke_syscall+0x54/0x110
  el0_svc_common.constprop.0+0x40/0xe0
  do_el0_svc+0x1c/0x28
  el0_svc+0x4c/0x3a4
  el0t_64_sync_handler+0xa0/0xe4
  el0t_64_sync+0x198/0x19c

  reply	other threads:[~2026-09-15 12:39 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-01 13:56 [PATCH RFC v4 00/25] fs,kthread: " Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 01/25] fs: add switch_fs_struct() Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 02/25] fs: notice when init abandons fs sharing Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 03/25] fs: add scoped_with_init_fs() Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 04/25] fs: add real_fs to track task's actual fs_struct Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 05/25] fs: make userspace_init_fs a dynamically-initialized pointer Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 06/25] rnbd: use scoped_with_init_fs() for block device open Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 07/25] crypto: ccp: use scoped_with_init_fs() for SEV file access Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 08/25] scsi: target: use scoped_with_init_fs() for ALUA metadata Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 09/25] scsi: target: use scoped_with_init_fs() for APTPL metadata Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 10/25] btrfs: use scoped_with_init_fs() for update_dev_time() Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 11/25] coredump: use scoped_with_init_fs() for coredump path resolution Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 12/25] fs: use scoped_with_init_fs() for kernel_read_file_from_path_initns() Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 13/25] ksmbd: use scoped_with_init_fs() for share path resolution Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 14/25] ksmbd: use scoped_with_init_fs() for filesystem info path lookup Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 15/25] ksmbd: use scoped_with_init_fs() for VFS path operations Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 16/25] pnfs/blocklayout: use scoped_with_init_fs() for SCSI device lookup Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 17/25] initramfs: use scoped_with_init_fs() for rootfs unpacking Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 18/25] af_unix: use scoped_with_init_fs() for coredump socket lookup Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 19/25] fs: stop sharing fs_struct between init_task and pid 1 Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 20/25] fs: add umh argument to struct kernel_clone_args Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 21/25] devtmpfs: create private mount namespace Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 22/25] nullfs: make nullfs multi-instance Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 23/25] fs: start all kthreads in nullfs Christian Brauner
2026-09-15 12:39   ` Zenghui Yu [this message]
2026-09-17 12:07     ` Christian Brauner
2026-09-18  1:59       ` Zenghui Yu
2026-06-01 13:56 ` [PATCH RFC v4 24/25] fs: stop rewriting kthread fs structs Christian Brauner
2026-06-01 13:56 ` [PATCH RFC v4 25/25] fs: stop rewriting paths for PF_EXITING | PF_DUMPCORE Christian Brauner
2026-07-05 12:34 ` [PATCH RFC v4 00/25] fs,kthread: start all kthreads in nullfs Askar Safin
2026-07-05 12:57 ` Askar Safin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=15174353-3f4a-a1ca-5bd1-ea2a4c77828e@huawei.com \
    --to=yuzenghui@huawei.com \
    --cc=brauner@kernel.org \
    --cc=jack@suse.cz \
    --cc=jannh@google.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®