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
This commit is contained in:
Rick Macklem 2023-02-04 14:45:23 -08:00
parent d94e0bdc14
commit db5655124c
3 changed files with 9 additions and 3 deletions

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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,