- Make new vnode construction MPSAFE.

- Replace use of lockmgr().
This commit is contained in:
ad 2008-01-25 20:29:28 +00:00
parent d7fd120577
commit de81194d0c
1 changed files with 27 additions and 18 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ptyfs_subr.c,v 1.13 2008/01/24 17:32:53 ad Exp $ */
/* $NetBSD: ptyfs_subr.c,v 1.14 2008/01/25 20:29:28 ad Exp $ */
/*
* Copyright (c) 1993
@ -73,7 +73,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ptyfs_subr.c,v 1.13 2008/01/24 17:32:53 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: ptyfs_subr.c,v 1.14 2008/01/25 20:29:28 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -94,7 +94,7 @@ __KERNEL_RCSID(0, "$NetBSD: ptyfs_subr.c,v 1.13 2008/01/24 17:32:53 ad Exp $");
#include <fs/ptyfs/ptyfs.h>
#include <miscfs/specfs/specdev.h>
static struct lock ptyfs_hashlock;
static kmutex_t ptyfs_hashlock;
static LIST_HEAD(ptyfs_hashhead, ptyfsnode) *ptyfs_used_tbl, *ptyfs_free_tbl;
static u_long ptyfs_used_mask, ptyfs_free_mask; /* size of hash table - 1 */
@ -105,7 +105,7 @@ static void ptyfs_getinfo(struct ptyfsnode *, struct lwp *);
static void ptyfs_hashins(struct ptyfsnode *);
static void ptyfs_hashrem(struct ptyfsnode *);
static struct vnode *ptyfs_used_get(ptyfstype, int, struct mount *);
static struct vnode *ptyfs_used_get(ptyfstype, int, struct mount *, int);
static struct ptyfsnode *ptyfs_free_get(ptyfstype, int, struct lwp *);
static void ptyfs_rehash(kmutex_t *, struct ptyfs_hashhead **,
@ -206,17 +206,22 @@ ptyfs_allocvp(struct mount *mp, struct vnode **vpp, ptyfstype type, int pty,
struct vnode *vp;
int error;
do {
if ((*vpp = ptyfs_used_get(type, pty, mp)) != NULL)
return 0;
} while (lockmgr(&ptyfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0));
retry:
if ((*vpp = ptyfs_used_get(type, pty, mp, LK_EXCLUSIVE)) != NULL)
return 0;
if ((error = getnewvnode(VT_PTYFS, mp, ptyfs_vnodeop_p, &vp)) != 0) {
*vpp = NULL;
lockmgr(&ptyfs_hashlock, LK_RELEASE, NULL);
return error;
}
mutex_enter(&ptyfs_hashlock);
if (ptyfs_used_get(type, pty, mp, 0) != NULL) {
mutex_exit(&ptyfs_hashlock);
ungetnewvnode(vp);
goto retry;
}
vp->v_data = ptyfs = ptyfs_free_get(type, pty, l);
ptyfs->ptyfs_vnode = vp;
@ -237,7 +242,7 @@ ptyfs_allocvp(struct mount *mp, struct vnode **vpp, ptyfstype type, int pty,
ptyfs_hashins(ptyfs);
uvm_vnp_setsize(vp, 0);
lockmgr(&ptyfs_hashlock, LK_RELEASE, NULL);
mutex_exit(&ptyfs_hashlock);
*vpp = vp;
return 0;
@ -259,11 +264,11 @@ ptyfs_freevp(struct vnode *vp)
void
ptyfs_hashinit(void)
{
lockinit(&ptyfs_hashlock, PINOD, "ptyfs_hashlock", 0, 0);
ptyfs_used_tbl = hashinit(desiredvnodes / 4, HASH_LIST, M_UFSMNT,
M_WAITOK, &ptyfs_used_mask);
ptyfs_free_tbl = hashinit(desiredvnodes / 4, HASH_LIST, M_UFSMNT,
M_WAITOK, &ptyfs_free_mask);
mutex_init(&ptyfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
mutex_init(&ptyfs_used_slock, MUTEX_DEFAULT, IPL_NONE);
mutex_init(&ptyfs_free_slock, MUTEX_DEFAULT, IPL_NONE);
}
@ -271,8 +276,8 @@ ptyfs_hashinit(void)
void
ptyfs_hashreinit(void)
{
ptyfs_rehash(&ptyfs_used_slock, &ptyfs_used_tbl, &ptyfs_used_mask);
ptyfs_rehash(&ptyfs_free_slock, &ptyfs_free_tbl, &ptyfs_free_mask);
ptyfs_rehash(&ptyfs_used_slock, &ptyfs_used_tbl, &ptyfs_used_mask);
ptyfs_rehash(&ptyfs_free_slock, &ptyfs_free_tbl, &ptyfs_free_mask);
}
static void
@ -343,7 +348,7 @@ ptyfs_free_get(ptyfstype type, int pty, struct lwp *l)
}
struct vnode *
ptyfs_used_get(ptyfstype type, int pty, struct mount *mp)
ptyfs_used_get(ptyfstype type, int pty, struct mount *mp, int flags)
{
struct ptyfs_hashhead *ppp;
struct ptyfsnode *pp;
@ -356,10 +361,14 @@ loop:
vp = PTYFSTOV(pp);
if (pty == pp->ptyfs_pty && pp->ptyfs_type == type &&
vp->v_mount == mp) {
mutex_enter(&vp->v_interlock);
mutex_exit(&ptyfs_used_slock);
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK))
goto loop;
if (flags == 0) {
mutex_exit(&ptyfs_used_slock);
} else {
mutex_enter(&vp->v_interlock);
mutex_exit(&ptyfs_used_slock);
if (vget(vp, flags | LK_INTERLOCK))
goto loop;
}
return vp;
}
}