aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2023-02-04 22:45:23 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2023-02-04 22:45:23 +0000
commitdb5655124ca4047ac397b9421ca4a08868a49ae9 (patch)
tree3e4f3104e2ebfcd99b50c07c7b8659b61124f87a
parentd94e0bdc1498fa95d1de0b54dfa9af0d73c0fb21 (diff)
downloadsrc-db5655124ca4047ac397b9421ca4a08868a49ae9.tar.gz
src-db5655124ca4047ac397b9421ca4a08868a49ae9.zip
vfs_mount.c: Free exports structures in vfs_destroy_mount()
During testing of exporting file systems in jails, I noticed that the export structures on a mount were not being free'd when the mount is dismounted. This bug appears to have been in the system for a very long time. It would have resulted in a slow memory leak when exported file systems were dismounted. Prior to r362158, freeing the structures during dismount would not have been safe, since VFS_CHECKEXP() returned a pointer into an export structure, which might still have been used by the NFS server for an in-progress RPC when the file system is dismounted. r362158 fixed this, so it should now be safe to free the structures in vfs_mount_destroy(), which is what this patch does. Reviewed by: kib MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D38385
-rw-r--r--sys/kern/vfs_export.c7
-rw-r--r--sys/kern/vfs_mount.c4
-rw-r--r--sys/sys/mount.h1
3 files changed, 9 insertions, 3 deletions
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index 024011de4c89..cab37ce205ad 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -70,7 +70,6 @@ static MALLOC_DEFINE(M_NETADDR, "export_host", "Export host address structure");
static struct radix_node_head *vfs_create_addrlist_af(
struct radix_node_head **prnh, int off);
#endif
-static void vfs_free_addrlist(struct netexport *nep);
static int vfs_free_netcred(struct radix_node *rn, void *w);
static void vfs_free_addrlist_af(struct radix_node_head **prnh);
static int vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
@@ -274,7 +273,7 @@ vfs_free_addrlist_af(struct radix_node_head **prnh)
/*
* Free the net address hash lists that are hanging off the mount points.
*/
-static void
+void
vfs_free_addrlist(struct netexport *nep)
{
struct ucred *cred;
@@ -285,8 +284,10 @@ vfs_free_addrlist(struct netexport *nep)
vfs_free_addrlist_af(&nep->ne6);
cred = nep->ne_defexported.netc_anon;
- if (cred != NULL)
+ if (cred != NULL) {
crfree(cred);
+ nep->ne_defexported.netc_anon = NULL;
+ }
}
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 67a72f095786..430bafc8502f 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -761,6 +761,10 @@ vfs_mount_destroy(struct mount *mp)
#endif
if (mp->mnt_opt != NULL)
vfs_freeopts(mp->mnt_opt);
+ if (mp->mnt_export != NULL) {
+ vfs_free_addrlist(mp->mnt_export);
+ free(mp->mnt_export, M_MOUNT);
+ }
crfree(mp->mnt_cred);
uma_zfree(mount_zone, mp);
}
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 4bfc77b7f1a1..5f02f261b8f4 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -1017,6 +1017,7 @@ void vfs_periodic(struct mount *, int);
int vfs_busy(struct mount *, int);
int vfs_export /* process mount export info */
(struct mount *, struct export_args *);
+void vfs_free_addrlist(struct netexport *);
void vfs_allocate_syncvnode(struct mount *);
void vfs_deallocate_syncvnode(struct mount *);
int vfs_donmount(struct thread *td, uint64_t fsflags,