The branch main has been updated by rmacklem:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=2e6615b26bb51ceadc99121f16856aad9345a3cf

commit 2e6615b26bb51ceadc99121f16856aad9345a3cf
Author:     Rick Macklem <[email protected]>
AuthorDate: 2026-06-16 15:35:30 +0000
Commit:     Rick Macklem <[email protected]>
CommitDate: 2026-06-16 15:35:30 +0000

    netexport: Move struct netexport in a .h file and refcnt it
    
    This patch moves "struct netexport" into a separate
    netexport.h file and refcounts the structure, plus adds
    a few fields that will be used in a future NFS server
    commit.
    
    The patch also includes some helper functions for
    handling the netextport structure:
    vfs_netexport_alloc(), vfs_netexport_acquire(),
    vfs_netexport_release() and vfs_netexport_reset().
    
    Reviewed by:    kib, markj
    Differential Revision:  https://reviews.freebsd.org/D57553
---
 sys/kern/vfs_export.c | 79 ++++++++++++++++++++++++++++----------------
 sys/kern/vfs_mount.c  |  2 +-
 sys/sys/mount.h       |  2 ++
 sys/sys/netexport.h   | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 145 insertions(+), 29 deletions(-)

diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index 566dd3d8770d..6dc4eafc4c60 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -58,6 +58,7 @@
 
 #include <netinet/in.h>
 #include <net/radix.h>
+#include <sys/netexport.h>
 
 #include <rpc/types.h>
 #include <rpc/auth.h>
@@ -72,31 +73,13 @@ static struct radix_node_head *vfs_create_addrlist_af(
                    struct radix_node_head **prnh, int off);
 #endif
 static int     vfs_free_netcred(struct radix_node *rn, void *w);
+static struct netexport *vfs_netexport_alloc(void);
+static void    vfs_netexport_reset(struct netexport *nep);
 static void    vfs_free_addrlist_af(struct radix_node_head **prnh);
 static int     vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
                    struct export_args *argp);
 static struct netcred *vfs_export_lookup(struct mount *, struct sockaddr *);
 
-/*
- * Network address lookup element
- */
-struct netcred {
-       struct  radix_node netc_rnodes[2];
-       uint64_t netc_exflags;
-       struct  ucred *netc_anon;
-       int     netc_numsecflavors;
-       int     netc_secflavors[MAXSECFLAVORS];
-};
-
-/*
- * Network export information
- */
-struct netexport {
-       struct  netcred ne_defexported;               /* Default export */
-       struct  radix_node_head *ne4;
-       struct  radix_node_head *ne6;
-};
-
 /*
  * Build hash lists of net addresses and hang them off the mount point.
  * Called by vfs_export() to set up the lists of export addresses.
@@ -350,7 +333,7 @@ vfs_export(struct mount *mp, struct export_args *argp, bool 
do_exjail)
                }
                vfs_free_addrlist(nep);
                mp->mnt_export = NULL;
-               free(nep, M_MOUNT);
+               vfs_netexport_release(nep);
                nep = NULL;
                MNT_ILOCK(mp);
                cr = mp->mnt_exjail;
@@ -369,7 +352,7 @@ vfs_export(struct mount *mp, struct export_args *argp, bool 
do_exjail)
                        MNT_IUNLOCK(mp);
                        if (do_exjail && nep != NULL) {
                                vfs_free_addrlist(nep);
-                               memset(nep, 0, sizeof(*nep));
+                               vfs_netexport_reset(nep);
                                new_nep = true;
                        }
                } else if (mp->mnt_exjail->cr_prison != pr) {
@@ -379,16 +362,14 @@ vfs_export(struct mount *mp, struct export_args *argp, 
bool do_exjail)
                } else
                        MNT_IUNLOCK(mp);
                if (nep == NULL) {
-                       nep = malloc(sizeof(struct netexport), M_MOUNT,
-                           M_WAITOK | M_ZERO);
-                       mp->mnt_export = nep;
+                       nep = mp->mnt_export = vfs_netexport_alloc();
                        new_nep = true;
                }
                if (argp->ex_flags & MNT_EXPUBLIC) {
                        if ((error = vfs_setpublicfs(mp, nep, argp)) != 0) {
                                if (new_nep) {
                                        mp->mnt_export = NULL;
-                                       free(nep, M_MOUNT);
+                                       vfs_netexport_release(nep);
                                }
                                goto out;
                        }
@@ -408,7 +389,7 @@ vfs_export(struct mount *mp, struct export_args *argp, bool 
do_exjail)
                if ((error = vfs_hang_addrlist(mp, nep, argp))) {
                        if (new_nep) {
                                mp->mnt_export = NULL;
-                               free(nep, M_MOUNT);
+                               vfs_netexport_release(nep);
                        }
                        goto out;
                }
@@ -507,7 +488,7 @@ tryagain:
                                mp->mnt_flag &= ~(MNT_EXPORTED | 
MNT_DEFEXPORTED);
                                MNT_IUNLOCK(mp);
                                vfs_free_addrlist(mp->mnt_export);
-                               free(mp->mnt_export, M_MOUNT);
+                               vfs_netexport_release(mp->mnt_export);
                                mp->mnt_export = NULL;
                        } else
                                MNT_IUNLOCK(mp);
@@ -698,3 +679,45 @@ vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, 
uint64_t *extflagsp,
        lockmgr(&mp->mnt_explock, LK_RELEASE, NULL);
        return (0);
 }
+
+static struct netexport *
+vfs_netexport_alloc(void)
+{
+       struct netexport *nep;
+
+       nep = malloc(sizeof(struct netexport), M_MOUNT, M_WAITOK | M_ZERO);
+       refcount_init(&nep->ne_ref, 1);
+       mtx_init(&nep->ne_mtx, "mntexplock", NULL, MTX_DEF);
+       return (nep);
+}
+
+static void
+vfs_netexport_reset(struct netexport *nep)
+{
+
+       KASSERT(refcount_load(&nep->ne_ref) > 0,
+           ("vfs_netexport_reset: invalid refcount"));
+       memset(&nep->ne_startzero, 0, __rangeof(struct netexport, ne_startzero,
+           ne_endzero));
+}
+
+u_int
+vfs_netexport_acquire(struct netexport *nep)
+{
+
+       KASSERT(refcount_load(&nep->ne_ref) > 0,
+           ("vfs_netexport_acquire: invalid refcount"));
+       return (refcount_acquire(&nep->ne_ref));
+}
+
+void
+vfs_netexport_release(struct netexport *nep)
+{
+
+       KASSERT(refcount_load(&nep->ne_ref) > 0,
+           ("vfs_netexport_release: invalid refcount"));
+       if (!refcount_release(&nep->ne_ref))
+               return;
+       mtx_destroy(&nep->ne_mtx);
+       free(nep, M_MOUNT);
+}
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index d7e6683e0446..4d724a0f1c38 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -765,7 +765,7 @@ vfs_mount_destroy(struct mount *mp)
        }
        if (mp->mnt_export != NULL) {
                vfs_free_addrlist(mp->mnt_export);
-               free(mp->mnt_export, M_MOUNT);
+               vfs_netexport_release(mp->mnt_export);
        }
        vfsconf_lock();
        mp->mnt_vfc->vfc_refcount--;
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index fa4c98d93bf8..dc4a49828bbe 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -1061,6 +1061,8 @@ void      vfs_exjail_delete(struct prison *);
 int    vfs_export                       /* process mount export info */
            (struct mount *, struct export_args *, bool);
 void   vfs_free_addrlist(struct netexport *);
+u_int  vfs_netexport_acquire(struct netexport *);
+void   vfs_netexport_release(struct netexport *);
 void   vfs_allocate_syncvnode(struct mount *);
 void   vfs_deallocate_syncvnode(struct mount *);
 int    vfs_donmount(struct thread *td, uint64_t fsflags,
diff --git a/sys/sys/netexport.h b/sys/sys/netexport.h
new file mode 100644
index 000000000000..4d0e7f987f93
--- /dev/null
+++ b/sys/sys/netexport.h
@@ -0,0 +1,91 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SYS_NETEXPORT_H_
+#define _SYS_NETEXPORT_H_
+
+/*
+ * This file must be included after net/radix.h so that "struct radix_node"
+ * is defined.
+ */
+#ifdef _KERNEL
+/*
+ * Network address lookup element
+ */
+struct netcred {
+       struct  radix_node netc_rnodes[2];
+       uint64_t netc_exflags;
+       struct  ucred *netc_anon;
+       int     netc_numsecflavors;
+       int     netc_secflavors[MAXSECFLAVORS];
+};
+
+/*
+ * Network export information
+ * ne_defexported - Protected by mnt_explock.
+ * ne4 - Protected by mnt_explock.
+ * ne6 - Protected by mnt_explock.
+ * The following fields are used by the pNFS server's replenisher process.
+ * ne_pnfsnumfile - Protected by the ne_mtx mutex.
+ * ne_pnfsnextfile - Protected by the vnode lock for the numfiles directory.
+ * ne_pnfsnumcnt - Handled as an atomic.
+ *                 (Although this value doesn't need to be exact, so using
+ *                  an atomic is not really necessary.)
+ */
+struct netexport {
+#define        ne_startzero    ne_defexported
+       struct  netcred ne_defexported;         /* Default export */
+       struct  radix_node_head *ne4;
+       struct  radix_node_head *ne6;
+#define        ne_endzero      ne_mtx
+       struct  mtx ne_mtx;                     /* For ne_pnfsnumfile. */
+       struct  vnode *ne_pnfsnumfile;
+       uint64_t ne_pnfsnextfile;
+       u_int   ne_ref;                         /* Refcount for structure */
+       u_int   ne_pnfsnumcnt;                  /* For stats, not protected. */
+};
+
+#define        MNTEXP_LOCK(n)          mtx_lock(&(n)->ne_mtx)
+#define        MNTEXP_UNLOCK(n)        mtx_unlock(&(n)->ne_mtx)
+#define        MNTEXP_MTX(n)           (&(n)->ne_mtx)
+
+#define        PNFSD_START             ((struct vnode *)-1)
+#define        PNFSD_STOP              ((struct vnode *)-2)
+#define        PNFSD_STOPPED           ((struct vnode *)-3)
+
+#endif /* _KERNEL */
+
+#endif /* !_SYS_NETEXPORT_H_ */

Reply via email to