From nobody Thu Sep 4 02:09:51 2025 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4cHNGR53xpz66Zgw; Thu, 04 Sep 2025 02:09:51 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4cHNGR3gR1z3Gct; Thu, 04 Sep 2025 02:09:51 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1756951791; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=CUPXYax615U13fFXVHzXw4tTQ0ZvMEIhmCVCI7MAUjU=; b=X1YbtzEa5uaG/tsSvSnvduz0SFMD12HhSDdsxdsdoYcQjBvE7XMPIPdNRa5//ZTkQX6ed4 +TUw0bropU0Gxo2Hjky2ccTPSf5aizXo9Jxzte7kaNKwiw2NShKXPLF018ztKIAjjTNY75 xBPMuwBapL0AHBs1aUFa1uOVcULysQ60sqJrgXQOFLnjRX5zKpmJnlKwZEG3EzvIuGKun9 75wWu8jIzoy1p+si9Fdr3KCJwwKRxrbITaUImrTGT9p7xbbmIfXxCfHPVVW6whEcHk7BlU Xl/c2R5JP0RyjKw0AM4HY7EZX+J7RVv+imi4STUTRz6jCpyVfM8tNOynPxgB4Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1756951791; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=CUPXYax615U13fFXVHzXw4tTQ0ZvMEIhmCVCI7MAUjU=; b=U8xdAoyfr0u23jg9j2aDwjNFBVUQDtmwiBI4KoSD8hWJ85VoYT2CdPKcph1mt+eWPirqCd CtWChefAgZhJ/cfvKm7s6wrFALmxppREma8mnf6d6i9CRCX+jOgugDjMAGo0+nuvbrfkpB 7+r5lNxQRizfJZfB0ipzzJFVQZFhTsv66+76dPEyfecIHOHxYbDBk/4959rS6zIVPq+lRT OExN/WzHXFCYxfM1N5x2wX1SG8IgkuEZkBvp/yLaUjOkEJLbaOv9u37eBvCiCCoDTZ4qcS em5UoPOQldhYIqh3He9ySKc+yNjvUHQOB/BgD20xeLQG3n3FIUJS0Lydn11iBg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1756951791; a=rsa-sha256; cv=none; b=WF/oK7CEwAMOIuX9P9j8M6OM1B7A5jJTcxO9ntlfKT9kHRbOVUM2CK6l9uzxwZj/Fs6mqt FlF7TEcaRUJmMituth2wsi35P0UrS9xQEiKQNWqtPDjLXiYrGs+vIdhV3VeP7nLqI3MXA5 0xUaPjL25B9o3HMDi2AlOdmxOfDFbPYcDd5EUG18qObayI/aEdlOzlwKGeMSkcpLTN4nve R+ZZtnwQu0B9J7FYpwZZWHmDGW0MFr0POTYrUIkEojsZLv2CAm8U1ll2mjFrBz8rt69nTM Oa99NjBBYRraqNSuMz9ZgLQKoS8jFuYAii7hvJ5xlWiFbVOPJluGKNbB0WIlVQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4cHNGR30kMzjHB; Thu, 04 Sep 2025 02:09:51 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 58429ppC012370; Thu, 4 Sep 2025 02:09:51 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 58429pWl012367; Thu, 4 Sep 2025 02:09:51 GMT (envelope-from git) Date: Thu, 4 Sep 2025 02:09:51 GMT Message-Id: <202509040209.58429pWl012367@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kyle Evans Subject: git: 65059dd2b6f9 - main - pseudofs: defer initialization until first mount List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kevans X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 65059dd2b6f94e570acc645be82b8ea056316459 Auto-Submitted: auto-generated The branch main has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=65059dd2b6f94e570acc645be82b8ea056316459 commit 65059dd2b6f94e570acc645be82b8ea056316459 Author: Kyle Evans AuthorDate: 2025-09-04 02:08:52 +0000 Commit: Kyle Evans CommitDate: 2025-09-04 02:08:52 +0000 pseudofs: defer initialization until first mount Currently, pseudofs all get fully constructed when the module is loaded and vfs registered, but this is pretty unnecessary. Just loading the fs doesn't mean that it will be used so we're adding overhead and risk[0] by fully initializing these at the start, along with committing resources that may not be used. Deferring pfs_init() allows us to reduce the risk of simply loading the module causing problems that are harder to avoid, and existing pseudo filesystems don't really care: configuration that is context-sensitive is generally deferred to access-time with PFS_PROCDEP. To preserve symmetry, we'll also teardown our pseudofs on last unmount, which leaves us with a vfs_uninit() implementation that simply destroys our lock and prints a message. [0] Example of such being recent bugs in linsysfs, which caused a panic as soon as the module was loaded because we're eager to set it up. Reviewed by: des (previous version), kib Differential Revision: https://reviews.freebsd.org/D52156 --- sys/fs/pseudofs/pseudofs.c | 71 ++++++++++++++++++++++++++++++++++++++----- sys/fs/pseudofs/pseudofs.h | 33 +++++++++++--------- sys/modules/pseudofs/Makefile | 4 +-- 3 files changed, 84 insertions(+), 24 deletions(-) diff --git a/sys/fs/pseudofs/pseudofs.c b/sys/fs/pseudofs/pseudofs.c index efeeb57e6448..20cb87c6c6d5 100644 --- a/sys/fs/pseudofs/pseudofs.c +++ b/sys/fs/pseudofs/pseudofs.c @@ -40,13 +40,18 @@ #include #include #include +#include #include +#include #include #include #include #include +static int pfs_setup(struct pfs_info *pi, struct vfsconf *vfc); +static int pfs_teardown(struct pfs_info *pi, struct vfsconf *vfc); + static MALLOC_DEFINE(M_PFSNODES, "pfs_nodes", "pseudofs nodes"); SYSCTL_NODE(_vfs, OID_AUTO, pfs, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, @@ -382,10 +387,20 @@ int pfs_mount(struct pfs_info *pi, struct mount *mp) { struct statfs *sbp; + int error = 0; if (mp->mnt_flag & MNT_UPDATE) return (EOPNOTSUPP); + sx_xlock(&pi->pi_mountlock); + if (pi->pi_root == NULL) + error = pfs_setup(pi, mp->mnt_vfc); + if (error == 0) + refcount_acquire(&pi->pi_mounts); + sx_xunlock(&pi->pi_mountlock); + if (error != 0) + return (error); + MNT_ILOCK(mp); mp->mnt_flag |= MNT_LOCAL; mp->mnt_kern_flag |= MNTK_NOMSYNC; @@ -424,10 +439,23 @@ pfs_cmount(struct mntarg *ma, void *data, uint64_t flags) int pfs_unmount(struct mount *mp, int mntflags) { + struct pfs_info *pi; int error; error = vflush(mp, 0, (mntflags & MNT_FORCE) ? FORCECLOSE : 0, curthread); + if (error != 0) + return (error); + + pi = (struct pfs_info *)mp->mnt_data; + sx_xlock(&pi->pi_mountlock); + if (!refcount_release_if_not_last(&pi->pi_mounts)) { + error = pfs_teardown(pi, mp->mnt_vfc); + if (error == 0) + refcount_release(&pi->pi_mounts); + } + sx_xunlock(&pi->pi_mountlock); + return (error); } @@ -454,10 +482,35 @@ pfs_statfs(struct mount *mp, struct statfs *sbp) } /* - * Initialize a pseudofs instance + * Initialize pseudofs synchronization bits. These will generally be needed + * in order to avoid problems with parallel mounting of pseudofs consumers. */ int -pfs_init(struct pfs_info *pi, struct vfsconf *vfc) +pfs_vfsinit(struct pfs_info *pi, struct vfsconf *vfc) +{ + + sx_init(&pi->pi_mountlock, "pfs mountlock"); + refcount_init(&pi->pi_mounts, 0); + return (0); +} + +int +pfs_vfsuninit(struct pfs_info *pi, struct vfsconf *vfc) +{ + + MPASS(pi->pi_root == NULL); + sx_destroy(&pi->pi_mountlock); + + if (bootverbose) + printf("%s unregistered\n", pi->pi_name); + return (0); +} + +/* + * Initialize a pseudofs instance + */ +static int +pfs_setup(struct pfs_info *pi, struct vfsconf *vfc) { struct pfs_node *root; int error; @@ -487,18 +540,20 @@ pfs_init(struct pfs_info *pi, struct vfsconf *vfc) /* * Destroy a pseudofs instance */ -int -pfs_uninit(struct pfs_info *pi, struct vfsconf *vfc) +static int +pfs_teardown(struct pfs_info *pi, struct vfsconf *vfc) { int error; + MPASS(pi->pi_root != NULL); + error = (pi->pi_uninit)(pi, vfc); + if (error != 0) + return (error); + pfs_destroy(pi->pi_root); pi->pi_root = NULL; pfs_fileno_uninit(pi); - if (bootverbose) - printf("%s unregistered\n", pi->pi_name); - error = (pi->pi_uninit)(pi, vfc); - return (error); + return (0); } /* diff --git a/sys/fs/pseudofs/pseudofs.h b/sys/fs/pseudofs/pseudofs.h index c60dd7b339d1..461a1d2402e4 100644 --- a/sys/fs/pseudofs/pseudofs.h +++ b/sys/fs/pseudofs/pseudofs.h @@ -31,6 +31,7 @@ #ifndef _PSEUDOFS_H_INCLUDED #define _PSEUDOFS_H_INCLUDED +#include #include /* @@ -188,9 +189,11 @@ typedef int (*pfs_destroy_t)(PFS_DESTROY_ARGS); /* * pfs_info: describes a pseudofs instance * - * The pi_mutex is only used to avoid using the global subr_unit lock - * for unrhdr. The rest of struct pfs_info is only modified during - * vfs_init() and vfs_uninit() of the consumer filesystem. + * The pi_mutex is used to avoid using the global subr_unit lock for unrhdr, and + * the pi_mountlock is used to coordinate initialization of the consumer + * filesystem on first mount. The rest of struct pfs_info is only modified + * during pi_init() and pi_uninit() of the consumer filesystem, which are fully + * serialized. */ struct pfs_info { char pi_name[PFS_FSNAMELEN]; @@ -198,9 +201,11 @@ struct pfs_info { pfs_init_t pi_uninit; /* members below this line are initialized at run time */ + struct sx pi_mountlock; struct pfs_node *pi_root; struct mtx pi_mutex; struct unrhdr *pi_unrhdr; + u_int pi_mounts; }; /* @@ -249,8 +254,8 @@ int pfs_unmount (struct mount *mp, int mntflags); int pfs_root (struct mount *mp, int flags, struct vnode **vpp); int pfs_statfs (struct mount *mp, struct statfs *sbp); -int pfs_init (struct pfs_info *pi, struct vfsconf *vfc); -int pfs_uninit (struct pfs_info *pi, struct vfsconf *vfc); +int pfs_vfsinit (struct pfs_info *pi, struct vfsconf *vfc); +int pfs_vfsuninit (struct pfs_info *pi, struct vfsconf *vfc); /* * Directory structure construction and manipulation @@ -276,9 +281,9 @@ int pfs_destroy (struct pfs_node *pn); #define PSEUDOFS(name, version, flags) \ \ static struct pfs_info name##_info = { \ - #name, \ - name##_init, \ - name##_uninit, \ + .pi_name = #name, \ + .pi_init = name##_init, \ + .pi_uninit = name##_uninit, \ }; \ \ static int \ @@ -287,22 +292,22 @@ _##name##_mount(struct mount *mp) { \ } \ \ static int \ -_##name##_init(struct vfsconf *vfc) { \ - return (pfs_init(&name##_info, vfc)); \ +_##name##_vfsinit(struct vfsconf *vfc) { \ + return (pfs_vfsinit(&name##_info, vfc)); \ } \ \ static int \ -_##name##_uninit(struct vfsconf *vfc) { \ - return (pfs_uninit(&name##_info, vfc)); \ +_##name##_vfsuninit(struct vfsconf *vfc) { \ + return (pfs_vfsuninit(&name##_info, vfc)); \ } \ \ static struct vfsops name##_vfsops = { \ .vfs_cmount = pfs_cmount, \ - .vfs_init = _##name##_init, \ + .vfs_init = _##name##_vfsinit, \ .vfs_mount = _##name##_mount, \ .vfs_root = pfs_root, \ .vfs_statfs = pfs_statfs, \ - .vfs_uninit = _##name##_uninit, \ + .vfs_uninit = _##name##_vfsuninit, \ .vfs_unmount = pfs_unmount, \ }; \ VFS_SET(name##_vfsops, name, VFCF_SYNTHETIC | flags); \ diff --git a/sys/modules/pseudofs/Makefile b/sys/modules/pseudofs/Makefile index cb92b8912c86..3928c950ab70 100644 --- a/sys/modules/pseudofs/Makefile +++ b/sys/modules/pseudofs/Makefile @@ -13,8 +13,8 @@ EXPORT_SYMS= pfs_cmount \ pfs_unmount \ pfs_root \ pfs_statfs \ - pfs_init \ - pfs_uninit \ + pfs_vfsinit \ + pfs_vfsuninit \ pfs_create_dir \ pfs_create_file \ pfs_create_link \