git: 2e6615b26bb5 - main - netexport: Move struct netexport in a .h file and refcnt it
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 16 Jun 2026 15:37:10 UTC
The branch main has been updated by rmacklem:
URL: https://cgit.FreeBSD.org/src/commit/?id=2e6615b26bb51ceadc99121f16856aad9345a3cf
commit 2e6615b26bb51ceadc99121f16856aad9345a3cf
Author: Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2026-06-16 15:35:30 +0000
Commit: Rick Macklem <rmacklem@FreeBSD.org>
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_ */