summaryrefslogtreecommitdiffstats
path: root/sys/fs/nullfs/null_subr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/nullfs/null_subr.c')
-rw-r--r--sys/fs/nullfs/null_subr.c44
1 files changed, 32 insertions, 12 deletions
diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c
index 900bd15..3671f0a 100644
--- a/sys/fs/nullfs/null_subr.c
+++ b/sys/fs/nullfs/null_subr.c
@@ -40,6 +40,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/mount.h>
@@ -59,8 +60,13 @@
#define NULL_NHASH(vp) \
(&null_node_hashtbl[(((uintptr_t)vp)>>LOG2_SIZEVNODE) & null_node_hash])
+
static LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
static u_long null_node_hash;
+struct lock null_hashlock;
+
+static MALLOC_DEFINE(M_NULLFSHASH, "NULLFS hash", "NULLFS hash table");
+MALLOC_DEFINE(M_NULLFSNODE, "NULLFS node", "NULLFS vnode private part");
static int null_node_alloc(struct mount *mp, struct vnode *lowervp,
struct vnode **vpp);
@@ -75,10 +81,19 @@ nullfs_init(vfsp)
struct vfsconf *vfsp;
{
-#ifdef DEBUG
- printf("nullfs_init\n"); /* printed during system boot */
-#endif
- null_node_hashtbl = hashinit(NNULLNODECACHE, M_CACHE, &null_node_hash);
+ NULLFSDEBUG("nullfs_init\n"); /* printed during system boot */
+ null_node_hashtbl = hashinit(NNULLNODECACHE, M_NULLFSHASH, &null_node_hash);
+ lockinit(&null_hashlock, PVFS, "nullhs", 0, 0);
+ return (0);
+}
+
+int
+nullfs_uninit(vfsp)
+ struct vfsconf *vfsp;
+{
+
+ if (null_node_hashtbl)
+ free(null_node_hashtbl, M_NULLFSHASH);
return (0);
}
@@ -103,9 +118,11 @@ null_node_find(mp, lowervp)
*/
hd = NULL_NHASH(lowervp);
loop:
+ lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, p);
for (a = hd->lh_first; a != 0; a = a->null_hash.le_next) {
if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) {
vp = NULLTOV(a);
+ lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
/*
* We need vget for the VXLOCK
* stuff, but we don't want to lock
@@ -118,6 +135,7 @@ loop:
return (vp);
}
}
+ lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
return NULLVP;
}
@@ -134,6 +152,7 @@ null_node_alloc(mp, lowervp, vpp)
struct vnode *lowervp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct null_node_hashhead *hd;
struct null_node *xp;
struct vnode *othervp, *vp;
@@ -144,11 +163,12 @@ null_node_alloc(mp, lowervp, vpp)
* might cause a bogus v_data pointer to get dereferenced
* elsewhere if MALLOC should block.
*/
- MALLOC(xp, struct null_node *, sizeof(struct null_node), M_TEMP, M_WAITOK);
+ MALLOC(xp, struct null_node *, sizeof(struct null_node),
+ M_NULLFSNODE, M_WAITOK);
error = getnewvnode(VT_NULL, mp, null_vnodeop_p, vpp);
if (error) {
- FREE(xp, M_TEMP);
+ FREE(xp, M_NULLFSNODE);
return (error);
}
vp = *vpp;
@@ -164,15 +184,17 @@ null_node_alloc(mp, lowervp, vpp)
*/
othervp = null_node_find(mp, lowervp);
if (othervp) {
- FREE(xp, M_TEMP);
+ FREE(xp, M_NULLFSNODE);
vp->v_type = VBAD; /* node is discarded */
vp->v_usecount = 0; /* XXX */
*vpp = othervp;
return 0;
};
+ lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, p);
VREF(lowervp); /* Extra VREF will be vrele'd in null_node_create */
hd = NULL_NHASH(lowervp);
LIST_INSERT_HEAD(hd, xp, null_hash);
+ lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
return 0;
}
@@ -196,7 +218,7 @@ null_node_create(mp, lowervp, newvpp)
* null_node_find has taken another reference
* to the alias vnode.
*/
-#ifdef DEBUG
+#ifdef NULLFS_DEBUG
vprint("null_node_create: exists", aliasvp);
#endif
/* VREF(aliasvp); --- done in null_node_find */
@@ -206,9 +228,7 @@ null_node_create(mp, lowervp, newvpp)
/*
* Get new vnode.
*/
-#ifdef DEBUG
- printf("null_node_create: create new alias vnode\n");
-#endif
+ NULLFSDEBUG("null_node_create: create new alias vnode\n");
/*
* Make new vnode reference the null_node.
@@ -233,7 +253,7 @@ null_node_create(mp, lowervp, newvpp)
};
#endif
-#ifdef DEBUG
+#ifdef NULLFS_DEBUG
vprint("null_node_create: alias", aliasvp);
vprint("null_node_create: lower", lowervp);
#endif
OpenPOWER on IntegriCloud