Module Name:    src
Committed By:   tls
Date:           Sun Aug 10 06:56:06 UTC 2014

Modified Files:
        src/sys/miscfs/deadfs [tls-earlyentropy]: dead_vnops.c
        src/sys/miscfs/fdesc [tls-earlyentropy]: fdesc.h fdesc_vfsops.c
            fdesc_vnops.c
        src/sys/miscfs/fifofs [tls-earlyentropy]: fifo_vnops.c
        src/sys/miscfs/genfs [tls-earlyentropy]: layer.h layer_extern.h
            layer_subr.c layer_vfsops.c layer_vnops.c
        src/sys/miscfs/kernfs [tls-earlyentropy]: files.kernfs kernfs.h
            kernfs_vfsops.c kernfs_vnops.c
        src/sys/miscfs/nullfs [tls-earlyentropy]: null_vfsops.c
        src/sys/miscfs/overlay [tls-earlyentropy]: overlay_vfsops.c
        src/sys/miscfs/procfs [tls-earlyentropy]: procfs.h procfs_linux.c
            procfs_subr.c procfs_vfsops.c procfs_vnops.c
        src/sys/miscfs/specfs [tls-earlyentropy]: spec_vnops.c specdev.h
        src/sys/miscfs/umapfs [tls-earlyentropy]: umap_vfsops.c
Removed Files:
        src/sys/miscfs/kernfs [tls-earlyentropy]: kernfs_subr.c

Log Message:
Rebase.


To generate a diff of this commit:
cvs rdiff -u -r1.56 -r1.56.2.1 src/sys/miscfs/deadfs/dead_vnops.c
cvs rdiff -u -r1.21 -r1.21.26.1 src/sys/miscfs/fdesc/fdesc.h
cvs rdiff -u -r1.88 -r1.88.2.1 src/sys/miscfs/fdesc/fdesc_vfsops.c
cvs rdiff -u -r1.119 -r1.119.2.1 src/sys/miscfs/fdesc/fdesc_vnops.c
cvs rdiff -u -r1.74 -r1.74.2.1 src/sys/miscfs/fifofs/fifo_vnops.c
cvs rdiff -u -r1.14 -r1.14.32.1 src/sys/miscfs/genfs/layer.h
cvs rdiff -u -r1.35 -r1.35.2.1 src/sys/miscfs/genfs/layer_extern.h \
    src/sys/miscfs/genfs/layer_subr.c
cvs rdiff -u -r1.43 -r1.43.2.1 src/sys/miscfs/genfs/layer_vfsops.c
cvs rdiff -u -r1.57 -r1.57.2.1 src/sys/miscfs/genfs/layer_vnops.c
cvs rdiff -u -r1.4 -r1.4.34.1 src/sys/miscfs/kernfs/files.kernfs
cvs rdiff -u -r1.37 -r1.37.12.1 src/sys/miscfs/kernfs/kernfs.h
cvs rdiff -u -r1.26 -r0 src/sys/miscfs/kernfs/kernfs_subr.c
cvs rdiff -u -r1.93 -r1.93.2.1 src/sys/miscfs/kernfs/kernfs_vfsops.c
cvs rdiff -u -r1.150 -r1.150.2.1 src/sys/miscfs/kernfs/kernfs_vnops.c
cvs rdiff -u -r1.87 -r1.87.2.1 src/sys/miscfs/nullfs/null_vfsops.c
cvs rdiff -u -r1.60 -r1.60.2.1 src/sys/miscfs/overlay/overlay_vfsops.c
cvs rdiff -u -r1.69 -r1.69.2.1 src/sys/miscfs/procfs/procfs.h
cvs rdiff -u -r1.67 -r1.67.2.1 src/sys/miscfs/procfs/procfs_linux.c
cvs rdiff -u -r1.104 -r1.104.2.1 src/sys/miscfs/procfs/procfs_subr.c
cvs rdiff -u -r1.90 -r1.90.2.1 src/sys/miscfs/procfs/procfs_vfsops.c
cvs rdiff -u -r1.189 -r1.189.2.1 src/sys/miscfs/procfs/procfs_vnops.c
cvs rdiff -u -r1.143 -r1.143.2.1 src/sys/miscfs/specfs/spec_vnops.c
cvs rdiff -u -r1.42 -r1.42.2.1 src/sys/miscfs/specfs/specdev.h
cvs rdiff -u -r1.91 -r1.91.2.1 src/sys/miscfs/umapfs/umap_vfsops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/miscfs/deadfs/dead_vnops.c
diff -u src/sys/miscfs/deadfs/dead_vnops.c:1.56 src/sys/miscfs/deadfs/dead_vnops.c:1.56.2.1
--- src/sys/miscfs/deadfs/dead_vnops.c:1.56	Thu Feb 27 16:51:38 2014
+++ src/sys/miscfs/deadfs/dead_vnops.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: dead_vnops.c,v 1.56 2014/02/27 16:51:38 hannken Exp $	*/
+/*	$NetBSD: dead_vnops.c,v 1.56.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dead_vnops.c,v 1.56 2014/02/27 16:51:38 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dead_vnops.c,v 1.56.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -87,6 +87,8 @@ const struct vnodeopv_entry_desc dead_vn
 	{ &vop_close_desc, dead_close },		/* close */
 	{ &vop_read_desc, dead_read },			/* read */
 	{ &vop_write_desc, dead_write },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_fcntl_desc, dead_fcntl },		/* fcntl */
 	{ &vop_ioctl_desc, dead_ioctl },		/* ioctl */
 	{ &vop_poll_desc, dead_poll },			/* poll */

Index: src/sys/miscfs/fdesc/fdesc.h
diff -u src/sys/miscfs/fdesc/fdesc.h:1.21 src/sys/miscfs/fdesc/fdesc.h:1.21.26.1
--- src/sys/miscfs/fdesc/fdesc.h:1.21	Tue Sep 27 01:22:12 2011
+++ src/sys/miscfs/fdesc/fdesc.h	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: fdesc.h,v 1.21 2011/09/27 01:22:12 christos Exp $	*/
+/*	$NetBSD: fdesc.h,v 1.21.26.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -56,11 +56,10 @@ typedef enum {
 } fdntype;
 
 struct fdescnode {
-	LIST_ENTRY(fdescnode) fd_hash;	/* Hash list */
 	struct vnode	*fd_vnode;	/* Back ptr to vnode */
 	fdntype		fd_type;	/* Type of this node */
 	unsigned	fd_fd;		/* Fd to be dup'ed */
-	char		*fd_link;	/* Link to fd/n */
+	const char	*fd_link;	/* Link to fd/n */
 	int		fd_ix;		/* filesystem index */
 };
 

Index: src/sys/miscfs/fdesc/fdesc_vfsops.c
diff -u src/sys/miscfs/fdesc/fdesc_vfsops.c:1.88 src/sys/miscfs/fdesc/fdesc_vfsops.c:1.88.2.1
--- src/sys/miscfs/fdesc/fdesc_vfsops.c:1.88	Sun Mar 23 15:21:16 2014
+++ src/sys/miscfs/fdesc/fdesc_vfsops.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: fdesc_vfsops.c,v 1.88 2014/03/23 15:21:16 hannken Exp $	*/
+/*	$NetBSD: fdesc_vfsops.c,v 1.88.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993, 1995
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdesc_vfsops.c,v 1.88 2014/03/23 15:21:16 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdesc_vfsops.c,v 1.88.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -78,7 +78,7 @@ int
 fdesc_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
 {
 	struct lwp *l = curlwp;
-	int error = 0;
+	int error = 0, ix;
 	struct vnode *rvp;
 
 	if (mp->mnt_flag & MNT_GETARGS) {
@@ -91,12 +91,11 @@ fdesc_mount(struct mount *mp, const char
 	if (mp->mnt_flag & MNT_UPDATE)
 		return (EOPNOTSUPP);
 
-	error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp);
+	ix = FD_ROOT;
+	error = vcache_get(mp, &ix, sizeof(ix), &rvp);
 	if (error)
-		return (error);
+		return error;
 
-	rvp->v_type = VDIR;
-	rvp->v_vflag |= VV_ROOT;
 	mp->mnt_stat.f_namemax = FDESC_MAXNAMLEN;
 	mp->mnt_flag |= MNT_LOCAL;
 	mp->mnt_data = rvp;
@@ -104,7 +103,6 @@ fdesc_mount(struct mount *mp, const char
 
 	error = set_statvfs_info(path, UIO_USERSPACE, "fdesc", UIO_SYSSPACE,
 	    mp->mnt_op->vfs_name, mp, l);
-	VOP_UNLOCK(rvp);
 	return error;
 }
 
@@ -174,6 +172,66 @@ fdesc_vget(struct mount *mp, ino_t ino,
 	return (EOPNOTSUPP);
 }
 
+int
+fdesc_loadvnode(struct mount *mp, struct vnode *vp,
+    const void *key, size_t key_len, const void **new_key)
+{
+	int ix;
+	struct fdescnode *fd;
+
+	KASSERT(key_len == sizeof(ix));
+	memcpy(&ix, key, key_len);
+
+	fd = kmem_alloc(sizeof(struct fdescnode), KM_SLEEP);
+	fd->fd_fd = -1;
+	fd->fd_link = NULL;
+	fd->fd_ix = ix;
+	fd->fd_vnode = vp;
+	vp->v_tag = VT_FDESC;
+	vp->v_op = fdesc_vnodeop_p;
+	vp->v_data = fd;
+	switch (ix) {
+	case FD_ROOT:
+		fd->fd_type = Froot;
+		vp->v_type = VDIR;
+		vp->v_vflag |= VV_ROOT;
+		break;
+	case FD_DEVFD:
+		fd->fd_type = Fdevfd;
+		vp->v_type = VDIR;
+		break;
+	case FD_CTTY:
+		fd->fd_type = Fctty;
+		vp->v_type = VNON;
+		break;
+	case FD_STDIN:
+		fd->fd_type = Flink;
+		fd->fd_link = "fd/0";
+		vp->v_type = VLNK;
+		break;
+	case FD_STDOUT:
+		fd->fd_type = Flink;
+		fd->fd_link = "fd/1";
+		vp->v_type = VLNK;
+		break;
+	case FD_STDERR:
+		fd->fd_type = Flink;
+		fd->fd_link = "fd/2";
+		vp->v_type = VLNK;
+		break;
+	default:
+		KASSERT(ix >= FD_DESC);
+		fd->fd_type = Fdesc;
+		fd->fd_fd = ix - FD_DESC;
+		vp->v_type = VNON;
+		break;
+	}
+	uvm_vnp_setsize(vp, 0);
+	*new_key = &fd->fd_ix;
+
+	return 0;
+}
+
 extern const struct vnodeopv_desc fdesc_vnodeop_opv_desc;
 
 const struct vnodeopv_desc * const fdesc_vnodeopv_descs[] = {
@@ -192,6 +250,7 @@ struct vfsops fdesc_vfsops = {
 	.vfs_statvfs = genfs_statvfs,
 	.vfs_sync = fdesc_sync,
 	.vfs_vget = fdesc_vget,
+	.vfs_loadvnode = fdesc_loadvnode,
 	.vfs_fhtovp = (void *)eopnotsupp,
 	.vfs_vptofh = (void *)eopnotsupp,
 	.vfs_init = fdesc_init,

Index: src/sys/miscfs/fdesc/fdesc_vnops.c
diff -u src/sys/miscfs/fdesc/fdesc_vnops.c:1.119 src/sys/miscfs/fdesc/fdesc_vnops.c:1.119.2.1
--- src/sys/miscfs/fdesc/fdesc_vnops.c:1.119	Thu Mar 20 18:04:05 2014
+++ src/sys/miscfs/fdesc/fdesc_vnops.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: fdesc_vnops.c,v 1.119 2014/03/20 18:04:05 christos Exp $	*/
+/*	$NetBSD: fdesc_vnops.c,v 1.119.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.c,v 1.119 2014/03/20 18:04:05 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.c,v 1.119.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -69,21 +69,12 @@ __KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.
 
 #define cttyvp(p) ((p)->p_lflag & PL_CONTROLT ? (p)->p_session->s_ttyvp : NULL)
 
-static kmutex_t fdcache_lock;
-
 dev_t devctty;
 
 #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)
 FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2
 #endif
 
-#define	NFDCACHE 4
-
-#define FD_NHASH(ix) \
-	(&fdhashtbl[(ix) & fdhash])
-LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl;
-u_long fdhash;
-
 int	fdesc_lookup(void *);
 #define	fdesc_create	genfs_eopnotsupp
 #define	fdesc_mknod	genfs_eopnotsupp
@@ -139,6 +130,8 @@ const struct vnodeopv_entry_desc fdesc_v
 	{ &vop_setattr_desc, fdesc_setattr },		/* setattr */
 	{ &vop_read_desc, fdesc_read },			/* read */
 	{ &vop_write_desc, fdesc_write },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_ioctl_desc, fdesc_ioctl },		/* ioctl */
 	{ &vop_fcntl_desc, fdesc_fcntl },		/* fcntl */
 	{ &vop_poll_desc, fdesc_poll },			/* poll */
@@ -185,76 +178,11 @@ fdesc_init(void)
 	/* locate the major number */
 	cttymajor = devsw_name2chr("ctty", NULL, 0);
 	devctty = makedev(cttymajor, 0);
-	mutex_init(&fdcache_lock, MUTEX_DEFAULT, IPL_NONE);
-	fdhashtbl = hashinit(NFDCACHE, HASH_LIST, true, &fdhash);
 }
 
-/*
- * Free hash table.
- */
 void
 fdesc_done(void)
 {
-	hashdone(fdhashtbl, HASH_LIST, fdhash);
-	mutex_destroy(&fdcache_lock);
-}
-
-/*
- * Return a locked vnode of the correct type.
- */
-int
-fdesc_allocvp(fdntype ftype, int ix, struct mount *mp, struct vnode **vpp)
-{
-	struct fdhashhead *fc;
-	struct fdescnode *fd;
-	int error = 0;
-
-	fc = FD_NHASH(ix);
-loop:
-	mutex_enter(&fdcache_lock);
-	LIST_FOREACH(fd, fc, fd_hash) {
-		if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) {
-			mutex_enter(fd->fd_vnode->v_interlock);
-			mutex_exit(&fdcache_lock);
-			if (vget(fd->fd_vnode, LK_EXCLUSIVE))
-				goto loop;
-			*vpp = fd->fd_vnode;
-			return 0;
-		}
-	}
-	mutex_exit(&fdcache_lock);
-
-	error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, NULL, vpp);
-	if (error)
-		return error;
-
-	mutex_enter(&fdcache_lock);
-	LIST_FOREACH(fd, fc, fd_hash) {
-		if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) {
-			/*
-			 * Another thread beat us, push back freshly
-			 * allocated vnode and retry.
-			 */
-			mutex_exit(&fdcache_lock);
-			ungetnewvnode(*vpp);
-			goto loop;
-		}
-	}
-
-	fd = malloc(sizeof(struct fdescnode), M_TEMP, M_WAITOK);
-	(*vpp)->v_data = fd;
-	fd->fd_vnode = *vpp;
-	fd->fd_type = ftype;
-	fd->fd_fd = -1;
-	fd->fd_link = 0;
-	fd->fd_ix = ix;
-	uvm_vnp_setsize(*vpp, 0);
-	error = VOP_LOCK(*vpp, LK_EXCLUSIVE);
-	KASSERT(error == 0);
-	LIST_INSERT_HEAD(fc, fd, fd_hash);
-	mutex_exit(&fdcache_lock);
-
-	return 0;
 }
 
 /*
@@ -276,9 +204,7 @@ fdesc_lookup(void *v)
 	const char *pname = cnp->cn_nameptr;
 	struct proc *p = l->l_proc;
 	unsigned fd = 0;
-	int error;
-	struct vnode *fvp;
-	const char *ln;
+	int error, ix = -1;
 	fdtab_t *dt;
 
 	dt = curlwp->l_fd->fd_dt;
@@ -299,11 +225,7 @@ fdesc_lookup(void *v)
 
 	case Froot:
 		if (cnp->cn_namelen == 2 && memcmp(pname, "fd", 2) == 0) {
-			error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp);
-			if (error)
-				goto bad;
-			*vpp = fvp;
-			fvp->v_type = VDIR;
+			ix = FD_DEVFD;
 			goto good;
 		}
 
@@ -313,58 +235,35 @@ fdesc_lookup(void *v)
 				error = ENXIO;
 				goto bad;
 			}
-			error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp);
-			if (error)
-				goto bad;
-			*vpp = fvp;
-			fvp->v_type = VCHR;
+			ix = FD_CTTY;
 			goto good;
 		}
 
-		ln = 0;
 		switch (cnp->cn_namelen) {
 		case 5:
 			if (memcmp(pname, "stdin", 5) == 0) {
-				ln = "fd/0";
-				fd = FD_STDIN;
+				ix = FD_STDIN;
+				goto good;
 			}
 			break;
 		case 6:
 			if (memcmp(pname, "stdout", 6) == 0) {
-				ln = "fd/1";
-				fd = FD_STDOUT;
-			} else
-			if (memcmp(pname, "stderr", 6) == 0) {
-				ln = "fd/2";
-				fd = FD_STDERR;
+				ix = FD_STDOUT;
+				goto good;
+			} else if (memcmp(pname, "stderr", 6) == 0) {
+				ix = FD_STDERR;
+				goto good;
 			}
 			break;
 		}
 
-		if (ln) {
-			error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp);
-			if (error)
-				goto bad;
-			/* XXXUNCONST */
-			VTOFDESC(fvp)->fd_link = __UNCONST(ln);
-			*vpp = fvp;
-			fvp->v_type = VLNK;
-			goto good;
-		} else {
-			error = ENOENT;
-			goto bad;
-		}
-
-		/* FALL THROUGH */
+		error = ENOENT;
+		goto bad;
 
 	case Fdevfd:
 		if (cnp->cn_namelen == 2 && memcmp(pname, "..", 2) == 0) {
-			VOP_UNLOCK(dvp);
-			error = fdesc_root(dvp->v_mount, vpp);
-			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
-			if (error)
-				goto bad;
-			return (error);
+			ix = FD_ROOT;
+			goto good;
 		}
 
 		fd = 0;
@@ -385,21 +284,18 @@ fdesc_lookup(void *v)
 			goto bad;
 		}
 
-		error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp);
-		if (error)
-			goto bad;
-		VTOFDESC(fvp)->fd_fd = fd;
-		*vpp = fvp;
+		ix = FD_DESC + fd;
 		goto good;
 	}
 
 bad:
 	*vpp = NULL;
-	return (error);
+	return error;
 
 good:
-	VOP_UNLOCK(*vpp);
-	return (0);
+	KASSERT(ix != -1);
+	error = vcache_get(dvp->v_mount, &ix, sizeof(ix), vpp);
+	return error;
 }
 
 int
@@ -793,8 +689,8 @@ fdesc_readlink(void *v)
 		return (EPERM);
 
 	if (VTOFDESC(vp)->fd_type == Flink) {
-		char *ln = VTOFDESC(vp)->fd_link;
-		error = uiomove(ln, strlen(ln), ap->a_uio);
+		const char *ln = VTOFDESC(vp)->fd_link;
+		error = uiomove(__UNCONST(ln), strlen(ln), ap->a_uio);
 	} else {
 		error = EOPNOTSUPP;
 	}
@@ -942,13 +838,15 @@ fdesc_inactive(void *v)
 		struct vnode *a_vp;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
+	struct fdescnode *fd = VTOFDESC(vp);
 
 	/*
 	 * Clear out the v_type field to avoid
-	 * nasty things happening in vgone().
+	 * nasty things happening on reclaim.
 	 */
+	if (fd->fd_type == Fctty || fd->fd_type == Fdesc)
+		vp->v_type = VNON;
 	VOP_UNLOCK(vp);
-	vp->v_type = VNON;
 	return (0);
 }
 
@@ -961,11 +859,9 @@ fdesc_reclaim(void *v)
 	struct vnode *vp = ap->a_vp;
 	struct fdescnode *fd = VTOFDESC(vp);
 
-	mutex_enter(&fdcache_lock);
-	LIST_REMOVE(fd, fd_hash);
-	free(vp->v_data, M_TEMP);
-	vp->v_data = 0;
-	mutex_exit(&fdcache_lock);
+	vp->v_data = NULL;
+	vcache_remove(vp->v_mount, &fd->fd_ix, sizeof(fd->fd_ix));
+	kmem_free(fd, sizeof(struct fdescnode));
 
 	return (0);
 }

Index: src/sys/miscfs/fifofs/fifo_vnops.c
diff -u src/sys/miscfs/fifofs/fifo_vnops.c:1.74 src/sys/miscfs/fifofs/fifo_vnops.c:1.74.2.1
--- src/sys/miscfs/fifofs/fifo_vnops.c:1.74	Fri Feb  7 15:29:22 2014
+++ src/sys/miscfs/fifofs/fifo_vnops.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: fifo_vnops.c,v 1.74 2014/02/07 15:29:22 hannken Exp $	*/
+/*	$NetBSD: fifo_vnops.c,v 1.74.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -58,7 +58,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fifo_vnops.c,v 1.74 2014/02/07 15:29:22 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fifo_vnops.c,v 1.74.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -116,7 +116,6 @@ fifo_lookup(void *v)
  * Open called to set up a new instance of a fifo or
  * to find an active instance of a fifo.
  */
-/* ARGSUSED */
 static int
 fifo_open(void *v)
 {
@@ -132,14 +131,13 @@ fifo_open(void *v)
 	int		error;
 
 	vp = ap->a_vp;
+	KASSERT(VOP_ISLOCKED(vp));
 
 	if ((fip = vp->v_fifoinfo) == NULL) {
 		fip = kmem_alloc(sizeof(*fip), KM_SLEEP);
-		vp->v_fifoinfo = fip;
 		error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL);
 		if (error != 0) {
 			kmem_free(fip, sizeof(*fip));
-			vp->v_fifoinfo = NULL;
 			return (error);
 		}
 		fip->fi_readsock = rso;
@@ -147,17 +145,15 @@ fifo_open(void *v)
 		if (error != 0) {
 			(void)soclose(rso);
 			kmem_free(fip, sizeof(*fip));
-			vp->v_fifoinfo = NULL;
 			return (error);
 		}
 		fip->fi_writesock = wso;
 		solock(wso);
-		if ((error = unp_connect2(wso, rso, PRU_CONNECT2)) != 0) {
+		if ((error = unp_connect2(wso, rso)) != 0) {
 			sounlock(wso);
 			(void)soclose(wso);
 			(void)soclose(rso);
 			kmem_free(fip, sizeof(*fip));
-			vp->v_fifoinfo = NULL;
 			return (error);
 		}
 		fip->fi_readers = 0;
@@ -166,6 +162,7 @@ fifo_open(void *v)
 		rso->so_state |= SS_CANTSENDMORE;
 		cv_init(&fip->fi_rcv, "fiford");
 		cv_init(&fip->fi_wcv, "fifowr");
+		vp->v_fifoinfo = fip;
 	} else {
 		wso = fip->fi_writesock;
 		rso = fip->fi_readsock;
@@ -636,6 +633,8 @@ const struct vnodeopv_entry_desc fifo_vn
 	{ &vop_setattr_desc, genfs_ebadf },		/* setattr */
 	{ &vop_read_desc, fifo_read },			/* read */
 	{ &vop_write_desc, fifo_write },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_ioctl_desc, fifo_ioctl },		/* ioctl */
 	{ &vop_poll_desc, fifo_poll },			/* poll */
 	{ &vop_kqfilter_desc, fifo_kqfilter },		/* kqfilter */

Index: src/sys/miscfs/genfs/layer.h
diff -u src/sys/miscfs/genfs/layer.h:1.14 src/sys/miscfs/genfs/layer.h:1.14.32.1
--- src/sys/miscfs/genfs/layer.h:1.14	Sun Jun  6 08:01:31 2010
+++ src/sys/miscfs/genfs/layer.h	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: layer.h,v 1.14 2010/06/06 08:01:31 hannken Exp $	*/
+/*	$NetBSD: layer.h,v 1.14.32.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1999 National Aeronautics & Space Administration
@@ -78,27 +78,16 @@ struct layer_args {
 
 #ifdef _KERNEL
 
-struct layer_node;
-
-LIST_HEAD(layer_node_hashhead, layer_node);
-
 struct layer_mount {
 	struct mount		*layerm_vfs;
 	struct vnode		*layerm_rootvp;	/* Ref to root layer_node */
 	u_int			layerm_flags;	/* mount point layer flags */
 	u_int			layerm_size;	/* size of fs's struct node */
-	enum vtype		layerm_tag;	/* vtag of our vnodes */
+	enum vtagtype		layerm_tag;	/* vtag of our vnodes */
 	int				/* bypass routine for this mount */
 				(*layerm_bypass)(void *);
-	int			(*layerm_alloc)	/* alloc a new layer node */
-				(struct mount *, struct vnode *,
-						struct vnode **);
 	int			(**layerm_vnodeop_p)	/* ops for our nodes */
 				(void *);
-	struct layer_node_hashhead	/* head of hash list for layer_nodes */
-				*layerm_node_hashtbl;
-	u_long			layerm_node_hash; /* hash mask for hash chain */
-	kmutex_t		layerm_hashlock; /* interlock for hash chain. */
 };
 
 #define	LAYERFS_MFLAGS		0x00000fff	/* reserved layer mount flags */
@@ -108,7 +97,6 @@ struct layer_mount {
  * A cache of vnode references
  */
 struct layer_node {
-	LIST_ENTRY(layer_node)	layer_hash;	/* Hash list */
 	struct vnode	        *layer_lowervp;	/* VREFed once */
 	struct vnode		*layer_vnode;	/* Back pointer */
 	unsigned int		layer_flags;	/* locking, etc. */

Index: src/sys/miscfs/genfs/layer_extern.h
diff -u src/sys/miscfs/genfs/layer_extern.h:1.35 src/sys/miscfs/genfs/layer_extern.h:1.35.2.1
--- src/sys/miscfs/genfs/layer_extern.h:1.35	Thu Feb 27 16:51:38 2014
+++ src/sys/miscfs/genfs/layer_extern.h	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: layer_extern.h,v 1.35 2014/02/27 16:51:38 hannken Exp $	*/
+/*	$NetBSD: layer_extern.h,v 1.35.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1999 National Aeronautics & Space Administration
@@ -76,14 +76,7 @@
 /* Routines to manage nodes. */
 void	layerfs_init(void);
 void	layerfs_done(void);
-int	layer_node_alloc(struct mount *, struct vnode *, struct vnode **);
 int	layer_node_create(struct mount *, struct vnode *, struct vnode **);
-struct vnode *layer_node_find(struct mount *, struct vnode *);
-
-#define LOG2_SIZEVNODE	7		/* log2(sizeof struct vnode) */
-#define LAYER_NHASH(lmp, vp) \
-	(&((lmp)->layerm_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & \
-		(lmp)->layerm_node_hash]))
 
 /* VFS routines */
 int	layerfs_start(struct mount *, int);
@@ -91,6 +84,8 @@ int	layerfs_root(struct mount *, struct 
 int	layerfs_quotactl(struct mount *, struct quotactl_args *);
 int	layerfs_statvfs(struct mount *, struct statvfs *);
 int	layerfs_sync(struct mount *, int, struct kauth_cred *);
+int	layerfs_loadvnode(struct mount *,  struct vnode *,
+	    const void *, size_t, const void **);
 int	layerfs_vget(struct mount *, ino_t, struct vnode **);
 int	layerfs_fhtovp(struct mount *, struct fid *, struct vnode **);
 int	layerfs_vptofh(struct vnode *, struct fid *, size_t *);
Index: src/sys/miscfs/genfs/layer_subr.c
diff -u src/sys/miscfs/genfs/layer_subr.c:1.35 src/sys/miscfs/genfs/layer_subr.c:1.35.2.1
--- src/sys/miscfs/genfs/layer_subr.c:1.35	Mon Feb 10 11:23:14 2014
+++ src/sys/miscfs/genfs/layer_subr.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: layer_subr.c,v 1.35 2014/02/10 11:23:14 hannken Exp $	*/
+/*	$NetBSD: layer_subr.c,v 1.35.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1999 National Aeronautics & Space Administration
@@ -69,7 +69,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: layer_subr.c,v 1.35 2014/02/10 11:23:14 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: layer_subr.c,v 1.35.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -81,7 +81,6 @@ __KERNEL_RCSID(0, "$NetBSD: layer_subr.c
 #include <sys/kmem.h>
 #include <sys/malloc.h>
 
-#include <miscfs/specfs/specdev.h>
 #include <miscfs/genfs/layer.h>
 #include <miscfs/genfs/layer_extern.h>
 
@@ -110,156 +109,18 @@ layerfs_done(void)
 }
 
 /*
- * layer_node_find: find and return alias for lower vnode or NULL.
- *
- * => Return alias vnode referenced. if already exists.
- * => The layermp's hashlock must be held on entry, we will unlock on success.
- */
-struct vnode *
-layer_node_find(struct mount *mp, struct vnode *lowervp)
-{
-	struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp);
-	struct layer_node_hashhead *hd;
-	struct layer_node *a;
-	struct vnode *vp;
-	int error;
-
-	/*
-	 * Find hash bucket and search the (two-way) linked list looking
-	 * for a layerfs node structure which is referencing the lower vnode.
-	 * If found, the increment the layer_node reference count, but NOT
-	 * the lower vnode's reference counter.
-	 */
-	KASSERT(mutex_owned(&lmp->layerm_hashlock));
-	hd = LAYER_NHASH(lmp, lowervp);
-loop:
-	LIST_FOREACH(a, hd, layer_hash) {
-		if (a->layer_lowervp != lowervp) {
-			continue;
-		}
-		vp = LAYERTOV(a);
-		if (vp->v_mount != mp) {
-			continue;
-		}
-		mutex_enter(vp->v_interlock);
-		mutex_exit(&lmp->layerm_hashlock);
-		error = vget(vp, 0);
-		if (error) {
-			mutex_enter(&lmp->layerm_hashlock);
-			goto loop;
-		}
-		return vp;
-	}
-	return NULL;
-}
-
-/*
- * layer_node_alloc: make a new layerfs vnode.
- *
- * => vp is the alias vnode, lowervp is the lower vnode.
- * => We will hold a reference to lowervp.
- */
-int
-layer_node_alloc(struct mount *mp, struct vnode *lowervp, struct vnode **vpp)
-{
-	struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp);
-	struct layer_node_hashhead *hd;
-	struct layer_node *xp;
-	struct vnode *vp, *nvp;
-	int error;
-
-	/* Get a new vnode and share its interlock with underlying vnode. */
-	error = getnewvnode(lmp->layerm_tag, mp, lmp->layerm_vnodeop_p,
-	    lowervp->v_interlock, &vp);
-	if (error) {
-		return error;
-	}
-	vp->v_type = lowervp->v_type;
-	mutex_enter(vp->v_interlock);
-	vp->v_iflag |= VI_LAYER;
-	mutex_exit(vp->v_interlock);
-
-	xp = kmem_alloc(lmp->layerm_size, KM_SLEEP);
-	if (xp == NULL) {
-		ungetnewvnode(vp);
-		return ENOMEM;
-	}
-	if (vp->v_type == VBLK || vp->v_type == VCHR) {
-		spec_node_init(vp, lowervp->v_rdev);
-	}
-
-	/*
-	 * Before inserting the node into the hash, check if other thread
-	 * did not race with us.  If so - return that node, destroy ours.
-	 */
-	mutex_enter(&lmp->layerm_hashlock);
-	if ((nvp = layer_node_find(mp, lowervp)) != NULL) {
-		ungetnewvnode(vp);
-		kmem_free(xp, lmp->layerm_size);
-		*vpp = nvp;
-		return 0;
-	}
-
-	vp->v_data = xp;
-	vp->v_vflag = (vp->v_vflag & ~VV_MPSAFE) |
-	    (lowervp->v_vflag & VV_MPSAFE);
-	xp->layer_vnode = vp;
-	xp->layer_lowervp = lowervp;
-	xp->layer_flags = 0;
-
-	/*
-	 * Insert the new node into the hash.
-	 * Add a reference to the lower node.
-	 */
-	vref(lowervp);
-	hd = LAYER_NHASH(lmp, lowervp);
-	LIST_INSERT_HEAD(hd, xp, layer_hash);
-	uvm_vnp_setsize(vp, 0);
-	mutex_exit(&lmp->layerm_hashlock);
-
-	*vpp = vp;
-	return 0;
-}
-
-/*
  * layer_node_create: try to find an existing layerfs vnode refering to it,
  * otherwise make a new vnode which contains a reference to the lower vnode.
- *
- * => Caller should lock the lower node.
  */
 int
 layer_node_create(struct mount *mp, struct vnode *lowervp, struct vnode **nvpp)
 {
+	int error;
 	struct vnode *aliasvp;
-	struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp);
 
-	mutex_enter(&lmp->layerm_hashlock);
-	aliasvp = layer_node_find(mp, lowervp);
-	if (aliasvp != NULL) {
-		/*
-		 * Note: layer_node_find() has taken another reference to
-		 * the alias vnode and moved the lock holding to aliasvp.
-		 */
-#ifdef LAYERFS_DIAGNOSTIC
-		if (layerfs_debug)
-			vprint("layer_node_create: exists", aliasvp);
-#endif
-	} else {
-		int error;
-
-		mutex_exit(&lmp->layerm_hashlock);
-		/*
-		 * Get a new vnode.  Make it to reference the layer_node.
-		 * Note: aliasvp will be return with the reference held.
-		 */
-		error = (lmp->layerm_alloc)(mp, lowervp, &aliasvp);
-		if (error)
-			return error;
-#ifdef LAYERFS_DIAGNOSTIC
-		if (layerfs_debug)
-			printf("layer_node_create: create new alias vnode\n");
-#endif
-	}
+	error = vcache_get(mp, &lowervp, sizeof(lowervp), &aliasvp);
+	if (error)
+		return error;
 
 	/*
 	 * Now that we acquired a reference on the upper vnode, release one

Index: src/sys/miscfs/genfs/layer_vfsops.c
diff -u src/sys/miscfs/genfs/layer_vfsops.c:1.43 src/sys/miscfs/genfs/layer_vfsops.c:1.43.2.1
--- src/sys/miscfs/genfs/layer_vfsops.c:1.43	Tue Feb 25 18:30:11 2014
+++ src/sys/miscfs/genfs/layer_vfsops.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: layer_vfsops.c,v 1.43 2014/02/25 18:30:11 pooka Exp $	*/
+/*	$NetBSD: layer_vfsops.c,v 1.43.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1999 National Aeronautics & Space Administration
@@ -74,7 +74,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: layer_vfsops.c,v 1.43 2014/02/25 18:30:11 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: layer_vfsops.c,v 1.43.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/sysctl.h>
@@ -86,6 +86,7 @@ __KERNEL_RCSID(0, "$NetBSD: layer_vfsops
 #include <sys/kauth.h>
 #include <sys/module.h>
 
+#include <miscfs/specfs/specdev.h>
 #include <miscfs/genfs/layer.h>
 #include <miscfs/genfs/layer_extern.h>
 
@@ -204,6 +205,43 @@ layerfs_sync(struct mount *mp, int waitf
 }
 
 int
+layerfs_loadvnode(struct mount *mp, struct vnode *vp,
+    const void *key, size_t key_len, const void **new_key)
+{
+	struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp);
+	struct vnode *lowervp;
+	struct layer_node *xp;
+
+	KASSERT(key_len == sizeof(struct vnode *));
+	memcpy(&lowervp, key, key_len);
+
+	xp = kmem_alloc(lmp->layerm_size, KM_SLEEP);
+	if (xp == NULL)
+		return ENOMEM;
+
+	/* Share the interlock with the lower node. */
+	mutex_obj_hold(lowervp->v_interlock);
+	uvm_obj_setlock(&vp->v_uobj, lowervp->v_interlock);
+	vp->v_iflag |= VI_LAYER | VI_LOCKSHARE;
+
+	vp->v_tag = lmp->layerm_tag;
+	vp->v_type = lowervp->v_type;
+	vp->v_op = lmp->layerm_vnodeop_p;
+	if (vp->v_type == VBLK || vp->v_type == VCHR)
+		spec_node_init(vp, lowervp->v_rdev);
+	vp->v_data = xp;
+	xp->layer_vnode = vp;
+	xp->layer_lowervp = lowervp;
+	xp->layer_flags = 0;
+	uvm_vnp_setsize(vp, 0);
+
+	/*  Add a reference to the lower node. */
+	vref(lowervp);
+	*new_key = &xp->layer_lowervp;
+	return 0;
+}
+
+int
 layerfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
 {
 	struct vnode *vp;

Index: src/sys/miscfs/genfs/layer_vnops.c
diff -u src/sys/miscfs/genfs/layer_vnops.c:1.57 src/sys/miscfs/genfs/layer_vnops.c:1.57.2.1
--- src/sys/miscfs/genfs/layer_vnops.c:1.57	Mon Mar 24 13:42:40 2014
+++ src/sys/miscfs/genfs/layer_vnops.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: layer_vnops.c,v 1.57 2014/03/24 13:42:40 hannken Exp $	*/
+/*	$NetBSD: layer_vnops.c,v 1.57.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1999 National Aeronautics & Space Administration
@@ -170,7 +170,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: layer_vnops.c,v 1.57 2014/03/24 13:42:40 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: layer_vnops.c,v 1.57.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -694,11 +694,9 @@ layer_reclaim(void *v)
 		 */
 		lmp->layerm_rootvp = NULL;
 	}
+	vcache_remove(vp->v_mount, &lowervp, sizeof(lowervp));
 	/* After this assignment, this node will not be re-used. */
 	xp->layer_lowervp = NULL;
-	mutex_enter(&lmp->layerm_hashlock);
-	LIST_REMOVE(xp, layer_hash);
-	mutex_exit(&lmp->layerm_hashlock);
 	kmem_free(vp->v_data, lmp->layerm_size);
 	vp->v_data = NULL;
 	vrele(lowervp);

Index: src/sys/miscfs/kernfs/files.kernfs
diff -u src/sys/miscfs/kernfs/files.kernfs:1.4 src/sys/miscfs/kernfs/files.kernfs:1.4.34.1
--- src/sys/miscfs/kernfs/files.kernfs:1.4	Wed Mar  3 01:26:01 2010
+++ src/sys/miscfs/kernfs/files.kernfs	Sun Aug 10 06:56:05 2014
@@ -1,7 +1,6 @@
-#	$NetBSD: files.kernfs,v 1.4 2010/03/03 01:26:01 pooka Exp $
+#	$NetBSD: files.kernfs,v 1.4.34.1 2014/08/10 06:56:05 tls Exp $
 
 deffs					KERNFS
 
-file	miscfs/kernfs/kernfs_subr.c	kernfs
 file	miscfs/kernfs/kernfs_vfsops.c	kernfs
 file	miscfs/kernfs/kernfs_vnops.c	kernfs

Index: src/sys/miscfs/kernfs/kernfs.h
diff -u src/sys/miscfs/kernfs/kernfs.h:1.37 src/sys/miscfs/kernfs/kernfs.h:1.37.12.1
--- src/sys/miscfs/kernfs/kernfs.h:1.37	Thu Mar 22 20:34:38 2012
+++ src/sys/miscfs/kernfs/kernfs.h	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: kernfs.h,v 1.37 2012/03/22 20:34:38 drochner Exp $	*/
+/*	$NetBSD: kernfs.h,v 1.37.12.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -39,6 +39,7 @@
 #ifdef _KERNEL
 #include <sys/queue.h>
 #include <sys/tree.h>
+#include <sys/mutex.h>
 
 /*
  * The different types of node in a kernfs filesystem
@@ -91,9 +92,8 @@ struct kernfs_node {
 	kfstype		kfs_type;	/* type of kernfs node */
 	mode_t		kfs_mode;	/* mode bits for stat() */
 	long		kfs_fileno;	/* unique file id */
-	u_int32_t	kfs_value;	/* SA id or SP id (KFSint) */
 	const struct kern_target *kfs_kt;
-	void		*kfs_v;		/* pointer to secasvar/secpolicy/mbuf */
+	void		*kfs_v;		/* dynamic node private data */
 	long		kfs_cookie;	/* fileno cookie */
 };
 
@@ -123,22 +123,10 @@ extern const int static_nkern_targets;
 extern int (**kernfs_vnodeop_p)(void *);
 extern struct vfsops kernfs_vfsops;
 extern dev_t rrootdev;
-
-struct secasvar;
-struct secpolicy;
+extern kmutex_t kfs_lock;
 
 int kernfs_root(struct mount *, struct vnode **);
 
-void kernfs_hashinit(void);
-void kernfs_hashreinit(void);
-void kernfs_hashdone(void);
-int kernfs_freevp(struct vnode *);
-int kernfs_allocvp(struct mount *, struct vnode **, kfstype,
-	const struct kern_target *, u_int32_t);
-
-void kernfs_revoke_sa(struct secasvar *);
-void kernfs_revoke_sp(struct secpolicy *);
-
 /*
  * Data types for the kernfs file operations.
  */

Index: src/sys/miscfs/kernfs/kernfs_vfsops.c
diff -u src/sys/miscfs/kernfs/kernfs_vfsops.c:1.93 src/sys/miscfs/kernfs/kernfs_vfsops.c:1.93.2.1
--- src/sys/miscfs/kernfs/kernfs_vfsops.c:1.93	Sun Mar 23 15:21:16 2014
+++ src/sys/miscfs/kernfs/kernfs_vfsops.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: kernfs_vfsops.c,v 1.93 2014/03/23 15:21:16 hannken Exp $	*/
+/*	$NetBSD: kernfs_vfsops.c,v 1.93.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993, 1995
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kernfs_vfsops.c,v 1.93 2014/03/23 15:21:16 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kernfs_vfsops.c,v 1.93.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
@@ -68,6 +68,7 @@ MODULE(MODULE_CLASS_VFS, kernfs, NULL);
 MALLOC_JUSTDEFINE(M_KERNFSMNT, "kernfs mount", "kernfs mount structures");
 
 dev_t rrootdev = NODEV;
+kmutex_t kfs_lock;
 
 VFS_PROTOS(kernfs);
 
@@ -80,20 +81,20 @@ kernfs_init(void)
 {
 
 	malloc_type_attach(M_KERNFSMNT);
-	kernfs_hashinit();
+	mutex_init(&kfs_lock, MUTEX_DEFAULT, IPL_NONE);
 }
 
 void
 kernfs_reinit(void)
 {
-	kernfs_hashreinit();
+
 }
 
 void
 kernfs_done(void)
 {
 
-	kernfs_hashdone();
+	mutex_destroy(&kfs_lock);
 	malloc_type_detach(M_KERNFSMNT);
 }
 
@@ -190,9 +191,20 @@ kernfs_unmount(struct mount *mp, int mnt
 int
 kernfs_root(struct mount *mp, struct vnode **vpp)
 {
+	const struct kern_target *root_target = &kern_targets[0];
+	int error;
 
 	/* setup "." */
-	return (kernfs_allocvp(mp, vpp, KFSkern, &kern_targets[0], 0));
+	error = vcache_get(mp, &root_target, sizeof(root_target), vpp);
+	if (error)
+		return error;
+	error = vn_lock(*vpp, LK_EXCLUSIVE);
+	if (error) {
+		vrele(*vpp);
+		*vpp = NULL;
+		return error;
+	}
+	return 0;
 }
 
 /*ARGSUSED*/
@@ -216,6 +228,70 @@ kernfs_vget(struct mount *mp, ino_t ino,
 	return (EOPNOTSUPP);
 }
 
+int
+kernfs_loadvnode(struct mount *mp, struct vnode *vp,
+    const void *key, size_t key_len, const void **new_key)
+{
+	const struct kern_target *kt;
+	struct kernfs_node *kfs, *kfsp;
+	long *cookie;
+
+	KASSERT(key_len == sizeof(kt));
+	memcpy(&kt, key, key_len);
+
+	kfs = kmem_zalloc(sizeof(struct kernfs_node), KM_SLEEP);
+	cookie = &(VFSTOKERNFS(mp)->fileno_cookie);
+	mutex_enter(&kfs_lock);
+again:
+	TAILQ_FOREACH(kfsp, &VFSTOKERNFS(mp)->nodelist, kfs_list) {
+		if (kfsp->kfs_cookie == *cookie) {
+			(*cookie) ++;
+			goto again;
+		}
+		if (TAILQ_NEXT(kfsp, kfs_list)) {
+			if (kfsp->kfs_cookie < *cookie &&
+			    *cookie < TAILQ_NEXT(kfsp, kfs_list)->kfs_cookie)
+				break;
+			if (kfsp->kfs_cookie + 1 <
+			    TAILQ_NEXT(kfsp, kfs_list)->kfs_cookie) {
+				*cookie = kfsp->kfs_cookie + 1;
+				break;
+			}
+		}
+	}
+
+	kfs->kfs_cookie = *cookie;
+
+	if (kfsp)
+		TAILQ_INSERT_AFTER(&VFSTOKERNFS(mp)->nodelist, kfsp, kfs,
+		    kfs_list);
+	else
+		TAILQ_INSERT_TAIL(&VFSTOKERNFS(mp)->nodelist, kfs, kfs_list);
+
+	kfs->kfs_type = kt->kt_tag;
+	kfs->kfs_vnode = vp;
+	kfs->kfs_fileno = KERNFS_FILENO(kt, kt->kt_tag, kfs->kfs_cookie);
+	kfs->kfs_kt = kt;
+	kfs->kfs_mode = kt->kt_mode;
+	vp->v_tag = VT_KERNFS;
+	vp->v_op = kernfs_vnodeop_p;
+	vp->v_data = kfs;
+	vp->v_type = kt->kt_vtype;
+	mutex_exit(&kfs_lock);
+
+	if (kt->kt_tag == KFSkern)
+		vp->v_vflag = VV_ROOT;
+
+	if (kt->kt_tag == KFSdevice) {
+		spec_node_init(vp, *(dev_t *)kt->kt_data);
+	}
+
+	uvm_vnp_setsize(vp, 0);
+
+	*new_key = &kfs->kfs_kt;
+	return 0;
+}
+
 extern const struct vnodeopv_desc kernfs_vnodeop_opv_desc;
 
 const struct vnodeopv_desc * const kernfs_vnodeopv_descs[] = {
@@ -234,6 +310,7 @@ struct vfsops kernfs_vfsops = {
 	.vfs_statvfs = genfs_statvfs,
 	.vfs_sync = kernfs_sync,
 	.vfs_vget = kernfs_vget,
+	.vfs_loadvnode = kernfs_loadvnode,
 	.vfs_fhtovp = (void *)eopnotsupp,
 	.vfs_vptofh = (void *)eopnotsupp,
 	.vfs_init = kernfs_init,

Index: src/sys/miscfs/kernfs/kernfs_vnops.c
diff -u src/sys/miscfs/kernfs/kernfs_vnops.c:1.150 src/sys/miscfs/kernfs/kernfs_vnops.c:1.150.2.1
--- src/sys/miscfs/kernfs/kernfs_vnops.c:1.150	Fri Feb  7 15:29:22 2014
+++ src/sys/miscfs/kernfs/kernfs_vnops.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: kernfs_vnops.c,v 1.150 2014/02/07 15:29:22 hannken Exp $	*/
+/*	$NetBSD: kernfs_vnops.c,v 1.150.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.150 2014/02/07 15:29:22 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.150.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -59,6 +59,7 @@ __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops
 
 #include <miscfs/genfs/genfs.h>
 #include <miscfs/kernfs/kernfs.h>
+#include <miscfs/specfs/specdev.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -190,6 +191,8 @@ const struct vnodeopv_entry_desc kernfs_
 	{ &vop_setattr_desc, kernfs_setattr },		/* setattr */
 	{ &vop_read_desc, kernfs_read },		/* read */
 	{ &vop_write_desc, kernfs_write },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_fcntl_desc, kernfs_fcntl },		/* fcntl */
 	{ &vop_ioctl_desc, kernfs_ioctl },		/* ioctl */
 	{ &vop_poll_desc, kernfs_poll },		/* poll */
@@ -519,11 +522,8 @@ kernfs_lookup(void *v)
 		break;
 
 	found:
-		error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);
-		if (error)
-			return error;
-		VOP_UNLOCK(*vpp);
-		return 0;
+		error = vcache_get(dvp->v_mount, &kt, sizeof(kt), vpp);
+		return error;
 
 	case KFSsubdir:
 		ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
@@ -653,6 +653,11 @@ kernfs_getattr(void *v)
 		vap->va_bytes = vap->va_size = DEV_BSIZE;
 		break;
 
+	case KFSdevice:
+		vap->va_nlink = 1;
+		vap->va_rdev = ap->a_vp->v_rdev;
+		break;
+
 	case KFSroot:
 		vap->va_nlink = 1;
 		vap->va_bytes = vap->va_size = DEV_BSIZE;
@@ -670,7 +675,6 @@ kernfs_getattr(void *v)
 	case KFSstring:
 	case KFShostname:
 	case KFSavenrun:
-	case KFSdevice:
 	case KFSmsgbuf:
 		vap->va_nlink = 1;
 		total = 0;
@@ -823,28 +827,17 @@ kernfs_ioctl(void *v)
 
 static int
 kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
-    u_int32_t value, struct vop_readdir_args *ap)
+    struct vop_readdir_args *ap)
 {
 	struct kernfs_node *kfs;
 	struct vnode *vp;
 	int error;
 
-	if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt,
-	    value)) != 0)
+	if ((error = vcache_get(ap->a_vp->v_mount, &kt, sizeof(kt), &vp)) != 0)
 		return error;
-	if (kt->kt_tag == KFSdevice) {
-		struct vattr va;
-
-		error = VOP_GETATTR(vp, &va, ap->a_cred);
-		if (error != 0) {
-			return error;
-		}
-		d->d_fileno = va.va_fileid;
-	} else {
-		kfs = VTOKERN(vp);
-		d->d_fileno = kfs->kfs_fileno;
-	}
-	vput(vp);
+	kfs = VTOKERN(vp);
+	d->d_fileno = kfs->kfs_fileno;
+	vrele(vp);
 	return 0;
 }
 
@@ -868,7 +861,7 @@ kernfs_setdirentfileno(struct dirent *d,
 		break;
 	}
 	if (ikt != thisdir_kfs->kfs_kt) {
-		if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0)
+		if ((error = kernfs_setdirentfileno_kt(d, ikt, ap)) != 0)
 			return error;
 	} else
 		d->d_fileno = thisdir_kfs->kfs_fileno;
@@ -1085,8 +1078,17 @@ kernfs_reclaim(void *v)
 	struct vop_reclaim_args /* {
 		struct vnode *a_vp;
 	} */ *ap = v;
+	struct vnode *vp = ap->a_vp;
+	struct kernfs_node *kfs = VTOKERN(vp);
 
-	return (kernfs_freevp(ap->a_vp));
+	vp->v_data = NULL;
+	vcache_remove(vp->v_mount, &kfs->kfs_kt, sizeof(kfs->kfs_kt));
+	mutex_enter(&kfs_lock);
+	TAILQ_REMOVE(&VFSTOKERNFS(vp->v_mount)->nodelist, kfs, kfs_list);
+	mutex_exit(&kfs_lock);
+	kmem_free(kfs, sizeof(struct kernfs_node));
+
+	return 0;
 }
 
 /*

Index: src/sys/miscfs/nullfs/null_vfsops.c
diff -u src/sys/miscfs/nullfs/null_vfsops.c:1.87 src/sys/miscfs/nullfs/null_vfsops.c:1.87.2.1
--- src/sys/miscfs/nullfs/null_vfsops.c:1.87	Sun Mar 23 15:21:16 2014
+++ src/sys/miscfs/nullfs/null_vfsops.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: null_vfsops.c,v 1.87 2014/03/23 15:21:16 hannken Exp $	*/
+/*	$NetBSD: null_vfsops.c,v 1.87.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1999 National Aeronautics & Space Administration
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: null_vfsops.c,v 1.87 2014/03/23 15:21:16 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: null_vfsops.c,v 1.87.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -107,6 +107,8 @@ nullfs_mount(struct mount *mp, const cha
 	struct nameidata nd;
 	int error;
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof(*args))
 		return EINVAL;
 
@@ -152,19 +154,13 @@ nullfs_mount(struct mount *mp, const cha
 	nmp->nullm_size = sizeof(struct null_node);
 	nmp->nullm_tag = VT_NULL;
 	nmp->nullm_bypass = layer_bypass;
-	nmp->nullm_alloc = layer_node_alloc;	/* the default alloc is fine */
 	nmp->nullm_vnodeop_p = null_vnodeop_p;
-	mutex_init(&nmp->nullm_hashlock, MUTEX_DEFAULT, IPL_NONE);
-	nmp->nullm_node_hashtbl = hashinit(desiredvnodes, HASH_LIST, true,
-	    &nmp->nullm_node_hash);
 
 	/* Setup a null node for root vnode. */
 	VOP_UNLOCK(lowerrootvp);
 	error = layer_node_create(mp, lowerrootvp, &vp);
 	if (error) {
 		vrele(lowerrootvp);
-		hashdone(nmp->nullm_node_hashtbl, HASH_LIST,
-		    nmp->nullm_node_hash);
 		kmem_free(nmp, sizeof(struct null_mount));
 		return error;
 	}
@@ -203,8 +199,6 @@ nullfs_unmount(struct mount *mp, int mnt
 	vgone(null_rootvp);
 
 	/* Finally, destroy the mount point structures. */
-	hashdone(nmp->nullm_node_hashtbl, HASH_LIST, nmp->nullm_node_hash);
-	mutex_destroy(&nmp->nullm_hashlock);
 	kmem_free(mp->mnt_data, sizeof(struct null_mount));
 	mp->mnt_data = NULL;
 	return 0;
@@ -227,6 +221,7 @@ struct vfsops nullfs_vfsops = {
 	.vfs_quotactl = layerfs_quotactl,
 	.vfs_statvfs = layerfs_statvfs,
 	.vfs_sync = layerfs_sync,
+	.vfs_loadvnode = layerfs_loadvnode,
 	.vfs_vget = layerfs_vget,
 	.vfs_fhtovp = layerfs_fhtovp,
 	.vfs_vptofh = layerfs_vptofh,

Index: src/sys/miscfs/overlay/overlay_vfsops.c
diff -u src/sys/miscfs/overlay/overlay_vfsops.c:1.60 src/sys/miscfs/overlay/overlay_vfsops.c:1.60.2.1
--- src/sys/miscfs/overlay/overlay_vfsops.c:1.60	Sun Mar 23 15:21:16 2014
+++ src/sys/miscfs/overlay/overlay_vfsops.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: overlay_vfsops.c,v 1.60 2014/03/23 15:21:16 hannken Exp $	*/
+/*	$NetBSD: overlay_vfsops.c,v 1.60.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1999, 2000 National Aeronautics & Space Administration
@@ -74,7 +74,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: overlay_vfsops.c,v 1.60 2014/03/23 15:21:16 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: overlay_vfsops.c,v 1.60.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -114,6 +114,8 @@ ov_mount(struct mount *mp, const char *p
 	printf("ov_mount(mp = %p)\n", mp);
 #endif
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 
@@ -161,11 +163,7 @@ ov_mount(struct mount *mp, const char *p
 	nmp->ovm_size = sizeof (struct overlay_node);
 	nmp->ovm_tag = VT_OVERLAY;
 	nmp->ovm_bypass = layer_bypass;
-	nmp->ovm_alloc = layer_node_alloc;	/* the default alloc is fine */
 	nmp->ovm_vnodeop_p = overlay_vnodeop_p;
-	mutex_init(&nmp->ovm_hashlock, MUTEX_DEFAULT, IPL_NONE);
-	nmp->ovm_node_hashtbl = hashinit(NOVERLAYNODECACHE, HASH_LIST, true,
-	     &nmp->ovm_node_hash);
 
 	/*
 	 * Fix up overlay node for root vnode
@@ -177,7 +175,6 @@ ov_mount(struct mount *mp, const char *p
 	 */
 	if (error) {
 		vrele(lowerrootvp);
-		hashdone(nmp->ovm_node_hashtbl, HASH_LIST, nmp->ovm_node_hash);
 		kmem_free(nmp, sizeof(struct overlay_mount));
 		return error;
 	}
@@ -234,8 +231,6 @@ ov_unmount(struct mount *mp, int mntflag
 	 * Finally, throw away the overlay_mount structure
 	 */
 	omp = mp->mnt_data;
-	mutex_destroy(&omp->ovm_hashlock);
-	hashdone(omp->ovm_node_hashtbl, HASH_LIST, omp->ovm_node_hash);
 	kmem_free(omp, sizeof(struct overlay_mount));
 	mp->mnt_data = NULL;
 	return 0;
@@ -258,6 +253,7 @@ struct vfsops overlay_vfsops = {
 	.vfs_quotactl = layerfs_quotactl,
 	.vfs_statvfs = layerfs_statvfs,
 	.vfs_sync = layerfs_sync,
+	.vfs_loadvnode = layerfs_loadvnode,
 	.vfs_vget = layerfs_vget,
 	.vfs_fhtovp = layerfs_fhtovp,
 	.vfs_vptofh = layerfs_vptofh,

Index: src/sys/miscfs/procfs/procfs.h
diff -u src/sys/miscfs/procfs/procfs.h:1.69 src/sys/miscfs/procfs/procfs.h:1.69.2.1
--- src/sys/miscfs/procfs/procfs.h:1.69	Sat Apr  5 18:42:32 2014
+++ src/sys/miscfs/procfs/procfs.h	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs.h,v 1.69 2014/04/05 18:42:32 christos Exp $	*/
+/*	$NetBSD: procfs.h,v 1.69.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1993
@@ -118,12 +118,17 @@ typedef enum {
 /*
  * control data for the proc file system.
  */
+struct pfskey {
+	pfstype		pk_type;	/* type of procfs node */
+	pid_t		pk_pid;		/* associated process */
+	int		pk_fd;		/* associated fd if not -1 */
+};
 struct pfsnode {
-	LIST_ENTRY(pfsnode) pfs_hash;	/* hash chain */
 	struct vnode	*pfs_vnode;	/* vnode associated with this pfsnode */
-	pfstype		pfs_type;	/* type of procfs node */
-	pid_t		pfs_pid;	/* associated process */
-	int		pfs_fd;		/* associated fd if not -1 */
+	struct pfskey	pfs_key;
+#define pfs_type pfs_key.pk_type
+#define pfs_pid pfs_key.pk_pid
+#define pfs_fd pfs_key.pk_fd
 	mode_t		pfs_mode;	/* mode bits for stat() */
 	u_long		pfs_flags;	/* open flags */
 	u_long		pfs_fileno;	/* unique file id */
@@ -187,9 +192,7 @@ const vfs_namemap_t *vfs_findname(const 
 
 int procfs_proc_lock(int, struct proc **, int);
 void procfs_proc_unlock(struct proc *);
-int procfs_freevp(struct vnode *);
-int procfs_allocvp(struct mount *, struct vnode **, pid_t, pfstype, int,
-    struct proc *);
+int procfs_allocvp(struct mount *, struct vnode **, pid_t, pfstype, int);
 int procfs_donote(struct lwp *, struct proc *, struct pfsnode *,
     struct uio *);
 int procfs_doregs(struct lwp *, struct lwp *, struct pfsnode *,
@@ -232,9 +235,6 @@ int procfs_doversion(struct lwp *, struc
     struct uio *);
 
 void procfs_revoke_vnodes(struct proc *, void *);
-void procfs_hashinit(void);
-void procfs_hashreinit(void);
-void procfs_hashdone(void);
 int procfs_getfp(struct pfsnode *, struct proc *, struct file **);
 
 /* functions to check whether or not files should be displayed */

Index: src/sys/miscfs/procfs/procfs_linux.c
diff -u src/sys/miscfs/procfs/procfs_linux.c:1.67 src/sys/miscfs/procfs/procfs_linux.c:1.67.2.1
--- src/sys/miscfs/procfs/procfs_linux.c:1.67	Sat Apr  5 18:42:32 2014
+++ src/sys/miscfs/procfs/procfs_linux.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*      $NetBSD: procfs_linux.c,v 1.67 2014/04/05 18:42:32 christos Exp $      */
+/*      $NetBSD: procfs_linux.c,v 1.67.2.1 2014/08/10 06:56:05 tls Exp $      */
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.67 2014/04/05 18:42:32 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.67.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -400,7 +400,7 @@ out:
 	return error;
 }
 
-#define USEC_2_TICKS(x)		((x) / 10000)
+#define UTIME2TICKS(s,u)	(((uint64_t)(s) * 1000000 + (u)) / 10000)
 
 /*
  * Linux compatible /proc/<pid>/stat. Only active when the -o linux
@@ -413,12 +413,11 @@ procfs_do_pid_stat(struct lwp *curl, str
 	char *bf;
 	struct proc *p = l->l_proc;
 	int len;
-	struct tty *tty = p->p_session->s_ttyp;
-	struct rusage *ru = &p->p_stats->p_ru;
 	struct rusage *cru = &p->p_stats->p_cru;
 	unsigned long stext = 0, etext = 0, sstack = 0;
 	struct timeval rt;
 	struct vmspace	*vm;
+	struct kinfo_proc2 ki;
 	int error = 0;
 
 	bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
@@ -432,65 +431,67 @@ procfs_do_pid_stat(struct lwp *curl, str
 	mutex_enter(proc_lock);
 	mutex_enter(p->p_lock);
 
+	fill_kproc2(p, &ki, false);
 	calcru(p, NULL, NULL, NULL, &rt);
 
 	len = snprintf(bf, LBFSZ,
-	    "%d (%s) %c %d %d %d %lld %d "
+	    "%d (%s) %c %d %d %d %u %d "
 	    "%u "
-	    "%lu %lu %lu %lu %lu %lu %lu %lu "
-	    "%d %d %d "
-	    "%lld %lld %lu %lu %" PRIu64 " "
+	    "%"PRIu64" %lu %"PRIu64" %lu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" "
+	    "%d %d %"PRIu64" "
+	    "%lld %"PRIu64" %"PRId64" %lu %"PRIu64" "
 	    "%lu %lu %lu "
 	    "%u %u "
 	    "%u %u %u %u "
-	    "%lu %lu %lu %d %d\n",
+	    "%"PRIu64" %"PRIu64" %"PRIu64" %d %"PRIu64"\n",
 
-	    p->p_pid,
-	    p->p_comm,
-	    "0IR3SZD"[(p->p_stat > 6) ? 0 : (int)p->p_stat],
-	    (p->p_pptr != NULL) ? p->p_pptr->p_pid : 0,
+	    ki.p_pid,						/* 1 pid */
+	    ki.p_comm,						/* 2 tcomm */
+	    "0RRSTZXR8"[(ki.p_stat > 8) ? 0 : (int)ki.p_stat],	/* 3 state */
+	    ki.p_ppid,						/* 4 ppid */
+	    ki.p__pgid,						/* 5 pgrp */
+	    ki.p_sid,						/* 6 sid */
+	    (ki.p_tdev != (uint32_t)NODEV) ? ki.p_tdev : 0,	/* 7 tty_nr */
+	    ki.p_tpgid,						/* 8 tty_pgrp */
 
-	    p->p_pgid,
-	    p->p_session->s_sid,
-	    (unsigned long long)(tty ? tty->t_dev : 0),
-	    (tty && tty->t_pgrp) ? tty->t_pgrp->pg_id : 0,
+	    ki.p_flag,						/* 9 flags */
 
-	    p->p_flag,
-
-	    ru->ru_minflt,
+	    ki.p_uru_minflt,					/* 10 min_flt */
 	    cru->ru_minflt,
-	    ru->ru_majflt,
+	    ki.p_uru_majflt,					/* 12 maj_flt */
 	    cru->ru_majflt,
-	    (long)USEC_2_TICKS(ru->ru_utime.tv_usec),
-	    (long)USEC_2_TICKS(ru->ru_stime.tv_usec),
-	    (long)USEC_2_TICKS(cru->ru_utime.tv_usec),
-	    (long)USEC_2_TICKS(cru->ru_stime.tv_usec),
-
-	    l->l_priority,				/* XXX: priority */
-	    p->p_nice - 20,
-	    0,
+	    UTIME2TICKS(ki.p_uutime_sec, ki.p_uutime_usec),	/* 14 utime */
+	    UTIME2TICKS(ki.p_ustime_sec, ki.p_ustime_usec),	/* 15 stime */
+	    UTIME2TICKS(cru->ru_utime.tv_sec, cru->ru_utime.tv_usec), /* 16 cutime */
+	    UTIME2TICKS(cru->ru_stime.tv_sec, cru->ru_stime.tv_usec), /* 17 cstime */
+
+	    ki.p_priority,				/* XXX: 18 priority */
+	    ki.p_nice - NZERO,				/* 19 nice */
+	    ki.p_nlwps,					/* 20 num_threads */
 
 	    (long long)rt.tv_sec,
-	    (long long)p->p_stats->p_start.tv_sec,
-	    (unsigned long)(vm->vm_tsize + vm->vm_dsize + vm->vm_ssize), /* size */
-	    (unsigned long)(vm->vm_rssize),	/* resident */
-	    p->p_rlimit[RLIMIT_RSS].rlim_cur,
-
-	    stext,					/* start code */
-	    etext,					/* end code */
-	    sstack,					/* mm start stack */
-	    0,						/* XXX: pc */
-	    0,						/* XXX: sp */
-	    p->p_sigpend.sp_set.__bits[0],		/* XXX: pending */
-	    0,						/* XXX: held */
-	    p->p_sigctx.ps_sigignore.__bits[0],		/* ignored */
-	    p->p_sigctx.ps_sigcatch.__bits[0],		/* caught */
-
-	    (unsigned long)(intptr_t)l->l_wchan,
-	    ru->ru_nvcsw,
-	    ru->ru_nivcsw,
-	    p->p_exitsig,
-	    0);						/* XXX: processor */
+	    UTIME2TICKS(ki.p_ustart_sec, ki.p_ustart_usec), /* 22 start_time */
+	    ki.p_vm_msize,				/* 23 vsize */
+	    PGTOKB(ki.p_vm_rssize),			/* 24 rss */
+	    p->p_rlimit[RLIMIT_RSS].rlim_cur,		/* 25 rsslim */
+
+	    stext,					/* 26 start_code */
+	    etext,					/* 27 end_code */
+	    sstack,					/* 28 start_stack */
+
+	    0,						/* XXX: 29 esp */
+	    0,						/* XXX: 30 eip */
+
+	    ki.p_siglist.__bits[0],			/* XXX: 31 pending */
+	    0,						/* XXX: 32 blocked */
+	    ki.p_sigignore.__bits[0],		/* 33 sigign */
+	    ki.p_sigcatch.__bits[0],		/* 34 sigcatch */
+
+	    ki.p_wchan,					/* 35 wchan */
+	    ki.p_uru_nvcsw,
+	    ki.p_uru_nivcsw,
+	    ki.p_exitsig,				/* 38 exit_signal */
+	    ki.p_cpuid);				/* 39 task_cpu */
 
 	mutex_exit(p->p_lock);
 	mutex_exit(proc_lock);

Index: src/sys/miscfs/procfs/procfs_subr.c
diff -u src/sys/miscfs/procfs/procfs_subr.c:1.104 src/sys/miscfs/procfs/procfs_subr.c:1.104.2.1
--- src/sys/miscfs/procfs/procfs_subr.c:1.104	Fri Feb  7 15:29:22 2014
+++ src/sys/miscfs/procfs/procfs_subr.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs_subr.c,v 1.104 2014/02/07 15:29:22 hannken Exp $	*/
+/*	$NetBSD: procfs_subr.c,v 1.104.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -102,7 +102,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.104 2014/02/07 15:29:22 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.104.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -118,224 +118,22 @@ __KERNEL_RCSID(0, "$NetBSD: procfs_subr.
 
 #include <miscfs/procfs/procfs.h>
 
-void procfs_hashins(struct pfsnode *);
-void procfs_hashrem(struct pfsnode *);
-struct vnode *procfs_hashget(pid_t, pfstype, int, struct mount *);
-
-LIST_HEAD(pfs_hashhead, pfsnode) *pfs_hashtbl;
-u_long	pfs_ihash;	/* size of hash table - 1 */
-#define PFSPIDHASH(pid)	((pid) & pfs_ihash)
-
-kmutex_t pfs_hashlock;
-kmutex_t pfs_ihash_lock;
-
-#define	ISSET(t, f)	((t) & (f))
-
 /*
- * allocate a pfsnode/vnode pair.  the vnode is
- * referenced, and locked.
- *
- * the pid, pfs_type, and mount point uniquely
- * identify a pfsnode.  the mount point is needed
- * because someone might mount this filesystem
- * twice.
- *
- * all pfsnodes are maintained on a singly-linked
- * list.  new nodes are only allocated when they cannot
- * be found on this list.  entries on the list are
- * removed when the vfs reclaim entry is called.
- *
- * a single lock is kept for the entire list.  this is
- * needed because the getnewvnode() function can block
- * waiting for a vnode to become free, in which case there
- * may be more than one process trying to get the same
- * vnode.  this lock is only taken if we are going to
- * call getnewvnode, since the kernel itself is single-threaded.
- *
- * if an entry is found on the list, then call vget() to
- * take a reference.  this is done because there may be
- * zero references to it and so it needs to removed from
- * the vnode free list.
+ * Allocate a pfsnode/vnode pair.  The vnode is referenced.
+ * The pid, type, and file descriptor uniquely identify a pfsnode.
  */
 int
 procfs_allocvp(struct mount *mp, struct vnode **vpp, pid_t pid,
-    pfstype pfs_type, int fd, struct proc *p)
+    pfstype type, int fd)
 {
-	struct pfsnode *pfs;
-	struct vnode *vp;
-	int error;
-
-	*vpp = procfs_hashget(pid, pfs_type, fd, mp);
-	if (*vpp != NULL)
-		return (0);
+	struct pfskey key;
 
-	error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, NULL, &vp);
-	if (error) {
-		*vpp = NULL;
-		return (error);
-	}
-	pfs = malloc(sizeof(struct pfsnode), M_TEMP, M_WAITOK);
+	memset(&key, 0, sizeof(key));
+	key.pk_type = type;
+	key.pk_pid = pid;
+	key.pk_fd = fd;
 
-	mutex_enter(&pfs_hashlock);
-	if ((*vpp = procfs_hashget(pid, pfs_type, fd, mp)) != NULL) {
-		mutex_exit(&pfs_hashlock);
-		ungetnewvnode(vp);
-		free(pfs, M_TEMP);
-		return 0;
-	}
-
-	vp->v_data = pfs;
-	pfs->pfs_pid = pid;
-	pfs->pfs_type = pfs_type;
-	pfs->pfs_vnode = vp;
-	pfs->pfs_flags = 0;
-	pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type, fd);
-	pfs->pfs_fd = fd;
-
-	switch (pfs_type) {
-	case PFSroot:	/* /proc = dr-xr-xr-x */
-		vp->v_vflag |= VV_ROOT;
-		/*FALLTHROUGH*/
-	case PFSproc:	/* /proc/N = dr-xr-xr-x */
-		pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
-		vp->v_type = VDIR;
-		break;
-
-	case PFStask:	/* /proc/N/task = dr-xr-xr-x */
-		if (fd == -1) {
-			pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|
-			    S_IROTH|S_IXOTH;
-			vp->v_type = VDIR;
-			break;
-		}
-		/*FALLTHROUGH*/
-	case PFScurproc:	/* /proc/curproc = lr-xr-xr-x */
-	case PFSself:	/* /proc/self    = lr-xr-xr-x */
-	case PFScwd:	/* /proc/N/cwd = lr-xr-xr-x */
-	case PFSchroot:	/* /proc/N/chroot = lr-xr-xr-x */
-	case PFSexe:	/* /proc/N/exe = lr-xr-xr-x */
-		pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
-		vp->v_type = VLNK;
-		break;
-
-	case PFSfd:
-		if (fd == -1) {	/* /proc/N/fd = dr-x------ */
-			pfs->pfs_mode = S_IRUSR|S_IXUSR;
-			vp->v_type = VDIR;
-		} else {	/* /proc/N/fd/M = [ps-]rw------- */
-			file_t *fp;
-			vnode_t *vxp;
-
-			if ((fp = fd_getfile2(p, pfs->pfs_fd)) == NULL) {
-				error = EBADF;
-				goto bad;
-			}
-
-			pfs->pfs_mode = S_IRUSR|S_IWUSR;
-			switch (fp->f_type) {
-			case DTYPE_VNODE:
-				vxp = fp->f_data;
-
-				/*
-				 * We make symlinks for directories
-				 * to avoid cycles.
-				 */
-				if (vxp->v_type == VDIR)
-					goto symlink;
-				vp->v_type = vxp->v_type;
-				break;
-			case DTYPE_PIPE:
-				vp->v_type = VFIFO;
-				break;
-			case DTYPE_SOCKET:
-				vp->v_type = VSOCK;
-				break;
-			case DTYPE_KQUEUE:
-			case DTYPE_MISC:
-			case DTYPE_SEM:
-			symlink:
-				pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|
-				    S_IXGRP|S_IROTH|S_IXOTH;
-				vp->v_type = VLNK;
-				break;
-			default:
-				error = EOPNOTSUPP;
-				closef(fp);
-				goto bad;
-			}
-			closef(fp);
-		}
-		break;
-
-	case PFSfile:	/* /proc/N/file = -rw------- */
-	case PFSmem:	/* /proc/N/mem = -rw------- */
-	case PFSregs:	/* /proc/N/regs = -rw------- */
-	case PFSfpregs:	/* /proc/N/fpregs = -rw------- */
-		pfs->pfs_mode = S_IRUSR|S_IWUSR;
-		vp->v_type = VREG;
-		break;
-
-	case PFSctl:	/* /proc/N/ctl = --w------ */
-	case PFSnote:	/* /proc/N/note = --w------ */
-	case PFSnotepg:	/* /proc/N/notepg = --w------ */
-		pfs->pfs_mode = S_IWUSR;
-		vp->v_type = VREG;
-		break;
-
-	case PFSmap:	/* /proc/N/map = -r--r--r-- */
-	case PFSmaps:	/* /proc/N/maps = -r--r--r-- */
-	case PFSstatus:	/* /proc/N/status = -r--r--r-- */
-	case PFSstat:	/* /proc/N/stat = -r--r--r-- */
-	case PFScmdline:	/* /proc/N/cmdline = -r--r--r-- */
-	case PFSemul:	/* /proc/N/emul = -r--r--r-- */
-	case PFSmeminfo:	/* /proc/meminfo = -r--r--r-- */
-	case PFScpustat:	/* /proc/stat = -r--r--r-- */
-	case PFSdevices:	/* /proc/devices = -r--r--r-- */
-	case PFScpuinfo:	/* /proc/cpuinfo = -r--r--r-- */
-	case PFSuptime:	/* /proc/uptime = -r--r--r-- */
-	case PFSmounts:	/* /proc/mounts = -r--r--r-- */
-	case PFSloadavg:	/* /proc/loadavg = -r--r--r-- */
-	case PFSstatm:	/* /proc/N/statm = -r--r--r-- */
-	case PFSversion:	/* /proc/version = -r--r--r-- */
-		pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH;
-		vp->v_type = VREG;
-		break;
-
-#ifdef __HAVE_PROCFS_MACHDEP
-	PROCFS_MACHDEP_NODETYPE_CASES
-		procfs_machdep_allocvp(vp);
-		break;
-#endif
-
-	default:
-		panic("procfs_allocvp");
-	}
-
-	procfs_hashins(pfs);
-	uvm_vnp_setsize(vp, 0);
-	mutex_exit(&pfs_hashlock);
-
-	*vpp = vp;
-	return (0);
-
- bad:
-	mutex_exit(&pfs_hashlock);
-	free(pfs, M_TEMP);
-	vp->v_data = NULL;
-	ungetnewvnode(vp);
-	return (error);
-}
-
-int
-procfs_freevp(struct vnode *vp)
-{
-	struct pfsnode *pfs = VTOPFS(vp);
-
-	procfs_hashrem(pfs);
-
-	free(vp->v_data, M_TEMP);
-	vp->v_data = NULL;
-	return (0);
+	return vcache_get(mp, &key, sizeof(key), vpp);
 }
 
 int
@@ -550,132 +348,34 @@ vfs_findname(const vfs_namemap_t *nm, co
 	return (0);
 }
 
-/*
- * Initialize pfsnode hash table.
- */
-void
-procfs_hashinit(void)
-{
-	mutex_init(&pfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
-	mutex_init(&pfs_ihash_lock, MUTEX_DEFAULT, IPL_NONE);
-	pfs_hashtbl = hashinit(desiredvnodes / 4, HASH_LIST, true, &pfs_ihash);
-}
-
-void
-procfs_hashreinit(void)
-{
-	struct pfsnode *pp;
-	struct pfs_hashhead *oldhash, *hash;
-	u_long i, oldmask, mask, val;
-
-	hash = hashinit(desiredvnodes / 4, HASH_LIST, true, &mask);
-
-	mutex_enter(&pfs_ihash_lock);
-	oldhash = pfs_hashtbl;
-	oldmask = pfs_ihash;
-	pfs_hashtbl = hash;
-	pfs_ihash = mask;
-	for (i = 0; i <= oldmask; i++) {
-		while ((pp = LIST_FIRST(&oldhash[i])) != NULL) {
-			LIST_REMOVE(pp, pfs_hash);
-			val = PFSPIDHASH(pp->pfs_pid);
-			LIST_INSERT_HEAD(&hash[val], pp, pfs_hash);
-		}
-	}
-	mutex_exit(&pfs_ihash_lock);
-	hashdone(oldhash, HASH_LIST, oldmask);
-}
-
-/*
- * Free pfsnode hash table.
- */
-void
-procfs_hashdone(void)
-{
-	hashdone(pfs_hashtbl, HASH_LIST, pfs_ihash);
-	mutex_destroy(&pfs_hashlock);
-	mutex_destroy(&pfs_ihash_lock);
-}
-
-struct vnode *
-procfs_hashget(pid_t pid, pfstype type, int fd, struct mount *mp)
+static bool
+procfs_revoke_selector(void *arg, struct vnode *vp)
 {
-	struct pfs_hashhead *ppp;
-	struct pfsnode *pp;
-	struct vnode *vp;
-
-loop:
-	mutex_enter(&pfs_ihash_lock);
-	ppp = &pfs_hashtbl[PFSPIDHASH(pid)];
-	LIST_FOREACH(pp, ppp, pfs_hash) {
-		vp = PFSTOV(pp);
-		if (pid == pp->pfs_pid && pp->pfs_type == type &&
-		    pp->pfs_fd == fd && vp->v_mount == mp) {
-			mutex_enter(vp->v_interlock);
-			mutex_exit(&pfs_ihash_lock);
-			if (vget(vp, 0))
-				goto loop;
-			return (vp);
-		}
-	}
-	mutex_exit(&pfs_ihash_lock);
-	return (NULL);
-}
-
-/*
- * Insert the pfsnode into the hash table and lock it.
- */
-void
-procfs_hashins(struct pfsnode *pp)
-{
-	struct pfs_hashhead *ppp;
+	struct proc *p = arg;
+	struct pfsnode *pfs = VTOPFS(vp);
 
-	mutex_enter(&pfs_ihash_lock);
-	ppp = &pfs_hashtbl[PFSPIDHASH(pp->pfs_pid)];
-	LIST_INSERT_HEAD(ppp, pp, pfs_hash);
-	mutex_exit(&pfs_ihash_lock);
-}
-
-/*
- * Remove the pfsnode from the hash table.
- */
-void
-procfs_hashrem(struct pfsnode *pp)
-{
-	mutex_enter(&pfs_ihash_lock);
-	LIST_REMOVE(pp, pfs_hash);
-	mutex_exit(&pfs_ihash_lock);
+	return (pfs != NULL && pfs->pfs_pid == p->p_pid);
 }
 
 void
 procfs_revoke_vnodes(struct proc *p, void *arg)
 {
-	struct pfsnode *pfs, *pnext;
 	struct vnode *vp;
+	struct vnode_iterator *marker;
 	struct mount *mp = (struct mount *)arg;
-	struct pfs_hashhead *ppp;
 
 	if (!(p->p_flag & PK_SUGID))
 		return;
 
-	mutex_enter(&pfs_ihash_lock);
-	ppp = &pfs_hashtbl[PFSPIDHASH(p->p_pid)];
-	for (pfs = LIST_FIRST(ppp); pfs; pfs = pnext) {
-		vp = PFSTOV(pfs);
-		pnext = LIST_NEXT(pfs, pfs_hash);
-		if (pfs->pfs_pid != p->p_pid || vp->v_mount != mp)
-			continue;
-		mutex_enter(vp->v_interlock);
-		mutex_exit(&pfs_ihash_lock);
-		if (vget(vp, 0) != 0) {
-			mutex_enter(&pfs_ihash_lock);
-			continue;
-		}
+	vfs_vnode_iterator_init(mp, &marker);
+
+	while ((vp = vfs_vnode_iterator_next(marker,
+	    procfs_revoke_selector, p)) != NULL) {
 		VOP_REVOKE(vp, REVOKEALL);
 		vrele(vp);
-		mutex_enter(&pfs_ihash_lock);
 	}
-	mutex_exit(&pfs_ihash_lock);
+
+	vfs_vnode_iterator_destroy(marker);
 }
 
 int

Index: src/sys/miscfs/procfs/procfs_vfsops.c
diff -u src/sys/miscfs/procfs/procfs_vfsops.c:1.90 src/sys/miscfs/procfs/procfs_vfsops.c:1.90.2.1
--- src/sys/miscfs/procfs/procfs_vfsops.c:1.90	Sun Mar 23 15:21:16 2014
+++ src/sys/miscfs/procfs/procfs_vfsops.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs_vfsops.c,v 1.90 2014/03/23 15:21:16 hannken Exp $	*/
+/*	$NetBSD: procfs_vfsops.c,v 1.90.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1993
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: procfs_vfsops.c,v 1.90 2014/03/23 15:21:16 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: procfs_vfsops.c,v 1.90.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -95,6 +95,8 @@ __KERNEL_RCSID(0, "$NetBSD: procfs_vfsop
 #include <sys/signalvar.h>
 #include <sys/vnode.h>
 #include <sys/malloc.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
 #include <sys/kauth.h>
 #include <sys/module.h>
 
@@ -130,6 +132,9 @@ procfs_mount(
 	struct procfs_args *args = data;
 	int error;
 
+	if (args == NULL)
+		return EINVAL;
+
 	if (UIO_MX & (UIO_MX-1)) {
 		log(LOG_ERR, "procfs: invalid directory entry size");
 		return (EINVAL);
@@ -201,7 +206,7 @@ procfs_root(struct mount *mp, struct vno
 {
 	int error;
 
-	error = procfs_allocvp(mp, vpp, 0, PFSroot, -1, NULL);
+	error = procfs_allocvp(mp, vpp, 0, PFSroot, -1);
 	if (error == 0) {
 		error = vn_lock(*vpp, LK_EXCLUSIVE);
 		if (error != 0) {
@@ -260,22 +265,187 @@ procfs_vget(struct mount *mp, ino_t ino,
 	return (EOPNOTSUPP);
 }
 
+int
+procfs_loadvnode(struct mount *mp, struct vnode *vp,
+    const void *key, size_t key_len, const void **new_key)
+{
+	int error;
+	struct pfskey pfskey;
+	struct pfsnode *pfs;
+
+	KASSERT(key_len == sizeof(pfskey));
+	memcpy(&pfskey, key, key_len);
+
+	pfs = kmem_alloc(sizeof(*pfs), KM_SLEEP);
+	pfs->pfs_pid = pfskey.pk_pid;
+	pfs->pfs_type = pfskey.pk_type;
+	pfs->pfs_fd = pfskey.pk_fd;
+	pfs->pfs_vnode = vp;
+	pfs->pfs_flags = 0;
+	pfs->pfs_fileno =
+	    PROCFS_FILENO(pfs->pfs_pid, pfs->pfs_type, pfs->pfs_fd);
+	vp->v_tag = VT_PROCFS;
+	vp->v_op = procfs_vnodeop_p;
+	vp->v_data = pfs;
+
+	switch (pfs->pfs_type) {
+	case PFSroot:	/* /proc = dr-xr-xr-x */
+		vp->v_vflag |= VV_ROOT;
+		/*FALLTHROUGH*/
+	case PFSproc:	/* /proc/N = dr-xr-xr-x */
+		pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
+		vp->v_type = VDIR;
+		break;
+
+	case PFStask:	/* /proc/N/task = dr-xr-xr-x */
+		if (pfs->pfs_fd == -1) {
+			pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|
+			    S_IROTH|S_IXOTH;
+			vp->v_type = VDIR;
+			break;
+		}
+		/*FALLTHROUGH*/
+	case PFScurproc:	/* /proc/curproc = lr-xr-xr-x */
+	case PFSself:	/* /proc/self    = lr-xr-xr-x */
+	case PFScwd:	/* /proc/N/cwd = lr-xr-xr-x */
+	case PFSchroot:	/* /proc/N/chroot = lr-xr-xr-x */
+	case PFSexe:	/* /proc/N/exe = lr-xr-xr-x */
+		pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
+		vp->v_type = VLNK;
+		break;
+
+	case PFSfd:
+		if (pfs->pfs_fd == -1) {	/* /proc/N/fd = dr-x------ */
+			pfs->pfs_mode = S_IRUSR|S_IXUSR;
+			vp->v_type = VDIR;
+		} else {	/* /proc/N/fd/M = [ps-]rw------- */
+			file_t *fp;
+			vnode_t *vxp;
+			struct proc *p;
+
+			mutex_enter(proc_lock);
+			p = proc_find(pfs->pfs_pid);
+			mutex_exit(proc_lock);
+			if (p == NULL) {
+				error = ENOENT;
+				goto bad;
+			}
+			KASSERT(rw_read_held(&p->p_reflock));
+			if ((fp = fd_getfile2(p, pfs->pfs_fd)) == NULL) {
+				error = EBADF;
+				goto bad;
+			}
+
+			pfs->pfs_mode = S_IRUSR|S_IWUSR;
+			switch (fp->f_type) {
+			case DTYPE_VNODE:
+				vxp = fp->f_data;
+
+				/*
+				 * We make symlinks for directories
+				 * to avoid cycles.
+				 */
+				if (vxp->v_type == VDIR)
+					goto symlink;
+				vp->v_type = vxp->v_type;
+				break;
+			case DTYPE_PIPE:
+				vp->v_type = VFIFO;
+				break;
+			case DTYPE_SOCKET:
+				vp->v_type = VSOCK;
+				break;
+			case DTYPE_KQUEUE:
+			case DTYPE_MISC:
+			case DTYPE_SEM:
+			symlink:
+				pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|
+				    S_IXGRP|S_IROTH|S_IXOTH;
+				vp->v_type = VLNK;
+				break;
+			default:
+				error = EOPNOTSUPP;
+				closef(fp);
+				goto bad;
+			}
+			closef(fp);
+		}
+		break;
+
+	case PFSfile:	/* /proc/N/file = -rw------- */
+	case PFSmem:	/* /proc/N/mem = -rw------- */
+	case PFSregs:	/* /proc/N/regs = -rw------- */
+	case PFSfpregs:	/* /proc/N/fpregs = -rw------- */
+		pfs->pfs_mode = S_IRUSR|S_IWUSR;
+		vp->v_type = VREG;
+		break;
+
+	case PFSctl:	/* /proc/N/ctl = --w------ */
+	case PFSnote:	/* /proc/N/note = --w------ */
+	case PFSnotepg:	/* /proc/N/notepg = --w------ */
+		pfs->pfs_mode = S_IWUSR;
+		vp->v_type = VREG;
+		break;
+
+	case PFSmap:	/* /proc/N/map = -r--r--r-- */
+	case PFSmaps:	/* /proc/N/maps = -r--r--r-- */
+	case PFSstatus:	/* /proc/N/status = -r--r--r-- */
+	case PFSstat:	/* /proc/N/stat = -r--r--r-- */
+	case PFScmdline:	/* /proc/N/cmdline = -r--r--r-- */
+	case PFSemul:	/* /proc/N/emul = -r--r--r-- */
+	case PFSmeminfo:	/* /proc/meminfo = -r--r--r-- */
+	case PFScpustat:	/* /proc/stat = -r--r--r-- */
+	case PFSdevices:	/* /proc/devices = -r--r--r-- */
+	case PFScpuinfo:	/* /proc/cpuinfo = -r--r--r-- */
+	case PFSuptime:	/* /proc/uptime = -r--r--r-- */
+	case PFSmounts:	/* /proc/mounts = -r--r--r-- */
+	case PFSloadavg:	/* /proc/loadavg = -r--r--r-- */
+	case PFSstatm:	/* /proc/N/statm = -r--r--r-- */
+	case PFSversion:	/* /proc/version = -r--r--r-- */
+		pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH;
+		vp->v_type = VREG;
+		break;
+
+#ifdef __HAVE_PROCFS_MACHDEP
+	PROCFS_MACHDEP_NODETYPE_CASES
+		procfs_machdep_allocvp(vp);
+		break;
+#endif
+
+	default:
+		panic("procfs_allocvp");
+	}
+
+	uvm_vnp_setsize(vp, 0);
+	*new_key = &pfs->pfs_key;
+
+	return 0;
+
+bad:
+	vp->v_tag =VT_NON;
+	vp->v_type = VNON;
+	vp->v_op = NULL;
+	vp->v_data = NULL;
+	kmem_free(pfs, sizeof(*pfs));
+	return error;
+}
+
 void
 procfs_init(void)
 {
-	procfs_hashinit();
+
 }
 
 void
 procfs_reinit(void)
 {
-	procfs_hashreinit();
+
 }
 
 void
 procfs_done(void)
 {
-	procfs_hashdone();
+
 }
 
 extern const struct vnodeopv_desc procfs_vnodeop_opv_desc;
@@ -296,6 +466,7 @@ struct vfsops procfs_vfsops = {
 	.vfs_statvfs = procfs_statvfs,
 	.vfs_sync = procfs_sync,
 	.vfs_vget = procfs_vget,
+	.vfs_loadvnode = procfs_loadvnode,
 	.vfs_fhtovp = (void *)eopnotsupp,
 	.vfs_vptofh = (void *)eopnotsupp,
 	.vfs_init = procfs_init,

Index: src/sys/miscfs/procfs/procfs_vnops.c
diff -u src/sys/miscfs/procfs/procfs_vnops.c:1.189 src/sys/miscfs/procfs/procfs_vnops.c:1.189.2.1
--- src/sys/miscfs/procfs/procfs_vnops.c:1.189	Fri Feb  7 15:29:22 2014
+++ src/sys/miscfs/procfs/procfs_vnops.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs_vnops.c,v 1.189 2014/02/07 15:29:22 hannken Exp $	*/
+/*	$NetBSD: procfs_vnops.c,v 1.189.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -105,7 +105,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.189 2014/02/07 15:29:22 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.189.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -259,6 +259,8 @@ const struct vnodeopv_entry_desc procfs_
 	{ &vop_setattr_desc, procfs_setattr },		/* setattr */
 	{ &vop_read_desc, procfs_read },		/* read */
 	{ &vop_write_desc, procfs_write },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_fcntl_desc, procfs_fcntl },		/* fcntl */
 	{ &vop_ioctl_desc, procfs_ioctl },		/* ioctl */
 	{ &vop_poll_desc, procfs_poll },		/* poll */
@@ -439,8 +441,18 @@ procfs_reclaim(void *v)
 	struct vop_reclaim_args /* {
 		struct vnode *a_vp;
 	} */ *ap = v;
+	struct vnode *vp = ap->a_vp;
+	struct pfsnode *pfs = VTOPFS(vp);
 
-	return (procfs_freevp(ap->a_vp));
+	/*
+	 * To interlock with procfs_revoke_vnodes().
+	 */
+	mutex_enter(vp->v_interlock);
+	vp->v_data = NULL;
+	mutex_exit(vp->v_interlock);
+	vcache_remove(vp->v_mount, &pfs->pfs_key, sizeof(pfs->pfs_key));
+	kmem_free(pfs, sizeof(*pfs));
+	return 0;
 }
 
 /*
@@ -1035,7 +1047,7 @@ procfs_lookup(void *v)
 
 		if (i != nproc_root_targets) {
 			error = procfs_allocvp(dvp->v_mount, vpp, 0,
-			    pt->pt_pfstype, -1, NULL);
+			    pt->pt_pfstype, -1);
 			return (error);
 		}
 
@@ -1055,14 +1067,14 @@ procfs_lookup(void *v)
 
 		if (procfs_proc_lock(pid, &p, ESRCH) != 0)
 			break;
-		error = procfs_allocvp(dvp->v_mount, vpp, vnpid, type, -1, p);
+		error = procfs_allocvp(dvp->v_mount, vpp, vnpid, type, -1);
 		procfs_proc_unlock(p);
 		return (error);
 
 	case PFSproc:
 		if (cnp->cn_flags & ISDOTDOT) {
 			error = procfs_allocvp(dvp->v_mount, vpp, 0, PFSroot,
-			    -1, NULL);
+			    -1);
 			return (error);
 		}
 
@@ -1110,7 +1122,7 @@ procfs_lookup(void *v)
 		}
 
 		error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
-		    pt->pt_pfstype, -1, p);
+		    pt->pt_pfstype, -1);
 		procfs_proc_unlock(p);
 		return (error);
 
@@ -1123,7 +1135,7 @@ procfs_lookup(void *v)
 
 		if (cnp->cn_flags & ISDOTDOT) {
 			error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
-			    PFSproc, -1, p);
+			    PFSproc, -1);
 			procfs_proc_unlock(p);
 			return (error);
 		}
@@ -1147,7 +1159,7 @@ procfs_lookup(void *v)
 
 		closef(fp);
 		error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
-		    PFSfd, fd, p);
+		    PFSfd, fd);
 		procfs_proc_unlock(p);
 		return error;
 	}
@@ -1159,7 +1171,7 @@ procfs_lookup(void *v)
 
 		if (cnp->cn_flags & ISDOTDOT) {
 			error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
-			    PFSproc, -1, p);
+			    PFSproc, -1);
 			procfs_proc_unlock(p);
 			return (error);
 		}
@@ -1170,7 +1182,7 @@ procfs_lookup(void *v)
 			return ENOENT;
 		}
 		error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
-		    PFStask, 0, p);
+		    PFStask, 0);
 		procfs_proc_unlock(p);
 		return error;
 	}

Index: src/sys/miscfs/specfs/spec_vnops.c
diff -u src/sys/miscfs/specfs/spec_vnops.c:1.143 src/sys/miscfs/specfs/spec_vnops.c:1.143.2.1
--- src/sys/miscfs/specfs/spec_vnops.c:1.143	Mon Mar 24 13:42:40 2014
+++ src/sys/miscfs/specfs/spec_vnops.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: spec_vnops.c,v 1.143 2014/03/24 13:42:40 hannken Exp $	*/
+/*	$NetBSD: spec_vnops.c,v 1.143.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -58,7 +58,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.143 2014/03/24 13:42:40 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.143.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/proc.h>
@@ -123,6 +123,8 @@ const struct vnodeopv_entry_desc spec_vn
 	{ &vop_setattr_desc, spec_setattr },		/* setattr */
 	{ &vop_read_desc, spec_read },			/* read */
 	{ &vop_write_desc, spec_write },		/* write */
+	{ &vop_fallocate_desc, spec_fallocate },	/* fallocate */
+	{ &vop_fdiscard_desc, spec_fdiscard },		/* fdiscard */
 	{ &vop_fcntl_desc, spec_fcntl },		/* fcntl */
 	{ &vop_ioctl_desc, spec_ioctl },		/* ioctl */
 	{ &vop_poll_desc, spec_poll },			/* poll */
@@ -838,6 +840,46 @@ spec_write(void *v)
 }
 
 /*
+ * fdiscard, which on disk devices becomes TRIM.
+ */
+int
+spec_fdiscard(void *v)
+{
+	struct vop_fdiscard_args /* {
+		struct vnode *a_vp;
+		off_t a_pos;
+		off_t a_len;
+	} */ *ap = v;
+	struct vnode *vp;
+	dev_t dev;
+
+	vp = ap->a_vp;
+	dev = NODEV;
+
+	mutex_enter(vp->v_interlock);
+	if (vdead_check(vp, VDEAD_NOWAIT) == 0 && vp->v_specnode != NULL) {
+		dev = vp->v_rdev;
+	}
+	mutex_exit(vp->v_interlock);
+
+	if (dev == NODEV) {
+		return ENXIO;
+	}
+
+	switch (vp->v_type) {
+	    case VCHR:
+		// this is not stored for character devices
+		//KASSERT(vp == vp->v_specnode->sn_dev->sd_cdevvp);
+		return cdev_discard(dev, ap->a_pos, ap->a_len);
+	    case VBLK:
+		KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp);
+		return bdev_discard(dev, ap->a_pos, ap->a_len);
+	    default:
+		panic("spec_fdiscard: not a device\n");
+	}
+}
+
+/*
  * Device ioctl operation.
  */
 /* ARGSUSED */

Index: src/sys/miscfs/specfs/specdev.h
diff -u src/sys/miscfs/specfs/specdev.h:1.42 src/sys/miscfs/specfs/specdev.h:1.42.2.1
--- src/sys/miscfs/specfs/specdev.h:1.42	Mon Sep 30 18:58:00 2013
+++ src/sys/miscfs/specfs/specdev.h	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: specdev.h,v 1.42 2013/09/30 18:58:00 hannken Exp $	*/
+/*	$NetBSD: specdev.h,v 1.42.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -119,6 +119,8 @@ int	spec_close(void *);
 #define	spec_setattr	genfs_ebadf
 int	spec_read(void *);
 int	spec_write(void *);
+#define spec_fallocate	genfs_eopnotsupp
+int	spec_fdiscard(void *);
 #define spec_fcntl	genfs_fcntl
 int	spec_ioctl(void *);
 int	spec_poll(void *);

Index: src/sys/miscfs/umapfs/umap_vfsops.c
diff -u src/sys/miscfs/umapfs/umap_vfsops.c:1.91 src/sys/miscfs/umapfs/umap_vfsops.c:1.91.2.1
--- src/sys/miscfs/umapfs/umap_vfsops.c:1.91	Sun Mar 23 15:21:16 2014
+++ src/sys/miscfs/umapfs/umap_vfsops.c	Sun Aug 10 06:56:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: umap_vfsops.c,v 1.91 2014/03/23 15:21:16 hannken Exp $	*/
+/*	$NetBSD: umap_vfsops.c,v 1.91.2.1 2014/08/10 06:56:05 tls Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: umap_vfsops.c,v 1.91 2014/03/23 15:21:16 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: umap_vfsops.c,v 1.91.2.1 2014/08/10 06:56:05 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -81,6 +81,8 @@ umapfs_mount(struct mount *mp, const cha
 	int i;
 #endif
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 
@@ -195,12 +197,7 @@ umapfs_mount(struct mount *mp, const cha
 	amp->umapm_size = sizeof(struct umap_node);
 	amp->umapm_tag = VT_UMAP;
 	amp->umapm_bypass = umap_bypass;
-	amp->umapm_alloc = layer_node_alloc;	/* the default alloc is fine */
 	amp->umapm_vnodeop_p = umap_vnodeop_p;
-	mutex_init(&amp->umapm_hashlock, MUTEX_DEFAULT, IPL_NONE);
-	amp->umapm_node_hashtbl = hashinit(NUMAPNODECACHE, HASH_LIST, true,
-	    &amp->umapm_node_hash);
-
 
 	/*
 	 * fix up umap node for root vnode.
@@ -212,8 +209,6 @@ umapfs_mount(struct mount *mp, const cha
 	 */
 	if (error) {
 		vrele(lowerrootvp);
-		hashdone(amp->umapm_node_hashtbl, HASH_LIST,
-		    amp->umapm_node_hash);
 		kmem_free(amp, sizeof(struct umap_mount));
 		return error;
 	}
@@ -269,8 +264,6 @@ umapfs_unmount(struct mount *mp, int mnt
 	/*
 	 * Finally, throw away the umap_mount structure
 	 */
-	mutex_destroy(&amp->umapm_hashlock);
-	hashdone(amp->umapm_node_hashtbl, HASH_LIST, amp->umapm_node_hash);
 	kmem_free(amp, sizeof(struct umap_mount));
 	mp->mnt_data = NULL;
 	return 0;
@@ -293,6 +286,7 @@ struct vfsops umapfs_vfsops = {
 	.vfs_quotactl = layerfs_quotactl,
 	.vfs_statvfs = layerfs_statvfs,
 	.vfs_sync = layerfs_sync,
+	.vfs_loadvnode = layerfs_loadvnode,
 	.vfs_vget = layerfs_vget,
 	.vfs_fhtovp = layerfs_fhtovp,
 	.vfs_vptofh = layerfs_vptofh,

Reply via email to