1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-30 16:51:41 +00:00

- Allocate mounts from a uma zone that uses UMA_ZONE_NOFREE to prevent

mount memory from being reclaimed.  This resolves a number of race
   conditions described in vfs_default.c and introduced with the
   VFS_LOCK_GIANT macros.
 - Let the mtx and lock remain valid after the mount structure has been
   freed by using init and fini calls.  Technically fini will never be
   called but is included for completeness.
 - Consistently use lockmgr directly rather than lockmgr to lock and
   vfs_unbusy to unlock.

Discussed with:	tegge
Tested by:	kris
Sponsored by:	Isilon Systems, Inc.
This commit is contained in:
Jeff Roberson 2006-03-31 03:49:51 +00:00
parent 9eee260594
commit a218edceb2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=157322

View File

@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysent.h>
#include <sys/systm.h>
#include <sys/vnode.h>
#include <vm/uma.h>
#include <geom/geom.h>
@ -91,6 +92,7 @@ SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0,
MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
MALLOC_DEFINE(M_VNODE_MARKER, "vnodemarker", "vnode marker");
static uma_zone_t mount_zone;
/* List of mounted filesystems. */
struct mntlist mountlist = TAILQ_HEAD_INITIALIZER(mountlist);
@ -423,6 +425,27 @@ vfs_rel(struct mount *mp)
MNT_IUNLOCK(mp);
}
static int
mount_init(void *mem, int size, int flags)
{
struct mount *mp;
mp = (struct mount *)mem;
mtx_init(&mp->mnt_mtx, "struct mount mtx", NULL, MTX_DEF);
lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
return (0);
}
static void
mount_fini(void *mem, int size)
{
struct mount *mp;
mp = (struct mount *)mem;
lockdestroy(&mp->mnt_lock);
mtx_destroy(&mp->mnt_mtx);
}
/*
* Allocate and initialize the mount point struct.
*/
@ -432,13 +455,13 @@ vfs_mount_alloc(struct vnode *vp, struct vfsconf *vfsp,
{
struct mount *mp;
mp = malloc(sizeof(struct mount), M_MOUNT, M_WAITOK | M_ZERO);
mp = uma_zalloc(mount_zone, M_WAITOK);
bzero(&mp->mnt_startzero,
__rangeof(struct mount, mnt_startzero, mnt_endzero));
TAILQ_INIT(&mp->mnt_nvnodelist);
mp->mnt_nvnodelistsize = 0;
mtx_init(&mp->mnt_mtx, "struct mount mtx", NULL, MTX_DEF);
lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
(void) vfs_busy(mp, LK_NOWAIT, 0, td);
mp->mnt_ref = 0;
(void) vfs_busy(mp, LK_NOWAIT, 0, td);
mp->mnt_op = vfsp->vfc_vfsops;
mp->mnt_vfc = vfsp;
vfsp->vfc_refcount++; /* XXX Unlocked */
@ -466,7 +489,7 @@ vfs_mount_destroy(struct mount *mp, struct thread *td)
{
int i;
vfs_unbusy(mp, td);
lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, td);
MNT_ILOCK(mp);
for (i = 0; mp->mnt_ref && i < 3; i++)
msleep(mp, MNT_MTX(mp), PVFS, "mntref", hz);
@ -512,7 +535,6 @@ vfs_mount_destroy(struct mount *mp, struct thread *td)
mp->mnt_vfc->vfc_refcount--;
if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
panic("unmount: dangling vnode");
lockdestroy(&mp->mnt_lock);
MNT_ILOCK(mp);
if (mp->mnt_kern_flag & MNTK_MWAIT)
wakeup(mp);
@ -526,14 +548,13 @@ vfs_mount_destroy(struct mount *mp, struct thread *td)
mp->mnt_nvnodelistsize = -1000;
mp->mnt_secondary_writes = -1000;
MNT_IUNLOCK(mp);
mtx_destroy(&mp->mnt_mtx);
#ifdef MAC
mac_destroy_mount(mp);
#endif
if (mp->mnt_opt != NULL)
vfs_freeopts(mp->mnt_opt);
crfree(mp->mnt_cred);
free(mp, M_MOUNT);
uma_zfree(mount_zone, mp);
}
static int
@ -1375,6 +1396,9 @@ vfs_mountroot(void)
root_mount_wait();
mount_zone = uma_zcreate("Mountpoints", sizeof(struct mount),
NULL, NULL, mount_init, mount_fini,
UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
devfs_first();
/*