The branch stable/14 has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=93006233f20317dfa18f65f879828910f95b10c5

commit 93006233f20317dfa18f65f879828910f95b10c5
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2025-08-27 22:24:01 +0000
Commit:     Konstantin Belousov <k...@freebsd.org>
CommitDate: 2025-09-04 00:43:14 +0000

    vfs: make vfscount refcounting handle possible kld unload
    
    (cherry picked from commit be8bae67002503baff6bb9fb77fbe6b80f035c33)
---
 sys/kern/vfs_init.c  | 16 ++++++++++++++--
 sys/kern/vfs_mount.c |  7 +++++--
 sys/sys/mount.h      |  1 +
 3 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c
index 64263caaef98..e516d929d9d0 100644
--- a/sys/kern/vfs_init.c
+++ b/sys/kern/vfs_init.c
@@ -108,6 +108,16 @@ struct vattr va_null;
  * Routines having to do with the management of the vnode table.
  */
 
+void
+vfs_unref_vfsconf(struct vfsconf *vfsp)
+{
+       vfsconf_lock();
+       KASSERT(vfsp->vfc_refcount > 0,
+           ("vfs %p refcount underflow %d", vfsp, vfsp->vfc_refcount));
+       vfsp->vfc_refcount--;
+       vfsconf_unlock();
+}
+
 static struct vfsconf *
 vfs_byname_locked(const char *name)
 {
@@ -128,9 +138,11 @@ vfs_byname(const char *name)
 {
        struct vfsconf *vfsp;
 
-       vfsconf_slock();
+       vfsconf_lock();
        vfsp = vfs_byname_locked(name);
-       vfsconf_sunlock();
+       if (vfsp != NULL)
+               vfsp->vfc_refcount++;
+       vfsconf_unlock();
        return (vfsp);
 }
 
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 1990f3714ab6..85d14a943d01 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -683,7 +683,6 @@ vfs_mount_alloc(struct vnode *vp, struct vfsconf *vfsp, 
const char *fspath,
        MPASSERT(mp->mnt_vfs_ops == 1, mp,
            ("vfs_ops should be 1 but %d found", mp->mnt_vfs_ops));
        (void) vfs_busy(mp, MBF_NOWAIT);
-       atomic_add_acq_int(&vfsp->vfc_refcount, 1);
        mp->mnt_op = vfsp->vfc_vfsops;
        mp->mnt_vfc = vfsp;
        mp->mnt_stat.f_type = vfsp->vfc_typenum;
@@ -731,7 +730,6 @@ vfs_mount_destroy(struct mount *mp)
            __FILE__, __LINE__));
        MPPASS(mp->mnt_writeopcount == 0, mp);
        MPPASS(mp->mnt_secondary_writes == 0, mp);
-       atomic_subtract_rel_int(&mp->mnt_vfc->vfc_refcount, 1);
        if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) {
                struct vnode *vp;
 
@@ -769,6 +767,9 @@ vfs_mount_destroy(struct mount *mp)
                vfs_free_addrlist(mp->mnt_export);
                free(mp->mnt_export, M_MOUNT);
        }
+       vfsconf_lock();
+       mp->mnt_vfc->vfc_refcount--;
+       vfsconf_unlock();
        crfree(mp->mnt_cred);
        uma_zfree(mount_zone, mp);
 }
@@ -1133,6 +1134,7 @@ vfs_domount_first(
        if (jailed(td->td_ucred) && (!prison_allow(td->td_ucred,
            vfsp->vfc_prison_flag) || vp == td->td_ucred->cr_prison->pr_root)) {
                vput(vp);
+               vfs_unref_vfsconf(vfsp);
                return (EPERM);
        }
 
@@ -1169,6 +1171,7 @@ vfs_domount_first(
        }
        if (error != 0) {
                vput(vp);
+               vfs_unref_vfsconf(vfsp);
                return (error);
        }
        vn_seqc_write_begin(vp);
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index efe230f518f8..f7e756e03c84 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -1002,6 +1002,7 @@ struct mntarg *mount_argsu(struct mntarg *ma, const char 
*name, const void *val,
 void   statfs_scale_blocks(struct statfs *sf, long max_size);
 struct vfsconf *vfs_byname(const char *);
 struct vfsconf *vfs_byname_kld(const char *, struct thread *td, int *);
+void   vfs_unref_vfsconf(struct vfsconf *vfsp);
 void   vfs_mount_destroy(struct mount *);
 void   vfs_event_signal(fsid_t *, u_int32_t, intptr_t);
 void   vfs_freeopts(struct vfsoptlist *opts);

Reply via email to