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_ */
