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

Modified Files:
        src/sys/fs [tls-earlyentropy]: unicode.h
        src/sys/fs/adosfs [tls-earlyentropy]: adosfs.h adutil.c advfsops.c
            advnops.c
        src/sys/fs/cd9660 [tls-earlyentropy]: cd9660_bmap.c cd9660_lookup.c
            cd9660_node.c cd9660_node.h cd9660_util.c cd9660_vfsops.c
            cd9660_vnops.c
        src/sys/fs/efs [tls-earlyentropy]: efs_vfsops.c efs_vnops.c files.efs
        src/sys/fs/filecorefs [tls-earlyentropy]: filecore_lookup.c
            filecore_vfsops.c filecore_vnops.c
        src/sys/fs/hfs [tls-earlyentropy]: hfs_vfsops.c hfs_vnops.c
        src/sys/fs/msdosfs [tls-earlyentropy]: denode.h msdosfs_denode.c
            msdosfs_lookup.c msdosfs_vfsops.c msdosfs_vnops.c msdosfsmount.h
        src/sys/fs/nilfs [tls-earlyentropy]: nilfs_vfsops.c nilfs_vnops.c
        src/sys/fs/ntfs [tls-earlyentropy]: ntfs_vfsops.c ntfs_vnops.c
        src/sys/fs/ptyfs [tls-earlyentropy]: ptyfs_vfsops.c ptyfs_vnops.c
        src/sys/fs/puffs [tls-earlyentropy]: puffs_vfsops.c puffs_vnops.c
        src/sys/fs/smbfs [tls-earlyentropy]: smbfs_vfsops.c smbfs_vnops.c
        src/sys/fs/sysvbfs [tls-earlyentropy]: sysvbfs.c sysvbfs_vfsops.c
            sysvbfs_vnops.c
        src/sys/fs/tmpfs [tls-earlyentropy]: tmpfs.h tmpfs_fifoops.c
            tmpfs_mem.c tmpfs_specops.c tmpfs_vfsops.c tmpfs_vnops.c
        src/sys/fs/udf [tls-earlyentropy]: udf_subr.c udf_vfsops.c udf_vnops.c
        src/sys/fs/union [tls-earlyentropy]: union_subr.c union_vfsops.c
            union_vnops.c
        src/sys/fs/unionfs [tls-earlyentropy]: unionfs_vfsops.c unionfs_vnops.c
        src/sys/fs/v7fs [tls-earlyentropy]: v7fs_extern.c v7fs_vfsops.c
            v7fs_vnops.c
Removed Files:
        src/sys/fs/efs [tls-earlyentropy]: efs_ihash.c efs_ihash.h

Log Message:
Rebase.


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.6.60.1 src/sys/fs/unicode.h
cvs rdiff -u -r1.12 -r1.12.10.1 src/sys/fs/adosfs/adosfs.h
cvs rdiff -u -r1.16 -r1.16.2.1 src/sys/fs/adosfs/adutil.c
cvs rdiff -u -r1.69 -r1.69.2.1 src/sys/fs/adosfs/advfsops.c
cvs rdiff -u -r1.43 -r1.43.2.1 src/sys/fs/adosfs/advnops.c
cvs rdiff -u -r1.4 -r1.4.64.1 src/sys/fs/cd9660/cd9660_bmap.c
cvs rdiff -u -r1.26 -r1.26.2.1 src/sys/fs/cd9660/cd9660_lookup.c
cvs rdiff -u -r1.30 -r1.30.2.1 src/sys/fs/cd9660/cd9660_node.c
cvs rdiff -u -r1.14 -r1.14.64.1 src/sys/fs/cd9660/cd9660_node.h
cvs rdiff -u -r1.10 -r1.10.26.1 src/sys/fs/cd9660/cd9660_util.c
cvs rdiff -u -r1.83 -r1.83.2.1 src/sys/fs/cd9660/cd9660_vfsops.c
cvs rdiff -u -r1.47 -r1.47.2.1 src/sys/fs/cd9660/cd9660_vnops.c
cvs rdiff -u -r1.10 -r0 src/sys/fs/efs/efs_ihash.c
cvs rdiff -u -r1.1 -r0 src/sys/fs/efs/efs_ihash.h
cvs rdiff -u -r1.24 -r1.24.10.1 src/sys/fs/efs/efs_vfsops.c
cvs rdiff -u -r1.31 -r1.31.2.1 src/sys/fs/efs/efs_vnops.c
cvs rdiff -u -r1.1 -r1.1.98.1 src/sys/fs/efs/files.efs
cvs rdiff -u -r1.19 -r1.19.2.1 src/sys/fs/filecorefs/filecore_lookup.c
cvs rdiff -u -r1.75 -r1.75.2.1 src/sys/fs/filecorefs/filecore_vfsops.c
cvs rdiff -u -r1.41 -r1.41.2.1 src/sys/fs/filecorefs/filecore_vnops.c
cvs rdiff -u -r1.30 -r1.30.2.1 src/sys/fs/hfs/hfs_vfsops.c
cvs rdiff -u -r1.29 -r1.29.2.1 src/sys/fs/hfs/hfs_vnops.c
cvs rdiff -u -r1.23 -r1.23.10.1 src/sys/fs/msdosfs/denode.h
cvs rdiff -u -r1.48 -r1.48.10.1 src/sys/fs/msdosfs/msdosfs_denode.c
cvs rdiff -u -r1.32 -r1.32.2.1 src/sys/fs/msdosfs/msdosfs_lookup.c
cvs rdiff -u -r1.106 -r1.106.2.1 src/sys/fs/msdosfs/msdosfs_vfsops.c
cvs rdiff -u -r1.89 -r1.89.2.1 src/sys/fs/msdosfs/msdosfs_vnops.c
cvs rdiff -u -r1.19 -r1.19.10.1 src/sys/fs/msdosfs/msdosfsmount.h
cvs rdiff -u -r1.15 -r1.15.2.1 src/sys/fs/nilfs/nilfs_vfsops.c
cvs rdiff -u -r1.27 -r1.27.2.1 src/sys/fs/nilfs/nilfs_vnops.c
cvs rdiff -u -r1.93 -r1.93.2.1 src/sys/fs/ntfs/ntfs_vfsops.c
cvs rdiff -u -r1.56 -r1.56.2.1 src/sys/fs/ntfs/ntfs_vnops.c
cvs rdiff -u -r1.49 -r1.49.2.1 src/sys/fs/ptyfs/ptyfs_vfsops.c
cvs rdiff -u -r1.46 -r1.46.2.1 src/sys/fs/ptyfs/ptyfs_vnops.c
cvs rdiff -u -r1.109 -r1.109.2.1 src/sys/fs/puffs/puffs_vfsops.c
cvs rdiff -u -r1.181 -r1.181.2.1 src/sys/fs/puffs/puffs_vnops.c
cvs rdiff -u -r1.99 -r1.99.2.1 src/sys/fs/smbfs/smbfs_vfsops.c
cvs rdiff -u -r1.89 -r1.89.2.1 src/sys/fs/smbfs/smbfs_vnops.c
cvs rdiff -u -r1.13 -r1.13.2.1 src/sys/fs/sysvbfs/sysvbfs.c
cvs rdiff -u -r1.42 -r1.42.2.1 src/sys/fs/sysvbfs/sysvbfs_vfsops.c
cvs rdiff -u -r1.53 -r1.53.2.1 src/sys/fs/sysvbfs/sysvbfs_vnops.c
cvs rdiff -u -r1.48 -r1.48.2.1 src/sys/fs/tmpfs/tmpfs.h
cvs rdiff -u -r1.10 -r1.10.2.1 src/sys/fs/tmpfs/tmpfs_fifoops.c
cvs rdiff -u -r1.4 -r1.4.28.1 src/sys/fs/tmpfs/tmpfs_mem.c
cvs rdiff -u -r1.11 -r1.11.2.1 src/sys/fs/tmpfs/tmpfs_specops.c
cvs rdiff -u -r1.58 -r1.58.2.1 src/sys/fs/tmpfs/tmpfs_vfsops.c
cvs rdiff -u -r1.118 -r1.118.2.1 src/sys/fs/tmpfs/tmpfs_vnops.c
cvs rdiff -u -r1.124 -r1.124.2.1 src/sys/fs/udf/udf_subr.c
cvs rdiff -u -r1.66 -r1.66.2.1 src/sys/fs/udf/udf_vfsops.c
cvs rdiff -u -r1.91 -r1.91.2.1 src/sys/fs/udf/udf_vnops.c
cvs rdiff -u -r1.63 -r1.63.2.1 src/sys/fs/union/union_subr.c
cvs rdiff -u -r1.71 -r1.71.2.1 src/sys/fs/union/union_vfsops.c
cvs rdiff -u -r1.59 -r1.59.2.1 src/sys/fs/union/union_vnops.c
cvs rdiff -u -r1.12 -r1.12.2.1 src/sys/fs/unionfs/unionfs_vfsops.c
cvs rdiff -u -r1.7 -r1.7.10.1 src/sys/fs/unionfs/unionfs_vnops.c
cvs rdiff -u -r1.2 -r1.2.2.1 src/sys/fs/v7fs/v7fs_extern.c
cvs rdiff -u -r1.9 -r1.9.2.1 src/sys/fs/v7fs/v7fs_vfsops.c
cvs rdiff -u -r1.16 -r1.16.2.1 src/sys/fs/v7fs/v7fs_vnops.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/fs/unicode.h
diff -u src/sys/fs/unicode.h:1.6 src/sys/fs/unicode.h:1.6.60.1
--- src/sys/fs/unicode.h:1.6	Mon Apr 28 20:24:02 2008
+++ src/sys/fs/unicode.h	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: unicode.h,v 1.6 2008/04/28 20:24:02 martin Exp $ */
+/* $NetBSD: unicode.h,v 1.6.60.1 2014/08/10 06:55:53 tls Exp $ */
 
 /*-
  * Copyright (c) 2001, 2004 The NetBSD Foundation, Inc.
@@ -76,7 +76,7 @@ static int wput_utf8(char *, size_t, u_i
 static u_int16_t
 wget_utf8(const char **str, size_t *sz)
 {
-	int c;
+	size_t c;
 	u_int16_t rune = 0;
 	const char *s = *str;
 	static const int _utf_count[16] = {

Index: src/sys/fs/adosfs/adosfs.h
diff -u src/sys/fs/adosfs/adosfs.h:1.12 src/sys/fs/adosfs/adosfs.h:1.12.10.1
--- src/sys/fs/adosfs/adosfs.h:1.12	Wed Oct  3 07:20:50 2012
+++ src/sys/fs/adosfs/adosfs.h	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: adosfs.h,v 1.12 2012/10/03 07:20:50 mlelstv Exp $	*/
+/*	$NetBSD: adosfs.h,v 1.12.10.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*
  * Copyright (c) 1994 Christian E. Hopps
@@ -73,7 +73,6 @@ enum anode_type { AROOT, ADIR, AFILE, AL
  */
 struct anode {
 	struct genfs_node gnode;
-	LIST_ENTRY(anode) link;
 	enum anode_type type;
 	char name[ADMAXNAMELEN+1];	/* (r/d/f) name for object */
 	struct datestamp mtimev;	/* (r) volume modified */
@@ -112,7 +111,6 @@ struct anode {
 #define ANODEHASHSZ (512)
 
 struct adosfsmount {
-	LIST_HEAD(anodechain, anode) anodetab[ANODEHASHSZ];
 	struct mount *mp;	/* owner mount */
 	u_int32_t dostype;	/* type of volume */
 	u_long rootb;		/* root block number */
@@ -169,10 +167,6 @@ int adoshash(const u_char *, int, int, i
 int adunixprot(int);
 int adosfs_getblktype(struct adosfsmount *, struct buf *);
 
-struct vnode *adosfs_ahashget(struct mount *, ino_t);
-void adosfs_ainshash(struct adosfsmount *, struct anode *);
-void adosfs_aremhash(struct anode *);
-
 int adosfs_lookup(void *);
 
 extern int (**adosfs_vnodeop_p)(void *);

Index: src/sys/fs/adosfs/adutil.c
diff -u src/sys/fs/adosfs/adutil.c:1.16 src/sys/fs/adosfs/adutil.c:1.16.2.1
--- src/sys/fs/adosfs/adutil.c:1.16	Thu Feb 27 16:51:37 2014
+++ src/sys/fs/adosfs/adutil.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: adutil.c,v 1.16 2014/02/27 16:51:37 hannken Exp $	*/
+/*	$NetBSD: adutil.c,v 1.16.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*
  * Copyright (c) 1994 Christian E. Hopps
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: adutil.c,v 1.16 2014/02/27 16:51:37 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: adutil.c,v 1.16.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/vnode.h>
@@ -47,62 +47,8 @@ __KERNEL_RCSID(0, "$NetBSD: adutil.c,v 1
 /*
  * look for anode in the mount's hash table, return locked.
  */
-#define AHASH(an) ((an) & (ANODEHASHSZ - 1))
 static int CapitalChar(int, int);
 
-extern kmutex_t adosfs_hashlock;
-
-struct vnode *
-adosfs_ahashget(struct mount *mp, ino_t an)
-{
-	struct anodechain *hp;
-	struct anode *ap;
-	struct vnode *vp;
-
-	hp = &VFSTOADOSFS(mp)->anodetab[AHASH(an)];
-
-start_over:
-	mutex_enter(&adosfs_hashlock);
-	for (ap = hp->lh_first; ap != NULL; ap = ap->link.le_next) {
-		if (ap->block == an) {
-			vp = ATOV(ap);
-			mutex_enter(vp->v_interlock);
-			mutex_exit(&adosfs_hashlock);
-			if (vget(vp, LK_EXCLUSIVE))
-				goto start_over;
-			return (ATOV(ap));
-		}
-	}
-	mutex_exit(&adosfs_hashlock);
-	return (NULL);
-}
-
-/*
- * insert in hash table and lock
- *
- * ap->vp must have been initialized before this call.
- */
-void
-adosfs_ainshash(struct adosfsmount *amp, struct anode *ap)
-{
-	int error __diagused;
-
-	error = VOP_LOCK(ATOV(ap), LK_EXCLUSIVE);
-	KASSERT(error == 0);
-
-	mutex_enter(&adosfs_hashlock);
-	LIST_INSERT_HEAD(&amp->anodetab[AHASH(ap->block)], ap, link);
-	mutex_exit(&adosfs_hashlock);
-}
-
-void
-adosfs_aremhash(struct anode *ap)
-{
-	mutex_enter(&adosfs_hashlock);
-	LIST_REMOVE(ap, link);
-	mutex_exit(&adosfs_hashlock);
-}
-
 int
 adosfs_getblktype(struct adosfsmount *amp, struct buf *bp)
 {

Index: src/sys/fs/adosfs/advfsops.c
diff -u src/sys/fs/adosfs/advfsops.c:1.69 src/sys/fs/adosfs/advfsops.c:1.69.2.1
--- src/sys/fs/adosfs/advfsops.c:1.69	Sun Mar 23 15:21:15 2014
+++ src/sys/fs/adosfs/advfsops.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: advfsops.c,v 1.69 2014/03/23 15:21:15 hannken Exp $	*/
+/*	$NetBSD: advfsops.c,v 1.69.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*
  * Copyright (c) 1994 Christian E. Hopps
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: advfsops.c,v 1.69 2014/03/23 15:21:15 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: advfsops.c,v 1.69.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -70,8 +70,6 @@ static struct sysctllog *adosfs_sysctl_l
 int adosfs_mountfs(struct vnode *, struct mount *, struct lwp *);
 int adosfs_loadbitmap(struct adosfsmount *);
 
-kmutex_t adosfs_hashlock;
-
 struct pool adosfs_node_pool;
 
 MALLOC_JUSTDEFINE(M_ANODE, "adosfs anode","adosfs anode structures and tables");
@@ -92,6 +90,8 @@ adosfs_mount(struct mount *mp, const cha
 	int error;
 	mode_t accessmode;
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 
@@ -167,7 +167,7 @@ adosfs_mountfs(struct vnode *devvp, stru
 	struct buf *bp;
 	struct vnode *rvp;
 	size_t bitmap_sz = 0;
-	int error, i;
+	int error;
 	uint64_t numsecs;
 	unsigned secsize;
 	unsigned long secsperblk, blksperdisk, resvblks;
@@ -262,12 +262,6 @@ adosfs_mountfs(struct vnode *devvp, stru
 	mp->mnt_flag |= MNT_LOCAL;
 
 	/*
-	 * init anode table.
-	 */
-	for (i = 0; i < ANODEHASHSZ; i++)
-		LIST_INIT(&amp->anodetab[i]);
-
-	/*
 	 * get the root anode, if not a valid fs this will fail.
 	 */
 	if ((error = VFS_ROOT(mp, &rvp)) != 0)
@@ -369,50 +363,55 @@ adosfs_statvfs(struct mount *mp, struct 
 }
 
 /*
- * lookup an anode, check mount's hash table if not found, create
- * return locked and referenced al la vget(vp, 1);
+ * lookup an anode, if not found, create
+ * return locked and referenced al la vget(vp, LK_EXCLUSIVE);
  */
 int
 adosfs_vget(struct mount *mp, ino_t an, struct vnode **vpp)
 {
+	int error;
+
+	error = vcache_get(mp, &an, sizeof(an), vpp);
+	if (error)
+		return error;
+	error = vn_lock(*vpp, LK_EXCLUSIVE);
+	if (error) {
+		vrele(*vpp);
+		*vpp = NULL;
+		return error;
+	}
+	return 0;
+}
+
+/*
+ * Initialize this vnode / anode pair.
+ * Caller assures no other thread will try to load this inode.
+ */
+int
+adosfs_loadvnode(struct mount *mp, struct vnode *vp,
+    const void *key, size_t key_len, const void **new_key)
+{
 	struct adosfsmount *amp;
-	struct vnode *vp;
 	struct anode *ap;
 	struct buf *bp;
+	ino_t an;
 	char *nam, *tmp;
 	int namlen, error;
 
-	error = 0;
+	KASSERT(key_len == sizeof(an));
+	memcpy(&an, key, key_len);
 	amp = VFSTOADOSFS(mp);
-	bp = NULL;
 
-	/*
-	 * check hash table. we are done if found
-	 */
-	if ((*vpp = adosfs_ahashget(mp, an)) != NULL)
-		return (0);
-
-	error = getnewvnode(VT_ADOSFS, mp, adosfs_vnodeop_p, NULL, &vp);
-	if (error)
-		return (error);
+	if ((error = bread(amp->devvp, an * amp->bsize / DEV_BSIZE,
+			   amp->bsize, NOCRED, 0, &bp)) != 0)
+		return error;
 
-	/*
-	 * setup, insert in hash, and lock before io.
-	 */
-	vp->v_data = ap = pool_get(&adosfs_node_pool, PR_WAITOK);
+	ap = pool_get(&adosfs_node_pool, PR_WAITOK);
 	memset(ap, 0, sizeof(struct anode));
 	ap->vp = vp;
 	ap->amp = amp;
 	ap->block = an;
 	ap->nwords = amp->nwords;
-	genfs_node_init(vp, &adosfs_genfsops);
-	adosfs_ainshash(amp, ap);
-
-	if ((error = bread(amp->devvp, an * amp->bsize / DEV_BSIZE,
-			   amp->bsize, NOCRED, 0, &bp)) != 0) {
-		vput(vp);
-		return (error);
-	}
 
 	/*
 	 * get type and fill rest in based on that.
@@ -466,9 +465,8 @@ adosfs_vget(struct mount *mp, ino_t an, 
 		ap->fsize = namlen;
 		break;
 	default:
-		brelse(bp, 0);
-		vput(vp);
-		return (EINVAL);
+		error = EINVAL;
+		goto bad;
 	}
 
 	/*
@@ -486,9 +484,8 @@ adosfs_vget(struct mount *mp, ino_t an, 
 		printf("adosfs: aget: name length too long blk %llu\n",
 		    (unsigned long long)an);
 #endif
-		brelse(bp, 0);
-		vput(vp);
-		return (EINVAL);
+		error = EINVAL;
+		goto bad;
 	}
 	memcpy(ap->name, nam, namlen);
 	ap->name[namlen] = 0;
@@ -529,15 +526,9 @@ adosfs_vget(struct mount *mp, ino_t an, 
 		bp = NULL;
 		error = bread(amp->devvp, ap->linkto * amp->bsize / DEV_BSIZE,
 		    amp->bsize, NOCRED, 0, &bp);
-		if (error) {
-			vput(vp);
-			return (error);
-		}
+		if (error)
+			goto bad;
 		ap->fsize = adoswordn(bp, ap->nwords - 47);
-		/*
-		 * Should ap->block be set to the real file header block?
-		 */
-		ap->block = ap->linkto;
 	}
 
 	if (ap->type == AROOT) {
@@ -584,10 +575,20 @@ adosfs_vget(struct mount *mp, ino_t an, 
 	ap->mtime.mins = adoswordn(bp, ap->nwords - 22);
 	ap->mtime.ticks = adoswordn(bp, ap->nwords - 21);
 
-	*vpp = vp;
 	brelse(bp, 0);
+	vp->v_tag = VT_ADOSFS;
+	vp->v_op = adosfs_vnodeop_p;
+	vp->v_data = ap;
+	genfs_node_init(vp, &adosfs_genfsops);
 	uvm_vnp_setsize(vp, ap->fsize);
-	return (0);
+	*new_key = &ap->block;
+	return 0;
+
+bad:
+	if (bp)
+		brelse(bp, 0);
+	pool_put(&adosfs_node_pool, ap);
+	return error;
 }
 
 /*
@@ -759,7 +760,6 @@ adosfs_init(void)
 {
 
 	malloc_type_attach(M_ANODE);
-	mutex_init(&adosfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
 	pool_init(&adosfs_node_pool, sizeof(struct anode), 0, 0, 0, "adosndpl",
 	    &pool_allocator_nointr, IPL_NONE);
 }
@@ -769,7 +769,6 @@ adosfs_done(void)
 {
 
 	pool_destroy(&adosfs_node_pool);
-	mutex_destroy(&adosfs_hashlock);
 	malloc_type_detach(M_ANODE);
 }
 
@@ -795,6 +794,7 @@ struct vfsops adosfs_vfsops = {
 	.vfs_statvfs = adosfs_statvfs,
 	.vfs_sync = adosfs_sync,
 	.vfs_vget = adosfs_vget,
+	.vfs_loadvnode = adosfs_loadvnode,
 	.vfs_fhtovp = adosfs_fhtovp,
 	.vfs_vptofh = adosfs_vptofh,
 	.vfs_init = adosfs_init,

Index: src/sys/fs/adosfs/advnops.c
diff -u src/sys/fs/adosfs/advnops.c:1.43 src/sys/fs/adosfs/advnops.c:1.43.2.1
--- src/sys/fs/adosfs/advnops.c:1.43	Thu Jan 23 10:13:56 2014
+++ src/sys/fs/adosfs/advnops.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: advnops.c,v 1.43 2014/01/23 10:13:56 hannken Exp $	*/
+/*	$NetBSD: advnops.c,v 1.43.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*
  * Copyright (c) 1994 Christian E. Hopps
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: advnops.c,v 1.43 2014/01/23 10:13:56 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: advnops.c,v 1.43.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -105,6 +105,8 @@ const struct vnodeopv_entry_desc adosfs_
 	{ &vop_setattr_desc, adosfs_setattr },		/* setattr */
 	{ &vop_read_desc, adosfs_read },		/* read */
 	{ &vop_write_desc, adosfs_write },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_fcntl_desc, adosfs_fcntl },		/* fcntl */
 	{ &vop_ioctl_desc, adosfs_ioctl },		/* ioctl */
 	{ &vop_poll_desc, adosfs_poll },		/* poll */
@@ -878,7 +880,7 @@ adosfs_reclaim(void *v)
 #endif
 	vp = sp->a_vp;
 	ap = VTOA(vp);
-	LIST_REMOVE(ap, link);
+	vcache_remove(vp->v_mount, &ap->block, sizeof(ap->block));
 	if (vp->v_type == VDIR && ap->tab)
 		free(ap->tab, M_ANODE);
 	else if (vp->v_type == VLNK && ap->slinkto)

Index: src/sys/fs/cd9660/cd9660_bmap.c
diff -u src/sys/fs/cd9660/cd9660_bmap.c:1.4 src/sys/fs/cd9660/cd9660_bmap.c:1.4.64.1
--- src/sys/fs/cd9660/cd9660_bmap.c:1.4	Wed Feb 27 19:43:36 2008
+++ src/sys/fs/cd9660/cd9660_bmap.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_bmap.c,v 1.4 2008/02/27 19:43:36 matt Exp $	*/
+/*	$NetBSD: cd9660_bmap.c,v 1.4.64.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (c) 1994
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cd9660_bmap.c,v 1.4 2008/02/27 19:43:36 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cd9660_bmap.c,v 1.4.64.1 2014/08/10 06:55:53 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/namei.h>
@@ -74,7 +74,7 @@ cd9660_bmap(void *v)
 	 * to physical mapping is requested.
 	 */
 	if (ap->a_vpp != NULL)
-		*ap->a_vpp = ip->i_devvp;
+		*ap->a_vpp = ip->i_mnt->im_devvp;
 	if (ap->a_bnp == NULL)
 		return (0);
 

Index: src/sys/fs/cd9660/cd9660_lookup.c
diff -u src/sys/fs/cd9660/cd9660_lookup.c:1.26 src/sys/fs/cd9660/cd9660_lookup.c:1.26.2.1
--- src/sys/fs/cd9660/cd9660_lookup.c:1.26	Fri Feb  7 15:29:21 2014
+++ src/sys/fs/cd9660/cd9660_lookup.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_lookup.c,v 1.26 2014/02/07 15:29:21 hannken Exp $	*/
+/*	$NetBSD: cd9660_lookup.c,v 1.26.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (c) 1989, 1993, 1994
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cd9660_lookup.c,v 1.26 2014/02/07 15:29:21 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cd9660_lookup.c,v 1.26.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/namei.h>
@@ -57,8 +57,6 @@ __KERNEL_RCSID(0, "$NetBSD: cd9660_looku
 #include <fs/cd9660/cd9660_rrip.h>
 #include <fs/cd9660/cd9660_mount.h>
 
-struct	nchstats iso_nchstats;
-
 /*
  * Convert a component of a pathname into a pointer to a locked inode.
  * This is a very central and rather complicated routine.
@@ -109,8 +107,7 @@ cd9660_lookup(void *v)
 	int saveoffset = -1;		/* offset of last directory entry in dir */
 	int numdirpasses;		/* strategy for directory search */
 	doff_t endsearch;		/* offset to end directory search */
-	struct vnode *pdp;		/* saved dp during symlink work */
-	struct vnode *tdp;		/* returned by cd9660_vget_internal */
+	struct vnode *tdp;		/* returned by vcache_get */
 	u_long bmask;			/* block offset mask */
 	int error;
 	ino_t ino = 0;
@@ -191,7 +188,7 @@ cd9660_lookup(void *v)
 		    &bp)))
 				return (error);
 		numdirpasses = 2;
-		iso_nchstats.ncs_2passes++;
+		namecache_count_2passes();
 	}
 	endsearch = dp->i_size;
 
@@ -343,7 +340,8 @@ notfound:
 
 found:
 	if (numdirpasses == 2)
-		iso_nchstats.ncs_pass2++;
+		namecache_count_pass2();
+	brelse(bp, 0);
 
 	/*
 	 * Found component in pathname.
@@ -353,46 +351,12 @@ found:
 	if ((flags & ISLASTCN) && nameiop == LOOKUP)
 		dp->i_diroff = dp->i_offset;
 
-	/*
-	 * Step through the translation in the name.  We do not `iput' the
-	 * directory because we may need it again if a symbolic link
-	 * is relative to the current directory.  Instead we save it
-	 * unlocked as "pdp".  We must get the target inode before unlocking
-	 * the directory to insure that the inode will not be removed
-	 * before we get it.  We prevent deadlock by always fetching
-	 * inodes from the root, moving down the directory tree. Thus
-	 * when following backward pointers ".." we must unlock the
-	 * parent directory before getting the requested directory.
-	 * There is a potential race condition here if both the current
-	 * and parent directories are removed before the `iget' for the
-	 * inode associated with ".." returns.  We hope that this occurs
-	 * infrequently since we cannot avoid this race condition without
-	 * implementing a sophisticated deadlock detection algorithm.
-	 * Note also that this simple deadlock detection scheme will not
-	 * work if the file system has any hard links other than ".."
-	 * that point backwards in the directory structure.
-	 */
-	pdp = vdp;
-
-	/*
-	 * If ino is different from dp->i_ino,
-	 * it's a relocated directory.
-	 */
-	brelse(bp, 0);
-	if (flags & ISDOTDOT) {
-		VOP_UNLOCK(pdp);	/* race to get the inode */
-		error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp,
-					     dp->i_ino != ino, ep);
-		vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY);
-		if (error)
-			return error;
-		*vpp = tdp;
-	} else if (dp->i_number == dp->i_ino) {
+	if (dp->i_number == dp->i_ino) {
 		vref(vdp);	/* we want ourself, ie "." */
 		*vpp = vdp;
 	} else {
-		error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp,
-					     dp->i_ino != ino, ep);
+		error = vcache_get(vdp->v_mount,
+		    &dp->i_ino, sizeof(dp->i_ino), &tdp);
 		if (error)
 			return (error);
 		*vpp = tdp;
@@ -403,8 +367,6 @@ found:
 	 */
 	cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags);
 
-	if (*vpp != vdp)
-		VOP_UNLOCK(*vpp);
 	return 0;
 }
 
@@ -418,6 +380,7 @@ cd9660_blkatoff(struct vnode *vp, off_t 
 {
 	struct iso_node *ip;
 	struct iso_mnt *imp;
+	struct vnode *devvp;
 	struct buf *bp;
 	daddr_t lbn;
 	int bsize, error;
@@ -427,7 +390,11 @@ cd9660_blkatoff(struct vnode *vp, off_t 
 	lbn = cd9660_lblkno(imp, offset);
 	bsize = cd9660_blksize(imp, ip, lbn);
 
-	if ((error = bread(vp, lbn, bsize, NOCRED, 0, &bp)) != 0) {
+	if ((error = VOP_BMAP(vp, lbn, &devvp, &lbn, NULL)) != 0) {
+		*bpp = NULL;
+		return error;
+	}
+	if ((error = bread(devvp, lbn, bsize, NOCRED, 0, &bp)) != 0) {
 		*bpp = NULL;
 		return (error);
 	}

Index: src/sys/fs/cd9660/cd9660_node.c
diff -u src/sys/fs/cd9660/cd9660_node.c:1.30 src/sys/fs/cd9660/cd9660_node.c:1.30.2.1
--- src/sys/fs/cd9660/cd9660_node.c:1.30	Thu Feb 27 16:51:38 2014
+++ src/sys/fs/cd9660/cd9660_node.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_node.c,v 1.30 2014/02/27 16:51:38 hannken Exp $	*/
+/*	$NetBSD: cd9660_node.c,v 1.30.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1994
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cd9660_node.c,v 1.30 2014/02/27 16:51:38 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cd9660_node.c,v 1.30.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -58,15 +58,6 @@ __KERNEL_RCSID(0, "$NetBSD: cd9660_node.
 #include <fs/cd9660/cd9660_mount.h>
 #include <fs/cd9660/iso_rrip.h>
 
-/*
- * Structures associated with iso_node caching.
- */
-LIST_HEAD(ihashhead, iso_node) *isohashtbl;
-u_long isohash;
-#define	INOHASH(device, inum)	(((device) + ((inum)>>12)) & isohash)
-kmutex_t cd9660_ihash_lock;
-kmutex_t cd9660_hashlock;
-
 extern int prtactive;	/* 1 => print out reclaim of active vnodes */
 
 struct pool cd9660_node_pool;
@@ -74,7 +65,7 @@ struct pool cd9660_node_pool;
 static u_int cd9660_chars2ui(const u_char *, int);
 
 /*
- * Initialize hash links for inodes and dnodes.
+ * Initialize pool for nodes.
  */
 void
 cd9660_init(void)
@@ -83,118 +74,29 @@ cd9660_init(void)
 	malloc_type_attach(M_ISOFSMNT);
 	pool_init(&cd9660_node_pool, sizeof(struct iso_node), 0, 0, 0,
 	    "cd9660nopl", &pool_allocator_nointr, IPL_NONE);
-	isohashtbl = hashinit(desiredvnodes, HASH_LIST, true, &isohash);
-	mutex_init(&cd9660_ihash_lock, MUTEX_DEFAULT, IPL_NONE);
-	mutex_init(&cd9660_hashlock, MUTEX_DEFAULT, IPL_NONE);
 }
 
 /*
- * Reinitialize inode hash table.
+ * Reinitialize.
  */
 
 void
 cd9660_reinit(void)
 {
-	struct iso_node *ip;
-	struct ihashhead *oldhash1, *hash1;
-	u_long oldmask1, mask1, val;
-	u_int i;
-
-	hash1 = hashinit(desiredvnodes, HASH_LIST, true, &mask1);
-
-	mutex_enter(&cd9660_ihash_lock);
-	oldhash1 = isohashtbl;
-	oldmask1 = isohash;
-	isohashtbl = hash1;
-	isohash = mask1;
-	for (i = 0; i <= oldmask1; i++) {
-		while ((ip = LIST_FIRST(&oldhash1[i])) != NULL) {
-			LIST_REMOVE(ip, i_hash);
-			val = INOHASH(ip->i_dev, ip->i_number);
-			LIST_INSERT_HEAD(&hash1[val], ip, i_hash);
-		}
-	}
-	mutex_exit(&cd9660_ihash_lock);
-	hashdone(oldhash1, HASH_LIST, oldmask1);
+
 }
 
 /*
- * Destroy node pool and hash table.
+ * Destroy node pool.
  */
 void
 cd9660_done(void)
 {
-	hashdone(isohashtbl, HASH_LIST, isohash);
 	pool_destroy(&cd9660_node_pool);
-	mutex_destroy(&cd9660_ihash_lock);
-	mutex_destroy(&cd9660_hashlock);
 	malloc_type_detach(M_ISOFSMNT);
 }
 
 /*
- * Use the device/inum pair to find the incore inode, and return a pointer
- * to it. If it is in core, but locked, wait for it.
- */
-struct vnode *
-cd9660_ihashget(dev_t dev, ino_t inum, int flags)
-{
-	struct iso_node *ip;
-	struct vnode *vp;
-
-loop:
-	mutex_enter(&cd9660_ihash_lock);
-	LIST_FOREACH(ip, &isohashtbl[INOHASH(dev, inum)], i_hash) {
-		if (inum == ip->i_number && dev == ip->i_dev) {
-			vp = ITOV(ip);
-			if (flags == 0) {
-				mutex_exit(&cd9660_ihash_lock);
-			} else {
-				mutex_enter(vp->v_interlock);
-				mutex_exit(&cd9660_ihash_lock);
-				if (vget(vp, flags))
-					goto loop;
-			}
-			return (vp);
-		}
-	}
-	mutex_exit(&cd9660_ihash_lock);
-	return (NULL);
-}
-
-/*
- * Insert the inode into the hash table, and return it locked.
- *
- * ip->i_vnode must be initialized first.
- */
-void
-cd9660_ihashins(struct iso_node *ip)
-{
-	struct ihashhead *ipp;
-	int error __diagused;
-
-	KASSERT(mutex_owned(&cd9660_hashlock));
-
-	mutex_enter(&cd9660_ihash_lock);
-	ipp = &isohashtbl[INOHASH(ip->i_dev, ip->i_number)];
-	LIST_INSERT_HEAD(ipp, ip, i_hash);
-	mutex_exit(&cd9660_ihash_lock);
-
-	error = VOP_LOCK(ITOV(ip), LK_EXCLUSIVE);
-	KASSERT(error == 0);
-}
-
-/*
- * Remove the inode from the hash table.
- */
-void
-cd9660_ihashrem(struct iso_node *ip)
-{
-	mutex_enter(&cd9660_ihash_lock);
-	LIST_REMOVE(ip, i_hash);
-	mutex_exit(&cd9660_ihash_lock);
-}
-
-/*
  * Last reference to an inode, write the inode out and if necessary,
  * truncate and deallocate the file.
  */
@@ -235,16 +137,12 @@ cd9660_reclaim(void *v)
 	if (prtactive && vp->v_usecount > 1)
 		vprint("cd9660_reclaim: pushing active", vp);
 	/*
-	 * Remove the inode from its hash chain.
+	 * Remove the inode from the vnode cache.
 	 */
-	cd9660_ihashrem(ip);
+	vcache_remove(vp->v_mount, &ip->i_number, sizeof(ip->i_number));
 	/*
 	 * Purge old data structures associated with the inode.
 	 */
-	if (ip->i_devvp) {
-		vrele(ip->i_devvp);
-		ip->i_devvp = 0;
-	}
 	genfs_node_destroy(vp);
 	pool_put(&cd9660_node_pool, vp->v_data);
 	vp->v_data = NULL;
@@ -440,7 +338,14 @@ isodirino(struct iso_directory_record *i
 {
 	ino_t ino;
 
-	ino = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length))
-	      << imp->im_bshift;
-	return (ino);
+	/*
+	 * Note there is an inverse calculation in
+	 * cd9660_vfsops.c:cd9660_loadvnode():
+	 *   ip->iso_start = ino >> imp->im_bshift;
+	 * and also a calculation of the isodir pointer
+	 * from an inode in cd9660_vnops.c:cd9660_readlink()
+	 */
+	ino = ((ino_t)isonum_733(isodir->extent) +
+		isonum_711(isodir->ext_attr_length)) << imp->im_bshift;
+	return ino;
 }

Index: src/sys/fs/cd9660/cd9660_node.h
diff -u src/sys/fs/cd9660/cd9660_node.h:1.14 src/sys/fs/cd9660/cd9660_node.h:1.14.64.1
--- src/sys/fs/cd9660/cd9660_node.h:1.14	Wed Feb 27 19:43:36 2008
+++ src/sys/fs/cd9660/cd9660_node.h	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_node.h,v 1.14 2008/02/27 19:43:36 matt Exp $	*/
+/*	$NetBSD: cd9660_node.h,v 1.14.64.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (c) 1994
@@ -63,7 +63,6 @@ typedef	struct	{
 
 struct iso_node {
 	struct	genfs_node i_gnode;
-	LIST_ENTRY(iso_node) i_hash;
 	struct	vnode *i_vnode;	/* vnode associated with this inode */
 	struct	vnode *i_devvp;	/* vnode for block I/O */
 	u_long	i_flag;		/* see below */
@@ -128,15 +127,8 @@ void	cd9660_defattr(struct iso_directory
 			struct iso_node *, struct buf *);
 void	cd9660_deftstamp(struct iso_directory_record *,
 			struct iso_node *, struct buf *);
-struct	vnode *cd9660_ihashget(dev_t, ino_t, int);
-void	cd9660_ihashins(struct iso_node *);
-void	cd9660_ihashrem(struct iso_node *);
 int	cd9660_tstamp_conv7(const u_char *, struct timespec *);
 int	cd9660_tstamp_conv17(const u_char *, struct timespec *);
-int	cd9660_vget_internal(struct mount *, ino_t, struct vnode **, int,
-			      struct iso_directory_record *);
-
-extern kmutex_t cd9660_hashlock;
 
 #endif /* _KERNEL */
 #endif /* _ISOFS_CD9660_CD9660_NODE_H_ */

Index: src/sys/fs/cd9660/cd9660_util.c
diff -u src/sys/fs/cd9660/cd9660_util.c:1.10 src/sys/fs/cd9660/cd9660_util.c:1.10.26.1
--- src/sys/fs/cd9660/cd9660_util.c:1.10	Tue Sep 27 01:01:43 2011
+++ src/sys/fs/cd9660/cd9660_util.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_util.c,v 1.10 2011/09/27 01:01:43 christos Exp $	*/
+/*	$NetBSD: cd9660_util.c,v 1.10.26.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (c) 1994
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cd9660_util.c,v 1.10 2011/09/27 01:01:43 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cd9660_util.c,v 1.10.26.1 2014/08/10 06:55:53 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -117,7 +117,6 @@ isofncmp(const u_char *fn, size_t fnlen,
 			case ';':
 				break;
 			}
-			fn++;
 			for (i = 0; fnlen-- != 0; i = i * 10 + *fn++ - '0') {
 				if (*fn < '0' || *fn > '9') {
 					return -1;

Index: src/sys/fs/cd9660/cd9660_vfsops.c
diff -u src/sys/fs/cd9660/cd9660_vfsops.c:1.83 src/sys/fs/cd9660/cd9660_vfsops.c:1.83.2.1
--- src/sys/fs/cd9660/cd9660_vfsops.c:1.83	Mon Mar 24 04:03:25 2014
+++ src/sys/fs/cd9660/cd9660_vfsops.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_vfsops.c,v 1.83 2014/03/24 04:03:25 dholland Exp $	*/
+/*	$NetBSD: cd9660_vfsops.c,v 1.83.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (c) 1994
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cd9660_vfsops.c,v 1.83 2014/03/24 04:03:25 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cd9660_vfsops.c,v 1.83.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -102,6 +102,7 @@ struct vfsops cd9660_vfsops = {
 	.vfs_statvfs = cd9660_statvfs,
 	.vfs_sync = cd9660_sync,
 	.vfs_vget = cd9660_vget,
+	.vfs_loadvnode = cd9660_loadvnode,
 	.vfs_fhtovp = cd9660_fhtovp,
 	.vfs_vptofh = cd9660_vptofh,
 	.vfs_init = cd9660_init,
@@ -126,8 +127,6 @@ static const struct genfs_ops cd9660_gen
  *
  * Name is updated by mount(8) after booting.
  */
-#define ROOTNAME	"root_device"
-
 static int iso_makemp(struct iso_mnt *isomp, struct buf *bp, int *ea_len);
 static int iso_mountfs(struct vnode *devvp, struct mount *mp,
 		struct lwp *l, struct iso_args *argp);
@@ -216,6 +215,8 @@ cd9660_mount(struct mount *mp, const cha
 	int error;
 	struct iso_mnt *imp = VFSTOISOFS(mp);
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 
@@ -584,12 +585,7 @@ cd9660_root(struct mount *mp, struct vno
 	    (struct iso_directory_record *)imp->root;
 	ino_t ino = isodirino(dp, imp);
 
-	/*
-	 * With RRIP we must use the `.' entry of the root directory.
-	 * Simply tell vget, that it's a relocated directory.
-	 */
-	return (cd9660_vget_internal(mp, ino, vpp,
-				     imp->iso_ftype == ISO_FTYPE_RRIP, dp));
+	return cd9660_vget(mp, ino, vpp);
 }
 
 /*
@@ -639,8 +635,10 @@ cd9660_sync(struct mount *mp, int waitfo
 struct ifid {
 	ushort	ifid_len;
 	ushort	ifid_pad;
-	int	ifid_ino;
-	long	ifid_start;
+	ino_t	ifid_ino;
+#ifdef	ISOFS_DBG
+	u_long	ifid_start;
+#endif
 };
 
 /* ARGSUSED */
@@ -657,7 +655,7 @@ cd9660_fhtovp(struct mount *mp, struct f
 
 	memcpy(&ifh, fhp, sizeof(ifh));
 #ifdef	ISOFS_DBG
-	printf("fhtovp: ino %d, start %ld\n",
+	printf("fhtovp: ino %"PRIu64", start %lu\n",
 	    ifh.ifid_ino, ifh.ifid_start);
 #endif
 
@@ -678,161 +676,110 @@ cd9660_fhtovp(struct mount *mp, struct f
 int
 cd9660_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
 {
+	int error;
 
-	/*
-	 * XXXX
-	 * It would be nice if we didn't always set the `relocated' flag
-	 * and force the extra read, but I don't want to think about fixing
-	 * that right now.
-	 */
-	return (cd9660_vget_internal(mp, ino, vpp,
-#if 0
-				     VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP,
-#else
-				     0,
-#endif
-				     NULL));
+	error = vcache_get(mp, &ino, sizeof(ino), vpp);
+	if (error)
+		return error;
+	error = vn_lock(*vpp, LK_EXCLUSIVE);
+	if (error) {
+		vrele(*vpp);
+		*vpp = NULL;
+		return error;
+	}
+	return 0;
 }
 
 int
-cd9660_vget_internal(struct mount *mp, ino_t ino, struct vnode **vpp,
-	int relocated, struct iso_directory_record *isodir)
+cd9660_loadvnode(struct mount *mp, struct vnode *vp,
+    const void *key, size_t key_len, const void **new_key)
 {
 	struct iso_mnt *imp;
 	struct iso_node *ip;
+	struct iso_directory_record *isodir;
 	struct buf *bp;
-	struct vnode *vp;
 	dev_t dev;
+	ino_t ino;
+	int lbn, off;
 	int error;
 
+	KASSERT(key_len == sizeof(ino));
+	memcpy(&ino, key, key_len);
 	imp = VFSTOISOFS(mp);
 	dev = imp->im_dev;
 
- retry:
-	if ((*vpp = cd9660_ihashget(dev, ino, LK_EXCLUSIVE)) != NULLVP)
-		return (0);
-
-	/* Allocate a new vnode/iso_node. */
-	error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, NULL, &vp);
-	if (error) {
-		*vpp = NULLVP;
-		return (error);
-	}
 	ip = pool_get(&cd9660_node_pool, PR_WAITOK);
 
-	/*
-	 * If someone beat us to it, put back the freshly allocated
-	 * vnode/inode pair and retry.
-	 */
-	mutex_enter(&cd9660_hashlock);
-	if (cd9660_ihashget(dev, ino, 0) != NULL) {
-		mutex_exit(&cd9660_hashlock);
-		ungetnewvnode(vp);
-		pool_put(&cd9660_node_pool, ip);
-		goto retry;
-	}
-
 	memset(ip, 0, sizeof(struct iso_node));
-	vp->v_data = ip;
 	ip->i_vnode = vp;
 	ip->i_dev = dev;
 	ip->i_number = ino;
 	ip->i_mnt = imp;
 	ip->i_devvp = imp->im_devvp;
-	genfs_node_init(vp, &cd9660_genfsops);
 
-	/*
-	 * Put it onto its hash chain and lock it so that other requests for
-	 * this inode will block if they arrive while we are sleeping waiting
-	 * for old data structures to be purged or for the contents of the
-	 * disk portion of this inode to be read.
-	 */
-	cd9660_ihashins(ip);
-	mutex_exit(&cd9660_hashlock);
-
-	if (isodir == 0) {
-		int lbn, off;
-
-		lbn = cd9660_lblkno(imp, ino);
-		if (lbn >= imp->volume_space_size) {
-			vput(vp);
-			printf("fhtovp: lbn exceed volume space %d\n", lbn);
-			return (ESTALE);
-		}
+	lbn = cd9660_lblkno(imp, ino);
+	if (lbn >= imp->volume_space_size) {
+		pool_put(&cd9660_node_pool, ip);
+		printf("fhtovp: lbn exceed volume space %d\n", lbn);
+		return (ESTALE);
+	}
 
-		off = cd9660_blkoff(imp, ino);
-		if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
-			vput(vp);
-			printf("fhtovp: crosses block boundary %d\n",
-			    off + ISO_DIRECTORY_RECORD_SIZE);
-			return (ESTALE);
-		}
+	off = cd9660_blkoff(imp, ino);
+	if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
+		pool_put(&cd9660_node_pool, ip);
+		printf("fhtovp: crosses block boundary %d\n",
+		    off + ISO_DIRECTORY_RECORD_SIZE);
+		return (ESTALE);
+	}
 
-		error = bread(imp->im_devvp,
-			      lbn << (imp->im_bshift - DEV_BSHIFT),
-			      imp->logical_block_size, NOCRED, 0, &bp);
-		if (error) {
-			vput(vp);
-			printf("fhtovp: bread error %d\n",error);
-			return (error);
-		}
-		isodir = (struct iso_directory_record *)((char *)bp->b_data + off);
+	error = bread(imp->im_devvp,
+		      lbn << (imp->im_bshift - DEV_BSHIFT),
+		      imp->logical_block_size, NOCRED, 0, &bp);
+	if (error) {
+		pool_put(&cd9660_node_pool, ip);
+		printf("fhtovp: bread error %d\n",error);
+		return (error);
+	}
+	isodir = (struct iso_directory_record *)((char *)bp->b_data + off);
 
-		if (off + isonum_711(isodir->length) >
-		    imp->logical_block_size) {
-			vput(vp);
-			if (bp != 0)
-				brelse(bp, 0);
-			printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
-			    off +isonum_711(isodir->length), off,
-			    isonum_711(isodir->length));
-			return (ESTALE);
-		}
+	if (off + isonum_711(isodir->length) > imp->logical_block_size) {
+		pool_put(&cd9660_node_pool, ip);
+		brelse(bp, 0);
+		printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
+		    off +isonum_711(isodir->length), off,
+		    isonum_711(isodir->length));
+		return (ESTALE);
+	}
 
 #if 0
-		if (isonum_733(isodir->extent) +
-		    isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
-			if (bp != 0)
-				brelse(bp, 0);
-			printf("fhtovp: file start miss %d vs %d\n",
-			    isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length),
-			    ifhp->ifid_start);
-			return (ESTALE);
-		}
-#endif
-	} else
-		bp = 0;
-
-	vref(ip->i_devvp);
-
-	if (relocated) {
-		/*
-		 * On relocated directories we must
-		 * read the `.' entry out of a dir.
-		 */
-		ip->iso_start = ino >> imp->im_bshift;
+	if (isonum_733(isodir->extent) +
+	    isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
+		pool_put(&cd9660_node_pool, ip);
 		if (bp != 0)
 			brelse(bp, 0);
-		if ((error = cd9660_blkatoff(vp, (off_t)0, NULL, &bp)) != 0) {
-			vput(vp);
-			return (error);
-		}
-		isodir = (struct iso_directory_record *)bp->b_data;
+		printf("fhtovp: file start miss %d vs %d\n",
+		    isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length),
+		    ifhp->ifid_start);
+		return (ESTALE);
 	}
+#endif
 
 	ip->iso_extent = isonum_733(isodir->extent);
 	ip->i_size = isonum_733(isodir->size);
 	ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
 
+	vp->v_tag = VT_ISOFS;
+	vp->v_op = cd9660_vnodeop_p;
+	vp->v_data = ip;
+	genfs_node_init(vp, &cd9660_genfsops);
+
 	/*
 	 * Setup time stamp, attribute
 	 */
-	vp->v_type = VNON;
 	switch (imp->iso_ftype) {
 	default:	/* ISO_FTYPE_9660 */
 	    {
 		struct buf *bp2;
-		int off;
 		if ((imp->im_flags & ISOFSMNT_EXTATT)
 		    && (off = isonum_711(isodir->ext_attr_length)))
 			cd9660_blkatoff(vp, (off_t)-(off << imp->im_bshift),
@@ -850,8 +797,7 @@ cd9660_vget_internal(struct mount *mp, i
 		break;
 	}
 
-	if (bp != 0)
-		brelse(bp, 0);
+	brelse(bp, 0);
 
 	/*
 	 * Initialize the associated vnode
@@ -889,8 +835,8 @@ cd9660_vget_internal(struct mount *mp, i
 	 * XXX need generation number?
 	 */
 
-	*vpp = vp;
-	return (0);
+	*new_key = &ip->i_number;
+	return 0;
 }
 
 /*
@@ -912,11 +858,13 @@ cd9660_vptofh(struct vnode *vp, struct f
 	memset(&ifh, 0, sizeof(ifh));
 	ifh.ifid_len = sizeof(struct ifid);
 	ifh.ifid_ino = ip->i_number;
+#ifdef	ISOFS_DBG
 	ifh.ifid_start = ip->iso_start;
+#endif
 	memcpy(fhp, &ifh, sizeof(ifh));
 
 #ifdef	ISOFS_DBG
-	printf("vptofh: ino %d, start %ld\n",
+	printf("vptofh: ino %"PRIu64", start %lu\n",
 	    ifh.ifid_ino,ifh.ifid_start);
 #endif
 	return 0;

Index: src/sys/fs/cd9660/cd9660_vnops.c
diff -u src/sys/fs/cd9660/cd9660_vnops.c:1.47 src/sys/fs/cd9660/cd9660_vnops.c:1.47.2.1
--- src/sys/fs/cd9660/cd9660_vnops.c:1.47	Thu Jan 23 10:13:56 2014
+++ src/sys/fs/cd9660/cd9660_vnops.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_vnops.c,v 1.47 2014/01/23 10:13:56 hannken Exp $	*/
+/*	$NetBSD: cd9660_vnops.c,v 1.47.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (c) 1994
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cd9660_vnops.c,v 1.47 2014/01/23 10:13:56 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cd9660_vnops.c,v 1.47.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -723,7 +723,7 @@ cd9660_strategy(void *v)
 		biodone(bp);
 		return (0);
 	}
-	vp = ip->i_devvp;
+	vp = ip->i_mnt->im_devvp;
 	return (VOP_STRATEGY(vp, bp));
 }
 
@@ -859,6 +859,8 @@ const struct vnodeopv_entry_desc cd9660_
 	{ &vop_setattr_desc, cd9660_setattr },		/* setattr */
 	{ &vop_read_desc, cd9660_read },		/* read */
 	{ &vop_write_desc, cd9660_write },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_fcntl_desc, genfs_fcntl },		/* fcntl */
 	{ &vop_ioctl_desc, cd9660_ioctl },		/* ioctl */
 	{ &vop_poll_desc, cd9660_poll },		/* poll */
@@ -909,6 +911,8 @@ const struct vnodeopv_entry_desc cd9660_
 	{ &vop_setattr_desc, cd9660_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, genfs_fcntl },		/* fcntl */
 	{ &vop_ioctl_desc, spec_ioctl },		/* ioctl */
 	{ &vop_poll_desc, spec_poll },			/* poll */
@@ -957,6 +961,8 @@ const struct vnodeopv_entry_desc cd9660_
 	{ &vop_setattr_desc, cd9660_setattr },		/* setattr */
 	{ &vop_read_desc, vn_fifo_bypass },		/* read */
 	{ &vop_write_desc, vn_fifo_bypass },		/* write */
+	{ &vop_fallocate_desc, vn_fifo_bypass },	/* fallocate */
+	{ &vop_fdiscard_desc, vn_fifo_bypass },		/* fdiscard */
 	{ &vop_fcntl_desc, genfs_fcntl },		/* fcntl */
 	{ &vop_ioctl_desc, vn_fifo_bypass },		/* ioctl */
 	{ &vop_poll_desc, vn_fifo_bypass },		/* poll */

Index: src/sys/fs/efs/efs_vfsops.c
diff -u src/sys/fs/efs/efs_vfsops.c:1.24 src/sys/fs/efs/efs_vfsops.c:1.24.10.1
--- src/sys/fs/efs/efs_vfsops.c:1.24	Thu Dec 20 08:03:42 2012
+++ src/sys/fs/efs/efs_vfsops.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: efs_vfsops.c,v 1.24 2012/12/20 08:03:42 hannken Exp $	*/
+/*	$NetBSD: efs_vfsops.c,v 1.24.10.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*
  * Copyright (c) 2006 Stephen M. Rumble <rum...@ephemeral.org>
@@ -17,7 +17,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: efs_vfsops.c,v 1.24 2012/12/20 08:03:42 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: efs_vfsops.c,v 1.24.10.1 2014/08/10 06:55:53 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -47,7 +47,6 @@ __KERNEL_RCSID(0, "$NetBSD: efs_vfsops.c
 #include <fs/efs/efs_dinode.h>
 #include <fs/efs/efs_inode.h>
 #include <fs/efs/efs_subr.h>
-#include <fs/efs/efs_ihash.h>
 
 MODULE(MODULE_CLASS_VFS, efs, NULL);
 
@@ -180,6 +179,8 @@ efs_mount(struct mount *mp, const char *
 	struct vnode *devvp;
 	int err, mode;
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 
@@ -339,74 +340,53 @@ efs_statvfs(struct mount *mp, struct sta
 /*
  * Obtain a locked vnode for the given on-disk inode number.
  *
- * We currently allocate a new vnode from getnewnode(), tack it with
- * our in-core inode structure (efs_inode), and read in the inode from
- * disk. The returned inode must be locked.
- *
  * Returns 0 on success.
  */
 static int
 efs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
 {
-	int err;
-	struct vnode *vp;
+	int error;
+
+	error = vcache_get(mp, &ino, sizeof(ino), vpp);
+	if (error)
+		return error;
+	error = vn_lock(*vpp, LK_EXCLUSIVE);
+	if (error) {
+		vrele(*vpp);
+		*vpp = NULL;
+		return error;
+	}
+	return 0;
+}
+
+/*
+ * Initialize this vnode / inode pair.
+ * Caller assures no other thread will try to load this inode.
+ */
+static int
+efs_loadvnode(struct mount *mp, struct vnode *vp,
+    const void *key, size_t key_len, const void **new_key)
+{
+	int error;
+	ino_t ino;
 	struct efs_inode *eip;
 	struct efs_mount *emp;
 
+	KASSERT(key_len == sizeof(ino));
+	memcpy(&ino, key, key_len);
 	emp = VFSTOEFS(mp);
 
-	while (true) {
-		*vpp = efs_ihashget(emp->em_dev, ino, LK_EXCLUSIVE);
-		if (*vpp != NULL)
-			return (0);
-
-		err = getnewvnode(VT_EFS, mp, efs_vnodeop_p, NULL, &vp);
-		if (err)
-			return (err);
-		
-		eip = pool_get(&efs_inode_pool, PR_WAITOK);
-
-		/*
-		 * See if anybody has raced us here.  If not, continue
-		 * setting up the new inode, otherwise start over.
-		 */
-		efs_ihashlock();
-
-		if (efs_ihashget(emp->em_dev, ino, 0) == NULL)
-			break;
-
-		efs_ihashunlock();
-		ungetnewvnode(vp);
-		pool_put(&efs_inode_pool, eip);
-	}
-
-	vp->v_vflag |= VV_LOCKSWORK;
+	eip = pool_get(&efs_inode_pool, PR_WAITOK);
 	eip->ei_mode = 0;
 	eip->ei_lockf = NULL;
 	eip->ei_number = ino;
 	eip->ei_dev = emp->em_dev;
 	eip->ei_vp = vp;
-	vp->v_data = eip;
-
-	/*
-	 * Place the vnode on the hash chain. Doing so will lock the
-	 * vnode, so it's okay to drop the global lock and read in
-	 * the inode from disk.
-	 */
-	efs_ihashins(eip);
-	efs_ihashunlock();
-
-	/*
-	 * Init genfs early, otherwise we'll trip up on genfs_node_destroy
-	 * in efs_reclaim when vput()ing in an error branch here.
-	 */
-	genfs_node_init(vp, &efs_genfsops);
 
-	err = efs_read_inode(emp, ino, NULL, &eip->ei_di);
-	if (err) {
-		vput(vp);
-		*vpp = NULL;
-		return (err);
+	error = efs_read_inode(emp, ino, NULL, &eip->ei_di);
+	if (error) {
+		pool_put(&efs_inode_pool, eip);
+		return error;
 	}
 
 	efs_sync_dinode_to_inode(eip);
@@ -414,9 +394,8 @@ efs_vget(struct mount *mp, ino_t ino, st
 	if (ino == EFS_ROOTINO && !S_ISDIR(eip->ei_mode)) {
 		printf("efs: root inode (%lu) is not a directory!\n",
 		    (ulong)EFS_ROOTINO);
-		vput(vp);
-		*vpp = NULL;
-		return (EIO);
+		pool_put(&efs_inode_pool, eip);
+		return EIO;
 	}
 
 	switch (eip->ei_mode & S_IFMT) {
@@ -431,6 +410,7 @@ efs_vget(struct mount *mp, ino_t ino, st
 		break;
 	case S_IFDIR:
 		vp->v_type = VDIR;
+		vp->v_op = efs_vnodeop_p;
 		if (ino == EFS_ROOTINO)
 			vp->v_vflag |= VV_ROOT;
 		break;
@@ -441,27 +421,30 @@ efs_vget(struct mount *mp, ino_t ino, st
 		break;
 	case S_IFREG:
 		vp->v_type = VREG;
+		vp->v_op = efs_vnodeop_p;
 		break;
 	case S_IFLNK:
 		vp->v_type = VLNK;
+		vp->v_op = efs_vnodeop_p;
 		break;
 	case S_IFSOCK:
 		vp->v_type = VSOCK;
+		vp->v_op = efs_vnodeop_p;
 		break;
 	default:
 		printf("efs: invalid mode 0x%x in inode %lu on mount %s\n",
 		    eip->ei_mode, (ulong)ino, mp->mnt_stat.f_mntonname);
-		vput(vp);
-		*vpp = NULL;
-		return (EIO);
+		pool_put(&efs_inode_pool, eip);
+		return EIO;
 	}
 
+	vp->v_tag = VT_EFS;
+	vp->v_vflag |= VV_LOCKSWORK;
+	vp->v_data = eip;
+	genfs_node_init(vp, &efs_genfsops);
 	uvm_vnp_setsize(vp, eip->ei_size);
-	*vpp = vp;
-
-	KASSERT(VOP_ISLOCKED(vp));
-
-	return (0);
+	*new_key = &eip->ei_number;
+	return 0;
 }
 
 /*
@@ -535,7 +518,6 @@ efs_init(void)
 	malloc_type_attach(M_EFSMNT);
 	malloc_type_attach(M_EFSINO);
 	malloc_type_attach(M_EFSTMP);
-	efs_ihashinit();
 	pool_init(&efs_inode_pool, sizeof(struct efs_inode), 0, 0, 0,
 	    "efsinopl", &pool_allocator_nointr, IPL_NONE);
 }
@@ -547,7 +529,6 @@ static void 
 efs_reinit(void)
 {
 	
-	efs_ihashreinit();
 }
 
 /*
@@ -558,7 +539,6 @@ efs_done(void)
 {
 	
 	pool_destroy(&efs_inode_pool);
-	efs_ihashdone();
 	malloc_type_detach(M_EFSMNT);
 	malloc_type_detach(M_EFSINO);
 	malloc_type_detach(M_EFSTMP);
@@ -586,6 +566,7 @@ struct vfsops efs_vfsops = {
 	.vfs_statvfs	= efs_statvfs,
 	.vfs_sync	= (void *)nullop,
 	.vfs_vget	= efs_vget,
+	.vfs_loadvnode	= efs_loadvnode,
 	.vfs_fhtovp	= efs_fhtovp,
 	.vfs_vptofh	= efs_vptofh,
 	.vfs_init	= efs_init,

Index: src/sys/fs/efs/efs_vnops.c
diff -u src/sys/fs/efs/efs_vnops.c:1.31 src/sys/fs/efs/efs_vnops.c:1.31.2.1
--- src/sys/fs/efs/efs_vnops.c:1.31	Fri Feb  7 15:29:21 2014
+++ src/sys/fs/efs/efs_vnops.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: efs_vnops.c,v 1.31 2014/02/07 15:29:21 hannken Exp $	*/
+/*	$NetBSD: efs_vnops.c,v 1.31.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*
  * Copyright (c) 2006 Stephen M. Rumble <rum...@ephemeral.org>
@@ -17,7 +17,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: efs_vnops.c,v 1.31 2014/02/07 15:29:21 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: efs_vnops.c,v 1.31.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -46,7 +46,6 @@ __KERNEL_RCSID(0, "$NetBSD: efs_vnops.c,
 #include <fs/efs/efs_dinode.h>
 #include <fs/efs/efs_inode.h>
 #include <fs/efs/efs_subr.h>
-#include <fs/efs/efs_ihash.h>
 
 MALLOC_DECLARE(M_EFSTMP);
 
@@ -79,30 +78,17 @@ efs_lookup(void *v)
 	}
 
 	/*
-	 * Handle the three lookup types: '.', '..', and everything else.
+	 * Handle the lookup types: '.' or everything else.
 	 */
 	if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
 		vref(ap->a_dvp);
 		*ap->a_vpp = ap->a_dvp;
-	} else if (cnp->cn_flags & ISDOTDOT) {
-		err = efs_inode_lookup(VFSTOEFS(ap->a_dvp->v_mount),
-		    EFS_VTOI(ap->a_dvp), ap->a_cnp, &ino);
-		if (err)
-			return (err);
-
-		VOP_UNLOCK(ap->a_dvp);	/* preserve lock order */
-
-		err = VFS_VGET(ap->a_dvp->v_mount, ino, &vp);
-		if (err) {
-			vn_lock(ap->a_dvp, LK_EXCLUSIVE | LK_RETRY);
-			return (err);
-		}
-		vn_lock(ap->a_dvp, LK_EXCLUSIVE | LK_RETRY);
-		*ap->a_vpp = vp;
 	} else {
 		err = efs_inode_lookup(VFSTOEFS(ap->a_dvp->v_mount),
 		    EFS_VTOI(ap->a_dvp), ap->a_cnp, &ino);
 		if (err) {
+			if (cnp->cn_flags & ISDOTDOT)
+				return (err);
 			if (err == ENOENT && nameiop != CREATE)
 				cache_enter(ap->a_dvp, NULL, cnp->cn_nameptr,
 					    cnp->cn_namelen, cnp->cn_flags);
@@ -116,7 +102,7 @@ efs_lookup(void *v)
 			}
 			return (err);
 		}
-		err = VFS_VGET(ap->a_dvp->v_mount, ino, &vp);
+		err = vcache_get(ap->a_dvp->v_mount, &ino, sizeof(ino), &vp);
 		if (err)
 			return (err);
 		*ap->a_vpp = vp;
@@ -125,9 +111,6 @@ efs_lookup(void *v)
 	cache_enter(ap->a_dvp, *ap->a_vpp, cnp->cn_nameptr, cnp->cn_namelen,
 		    cnp->cn_flags);
 
-	if (*ap->a_vpp != ap->a_dvp)
-		VOP_UNLOCK(*ap->a_vpp);
-
 	return 0;
 }
 
@@ -598,10 +581,11 @@ efs_reclaim(void *v)
 		struct vnode *a_vp;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
+	struct efs_inode *eip = EFS_VTOI(vp);
 
-	efs_ihashrem(EFS_VTOI(vp));
+	vcache_remove(vp->v_mount, &eip->ei_number, sizeof(eip->ei_number));
 	genfs_node_destroy(vp);
-	pool_put(&efs_inode_pool, vp->v_data);
+	pool_put(&efs_inode_pool, eip);
 	vp->v_data = NULL;
 
 	return (0);
@@ -809,6 +793,8 @@ const struct vnodeopv_entry_desc efs_vno
 	{ &vop_setattr_desc,	genfs_eopnotsupp},	/* setattr */
 	{ &vop_read_desc,	efs_read	},	/* read */
 	{ &vop_write_desc,	genfs_eopnotsupp},	/* write */
+	{ &vop_fallocate_desc,	genfs_eopnotsupp},	/* fallocate */
+	{ &vop_fdiscard_desc,	genfs_eopnotsupp},	/* fdiscard */
 	{ &vop_ioctl_desc,	genfs_enoioctl	},	/* ioctl */
 	{ &vop_fcntl_desc,	genfs_fcntl	},	/* fcntl */
 	{ &vop_poll_desc,	genfs_poll	},	/* poll */
@@ -865,6 +851,8 @@ const struct vnodeopv_entry_desc efs_spe
 	{ &vop_setattr_desc,	genfs_eopnotsupp},	/* 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_ioctl_desc,	spec_ioctl	},	/* ioctl */
 	{ &vop_fcntl_desc,	genfs_fcntl	},	/* fcntl */
 	{ &vop_poll_desc,	spec_poll	},	/* poll */
@@ -921,6 +909,8 @@ const struct vnodeopv_entry_desc efs_fif
 	{ &vop_setattr_desc,	genfs_eopnotsupp},	/* setattr */
 	{ &vop_read_desc,	vn_fifo_bypass	},	/* read */
 	{ &vop_write_desc,	vn_fifo_bypass	},	/* write */
+	{ &vop_fallocate_desc,	vn_fifo_bypass	},	/* fallocate */
+	{ &vop_fdiscard_desc,	vn_fifo_bypass	},	/* fdiscard */
 	{ &vop_ioctl_desc,	vn_fifo_bypass	},	/* ioctl */
 	{ &vop_fcntl_desc,	genfs_fcntl	},	/* fcntl */
 	{ &vop_poll_desc,	vn_fifo_bypass	},	/* poll */

Index: src/sys/fs/efs/files.efs
diff -u src/sys/fs/efs/files.efs:1.1 src/sys/fs/efs/files.efs:1.1.98.1
--- src/sys/fs/efs/files.efs:1.1	Fri Jun 29 23:30:30 2007
+++ src/sys/fs/efs/files.efs	Sun Aug 10 06:55:53 2014
@@ -1,9 +1,8 @@
-#	$NetBSD: files.efs,v 1.1 2007/06/29 23:30:30 rumble Exp $
+#	$NetBSD: files.efs,v 1.1.98.1 2014/08/10 06:55:53 tls Exp $
 
 deffs	EFS
 
 file	fs/efs/efs_genfs.c		efs
-file	fs/efs/efs_ihash.c		efs
 file	fs/efs/efs_subr.c		efs
 file	fs/efs/efs_vnops.c		efs
 file	fs/efs/efs_vfsops.c		efs

Index: src/sys/fs/filecorefs/filecore_lookup.c
diff -u src/sys/fs/filecorefs/filecore_lookup.c:1.19 src/sys/fs/filecorefs/filecore_lookup.c:1.19.2.1
--- src/sys/fs/filecorefs/filecore_lookup.c:1.19	Fri Feb  7 15:29:21 2014
+++ src/sys/fs/filecorefs/filecore_lookup.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: filecore_lookup.c,v 1.19 2014/02/07 15:29:21 hannken Exp $	*/
+/*	$NetBSD: filecore_lookup.c,v 1.19.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (c) 1989, 1993, 1994 The Regents of the University of California.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: filecore_lookup.c,v 1.19 2014/02/07 15:29:21 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: filecore_lookup.c,v 1.19.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/namei.h>
@@ -80,8 +80,6 @@ __KERNEL_RCSID(0, "$NetBSD: filecore_loo
 #include <fs/filecorefs/filecore_extern.h>
 #include <fs/filecorefs/filecore_node.h>
 
-struct	nchstats filecore_nchstats;
-
 /*
  * Convert a component of a pathname into a pointer to a locked inode.
  * This is a very central and rather complicated routine.
@@ -193,7 +191,7 @@ filecore_lookup(void *v)
 	} else {
 		i = dp->i_diroff;
 		numdirpasses = 2;
-		filecore_nchstats.ncs_2passes++;
+		namecache_count_2passes();
 	}
 	endsearch = FILECORE_MAXDIRENTS;
 
@@ -251,7 +249,7 @@ notfound:
 
 found:
 	if (numdirpasses == 2)
-		filecore_nchstats.ncs_pass2++;
+		namecache_count_pass2();
 
 	/*
 	 * Found component in pathname.

Index: src/sys/fs/filecorefs/filecore_vfsops.c
diff -u src/sys/fs/filecorefs/filecore_vfsops.c:1.75 src/sys/fs/filecorefs/filecore_vfsops.c:1.75.2.1
--- src/sys/fs/filecorefs/filecore_vfsops.c:1.75	Sun Mar 23 15:21:15 2014
+++ src/sys/fs/filecorefs/filecore_vfsops.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: filecore_vfsops.c,v 1.75 2014/03/23 15:21:15 hannken Exp $	*/
+/*	$NetBSD: filecore_vfsops.c,v 1.75.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (c) 1994 The Regents of the University of California.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: filecore_vfsops.c,v 1.75 2014/03/23 15:21:15 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: filecore_vfsops.c,v 1.75.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -229,6 +229,8 @@ filecore_mount(struct mount *mp, const c
 	int error;
 	struct filecore_mnt *fcmp = NULL;
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 

Index: src/sys/fs/filecorefs/filecore_vnops.c
diff -u src/sys/fs/filecorefs/filecore_vnops.c:1.41 src/sys/fs/filecorefs/filecore_vnops.c:1.41.2.1
--- src/sys/fs/filecorefs/filecore_vnops.c:1.41	Thu Jan 23 10:13:56 2014
+++ src/sys/fs/filecorefs/filecore_vnops.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: filecore_vnops.c,v 1.41 2014/01/23 10:13:56 hannken Exp $	*/
+/*	$NetBSD: filecore_vnops.c,v 1.41.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (c) 1994 The Regents of the University of California.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: filecore_vnops.c,v 1.41 2014/01/23 10:13:56 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: filecore_vnops.c,v 1.41.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -565,6 +565,8 @@ const struct vnodeopv_entry_desc filecor
 	{ &vop_setattr_desc, filecore_setattr },	/* setattr */
 	{ &vop_read_desc, filecore_read },		/* read */
 	{ &vop_write_desc, filecore_write },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_fcntl_desc, filecore_fcntl },		/* fcntl */
 	{ &vop_ioctl_desc, filecore_ioctl },		/* ioctl */
 	{ &vop_poll_desc, filecore_poll },		/* poll */

Index: src/sys/fs/hfs/hfs_vfsops.c
diff -u src/sys/fs/hfs/hfs_vfsops.c:1.30 src/sys/fs/hfs/hfs_vfsops.c:1.30.2.1
--- src/sys/fs/hfs/hfs_vfsops.c:1.30	Sun Mar 23 15:21:15 2014
+++ src/sys/fs/hfs/hfs_vfsops.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: hfs_vfsops.c,v 1.30 2014/03/23 15:21:15 hannken Exp $	*/
+/*	$NetBSD: hfs_vfsops.c,v 1.30.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (c) 2005, 2007 The NetBSD Foundation, Inc.
@@ -99,7 +99,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hfs_vfsops.c,v 1.30 2014/03/23 15:21:15 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hfs_vfsops.c,v 1.30.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
@@ -201,6 +201,8 @@ hfs_mount(struct mount *mp, const char *
 	int update;
 	mode_t accessmode;
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 

Index: src/sys/fs/hfs/hfs_vnops.c
diff -u src/sys/fs/hfs/hfs_vnops.c:1.29 src/sys/fs/hfs/hfs_vnops.c:1.29.2.1
--- src/sys/fs/hfs/hfs_vnops.c:1.29	Fri Feb  7 15:29:21 2014
+++ src/sys/fs/hfs/hfs_vnops.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: hfs_vnops.c,v 1.29 2014/02/07 15:29:21 hannken Exp $	*/
+/*	$NetBSD: hfs_vnops.c,v 1.29.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (c) 2005, 2007 The NetBSD Foundation, Inc.
@@ -101,7 +101,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hfs_vnops.c,v 1.29 2014/02/07 15:29:21 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hfs_vnops.c,v 1.29.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ipsec.h"
@@ -165,6 +165,8 @@ const struct vnodeopv_entry_desc hfs_vno
 	{ &vop_setattr_desc, hfs_vop_setattr },		/* setattr */
 	{ &vop_read_desc, hfs_vop_read },		/* read */
 	{ &vop_write_desc, genfs_eopnotsupp },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_ioctl_desc, genfs_eopnotsupp },		/* ioctl */
 	{ &vop_fcntl_desc, genfs_fcntl },		/* fcntl */
 	{ &vop_poll_desc, genfs_eopnotsupp },		/* poll */
@@ -219,6 +221,8 @@ const struct vnodeopv_entry_desc hfs_spe
 	{ &vop_setattr_desc, hfs_vop_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_ioctl_desc, spec_ioctl },		/* ioctl */
 	{ &vop_fcntl_desc, genfs_fcntl },		/* fcntl */
 	{ &vop_poll_desc, spec_poll },			/* poll */
@@ -275,6 +279,8 @@ const struct vnodeopv_entry_desc hfs_fif
 	{ &vop_setattr_desc, hfs_vop_setattr },		/* setattr */
 	{ &vop_read_desc, vn_fifo_bypass },		/* read */
 	{ &vop_write_desc, vn_fifo_bypass },		/* write */
+	{ &vop_fallocate_desc, vn_fifo_bypass },	/* fallocate */
+	{ &vop_fdiscard_desc, vn_fifo_bypass },		/* fdiscard */
 	{ &vop_ioctl_desc, vn_fifo_bypass },		/* ioctl */
 	{ &vop_fcntl_desc, genfs_fcntl },		/* fcntl */
 	{ &vop_poll_desc, vn_fifo_bypass },		/* poll */

Index: src/sys/fs/msdosfs/denode.h
diff -u src/sys/fs/msdosfs/denode.h:1.23 src/sys/fs/msdosfs/denode.h:1.23.10.1
--- src/sys/fs/msdosfs/denode.h:1.23	Sat Jan 26 19:45:02 2013
+++ src/sys/fs/msdosfs/denode.h	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: denode.h,v 1.23 2013/01/26 19:45:02 christos Exp $	*/
+/*	$NetBSD: denode.h,v 1.23.10.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -153,15 +153,21 @@ struct fatcache {
  * This is the in memory variant of a dos directory entry.  It is usually
  * contained within a vnode.
  */
+struct denode_key {
+	u_long dk_dirclust;	/* cluster of the directory file containing this entry */
+	u_long dk_diroffset;	/* offset of this entry in the directory cluster */
+	void *dk_dirgen;	/* non zero and unique for unlinked nodes */
+};
 struct denode {
 	struct genfs_node de_gnode;
-	LIST_ENTRY(denode) de_hash;
 	struct vnode *de_vnode;	/* addr of vnode we are part of */
 	struct vnode *de_devvp;	/* vnode of blk dev we live on */
 	u_long de_flag;		/* flag bits */
 	dev_t de_dev;		/* device where direntry lives */
-	u_long de_dirclust;	/* cluster of the directory file containing this entry */
-	u_long de_diroffset;	/* offset of this entry in the directory cluster */
+	struct denode_key de_key;
+#define de_dirclust de_key.dk_dirclust
+#define de_diroffset de_key.dk_diroffset
+#define de_dirgen de_key.dk_dirgen
 	u_long de_fndoffset;	/* offset of found dir entry */
 	int de_fndcnt;		/* number of slots before de_fndoffset */
 	long de_refcnt;		/* reference count */
@@ -303,7 +309,11 @@ int msdosfs_update(struct vnode *, const
 int createde(struct denode *, struct denode *,
 		struct denode **, struct componentname *);
 int deextend(struct denode *, u_long, struct kauth_cred *);
+#ifdef MAKEFS
 int deget(struct msdosfsmount *, u_long, u_long, struct denode **);
+#else
+int deget(struct msdosfsmount *, u_long, u_long, struct vnode **);
+#endif
 int detrunc(struct denode *, u_long, int, struct kauth_cred *);
 int deupdat(struct denode *, int);
 int doscheckpath(struct denode *, struct denode *);
@@ -311,7 +321,6 @@ int dosdirempty(struct denode *);
 int readde(struct denode *, struct buf **, struct direntry **);
 int readep(struct msdosfsmount *, u_long, u_long,
 		struct buf **, struct direntry **);
-void reinsert(struct denode *);
 int removede(struct denode *, struct denode *);
 int uniqdosname(struct denode *, struct componentname *, u_char *);
 int findwin95(struct denode *);

Index: src/sys/fs/msdosfs/msdosfs_denode.c
diff -u src/sys/fs/msdosfs/msdosfs_denode.c:1.48 src/sys/fs/msdosfs/msdosfs_denode.c:1.48.10.1
--- src/sys/fs/msdosfs/msdosfs_denode.c:1.48	Thu Dec 20 08:03:42 2012
+++ src/sys/fs/msdosfs/msdosfs_denode.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: msdosfs_denode.c,v 1.48 2012/12/20 08:03:42 hannken Exp $	*/
+/*	$NetBSD: msdosfs_denode.c,v 1.48.10.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: msdosfs_denode.c,v 1.48 2012/12/20 08:03:42 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: msdosfs_denode.c,v 1.48.10.1 2014/08/10 06:55:53 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -72,14 +72,6 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_deno
 #include <fs/msdosfs/denode.h>
 #include <fs/msdosfs/fat.h>
 
-LIST_HEAD(ihashhead, denode) *dehashtbl;
-u_long dehash;			/* size of hash table - 1 */
-#define	DEHASH(dev, dcl, doff) \
-    (((dev) + (dcl) + (doff) / sizeof(struct direntry)) & dehash)
-
-kmutex_t msdosfs_ihash_lock;
-kmutex_t msdosfs_hashlock;
-
 struct pool msdosfs_denode_pool;
 
 extern int prtactive;
@@ -138,10 +130,6 @@ static const struct genfs_ops msdosfs_ge
 	.gop_markupdate = msdosfs_gop_markupdate,
 };
 
-static struct denode *msdosfs_hashget(dev_t, u_long, u_long, int);
-static void msdosfs_hashins(struct denode *);
-static void msdosfs_hashrem(struct denode *);
-
 MALLOC_DECLARE(M_MSDOSFSFAT);
 
 void
@@ -155,112 +143,33 @@ msdosfs_init(void)
 	    "msdosnopl", &pool_allocator_nointr, IPL_NONE);
 	pool_init(&fh_pool, sizeof(struct fh_node), 0, 0, 0,
 	    "msdosfhpl", &pool_allocator_nointr, IPL_NONE);
-	dehashtbl = hashinit(desiredvnodes / 2, HASH_LIST, true, &dehash);
 	rb_tree_init(&fh_rbtree, &fh_rbtree_ops);
-	mutex_init(&msdosfs_ihash_lock, MUTEX_DEFAULT, IPL_NONE);
 	mutex_init(&fh_lock, MUTEX_DEFAULT, IPL_NONE);
-	mutex_init(&msdosfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
 }
 
 /*
- * Reinitialize inode hash table.
+ * Reinitialize.
  */
 
 void
 msdosfs_reinit(void)
 {
-	struct denode *dep;
-	struct ihashhead *oldhash, *hash;
-	u_long oldmask, mask, val;
-	int i;
-
-	hash = hashinit(desiredvnodes / 2, HASH_LIST, true, &mask);
-
-	mutex_enter(&msdosfs_ihash_lock);
-	oldhash = dehashtbl;
-	oldmask = dehash;
-	dehashtbl = hash;
-	dehash = mask;
-	for (i = 0; i <= oldmask; i++) {
-		while ((dep = LIST_FIRST(&oldhash[i])) != NULL) {
-			LIST_REMOVE(dep, de_hash);
-			val = DEHASH(dep->de_dev, dep->de_dirclust,
-			    dep->de_diroffset);
-			LIST_INSERT_HEAD(&hash[val], dep, de_hash);
-		}
-	}
-	mutex_exit(&msdosfs_ihash_lock);
-	hashdone(oldhash, HASH_LIST, oldmask);
+
 }
 
 void
 msdosfs_done(void)
 {
-	hashdone(dehashtbl, HASH_LIST, dehash);
 	pool_destroy(&msdosfs_denode_pool);
 	pool_destroy(&fh_pool);
-	mutex_destroy(&msdosfs_ihash_lock);
 	mutex_destroy(&fh_lock);
-	mutex_destroy(&msdosfs_hashlock);
 	malloc_type_detach(M_MSDOSFSTMP);
 	malloc_type_detach(M_MSDOSFSFAT);
 	malloc_type_detach(M_MSDOSFSMNT);
 }
 
-static struct denode *
-msdosfs_hashget(dev_t dev, u_long dirclust, u_long diroff, int flags)
-{
-	struct denode *dep;
-	struct vnode *vp;
-
-loop:
-	mutex_enter(&msdosfs_ihash_lock);
-	LIST_FOREACH(dep, &dehashtbl[DEHASH(dev, dirclust, diroff)], de_hash) {
-		if (dirclust == dep->de_dirclust &&
-		    diroff == dep->de_diroffset &&
-		    dev == dep->de_dev &&
-		    dep->de_refcnt != 0) {
-			vp = DETOV(dep);
-			if (flags == 0) {
-				mutex_exit(&msdosfs_ihash_lock);
-			} else {
-				mutex_enter(vp->v_interlock);
-				mutex_exit(&msdosfs_ihash_lock);
-				if (vget(vp, flags))
-					goto loop;
-			}
-			return (dep);
-		}
-	}
-	mutex_exit(&msdosfs_ihash_lock);
-	return (NULL);
-}
-
-static void
-msdosfs_hashins(struct denode *dep)
-{
-	struct ihashhead *depp;
-	int val;
-
-	KASSERT(mutex_owned(&msdosfs_hashlock));
-
-	mutex_enter(&msdosfs_ihash_lock);
-	val = DEHASH(dep->de_dev, dep->de_dirclust, dep->de_diroffset);
-	depp = &dehashtbl[val];
-	LIST_INSERT_HEAD(depp, dep, de_hash);
-	mutex_exit(&msdosfs_ihash_lock);
-}
-
-static void
-msdosfs_hashrem(struct denode *dep)
-{
-	mutex_enter(&msdosfs_ihash_lock);
-	LIST_REMOVE(dep, de_hash);
-	mutex_exit(&msdosfs_ihash_lock);
-}
-
 /*
- * If deget() succeeds it returns with the gotten denode locked().
+ * If deget() succeeds it returns with the gotten denode unlocked.
  *
  * pmp	     - address of msdosfsmount structure of the filesystem containing
  *	       the denode of interest.  The pm_dev field and the address of
@@ -269,26 +178,18 @@ msdosfs_hashrem(struct denode *dep)
  *	       diroffset is relative to the beginning of the root directory,
  *	       otherwise it is cluster relative.
  * diroffset - offset past begin of cluster of denode we want
- * depp	     - returns the address of the gotten denode.
+ * vpp	     - returns the address of the gotten vnode.
  */
 int
-deget(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset, struct denode **depp)
+deget(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset,
+    struct vnode **vpp)
 	/* pmp:	 so we know the maj/min number */
 	/* dirclust:		 cluster this dir entry came from */
 	/* diroffset:		 index of entry within the cluster */
-	/* depp:		 returns the addr of the gotten denode */
+	/* vpp:			 returns the addr of the gotten vnode */
 {
 	int error;
-	extern int (**msdosfs_vnodeop_p)(void *);
-	struct direntry *direntptr;
-	struct denode *ldep;
-	struct vnode *nvp;
-	struct buf *bp;
-
-#ifdef MSDOSFS_DEBUG
-	printf("deget(pmp %p, dirclust %lu, diroffset %lx, depp %p)\n",
-	    pmp, dirclust, diroffset, depp);
-#endif
+	struct denode_key key;
 
 	/*
 	 * On FAT32 filesystems, root is a (more or less) normal
@@ -297,78 +198,59 @@ deget(struct msdosfsmount *pmp, u_long d
 	if (FAT32(pmp) && dirclust == MSDOSFSROOT)
 		dirclust = pmp->pm_rootdirblk;
 
-	/*
-	 * See if the denode is in the denode cache. Use the location of
-	 * the directory entry to compute the hash value. For subdir use
-	 * address of "." entry. For root dir (if not FAT32) use cluster
-	 * MSDOSFSROOT, offset MSDOSFSROOT_OFS
-	 *
-	 * NOTE: The check for de_refcnt > 0 below insures the denode being
-	 * examined does not represent an unlinked but still open file.
-	 * These files are not to be accessible even when the directory
-	 * entry that represented the file happens to be reused while the
-	 * deleted file is still open.
-	 */
- retry:
-	ldep = msdosfs_hashget(pmp->pm_dev, dirclust, diroffset, LK_EXCLUSIVE);
-	if (ldep) {
-		*depp = ldep;
-		return (0);
-	}
+	memset(&key, 0, sizeof(key));
+	key.dk_dirclust = dirclust;
+	key.dk_diroffset = diroffset;
+	/* key.dk_dirgen = NULL; */
 
-	/*
-	 * Directory entry was not in cache, have to create a vnode and
-	 * copy it from the passed disk buffer.
-	 */
-	error = getnewvnode(VT_MSDOSFS, pmp->pm_mountp, msdosfs_vnodeop_p,
-	    NULL, &nvp);
-	if (error) {
-		*depp = 0;
-		return (error);
-	}
-	ldep = pool_get(&msdosfs_denode_pool, PR_WAITOK);
+	error = vcache_get(pmp->pm_mountp, &key, sizeof(key), vpp);
+	return error;
+}
 
-	/*
-	 * If someone beat us to it, put back the freshly allocated
-	 * vnode/inode pair and retry.
-	 */
-	mutex_enter(&msdosfs_hashlock);
-	if (msdosfs_hashget(pmp->pm_dev, dirclust, diroffset, 0)) {
-		mutex_exit(&msdosfs_hashlock);
-		ungetnewvnode(nvp);
-		pool_put(&msdosfs_denode_pool, ldep);
-		goto retry;
-	}
-	memset(ldep, 0, sizeof *ldep);
-	nvp->v_data = ldep;
-	ldep->de_vnode = nvp;
-	ldep->de_flag = 0;
-	ldep->de_devvp = 0;
-	ldep->de_lockf = 0;
-	ldep->de_dev = pmp->pm_dev;
-	ldep->de_dirclust = dirclust;
-	ldep->de_diroffset = diroffset;
-	fc_purge(ldep, 0);	/* init the FAT cache for this denode */
+int
+msdosfs_loadvnode(struct mount *mp, struct vnode *vp,
+    const void *key, size_t key_len, const void **new_key)
+{
+	bool is_root;
+	int error;
+	extern int (**msdosfs_vnodeop_p)(void *);
+	struct msdosfsmount *pmp;
+	struct direntry *direntptr;
+	struct denode *ldep;
+	struct buf *bp;
+	struct denode_key dkey;
 
-	/*
-	 * Insert the denode into the hash queue and lock the denode so it
-	 * can't be accessed until we've read it in and have done what we
-	 * need to it.
-	 */
-	vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY);
-	genfs_node_init(nvp, &msdosfs_genfsops);
-	msdosfs_hashins(ldep);
-	mutex_exit(&msdosfs_hashlock);
+	KASSERT(key_len == sizeof(dkey));
+	memcpy(&dkey, key, key_len);
+	KASSERT(dkey.dk_dirgen == NULL);
+
+	pmp = VFSTOMSDOSFS(mp);
+	is_root = ((dkey.dk_dirclust == MSDOSFSROOT ||
+	    (FAT32(pmp) && dkey.dk_dirclust == pmp->pm_rootdirblk)) &&
+	    dkey.dk_diroffset == MSDOSFSROOT_OFS);
 
+#ifdef MSDOSFS_DEBUG
+	printf("loadvnode(pmp %p, dirclust %lu, diroffset %lx, vp %p)\n",
+	    pmp, dkey.dk_dirclust, dkey.dk_diroffset, vp);
+#endif
+
+	ldep = pool_get(&msdosfs_denode_pool, PR_WAITOK);
+	memset(ldep, 0, sizeof *ldep);
+	/* ldep->de_flag = 0; */
+	/* ldep->de_devvp = 0; */
+	/* ldep->de_lockf = 0; */
+	ldep->de_dev = pmp->pm_dev;
+	ldep->de_dirclust = dkey.dk_dirclust;
+	ldep->de_diroffset = dkey.dk_diroffset;
 	ldep->de_pmp = pmp;
 	ldep->de_devvp = pmp->pm_devvp;
 	ldep->de_refcnt = 1;
+	fc_purge(ldep, 0);	/* init the FAT cache for this denode */
+
 	/*
 	 * Copy the directory entry into the denode area of the vnode.
 	 */
-	if ((dirclust == MSDOSFSROOT
-	     || (FAT32(pmp) && dirclust == pmp->pm_rootdirblk))
-	    && diroffset == MSDOSFSROOT_OFS) {
+	if (is_root) {
 		/*
 		 * Directory entry for the root directory. There isn't one,
 		 * so we manufacture one. We should probably rummage
@@ -376,15 +258,14 @@ deget(struct msdosfsmount *pmp, u_long d
 		 * exists), and then use the time and date from that entry
 		 * as the time and date for the root denode.
 		 */
-		nvp->v_vflag |= VV_ROOT; /* should be further down XXX */
-
 		ldep->de_Attributes = ATTR_DIRECTORY;
 		if (FAT32(pmp))
 			ldep->de_StartCluster = pmp->pm_rootdirblk;
 			/* de_FileSize will be filled in further down */
 		else {
 			ldep->de_StartCluster = MSDOSFSROOT;
-			ldep->de_FileSize = pmp->pm_rootdirsize * pmp->pm_BytesPerSec;
+			ldep->de_FileSize = pmp->pm_rootdirsize *
+			    pmp->pm_BytesPerSec;
 		}
 		/*
 		 * fill in time and date so that dos2unixtime() doesn't
@@ -401,12 +282,11 @@ deget(struct msdosfsmount *pmp, u_long d
 		ldep->de_MDate = ldep->de_CDate;
 		/* leave the other fields as garbage */
 	} else {
-		error = readep(pmp, dirclust, diroffset, &bp, &direntptr);
+		error = readep(pmp, ldep->de_dirclust, ldep->de_diroffset,
+		    &bp, &direntptr);
 		if (error) {
-			ldep->de_devvp = NULL;
-			ldep->de_Name[0] = SLOT_DELETED;
-			vput(nvp);
-			return (error);
+			pool_put(&msdosfs_denode_pool, ldep);
+			return error;
 		}
 		DE_INTERNALIZE(ldep, direntptr);
 		brelse(bp, 0);
@@ -414,7 +294,7 @@ deget(struct msdosfsmount *pmp, u_long d
 
 	/*
 	 * Fill in a few fields of the vnode and finish filling in the
-	 * denode.  Then return the address of the found denode.
+	 * denode.
 	 */
 	if (ldep->de_Attributes & ATTR_DIRECTORY) {
 		/*
@@ -425,21 +305,30 @@ deget(struct msdosfsmount *pmp, u_long d
 		 */
 		u_long size;
 
-		nvp->v_type = VDIR;
+		vp->v_type = VDIR;
 		if (ldep->de_StartCluster != MSDOSFSROOT) {
 			error = pcbmap(ldep, CLUST_END, 0, &size, 0);
 			if (error == E2BIG) {
 				ldep->de_FileSize = de_cn2off(pmp, size);
 				error = 0;
 			} else
-				printf("deget(): pcbmap returned %d\n", error);
+				printf("loadvnode(): pcbmap returned %d\n",
+				    error);
 		}
 	} else
-		nvp->v_type = VREG;
+		vp->v_type = VREG;
 	vref(ldep->de_devvp);
-	*depp = ldep;
-	uvm_vnp_setsize(nvp, ldep->de_FileSize);
-	return (0);
+	if (is_root)
+		vp->v_vflag |= VV_ROOT;
+	vp->v_tag = VT_MSDOSFS;
+	vp->v_op = msdosfs_vnodeop_p;
+	vp->v_data = ldep;
+	ldep->de_vnode = vp;
+	genfs_node_init(vp, &msdosfs_genfsops);
+	uvm_vnp_setsize(vp, ldep->de_FileSize);
+	*new_key = &ldep->de_key;
+
+	return 0;
 }
 
 int
@@ -641,29 +530,6 @@ deextend(struct denode *dep, u_long leng
 	return (deupdat(dep, 1));
 }
 
-/*
- * Move a denode to its correct hash queue after the file it represents has
- * been moved to a new directory.
- */
-void
-reinsert(struct denode *dep)
-{
-	/*
-	 * Fix up the denode cache.  If the denode is for a directory,
-	 * there is nothing to do since the hash is based on the starting
-	 * cluster of the directory file and that hasn't changed.  If for a
-	 * file the hash is based on the location of the directory entry,
-	 * so we must remove it from the cache and re-enter it with the
-	 * hash based on the new location of the directory entry.
-	 */
-	if (dep->de_Attributes & ATTR_DIRECTORY)
-		return;
-	mutex_enter(&msdosfs_hashlock);
-	msdosfs_hashrem(dep);
-	msdosfs_hashins(dep);
-	mutex_exit(&msdosfs_hashlock);
-}
-
 int
 msdosfs_reclaim(void *v)
 {
@@ -671,8 +537,10 @@ msdosfs_reclaim(void *v)
 		struct vnode *a_vp;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
+	struct mount *mp = vp->v_mount;
 	struct denode *dep = VTODE(vp);
 
+	fstrans_start(mp, FSTRANS_LAZY);
 #ifdef MSDOSFS_DEBUG
 	printf("msdosfs_reclaim(): dep %p, file %s, refcnt %ld\n",
 	    dep, dep->de_Name, dep->de_refcnt);
@@ -681,9 +549,9 @@ msdosfs_reclaim(void *v)
 	if (prtactive && vp->v_usecount > 1)
 		vprint("msdosfs_reclaim(): pushing active", vp);
 	/*
-	 * Remove the denode from its hash chain.
+	 * Remove the denode from the vnode cache.
 	 */
-	msdosfs_hashrem(dep);
+	vcache_remove(vp->v_mount, &dep->de_key, sizeof(dep->de_key));
 	/*
 	 * Purge old data structures associated with the denode.
 	 */
@@ -694,9 +562,15 @@ msdosfs_reclaim(void *v)
 #if 0 /* XXX */
 	dep->de_flag = 0;
 #endif
+	/*
+	 * To interlock with msdosfs_sync().
+	 */
 	genfs_node_destroy(vp);
-	pool_put(&msdosfs_denode_pool, dep);
+	mutex_enter(vp->v_interlock);
 	vp->v_data = NULL;
+	mutex_exit(vp->v_interlock);
+	pool_put(&msdosfs_denode_pool, dep);
+	fstrans_done(mp);
 	return (0);
 }
 

Index: src/sys/fs/msdosfs/msdosfs_lookup.c
diff -u src/sys/fs/msdosfs/msdosfs_lookup.c:1.32 src/sys/fs/msdosfs/msdosfs_lookup.c:1.32.2.1
--- src/sys/fs/msdosfs/msdosfs_lookup.c:1.32	Fri Feb  7 15:29:21 2014
+++ src/sys/fs/msdosfs/msdosfs_lookup.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: msdosfs_lookup.c,v 1.32 2014/02/07 15:29:21 hannken Exp $	*/
+/*	$NetBSD: msdosfs_lookup.c,v 1.32.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -52,7 +52,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: msdosfs_lookup.c,v 1.32 2014/02/07 15:29:21 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: msdosfs_lookup.c,v 1.32.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #include <sys/param.h>
 
@@ -64,6 +64,7 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_look
 #include <sys/dirent.h>
 #include <sys/buf.h>
 #include <sys/vnode.h>
+#include <sys/atomic.h>
 #else
 #include <ffs/buf.h>
 #endif /* _KERNEL */
@@ -113,9 +114,7 @@ msdosfs_lookup(void *v)
 	int blsize;
 	int isadir;		/* ~0 if found direntry is a directory	 */
 	u_long scn;		/* starting cluster number		 */
-	struct vnode *pdp;
 	struct denode *dp;
-	struct denode *tdp;
 	struct msdosfsmount *pmp;
 	struct buf *bp = 0;
 	struct direntry *dep;
@@ -217,7 +216,7 @@ msdosfs_lookup(void *v)
 	 * Search the directory pointed at by vdp for the name pointed at
 	 * by cnp->cn_nameptr.
 	 */
-	tdp = NULL;
+
 	/*
 	 * The outer loop ranges over the clusters that make up the
 	 * directory.  Note that the root directory is different from all
@@ -491,11 +490,8 @@ foundroot:
 			*vpp = vdp;
 			return (0);
 		}
-		if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0)
-			return (error);
-		*vpp = DETOV(tdp);
-		VOP_UNLOCK(*vpp);
-		return (0);
+		error = deget(pmp, cluster, blkoff, vpp);
+		return error;
 	}
 
 	/*
@@ -523,48 +519,15 @@ foundroot:
 		if (dp->de_StartCluster == scn && isadir)
 			return (EISDIR);
 
-		if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0)
-			return (error);
-		*vpp = DETOV(tdp);
-		VOP_UNLOCK(*vpp);
-		return (0);
+		error = deget(pmp, cluster, blkoff, vpp);
+		return error;
 	}
 
-	/*
-	 * Step through the translation in the name.  We do not `vput' the
-	 * directory because we may need it again if a symbolic link
-	 * is relative to the current directory.  Instead we save it
-	 * unlocked as "pdp".  We must get the target inode before unlocking
-	 * the directory to insure that the inode will not be removed
-	 * before we get it.  We prevent deadlock by always fetching
-	 * inodes from the root, moving down the directory tree. Thus
-	 * when following backward pointers ".." we must unlock the
-	 * parent directory before getting the requested directory.
-	 * There is a potential race condition here if both the current
-	 * and parent directories are removed before the VFS_VGET for the
-	 * inode associated with ".." returns.  We hope that this occurs
-	 * infrequently since we cannot avoid this race condition without
-	 * implementing a sophisticated deadlock detection algorithm.
-	 * Note also that this simple deadlock detection scheme will not
-	 * work if the file system has any hard links other than ".."
-	 * that point backwards in the directory structure.
-	 */
-	pdp = vdp;
-	if (flags & ISDOTDOT) {
-		VOP_UNLOCK(pdp);	/* race to get the inode */
-		error = deget(pmp, cluster, blkoff, &tdp);
-		vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY);
-		if (error) {
-			return error;
-		}
-		*vpp = DETOV(tdp);
-	} else if (dp->de_StartCluster == scn && isadir) {
+	if (dp->de_StartCluster == scn && isadir) {
 		vref(vdp);	/* we want ourself, ie "." */
 		*vpp = vdp;
-	} else {
-		if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0)
-			return (error);
-		*vpp = DETOV(tdp);
+	} else if ((error = deget(pmp, cluster, blkoff, vpp)) != 0) {
+		return error;
 	}
 
 	/*
@@ -572,9 +535,6 @@ foundroot:
 	 */
 	cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags);
 
-	if (*vpp != vdp)
-		VOP_UNLOCK(*vpp);
-
 	return 0;
 }
 #endif /* _KERNEL */
@@ -707,6 +667,7 @@ createde(struct denode *dep, struct deno
 	 */
 	if (depp) {
 		u_long diroffset = clusoffset;
+
 		if (dep->de_Attributes & ATTR_DIRECTORY) {
 			dirclust = dep->de_StartCluster;
 			if (FAT32(pmp) && dirclust == pmp->pm_rootdirblk)
@@ -716,10 +677,16 @@ createde(struct denode *dep, struct deno
 			else
 				diroffset = 0;
 		}
+#ifdef MAKEFS
 		error = deget(pmp, dirclust, diroffset, depp);
-#ifndef MAKEFS
+#else
+		struct vnode *vp;
+
+		error = deget(pmp, dirclust, diroffset, &vp);
 		if (error == 0)
-			VOP_UNLOCK(DETOV(*depp));
+			*depp = VTODE(vp);
+		else
+			*depp = NULL;
 #endif
 		return error;
 	}
@@ -935,9 +902,24 @@ doscheckpath(struct denode *source, stru
 		vput(DETOV(dep));
 		brelse(bp, 0);
 		bp = NULL;
+#ifdef MAKEFS
 		/* NOTE: deget() clears dep on error */
 		if ((error = deget(pmp, scn, 0, &dep)) != 0)
 			break;
+#else
+		struct vnode *vp;
+
+		dep = NULL;
+		error = deget(pmp, scn, 0, &vp);
+		if (error)
+			break;
+		error = vn_lock(vp, LK_EXCLUSIVE);
+		if (error) {
+			vrele(vp);
+			break;
+		}
+		dep = VTODE(vp);
+#endif
 	}
 out:
 	if (bp)
@@ -1019,7 +1001,20 @@ removede(struct denode *pdep, struct den
 	    dep->de_Name, dep, offset);
 #endif
 
-	dep->de_refcnt--;
+	if (--dep->de_refcnt == 0) {
+#ifndef MAKEFS
+		struct denode_key old_key = dep->de_key;
+		struct denode_key new_key = dep->de_key;
+
+		KASSERT(new_key.dk_dirgen == NULL);
+		new_key.dk_dirgen = dep;
+		vcache_rekey_enter(pmp->pm_mountp, DETOV(dep), &old_key,
+		    sizeof(old_key), &new_key, sizeof(new_key));
+		dep->de_key = new_key;
+		vcache_rekey_exit(pmp->pm_mountp, DETOV(dep), &old_key,
+		    sizeof(old_key), &dep->de_key, sizeof(dep->de_key));
+#endif
+	}
 	offset += sizeof(struct direntry);
 	do {
 		offset -= sizeof(struct direntry);

Index: src/sys/fs/msdosfs/msdosfs_vfsops.c
diff -u src/sys/fs/msdosfs/msdosfs_vfsops.c:1.106 src/sys/fs/msdosfs/msdosfs_vfsops.c:1.106.2.1
--- src/sys/fs/msdosfs/msdosfs_vfsops.c:1.106	Sun Mar 23 15:21:15 2014
+++ src/sys/fs/msdosfs/msdosfs_vfsops.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: msdosfs_vfsops.c,v 1.106 2014/03/23 15:21:15 hannken Exp $	*/
+/*	$NetBSD: msdosfs_vfsops.c,v 1.106.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.106 2014/03/23 15:21:15 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.106.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -88,16 +88,16 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_vfso
 MODULE(MODULE_CLASS_VFS, msdos, NULL);
 
 #ifdef MSDOSFS_DEBUG
-#define DPRINTF(a) uprintf a
+#define DPRINTF(fmt, ...) uprintf("%s(): " fmt "\n", __func__, ##__VA_ARGS__)
 #else
-#define DPRINTF(a)
+#define DPRINTF(fmt, ...)
 #endif
 
+#define GEMDOSFS_BSIZE	512
+
 #define MSDOSFS_NAMEMAX(pmp) \
 	(pmp)->pm_flags & MSDOSFSMNT_LONGNAME ? WIN_MAXLEN : 12
 
-VFS_PROTOS(msdosfs);
-
 int msdosfs_mountfs(struct vnode *, struct mount *, struct lwp *,
     struct msdosfs_args *);
 
@@ -107,8 +107,6 @@ MALLOC_JUSTDEFINE(M_MSDOSFSMNT, "MSDOSFS
 MALLOC_JUSTDEFINE(M_MSDOSFSFAT, "MSDOSFS FAT", "MSDOS FS FAT table");
 MALLOC_JUSTDEFINE(M_MSDOSFSTMP, "MSDOSFS temp", "MSDOS FS temp. structures");
 
-#define ROOTNAME "root_device"
-
 static struct sysctllog *msdosfs_sysctl_log;
 
 extern const struct vnodeopv_desc msdosfs_vnodeop_opv_desc;
@@ -129,6 +127,7 @@ struct vfsops msdosfs_vfsops = {
 	.vfs_statvfs = msdosfs_statvfs,
 	.vfs_sync = msdosfs_sync,
 	.vfs_vget = msdosfs_vget,
+	.vfs_loadvnode = msdosfs_loadvnode,
 	.vfs_fhtovp = msdosfs_fhtovp,
 	.vfs_vptofh = msdosfs_vptofh,
 	.vfs_init = msdosfs_init,
@@ -284,6 +283,8 @@ msdosfs_mount(struct mount *mp, const ch
 	int error, flags;
 	mode_t accessmode;
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 
@@ -336,7 +337,7 @@ msdosfs_mount(struct mount *mp, const ch
 			/* not yet implemented */
 			error = EOPNOTSUPP;
 		if (error) {
-			DPRINTF(("vflush %d\n", error));
+			DPRINTF("vflush %d", error);
 			return (error);
 		}
 		if ((pmp->pm_flags & MSDOSFSMNT_RONLY) &&
@@ -356,14 +357,14 @@ msdosfs_mount(struct mount *mp, const ch
 			    KAUTH_SYSTEM_MOUNT, KAUTH_REQ_SYSTEM_MOUNT_DEVICE,
 			    mp, devvp, KAUTH_ARG(VREAD | VWRITE));
 			VOP_UNLOCK(devvp);
-			DPRINTF(("KAUTH_REQ_SYSTEM_MOUNT_DEVICE %d\n", error));
+			DPRINTF("KAUTH_REQ_SYSTEM_MOUNT_DEVICE %d", error);
 			if (error)
 				return (error);
 
 			pmp->pm_flags &= ~MSDOSFSMNT_RONLY;
 		}
 		if (args->fspec == NULL) {
-			DPRINTF(("missing fspec\n"));
+			DPRINTF("missing fspec");
 			return EINVAL;
 		}
 	}
@@ -374,17 +375,17 @@ msdosfs_mount(struct mount *mp, const ch
 	error = namei_simple_user(args->fspec,
 				NSM_FOLLOW_NOEMULROOT, &devvp);
 	if (error != 0) {
-		DPRINTF(("namei %d\n", error));
+		DPRINTF("namei %d", error);
 		return (error);
 	}
 
 	if (devvp->v_type != VBLK) {
-		DPRINTF(("not block\n"));
+		DPRINTF("not block");
 		vrele(devvp);
 		return (ENOTBLK);
 	}
 	if (bdevsw_lookup(devvp->v_rdev) == NULL) {
-		DPRINTF(("no block switch\n"));
+		DPRINTF("no block switch");
 		vrele(devvp);
 		return (ENXIO);
 	}
@@ -400,7 +401,7 @@ msdosfs_mount(struct mount *mp, const ch
 	    KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp, KAUTH_ARG(accessmode));
 	VOP_UNLOCK(devvp);
 	if (error) {
-		DPRINTF(("KAUTH_REQ_SYSTEM_MOUNT_DEVICE %d\n", error));
+		DPRINTF("KAUTH_REQ_SYSTEM_MOUNT_DEVICE %d", error);
 		vrele(devvp);
 		return (error);
 	}
@@ -415,12 +416,12 @@ msdosfs_mount(struct mount *mp, const ch
 		error = VOP_OPEN(devvp, xflags, FSCRED);
 		VOP_UNLOCK(devvp);
 		if (error) {
-			DPRINTF(("VOP_OPEN %d\n", error));
+			DPRINTF("VOP_OPEN %d", error);
 			goto fail;
 		}
 		error = msdosfs_mountfs(devvp, mp, l, args);
 		if (error) {
-			DPRINTF(("msdosfs_mountfs %d\n", error));
+			DPRINTF("msdosfs_mountfs %d", error);
 			vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
 			(void) VOP_CLOSE(devvp, xflags, NOCRED);
 			VOP_UNLOCK(devvp);
@@ -432,14 +433,13 @@ msdosfs_mount(struct mount *mp, const ch
 	} else {
 		vrele(devvp);
 		if (devvp != pmp->pm_devvp) {
-			DPRINTF(("devvp %p pmp %p\n", 
-			    devvp, pmp->pm_devvp));
+			DPRINTF("devvp %p pmp %p", devvp, pmp->pm_devvp);
 			return (EINVAL);	/* needs translation */
 		}
 	}
 	if ((error = update_mp(mp, args)) != 0) {
 		msdosfs_unmount(mp, MNT_FORCE);
-		DPRINTF(("update_mp %d\n", error));
+		DPRINTF("update_mp %d", error);
 		return error;
 	}
 
@@ -465,8 +465,7 @@ msdosfs_mountfs(struct vnode *devvp, str
 	struct byte_bpb50 *b50;
 	struct byte_bpb710 *b710;
 	uint8_t SecPerClust;
-	int	ronly, error, tmp;
-	int	bsize;
+	int	ronly, error, BlkPerSec;
 	uint64_t psize;
 	unsigned secsize;
 
@@ -493,16 +492,19 @@ msdosfs_mountfs(struct vnode *devvp, str
 		psize = 0;
 		error = 0;
 	}
+	if (secsize < DEV_BSIZE) {
+		DPRINTF("Invalid block secsize (%d < DEV_BSIZE)", secsize);
+		error = EINVAL;
+		goto error_exit;
+	}
 
 	if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
-		bsize = secsize;
-		if (bsize != 512) {
-			DPRINTF(("Invalid block bsize %d for GEMDOS\n", bsize));
+		if (secsize != GEMDOSFS_BSIZE) {
+			DPRINTF("Invalid block secsize %d for GEMDOS", secsize);
 			error = EINVAL;
 			goto error_exit;
 		}
-	} else
-		bsize = 0;
+	}
 
 	/*
 	 * Read the boot sector of the filesystem, and then check the
@@ -518,16 +520,15 @@ msdosfs_mountfs(struct vnode *devvp, str
 	if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
 		if (bsp->bs50.bsBootSectSig0 != BOOTSIG0
 		    || bsp->bs50.bsBootSectSig1 != BOOTSIG1) {
-			DPRINTF(("bootsig0 %d bootsig1 %d\n", 
+			DPRINTF("bootsig0 %d bootsig1 %d", 
 			    bsp->bs50.bsBootSectSig0,
-			    bsp->bs50.bsBootSectSig1));
+			    bsp->bs50.bsBootSectSig1);
 			error = EINVAL;
 			goto error_exit;
 		}
 	}
 
-	pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK);
-	memset(pmp, 0, sizeof *pmp);
+	pmp = malloc(sizeof(*pmp), M_MSDOSFSMNT, M_WAITOK|M_ZERO);
 	pmp->pm_mountp = mp;
 
 	/*
@@ -546,19 +547,6 @@ msdosfs_mountfs(struct vnode *devvp, str
 	pmp->pm_Heads = getushort(b50->bpbHeads);
 	pmp->pm_Media = b50->bpbMedia;
 
-	if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
-		/* XXX - We should probably check more values here */
-    		if (!pmp->pm_BytesPerSec || !SecPerClust
-	    		|| pmp->pm_SecPerTrack > 63) {
-			DPRINTF(("bytespersec %d secperclust %d "
-			    "secpertrack %d\n", 
-			    pmp->pm_BytesPerSec, SecPerClust,
-			    pmp->pm_SecPerTrack));
-			error = EINVAL;
-			goto error_exit;
-		}
-	}
-
 	if (pmp->pm_Sectors == 0) {
 		pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
 		pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);
@@ -567,16 +555,40 @@ msdosfs_mountfs(struct vnode *devvp, str
 		pmp->pm_HugeSectors = pmp->pm_Sectors;
 	}
 
+	/*
+	 * Sanity checks, from the FAT specification:
+	 * - sectors per cluster: >= 1, power of 2
+	 * - logical sector size: >= 1, power of 2
+	 * - cluster size:        <= max FS block size
+	 * - number of sectors:   >= 1
+	 */
+	if ((SecPerClust == 0) || !powerof2(SecPerClust) ||
+	    (pmp->pm_BytesPerSec == 0) || !powerof2(pmp->pm_BytesPerSec) ||
+	    (SecPerClust * pmp->pm_BytesPerSec > MAXBSIZE) ||
+	    (pmp->pm_HugeSectors == 0)) {
+		DPRINTF("consistency checks");
+		error = EINVAL;
+		goto error_exit;
+	}
+
+	if (!(argp->flags & MSDOSFSMNT_GEMDOSFS) &&
+	    (pmp->pm_SecPerTrack > 63)) {
+		DPRINTF("SecPerTrack %d", pmp->pm_SecPerTrack);
+		error = EINVAL;
+		goto error_exit;
+	}
+
 	if (pmp->pm_RootDirEnts == 0) {
-		unsigned short vers = getushort(b710->bpbFSVers);
+		unsigned short FSVers = getushort(b710->bpbFSVers);
+		unsigned short ExtFlags = getushort(b710->bpbExtFlags);
 		/*
 		 * Some say that bsBootSectSig[23] must be zero, but
 		 * Windows does not require this and some digital cameras
 		 * do not set these to zero.  Therefore, do not insist.
 		 */
-		if (pmp->pm_Sectors || pmp->pm_FATsecs || vers) {
-			DPRINTF(("sectors %d fatsecs %lu vers %d\n",
-			    pmp->pm_Sectors, pmp->pm_FATsecs, vers));
+		if (pmp->pm_Sectors || pmp->pm_FATsecs || FSVers) {
+			DPRINTF("Sectors %d FATsecs %lu FSVers %d",
+			    pmp->pm_Sectors, pmp->pm_FATsecs, FSVers);
 			error = EINVAL;
 			goto error_exit;
 		}
@@ -585,38 +597,31 @@ msdosfs_mountfs(struct vnode *devvp, str
 		pmp->pm_fatdiv = 1;
 		pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);
 
-		/* mirrorring is enabled if the FATMIRROR bit is not set */
-		if ((getushort(b710->bpbExtFlags) & FATMIRROR) == 0)
+		/* Mirroring is enabled if the FATMIRROR bit is not set. */
+		if ((ExtFlags & FATMIRROR) == 0)
 			pmp->pm_flags |= MSDOSFS_FATMIRROR;
 		else
-			pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
+			pmp->pm_curfat = ExtFlags & FATNUM;
 	} else
 		pmp->pm_flags |= MSDOSFS_FATMIRROR;
 
 	if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
 		if (FAT32(pmp)) {
-			DPRINTF(("FAT32 for GEMDOS\n"));
-			/*
-			 * GEMDOS doesn't know FAT32.
-			 */
+			/* GEMDOS doesn't know FAT32. */
+			DPRINTF("FAT32 for GEMDOS");
 			error = EINVAL;
 			goto error_exit;
 		}
 
 		/*
 		 * Check a few values (could do some more):
-		 * - logical sector size: power of 2, >= block size
-		 * - sectors per cluster: power of 2, >= 1
-		 * - number of sectors:   >= 1, <= size of partition
+		 * - logical sector size: >= block size
+		 * - number of sectors:   <= size of partition
 		 */
-		if ( (SecPerClust == 0)
-		  || (SecPerClust & (SecPerClust - 1))
-		  || (pmp->pm_BytesPerSec < bsize)
-		  || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1))
-		  || (pmp->pm_HugeSectors == 0)
-		  || (pmp->pm_HugeSectors * (pmp->pm_BytesPerSec / bsize)
-		      > psize)) {
-			DPRINTF(("consistency checks for GEMDOS\n"));
+		if ((pmp->pm_BytesPerSec < GEMDOSFS_BSIZE) ||
+		    (pmp->pm_HugeSectors *
+		     (pmp->pm_BytesPerSec / GEMDOSFS_BSIZE) > psize)) {
+			DPRINTF("consistency checks for GEMDOS");
 			error = EINVAL;
 			goto error_exit;
 		}
@@ -626,19 +631,19 @@ msdosfs_mountfs(struct vnode *devvp, str
 		 * always be the same as the number of bytes per disk block
 		 * Let's pretend it is.
 		 */
-		tmp = pmp->pm_BytesPerSec / bsize;
-		pmp->pm_BytesPerSec  = bsize;
-		pmp->pm_HugeSectors *= tmp;
-		pmp->pm_HiddenSects *= tmp;
-		pmp->pm_ResSectors  *= tmp;
-		pmp->pm_Sectors     *= tmp;
-		pmp->pm_FATsecs     *= tmp;
-		SecPerClust         *= tmp;
+		BlkPerSec = pmp->pm_BytesPerSec / GEMDOSFS_BSIZE;
+		pmp->pm_BytesPerSec  = GEMDOSFS_BSIZE;
+		pmp->pm_HugeSectors *= BlkPerSec;
+		pmp->pm_HiddenSects *= BlkPerSec;
+		pmp->pm_ResSectors  *= BlkPerSec;
+		pmp->pm_Sectors     *= BlkPerSec;
+		pmp->pm_FATsecs     *= BlkPerSec;
+		SecPerClust         *= BlkPerSec;
 	}
 
 	/* Check that fs has nonzero FAT size */
 	if (pmp->pm_FATsecs == 0) {
-		DPRINTF(("FATsecs is 0\n"));
+		DPRINTF("FATsecs is 0");
 		error = EINVAL;
 		goto error_exit;
 	}
@@ -711,8 +716,8 @@ msdosfs_mountfs(struct vnode *devvp, str
 	 * must be a power of 2
 	 */
 	if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) {
-		DPRINTF(("bpcluster %lu cnshift %lu\n", 
-		    pmp->pm_bpcluster, pmp->pm_cnshift));
+		DPRINTF("bpcluster %lu cnshift %lu", pmp->pm_bpcluster,
+		    pmp->pm_cnshift);
 		error = EINVAL;
 		goto error_exit;
 	}
@@ -723,8 +728,8 @@ msdosfs_mountfs(struct vnode *devvp, str
 	 * 32KiB due to limits in Windows versions before Vista.
 	 */
 	if (pmp->pm_bpcluster > MAXBSIZE) {
-		DPRINTF(("bpcluster %lu > MAXBSIZE %d\n",
-		    pmp->pm_bpcluster, MAXBSIZE));
+		DPRINTF("bpcluster %lu > MAXBSIZE %d",
+		    pmp->pm_bpcluster, MAXBSIZE);
 		error = EINVAL;
 		goto error_exit;
 	}
@@ -740,6 +745,7 @@ msdosfs_mountfs(struct vnode *devvp, str
 	 */
 	if (pmp->pm_fsinfo) {
 		struct fsinfo *fp;
+		const int rdsz = roundup(sizeof(*fp), pmp->pm_BytesPerSec);
 
 		/*
 		 * XXX	If the fsinfo block is stored on media with
@@ -747,7 +753,7 @@ msdosfs_mountfs(struct vnode *devvp, str
 		 *	padded at the end or in the middle?
 		 */
 		if ((error = bread(devvp, de_bn2kb(pmp, pmp->pm_fsinfo),
-		    pmp->pm_BytesPerSec, NOCRED, 0, &bp)) != 0)
+		    rdsz, NOCRED, 0, &bp)) != 0)
 			goto error_exit;
 		fp = (struct fsinfo *)bp->b_data;
 		if (!memcmp(fp->fsisig1, "RRaA", 4)
@@ -790,7 +796,7 @@ msdosfs_mountfs(struct vnode *devvp, str
 	 * Have the inuse map filled in.
 	 */
 	if ((error = fillinusemap(pmp)) != 0) {
-		DPRINTF(("fillinusemap %d\n", error));
+		DPRINTF("fillinusemap %d", error);
 		goto error_exit;
 	}
 
@@ -908,16 +914,20 @@ int
 msdosfs_root(struct mount *mp, struct vnode **vpp)
 {
 	struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
-	struct denode *ndep;
 	int error;
 
 #ifdef MSDOSFS_DEBUG
 	printf("msdosfs_root(); mp %p, pmp %p\n", mp, pmp);
 #endif
-	if ((error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, &ndep)) != 0)
-		return (error);
-	*vpp = DETOV(ndep);
-	return (0);
+	if ((error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, vpp)) != 0)
+		return error;
+	error = vn_lock(*vpp, LK_EXCLUSIVE);
+	if (error) {
+		vrele(*vpp);
+		*vpp = NULL;
+		return error;
+	}
+	return 0;
 }
 
 int
@@ -941,14 +951,34 @@ msdosfs_statvfs(struct mount *mp, struct
 	return (0);
 }
 
+struct msdosfs_sync_ctx {
+	int waitfor;
+};
+
+static bool
+msdosfs_sync_selector(void *cl, struct vnode *vp)
+{
+	struct msdosfs_sync_ctx *c = cl;
+	struct denode *dep;
+
+	dep = VTODE(vp);
+	if (c->waitfor == MNT_LAZY || vp->v_type == VNON ||
+	    dep == NULL || (((dep->de_flag &
+	    (DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0) &&
+	     (LIST_EMPTY(&vp->v_dirtyblkhd) &&
+	      UVM_OBJ_IS_CLEAN(&vp->v_uobj))))
+		return false;
+	return true;
+}
+
 int
 msdosfs_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
 {
 	struct vnode *vp;
 	struct vnode_iterator *marker;
-	struct denode *dep;
 	struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
 	int error, allerror = 0;
+	struct msdosfs_sync_ctx ctx;
 
 	/*
 	 * If we ever switch to not updating all of the FATs all the time,
@@ -966,21 +996,15 @@ msdosfs_sync(struct mount *mp, int waitf
 	 * Write back each (modified) denode.
 	 */
 	vfs_vnode_iterator_init(mp, &marker);
-	while (vfs_vnode_iterator_next(marker, &vp)) {
+	ctx.waitfor = waitfor;
+	while ((vp = vfs_vnode_iterator_next(marker, msdosfs_sync_selector,
+	    &ctx)))
+	{
 		error = vn_lock(vp, LK_EXCLUSIVE);
 		if (error) {
 			vrele(vp);
 			continue;
 		}
-		dep = VTODE(vp);
-		if (waitfor == MNT_LAZY || vp->v_type == VNON ||
-		    dep == NULL || (((dep->de_flag &
-		    (DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0) &&
-		     (LIST_EMPTY(&vp->v_dirtyblkhd) &&
-		      UVM_OBJ_IS_CLEAN(&vp->v_uobj)))) {
-			vput(vp);
-			continue;
-		}
 		if ((error = VOP_FSYNC(vp, cred,
 		    waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0)) != 0)
 			allerror = error;
@@ -1003,13 +1027,11 @@ msdosfs_fhtovp(struct mount *mp, struct 
 {
 	struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
 	struct defid defh;
-	struct denode *dep;
 	uint32_t gen;
 	int error;
 
 	if (fhp->fid_len != sizeof(struct defid)) {
-		DPRINTF(("fid_len %d %zd\n", fhp->fid_len,
-		    sizeof(struct defid)));
+		DPRINTF("fid_len %d %zd", fhp->fid_len, sizeof(struct defid));
 		return EINVAL;
 	}
 	memcpy(&defh, fhp, sizeof(defh));
@@ -1021,14 +1043,19 @@ msdosfs_fhtovp(struct mount *mp, struct 
 		*vpp = NULLVP;
 		return error;
 	}
-	error = deget(pmp, defh.defid_dirclust, defh.defid_dirofs, &dep);
+	error = deget(pmp, defh.defid_dirclust, defh.defid_dirofs, vpp);
 	if (error) {
-		DPRINTF(("deget %d\n", error));
+		DPRINTF("deget %d", error);
 		*vpp = NULLVP;
-		return (error);
+		return error;
 	}
-	*vpp = DETOV(dep);
-	return (0);
+	error = vn_lock(*vpp, LK_EXCLUSIVE);
+	if (error) {
+		vrele(*vpp);
+		*vpp = NULLVP;
+		return error;
+	}
+	return 0;
 }
 
 int

Index: src/sys/fs/msdosfs/msdosfs_vnops.c
diff -u src/sys/fs/msdosfs/msdosfs_vnops.c:1.89 src/sys/fs/msdosfs/msdosfs_vnops.c:1.89.2.1
--- src/sys/fs/msdosfs/msdosfs_vnops.c:1.89	Thu Jan 23 10:13:56 2014
+++ src/sys/fs/msdosfs/msdosfs_vnops.c	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: msdosfs_vnops.c,v 1.89 2014/01/23 10:13:56 hannken Exp $	*/
+/*	$NetBSD: msdosfs_vnops.c,v 1.89.2.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.89 2014/01/23 10:13:56 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.89.2.1 2014/08/10 06:55:53 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1072,18 +1072,25 @@ abortit:
 		}
 		cache_purge(fvp);
 		if (!doingdirectory) {
+			struct denode_key old_key = ip->de_key;
+			struct denode_key new_key = ip->de_key;
+
 			error = pcbmap(dp, de_cluster(pmp, to_diroffset), 0,
-				       &ip->de_dirclust, 0);
+				       &new_key.dk_dirclust, 0);
 			if (error) {
 				/* XXX should really panic here, fs is corrupt */
 				VOP_UNLOCK(fvp);
 				goto bad;
 			}
-			ip->de_diroffset = to_diroffset;
-			if (ip->de_dirclust != MSDOSFSROOT)
-				ip->de_diroffset &= pmp->pm_crbomask;
+			new_key.dk_diroffset = to_diroffset;
+			if (new_key.dk_dirclust != MSDOSFSROOT)
+				new_key.dk_diroffset &= pmp->pm_crbomask;
+			vcache_rekey_enter(pmp->pm_mountp, fvp, &old_key,
+			    sizeof(old_key), &new_key, sizeof(new_key));
+			ip->de_key = new_key;
+			vcache_rekey_exit(pmp->pm_mountp, fvp, &old_key,
+			    sizeof(old_key), &ip->de_key, sizeof(ip->de_key));
 		}
-		reinsert(ip);
 	}
 
 	/*
@@ -1871,6 +1878,8 @@ const struct vnodeopv_entry_desc msdosfs
 	{ &vop_setattr_desc, msdosfs_setattr },		/* setattr */
 	{ &vop_read_desc, msdosfs_read },		/* read */
 	{ &vop_write_desc, msdosfs_write },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_fcntl_desc, genfs_fcntl },		/* fcntl */
 	{ &vop_ioctl_desc, msdosfs_ioctl },		/* ioctl */
 	{ &vop_poll_desc, msdosfs_poll },		/* poll */

Index: src/sys/fs/msdosfs/msdosfsmount.h
diff -u src/sys/fs/msdosfs/msdosfsmount.h:1.19 src/sys/fs/msdosfs/msdosfsmount.h:1.19.10.1
--- src/sys/fs/msdosfs/msdosfsmount.h:1.19	Sat Jan 26 16:51:51 2013
+++ src/sys/fs/msdosfs/msdosfsmount.h	Sun Aug 10 06:55:53 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: msdosfsmount.h,v 1.19 2013/01/26 16:51:51 christos Exp $	*/
+/*	$NetBSD: msdosfsmount.h,v 1.19.10.1 2014/08/10 06:55:53 tls Exp $	*/
 
 /*-
  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -251,5 +251,9 @@ void msdosfs_init(void);
 void msdosfs_reinit(void);
 void msdosfs_done(void);
 
+#ifndef MAKEFS
+VFS_PROTOS(msdosfs);
+#endif
+
 #endif /* _KERNEL || MAKEFS */
 #endif /* _MSDOSFS_MSDOSFSMOUNT_H_ */

Index: src/sys/fs/nilfs/nilfs_vfsops.c
diff -u src/sys/fs/nilfs/nilfs_vfsops.c:1.15 src/sys/fs/nilfs/nilfs_vfsops.c:1.15.2.1
--- src/sys/fs/nilfs/nilfs_vfsops.c:1.15	Sun Mar 23 15:21:15 2014
+++ src/sys/fs/nilfs/nilfs_vfsops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: nilfs_vfsops.c,v 1.15 2014/03/23 15:21:15 hannken Exp $ */
+/* $NetBSD: nilfs_vfsops.c,v 1.15.2.1 2014/08/10 06:55:54 tls Exp $ */
 
 /*
  * Copyright (c) 2008, 2009 Reinoud Zandijk
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: nilfs_vfsops.c,v 1.15 2014/03/23 15:21:15 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nilfs_vfsops.c,v 1.15.2.1 2014/08/10 06:55:54 tls Exp $");
 #endif /* not lint */
 
 
@@ -800,6 +800,8 @@ nilfs_mount(struct mount *mp, const char
 
 	DPRINTF(VFSCALL, ("nilfs_mount called\n"));
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 

Index: src/sys/fs/nilfs/nilfs_vnops.c
diff -u src/sys/fs/nilfs/nilfs_vnops.c:1.27 src/sys/fs/nilfs/nilfs_vnops.c:1.27.2.1
--- src/sys/fs/nilfs/nilfs_vnops.c:1.27	Fri Feb  7 15:29:21 2014
+++ src/sys/fs/nilfs/nilfs_vnops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: nilfs_vnops.c,v 1.27 2014/02/07 15:29:21 hannken Exp $ */
+/* $NetBSD: nilfs_vnops.c,v 1.27.2.1 2014/08/10 06:55:54 tls Exp $ */
 
 /*
  * Copyright (c) 2008, 2009 Reinoud Zandijk
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: nilfs_vnops.c,v 1.27 2014/02/07 15:29:21 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nilfs_vnops.c,v 1.27.2.1 2014/08/10 06:55:54 tls Exp $");
 #endif /* not lint */
 
 
@@ -1572,6 +1572,8 @@ const struct vnodeopv_entry_desc nilfs_v
 	{ &vop_setattr_desc, nilfs_setattr },	/* setattr */	/* TODO chflags */
 	{ &vop_read_desc, nilfs_read },		/* read */
 	{ &vop_write_desc, nilfs_write },	/* write */	/* WRITE */
+	{ &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */
 	{ &vop_fcntl_desc, genfs_fcntl },	/* fcntl */	/* TODO? */
 	{ &vop_ioctl_desc, genfs_enoioctl },	/* ioctl */	/* TODO? */
 	{ &vop_poll_desc, genfs_poll },		/* poll */	/* TODO/OK? */

Index: src/sys/fs/ntfs/ntfs_vfsops.c
diff -u src/sys/fs/ntfs/ntfs_vfsops.c:1.93 src/sys/fs/ntfs/ntfs_vfsops.c:1.93.2.1
--- src/sys/fs/ntfs/ntfs_vfsops.c:1.93	Sun Mar 23 15:21:15 2014
+++ src/sys/fs/ntfs/ntfs_vfsops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ntfs_vfsops.c,v 1.93 2014/03/23 15:21:15 hannken Exp $	*/
+/*	$NetBSD: ntfs_vfsops.c,v 1.93.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*-
  * Copyright (c) 1998, 1999 Semen Ustimenko
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ntfs_vfsops.c,v 1.93 2014/03/23 15:21:15 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ntfs_vfsops.c,v 1.93.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -172,6 +172,8 @@ ntfs_mount (
 	struct vnode	*devvp;
 	struct ntfs_args *args = data;
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 

Index: src/sys/fs/ntfs/ntfs_vnops.c
diff -u src/sys/fs/ntfs/ntfs_vnops.c:1.56 src/sys/fs/ntfs/ntfs_vnops.c:1.56.2.1
--- src/sys/fs/ntfs/ntfs_vnops.c:1.56	Fri Feb  7 15:29:21 2014
+++ src/sys/fs/ntfs/ntfs_vnops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ntfs_vnops.c,v 1.56 2014/02/07 15:29:21 hannken Exp $	*/
+/*	$NetBSD: ntfs_vnops.c,v 1.56.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ntfs_vnops.c,v 1.56 2014/02/07 15:29:21 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ntfs_vnops.c,v 1.56.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -818,6 +818,8 @@ const struct vnodeopv_entry_desc ntfs_vn
 	{ &vop_setattr_desc, genfs_eopnotsupp },	/* setattr */
 	{ &vop_read_desc, (vop_t *) ntfs_read },	/* read */
 	{ &vop_write_desc, (vop_t *) ntfs_write },	/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_fcntl_desc, genfs_fcntl },		/* fcntl */
 	{ &vop_ioctl_desc, genfs_enoioctl },		/* ioctl */
 	{ &vop_poll_desc, genfs_poll },			/* poll */

Index: src/sys/fs/ptyfs/ptyfs_vfsops.c
diff -u src/sys/fs/ptyfs/ptyfs_vfsops.c:1.49 src/sys/fs/ptyfs/ptyfs_vfsops.c:1.49.2.1
--- src/sys/fs/ptyfs/ptyfs_vfsops.c:1.49	Fri Apr  4 18:10:29 2014
+++ src/sys/fs/ptyfs/ptyfs_vfsops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ptyfs_vfsops.c,v 1.49 2014/04/04 18:10:29 christos Exp $	*/
+/*	$NetBSD: ptyfs_vfsops.c,v 1.49.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993, 1995
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ptyfs_vfsops.c,v 1.49 2014/04/04 18:10:29 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ptyfs_vfsops.c,v 1.49.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -259,6 +259,8 @@ ptyfs_mount(struct mount *mp, const char
 	struct ptyfsmount *pmnt;
 	struct ptyfs_args *args = data;
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len != sizeof *args && *data_len != OSIZE)
 		return EINVAL;
 

Index: src/sys/fs/ptyfs/ptyfs_vnops.c
diff -u src/sys/fs/ptyfs/ptyfs_vnops.c:1.46 src/sys/fs/ptyfs/ptyfs_vnops.c:1.46.2.1
--- src/sys/fs/ptyfs/ptyfs_vnops.c:1.46	Fri Apr  4 18:10:29 2014
+++ src/sys/fs/ptyfs/ptyfs_vnops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ptyfs_vnops.c,v 1.46 2014/04/04 18:10:29 christos Exp $	*/
+/*	$NetBSD: ptyfs_vnops.c,v 1.46.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 1993, 1995
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ptyfs_vnops.c,v 1.46 2014/04/04 18:10:29 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ptyfs_vnops.c,v 1.46.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -176,6 +176,8 @@ const struct vnodeopv_entry_desc ptyfs_v
 	{ &vop_setattr_desc, ptyfs_setattr },		/* setattr */
 	{ &vop_read_desc, ptyfs_read },			/* read */
 	{ &vop_write_desc, ptyfs_write },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_ioctl_desc, ptyfs_ioctl },		/* ioctl */
 	{ &vop_fcntl_desc, ptyfs_fcntl },		/* fcntl */
 	{ &vop_poll_desc, ptyfs_poll },			/* poll */

Index: src/sys/fs/puffs/puffs_vfsops.c
diff -u src/sys/fs/puffs/puffs_vfsops.c:1.109 src/sys/fs/puffs/puffs_vfsops.c:1.109.2.1
--- src/sys/fs/puffs/puffs_vfsops.c:1.109	Sun Mar 23 15:21:15 2014
+++ src/sys/fs/puffs/puffs_vfsops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: puffs_vfsops.c,v 1.109 2014/03/23 15:21:15 hannken Exp $	*/
+/*	$NetBSD: puffs_vfsops.c,v 1.109.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 2005, 2006  Antti Kantee.  All Rights Reserved.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.109 2014/03/23 15:21:15 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.109.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -102,6 +102,8 @@ puffs_vfsop_mount(struct mount *mp, cons
 	int error = 0, i;
 	pid_t mntpid = curlwp->l_proc->p_pid;
 
+	if (data == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 
@@ -116,12 +118,6 @@ puffs_vfsop_mount(struct mount *mp, cons
 	if (mp->mnt_flag & MNT_UPDATE)
 		return EOPNOTSUPP;
 
-	/*
-	 * We need the file system name
-	 */
-	if (!data)
-		return EINVAL;
-
 	args = (struct puffs_kargs *)data;
 
 	if (args->pa_vers != PUFFSVERSION) {
@@ -514,6 +510,13 @@ puffs_vfsop_statvfs(struct mount *mp, st
 	return error;
 }
 
+static bool
+pageflush_selector(void *cl, struct vnode *vp)
+{
+	return vp->v_type == VREG &&
+	    !(LIST_EMPTY(&vp->v_dirtyblkhd) && UVM_OBJ_IS_CLEAN(&vp->v_uobj));
+}
+
 static int
 pageflush(struct mount *mp, kauth_cred_t cred, int waitfor)
 {
@@ -532,7 +535,9 @@ pageflush(struct mount *mp, kauth_cred_t
 	 * all the nodes it knows to exist.
 	 */
 	vfs_vnode_iterator_init(mp, &marker);
-	while (vfs_vnode_iterator_next(marker, &vp)) {
+	while ((vp = vfs_vnode_iterator_next(marker, pageflush_selector,
+	    NULL)))
+	{
 		/*
 		 * Here we try to get a reference to the vnode and to
 		 * lock it.  This is mostly cargo-culted, but I will
@@ -554,11 +559,6 @@ pageflush(struct mount *mp, kauth_cred_t
 			continue;
 		}
 		pn = VPTOPP(vp);
-		if (vp->v_type != VREG || UVM_OBJ_IS_CLEAN(&vp->v_uobj)) {
-			vput(vp);
-			continue;
-		}
-
 		/* hmm.. is the FAF thing entirely sensible? */
 		if (waitfor == MNT_LAZY) {
 			mutex_enter(vp->v_interlock);

Index: src/sys/fs/puffs/puffs_vnops.c
diff -u src/sys/fs/puffs/puffs_vnops.c:1.181 src/sys/fs/puffs/puffs_vnops.c:1.181.2.1
--- src/sys/fs/puffs/puffs_vnops.c:1.181	Mon Mar 24 13:42:40 2014
+++ src/sys/fs/puffs/puffs_vnops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: puffs_vnops.c,v 1.181 2014/03/24 13:42:40 hannken Exp $	*/
+/*	$NetBSD: puffs_vnops.c,v 1.181.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 2005, 2006, 2007  Antti Kantee.  All Rights Reserved.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.181 2014/03/24 13:42:40 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.181.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/buf.h>
@@ -113,6 +113,8 @@ const struct vnodeopv_entry_desc puffs_v
         { &vop_setattr_desc, puffs_vnop_checkop },	/* setattr */
         { &vop_read_desc, puffs_vnop_checkop },		/* read */
         { &vop_write_desc, puffs_vnop_checkop },	/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
         { &vop_fsync_desc, puffs_vnop_fsync },		/* REAL fsync */
         { &vop_seek_desc, puffs_vnop_checkop },		/* seek */
         { &vop_remove_desc, puffs_vnop_checkop },	/* remove */
@@ -168,6 +170,8 @@ const struct vnodeopv_entry_desc puffs_s
 	{ &vop_setattr_desc, puffs_vnop_checkop },	/* setattr */
 	{ &vop_read_desc, puffs_vnop_spec_read },	/* update, read */
 	{ &vop_write_desc, puffs_vnop_spec_write },	/* update, write */
+	{ &vop_fallocate_desc, spec_fallocate },	/* fallocate */
+	{ &vop_fdiscard_desc, spec_fdiscard },		/* fdiscard */
 	{ &vop_ioctl_desc, spec_ioctl },		/* spec_ioctl */
 	{ &vop_fcntl_desc, genfs_fcntl },		/* dummy */
 	{ &vop_poll_desc, spec_poll },			/* spec_poll */
@@ -225,6 +229,8 @@ const struct vnodeopv_entry_desc puffs_f
 	{ &vop_setattr_desc, puffs_vnop_checkop },	/* setattr */
 	{ &vop_read_desc, puffs_vnop_fifo_read },	/* read, update */
 	{ &vop_write_desc, puffs_vnop_fifo_write },	/* write, update */
+	{ &vop_fallocate_desc, vn_fifo_bypass },	/* fallocate */
+	{ &vop_fdiscard_desc, vn_fifo_bypass },		/* fdiscard */
 	{ &vop_ioctl_desc, vn_fifo_bypass },		/* ioctl */
 	{ &vop_fcntl_desc, genfs_fcntl },		/* dummy */
 	{ &vop_poll_desc, vn_fifo_bypass },		/* poll */

Index: src/sys/fs/smbfs/smbfs_vfsops.c
diff -u src/sys/fs/smbfs/smbfs_vfsops.c:1.99 src/sys/fs/smbfs/smbfs_vfsops.c:1.99.2.1
--- src/sys/fs/smbfs/smbfs_vfsops.c:1.99	Sun Mar 23 15:21:15 2014
+++ src/sys/fs/smbfs/smbfs_vfsops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: smbfs_vfsops.c,v 1.99 2014/03/23 15:21:15 hannken Exp $	*/
+/*	$NetBSD: smbfs_vfsops.c,v 1.99.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 2000-2001, Boris Popov
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: smbfs_vfsops.c,v 1.99 2014/03/23 15:21:15 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smbfs_vfsops.c,v 1.99.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -62,7 +62,7 @@ __KERNEL_RCSID(0, "$NetBSD: smbfs_vfsops
 #include <fs/smbfs/smbfs_node.h>
 #include <fs/smbfs/smbfs_subr.h>
 
-MODULE(MODULE_CLASS_VFS, smbfs, NULL);
+MODULE(MODULE_CLASS_VFS, smbfs, "nsmb");
 
 VFS_PROTOS(smbfs);
 
@@ -156,6 +156,8 @@ smbfs_mount(struct mount *mp, const char
 	char *fromname;
 	int error;
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 
@@ -398,6 +400,23 @@ smbfs_statvfs(struct mount *mp, struct s
 	return 0;
 }
 
+static bool
+smbfs_sync_selector(void *cl, struct vnode *vp)
+{
+	struct smbnode *np;
+
+	np = VTOSMB(vp);
+	if (np == NULL)
+		return false;
+
+	if ((vp->v_type == VNON || (np->n_flag & NMODIFIED) == 0) &&
+	     LIST_EMPTY(&vp->v_dirtyblkhd) &&
+	     UVM_OBJ_IS_CLEAN(&vp->v_uobj))
+		return false;
+
+	return true;
+}
+
 /*
  * Flush out the buffer cache
  */
@@ -406,27 +425,17 @@ smbfs_sync(struct mount *mp, int waitfor
 {
 	struct vnode *vp;
 	struct vnode_iterator *marker;
-	struct smbnode *np;
 	int error, allerror = 0;
 
 	vfs_vnode_iterator_init(mp, &marker);
-	while (vfs_vnode_iterator_next(marker, &vp)) {
+	while ((vp = vfs_vnode_iterator_next(marker, smbfs_sync_selector,
+	    NULL)))
+	{
 		error = vn_lock(vp, LK_EXCLUSIVE);
 		if (error) {
 			vrele(vp);
 			continue;
 		}
-		np = VTOSMB(vp);
-		if (np == NULL) {
-			vput(vp);
-			continue;
-		}
-		if ((vp->v_type == VNON || (np->n_flag & NMODIFIED) == 0) &&
-		    LIST_EMPTY(&vp->v_dirtyblkhd) &&
-		     vp->v_uobj.uo_npages == 0) {
-			vput(vp);
-			continue;
-		}
 		error = VOP_FSYNC(vp, cred,
 		    waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0);
 		if (error)

Index: src/sys/fs/smbfs/smbfs_vnops.c
diff -u src/sys/fs/smbfs/smbfs_vnops.c:1.89 src/sys/fs/smbfs/smbfs_vnops.c:1.89.2.1
--- src/sys/fs/smbfs/smbfs_vnops.c:1.89	Fri Feb  7 15:29:21 2014
+++ src/sys/fs/smbfs/smbfs_vnops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: smbfs_vnops.c,v 1.89 2014/02/07 15:29:21 hannken Exp $	*/
+/*	$NetBSD: smbfs_vnops.c,v 1.89.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: smbfs_vnops.c,v 1.89 2014/02/07 15:29:21 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smbfs_vnops.c,v 1.89.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -127,6 +127,8 @@ static struct vnodeopv_entry_desc smbfs_
 	{ &vop_advlock_desc,		smbfs_advlock },
 	{ &vop_close_desc,		smbfs_close },
 	{ &vop_create_desc,		smbfs_create },
+	{ &vop_fallocate_desc,		genfs_eopnotsupp },
+	{ &vop_fdiscard_desc,		genfs_eopnotsupp },
 	{ &vop_fsync_desc,		smbfs_fsync },
 	{ &vop_getattr_desc,		smbfs_getattr },
 	{ &vop_getpages_desc,		genfs_compat_getpages },
@@ -1244,9 +1246,11 @@ smbfs_lookup(void *v)
 		}
 
 		newvp = *vpp;
-		vn_lock(newvp, LK_SHARED | LK_RETRY);
+		if (newvp != dvp)
+			vn_lock(newvp, LK_SHARED | LK_RETRY);
 		error = VOP_GETATTR(newvp, &vattr, cnp->cn_cred);
-		VOP_UNLOCK(newvp);
+		if (newvp != dvp)
+			VOP_UNLOCK(newvp);
 		/*
 		 * If the file type on the server is inconsistent
 		 * with what it was when we created the vnode,

Index: src/sys/fs/sysvbfs/sysvbfs.c
diff -u src/sys/fs/sysvbfs/sysvbfs.c:1.13 src/sys/fs/sysvbfs/sysvbfs.c:1.13.2.1
--- src/sys/fs/sysvbfs/sysvbfs.c:1.13	Sun Mar 23 15:21:15 2014
+++ src/sys/fs/sysvbfs/sysvbfs.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysvbfs.c,v 1.13 2014/03/23 15:21:15 hannken Exp $	*/
+/*	$NetBSD: sysvbfs.c,v 1.13.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*-
  * Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysvbfs.c,v 1.13 2014/03/23 15:21:15 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysvbfs.c,v 1.13.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/resource.h>
 #include <sys/param.h>
@@ -59,6 +59,8 @@ const struct vnodeopv_entry_desc sysvbfs
 	{ &vop_setattr_desc, sysvbfs_setattr },		/* setattr */
 	{ &vop_read_desc, sysvbfs_read },		/* read */
 	{ &vop_write_desc, sysvbfs_write },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_fcntl_desc, genfs_fcntl },		/* fcntl */
 	{ &vop_ioctl_desc, genfs_enoioctl },		/* ioctl */
 	{ &vop_poll_desc, genfs_poll },			/* poll */

Index: src/sys/fs/sysvbfs/sysvbfs_vfsops.c
diff -u src/sys/fs/sysvbfs/sysvbfs_vfsops.c:1.42 src/sys/fs/sysvbfs/sysvbfs_vfsops.c:1.42.2.1
--- src/sys/fs/sysvbfs/sysvbfs_vfsops.c:1.42	Wed Dec 25 11:15:49 2013
+++ src/sys/fs/sysvbfs/sysvbfs_vfsops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysvbfs_vfsops.c,v 1.42 2013/12/25 11:15:49 mlelstv Exp $	*/
+/*	$NetBSD: sysvbfs_vfsops.c,v 1.42.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*-
  * Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysvbfs_vfsops.c,v 1.42 2013/12/25 11:15:49 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysvbfs_vfsops.c,v 1.42.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -77,6 +77,8 @@ sysvbfs_mount(struct mount *mp, const ch
 
 	DPRINTF("%s: mnt_flag=%x\n", __func__, mp->mnt_flag);
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 

Index: src/sys/fs/sysvbfs/sysvbfs_vnops.c
diff -u src/sys/fs/sysvbfs/sysvbfs_vnops.c:1.53 src/sys/fs/sysvbfs/sysvbfs_vnops.c:1.53.2.1
--- src/sys/fs/sysvbfs/sysvbfs_vnops.c:1.53	Fri Feb  7 15:29:21 2014
+++ src/sys/fs/sysvbfs/sysvbfs_vnops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysvbfs_vnops.c,v 1.53 2014/02/07 15:29:21 hannken Exp $	*/
+/*	$NetBSD: sysvbfs_vnops.c,v 1.53.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*-
  * Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysvbfs_vnops.c,v 1.53 2014/02/07 15:29:21 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysvbfs_vnops.c,v 1.53.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -450,7 +450,7 @@ sysvbfs_read(void *arg)
 		DPRINTF("%s: read %ldbyte\n", __func__, sz);
 	}
 
-	return  sysvbfs_update(v, NULL, NULL, UPDATE_WAIT);
+	return sysvbfs_update(v, NULL, NULL, UPDATE_WAIT);
 }
 
 int

Index: src/sys/fs/tmpfs/tmpfs.h
diff -u src/sys/fs/tmpfs/tmpfs.h:1.48 src/sys/fs/tmpfs/tmpfs.h:1.48.2.1
--- src/sys/fs/tmpfs/tmpfs.h:1.48	Sat Nov 23 16:35:32 2013
+++ src/sys/fs/tmpfs/tmpfs.h	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: tmpfs.h,v 1.48 2013/11/23 16:35:32 rmind Exp $	*/
+/*	$NetBSD: tmpfs.h,v 1.48.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -279,6 +279,7 @@ void		tmpfs_update(vnode_t *, unsigned);
 
 void		tmpfs_mntmem_init(tmpfs_mount_t *, uint64_t);
 void		tmpfs_mntmem_destroy(tmpfs_mount_t *);
+int		tmpfs_mntmem_set(tmpfs_mount_t *, uint64_t);
 
 size_t		tmpfs_mem_info(bool);
 uint64_t	tmpfs_bytes_max(tmpfs_mount_t *);
@@ -306,13 +307,6 @@ bool		tmpfs_strname_neqlen(struct compon
     KASSERT((node)->tn_size % sizeof(tmpfs_dirent_t) == 0);
 
 /*
- * Memory management stuff.
- */
-
-/* Amount of memory pages to reserve for the system. */
-#define	TMPFS_PAGES_RESERVED	(4 * 1024 * 1024 / PAGE_SIZE)
-
-/*
  * Routines to convert VFS structures to tmpfs internal ones.
  */
 

Index: src/sys/fs/tmpfs/tmpfs_fifoops.c
diff -u src/sys/fs/tmpfs/tmpfs_fifoops.c:1.10 src/sys/fs/tmpfs/tmpfs_fifoops.c:1.10.2.1
--- src/sys/fs/tmpfs/tmpfs_fifoops.c:1.10	Sat Nov 23 16:35:32 2013
+++ src/sys/fs/tmpfs/tmpfs_fifoops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: tmpfs_fifoops.c,v 1.10 2013/11/23 16:35:32 rmind Exp $	*/
+/*	$NetBSD: tmpfs_fifoops.c,v 1.10.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_fifoops.c,v 1.10 2013/11/23 16:35:32 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_fifoops.c,v 1.10.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/vnode.h>
@@ -59,6 +59,8 @@ const struct vnodeopv_entry_desc tmpfs_f
 	{ &vop_setattr_desc,		tmpfs_fifo_setattr },
 	{ &vop_read_desc,		tmpfs_fifo_read },
 	{ &vop_write_desc,		tmpfs_fifo_write },
+	{ &vop_fallocate_desc,		vn_fifo_bypass },
+	{ &vop_fdiscard_desc,		vn_fifo_bypass },
 	{ &vop_ioctl_desc,		tmpfs_fifo_ioctl },
 	{ &vop_fcntl_desc,		tmpfs_fifo_fcntl },
 	{ &vop_poll_desc,		tmpfs_fifo_poll },

Index: src/sys/fs/tmpfs/tmpfs_mem.c
diff -u src/sys/fs/tmpfs/tmpfs_mem.c:1.4 src/sys/fs/tmpfs/tmpfs_mem.c:1.4.28.1
--- src/sys/fs/tmpfs/tmpfs_mem.c:1.4	Tue May 24 01:09:47 2011
+++ src/sys/fs/tmpfs/tmpfs_mem.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: tmpfs_mem.c,v 1.4 2011/05/24 01:09:47 rmind Exp $	*/
+/*	$NetBSD: tmpfs_mem.c,v 1.4.28.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_mem.c,v 1.4 2011/05/24 01:09:47 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_mem.c,v 1.4.28.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -65,13 +65,31 @@ tmpfs_mntmem_destroy(struct tmpfs_mount 
 	mutex_destroy(&mp->tm_acc_lock);
 }
 
+int
+tmpfs_mntmem_set(struct tmpfs_mount *mp, uint64_t memlimit)
+{
+	int error;
+
+	mutex_enter(&mp->tm_acc_lock);
+	if (round_page(mp->tm_bytes_used) >= memlimit)
+		error = EBUSY;
+	else {
+		error = 0;
+		mp->tm_mem_limit = memlimit;
+	}
+	mutex_exit(&mp->tm_acc_lock);
+	return error;
+}
+
+	
+
 /*
  * tmpfs_mem_info: return the number of available memory pages.
  *
  * => If 'total' is true, then return _total_ amount of pages.
  * => If false, then return the amount of _free_ memory pages.
  *
- * Remember to remove TMPFS_PAGES_RESERVED from the returned value to avoid
+ * Remember to remove uvmexp.freetarg from the returned value to avoid
  * excessive memory usage.
  */
 size_t
@@ -97,13 +115,13 @@ tmpfs_mem_info(bool total)
 uint64_t
 tmpfs_bytes_max(struct tmpfs_mount *mp)
 {
-	size_t freepages = tmpfs_mem_info(false);
+	psize_t freepages = tmpfs_mem_info(false);
 	uint64_t avail_mem;
 
-	if (freepages < TMPFS_PAGES_RESERVED) {
+	if (freepages < uvmexp.freetarg) {
 		freepages = 0;
 	} else {
-		freepages -= TMPFS_PAGES_RESERVED;
+		freepages -= uvmexp.freetarg;
 	}
 	avail_mem = round_page(mp->tm_bytes_used) + (freepages << PAGE_SHIFT);
 	return MIN(mp->tm_mem_limit, avail_mem);

Index: src/sys/fs/tmpfs/tmpfs_specops.c
diff -u src/sys/fs/tmpfs/tmpfs_specops.c:1.11 src/sys/fs/tmpfs/tmpfs_specops.c:1.11.2.1
--- src/sys/fs/tmpfs/tmpfs_specops.c:1.11	Sat Nov 23 16:35:32 2013
+++ src/sys/fs/tmpfs/tmpfs_specops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: tmpfs_specops.c,v 1.11 2013/11/23 16:35:32 rmind Exp $	*/
+/*	$NetBSD: tmpfs_specops.c,v 1.11.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_specops.c,v 1.11 2013/11/23 16:35:32 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_specops.c,v 1.11.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/vnode.h>
@@ -62,6 +62,8 @@ const struct vnodeopv_entry_desc tmpfs_s
 	{ &vop_setattr_desc,		tmpfs_spec_setattr },
 	{ &vop_read_desc,		tmpfs_spec_read },
 	{ &vop_write_desc,		tmpfs_spec_write },
+	{ &vop_fallocate_desc,		spec_fallocate },
+	{ &vop_fdiscard_desc,		spec_fdiscard },
 	{ &vop_ioctl_desc,		tmpfs_spec_ioctl },
 	{ &vop_fcntl_desc,		tmpfs_spec_fcntl },
 	{ &vop_poll_desc,		tmpfs_spec_poll },

Index: src/sys/fs/tmpfs/tmpfs_vfsops.c
diff -u src/sys/fs/tmpfs/tmpfs_vfsops.c:1.58 src/sys/fs/tmpfs/tmpfs_vfsops.c:1.58.2.1
--- src/sys/fs/tmpfs/tmpfs_vfsops.c:1.58	Sun Mar 23 15:21:16 2014
+++ src/sys/fs/tmpfs/tmpfs_vfsops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: tmpfs_vfsops.c,v 1.58 2014/03/23 15:21:16 hannken Exp $	*/
+/*	$NetBSD: tmpfs_vfsops.c,v 1.58.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_vfsops.c,v 1.58 2014/03/23 15:21:16 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_vfsops.c,v 1.58.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -103,6 +103,9 @@ tmpfs_mount(struct mount *mp, const char
 	ino_t nodes;
 	int error;
 
+	if (args == NULL)
+		return EINVAL;
+
 	/* Validate the version. */
 	if (*data_len < sizeof(*args) ||
 	    args->ta_version != TMPFS_ARGS_VERSION)
@@ -127,13 +130,17 @@ tmpfs_mount(struct mount *mp, const char
 		return 0;
 	}
 
-	if (mp->mnt_flag & MNT_UPDATE) {
-		/* TODO */
-		return EOPNOTSUPP;
-	}
 
 	/* Prohibit mounts if there is not enough memory. */
-	if (tmpfs_mem_info(true) < TMPFS_PAGES_RESERVED)
+	if (tmpfs_mem_info(true) < uvmexp.freetarg)
+		return EINVAL;
+
+	/* Check for invalid uid and gid arguments */
+	if (args->ta_root_uid == VNOVAL || args->ta_root_gid == VNOVAL)
+		return EINVAL;
+
+	/* This can never happen? */
+	if ((args->ta_root_mode & ALLPERMS) == VNOVAL)
 		return EINVAL;
 
 	/* Get the memory usage limit for this file-system. */
@@ -152,6 +159,20 @@ tmpfs_mount(struct mount *mp, const char
 	nodes = MIN(nodes, INT_MAX);
 	KASSERT(nodes >= 3);
 
+	if (mp->mnt_flag & MNT_UPDATE) {
+		tmp = VFS_TO_TMPFS(mp);
+		if (nodes < tmp->tm_nodes_cnt)
+			return EBUSY;
+		if ((error = tmpfs_mntmem_set(tmp, memlimit)) != 0)
+			return error;
+		tmp->tm_nodes_max = nodes;
+		root = tmp->tm_root;
+		root->tn_uid = args->ta_root_uid;
+		root->tn_gid = args->ta_root_gid;
+		root->tn_mode = args->ta_root_mode;
+		return 0;
+	}
+
 	/* Allocate the tmpfs mount structure and fill it. */
 	tmp = kmem_zalloc(sizeof(tmpfs_mount_t), KM_SLEEP);
 	if (tmp == NULL)

Index: src/sys/fs/tmpfs/tmpfs_vnops.c
diff -u src/sys/fs/tmpfs/tmpfs_vnops.c:1.118 src/sys/fs/tmpfs/tmpfs_vnops.c:1.118.2.1
--- src/sys/fs/tmpfs/tmpfs_vnops.c:1.118	Thu Feb 27 16:51:38 2014
+++ src/sys/fs/tmpfs/tmpfs_vnops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: tmpfs_vnops.c,v 1.118 2014/02/27 16:51:38 hannken Exp $	*/
+/*	$NetBSD: tmpfs_vnops.c,v 1.118.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.118 2014/02/27 16:51:38 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.118.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/dirent.h>
@@ -74,6 +74,8 @@ const struct vnodeopv_entry_desc tmpfs_v
 	{ &vop_setattr_desc,		tmpfs_setattr },
 	{ &vop_read_desc,		tmpfs_read },
 	{ &vop_write_desc,		tmpfs_write },
+	{ &vop_fallocate_desc,		genfs_eopnotsupp },
+	{ &vop_fdiscard_desc,		genfs_eopnotsupp },
 	{ &vop_ioctl_desc,		tmpfs_ioctl },
 	{ &vop_fcntl_desc,		tmpfs_fcntl },
 	{ &vop_poll_desc,		tmpfs_poll },
@@ -343,7 +345,7 @@ tmpfs_mknod(void *v)
 	enum vtype vt = vap->va_type;
 
 	if (vt != VBLK && vt != VCHR && vt != VFIFO) {
-		vput(dvp);
+		*vpp = NULL;
 		return EINVAL;
 	}
 	return tmpfs_construct_node(dvp, vpp, vap, cnp, NULL);

Index: src/sys/fs/udf/udf_subr.c
diff -u src/sys/fs/udf/udf_subr.c:1.124 src/sys/fs/udf/udf_subr.c:1.124.2.1
--- src/sys/fs/udf/udf_subr.c:1.124	Sun Mar 23 09:34:42 2014
+++ src/sys/fs/udf/udf_subr.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_subr.c,v 1.124 2014/03/23 09:34:42 christos Exp $ */
+/* $NetBSD: udf_subr.c,v 1.124.2.1 2014/08/10 06:55:54 tls Exp $ */
 
 /*
  * Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -29,7 +29,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.124 2014/03/23 09:34:42 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.124.2.1 2014/08/10 06:55:54 tls Exp $");
 #endif /* not lint */
 
 
@@ -1808,8 +1808,8 @@ udf_write_metadata_partition_spacetable(
 	dscr = (union dscrptr *) ump->metadata_unalloc_dscr;
 	new_inflen = udf_tagsize(dscr, 1);
 
-	DPRINTF(VOLUMES, ("Resize and write out metadata space bitmap from "
-		"%"PRIu64" to %"PRIu64" bytes\n", inflen, new_inflen));
+	DPRINTF(VOLUMES, ("Resize and write out metadata space bitmap "
+		" for %"PRIu64" bytes\n", new_inflen));
 
 	error = udf_resize_node(bitmap_node, new_inflen, &dummy);
 	if (error)

Index: src/sys/fs/udf/udf_vfsops.c
diff -u src/sys/fs/udf/udf_vfsops.c:1.66 src/sys/fs/udf/udf_vfsops.c:1.66.2.1
--- src/sys/fs/udf/udf_vfsops.c:1.66	Sun Mar 23 15:21:16 2014
+++ src/sys/fs/udf/udf_vfsops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_vfsops.c,v 1.66 2014/03/23 15:21:16 hannken Exp $ */
+/* $NetBSD: udf_vfsops.c,v 1.66.2.1 2014/08/10 06:55:54 tls Exp $ */
 
 /*
  * Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.66 2014/03/23 15:21:16 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.66.2.1 2014/08/10 06:55:54 tls Exp $");
 #endif /* not lint */
 
 
@@ -316,6 +316,8 @@ udf_mount(struct mount *mp, const char *
 
 	DPRINTF(CALL, ("udf_mount called\n"));
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 

Index: src/sys/fs/udf/udf_vnops.c
diff -u src/sys/fs/udf/udf_vnops.c:1.91 src/sys/fs/udf/udf_vnops.c:1.91.2.1
--- src/sys/fs/udf/udf_vnops.c:1.91	Sun Mar 23 09:34:42 2014
+++ src/sys/fs/udf/udf_vnops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_vnops.c,v 1.91 2014/03/23 09:34:42 christos Exp $ */
+/* $NetBSD: udf_vnops.c,v 1.91.2.1 2014/08/10 06:55:54 tls Exp $ */
 
 /*
  * Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.91 2014/03/23 09:34:42 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.91.2.1 2014/08/10 06:55:54 tls Exp $");
 #endif /* not lint */
 
 
@@ -67,6 +67,9 @@ __KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,
 
 #define VTOI(vnode) ((struct udf_node *) (vnode)->v_data)
 
+/* forward declarations */
+static int udf_do_readlink(struct udf_node *udf_node, uint64_t filesize,
+	uint8_t *targetbuf, int *length);
 
 /* externs */
 extern int prtactive;
@@ -865,10 +868,10 @@ udf_getattr(void *v)
 	uint64_t filesize, blkssize;
 	uint32_t nlink;
 	uint32_t offset, a_l;
-	uint8_t *filedata;
+	uint8_t *filedata, *targetbuf;
 	uid_t uid;
 	gid_t gid;
-	int error;
+	int length, error;
 
 	DPRINTF(CALL, ("udf_getattr called\n"));
 
@@ -939,6 +942,22 @@ udf_getattr(void *v)
 	if (vap->va_type == VDIR)
 		vap->va_nlink++;
 
+	/*
+	 * BUG-ALERT: Posix requires the va_size to be pathlength for symbolic
+	 * links.
+	 */
+	if (vap->va_type == VLNK) {
+		/* claim temporary buffers for translation */
+		targetbuf = malloc(PATH_MAX+1, M_UDFTEMP, M_WAITOK);
+		error = udf_do_readlink(udf_node, filesize, targetbuf, &length);
+		if (!error) {
+			vap->va_size = length;
+			KASSERT(length == strlen(targetbuf));
+		}
+		free(targetbuf, M_UDFTEMP);
+		/* XXX return error? */
+	}
+
 	/* access times */
 	udf_timestamp_to_timespec(ump, atime,    &vap->va_atime);
 	udf_timestamp_to_timespec(ump, mtime,    &vap->va_mtime);
@@ -1020,8 +1039,6 @@ udf_chown(struct vnode *vp, uid_t new_ui
 
 	/* mark node changed */
 	udf_node->i_flags |= IN_CHANGE;
-	if (vp->v_mount->mnt_flag & MNT_RELATIME)
-		udf_node->i_flags |= IN_ACCESS;
 
 	return 0;
 }
@@ -1059,8 +1076,6 @@ udf_chmod(struct vnode *vp, mode_t mode,
 
 	/* mark node changed */
 	udf_node->i_flags |= IN_CHANGE;
-	if (vp->v_mount->mnt_flag & MNT_RELATIME)
-		udf_node->i_flags |= IN_ACCESS;
 
 	return 0;
 }
@@ -1734,49 +1749,30 @@ udf_symlink(void *v)
 
 /* --------------------------------------------------------------------- */
 
-int
-udf_readlink(void *v)
+static int
+udf_do_readlink(struct udf_node *udf_node, uint64_t filesize,
+	uint8_t *targetbuf, int *length)
 {
-	struct vop_readlink_args /* {
-		struct vnode *a_vp;
-		struct uio *a_uio;
-		kauth_cred_t a_cred;
-	} */ *ap = v;
-	struct vnode *vp = ap->a_vp;
-	struct uio *uio = ap->a_uio;
-	kauth_cred_t cred = ap->a_cred;
-	struct udf_node *udf_node;
 	struct pathcomp pathcomp;
-	struct vattr vattr;
-	uint8_t *pathbuf, *targetbuf, *tmpname;
+	uint8_t *pathbuf, *tmpname;
 	uint8_t *pathpos, *targetpos;
 	char *mntonname;
 	int pathlen, targetlen, namelen, mntonnamelen, len, l_ci;
 	int first, error;
 
-	DPRINTF(CALL, ("udf_readlink called\n"));
-
-	udf_node = VTOI(vp);
-	error = VOP_GETATTR(vp, &vattr, cred);
-	if (error)
-		return error;
-
-	/* claim temporary buffers for translation */
 	pathbuf   = malloc(UDF_SYMLINKBUFLEN, M_UDFTEMP, M_WAITOK);
-	targetbuf = malloc(PATH_MAX+1, M_UDFTEMP, M_WAITOK);
 	tmpname   = malloc(PATH_MAX+1, M_UDFTEMP, M_WAITOK);
 	memset(pathbuf, 0, UDF_SYMLINKBUFLEN);
 	memset(targetbuf, 0, PATH_MAX);
 
 	/* read contents of file in our temporary buffer */
 	error = vn_rdwr(UIO_READ, udf_node->vnode,
-		pathbuf, vattr.va_size, 0,
+		pathbuf, filesize, 0,
 		UIO_SYSSPACE, IO_NODELOCKED | IO_ALTSEMANTICS,
 		FSCRED, NULL, NULL);
 	if (error) {
 		/* failed to read in symlink contents */
 		free(pathbuf, M_UDFTEMP);
-		free(targetbuf, M_UDFTEMP);
 		free(tmpname, M_UDFTEMP);
 		return error;
 	}
@@ -1791,7 +1787,7 @@ udf_readlink(void *v)
 
 	error = 0;
 	first = 1;
-	while (vattr.va_size - pathlen >= UDF_PATH_COMP_SIZE) {
+	while (filesize - pathlen >= UDF_PATH_COMP_SIZE) {
 		len = UDF_PATH_COMP_SIZE;
 		memcpy(&pathcomp, pathpos, len);
 		l_ci = pathcomp.l_ci;
@@ -1812,7 +1808,7 @@ udf_readlink(void *v)
 			}
 			memcpy(targetpos, mntonname, mntonnamelen);
 			targetpos += mntonnamelen; targetlen -= mntonnamelen;
-			if (vattr.va_size-pathlen > UDF_PATH_COMP_SIZE+l_ci) {
+			if (filesize-pathlen > UDF_PATH_COMP_SIZE+l_ci) {
 				/* more follows, so must be directory */
 				*targetpos++ = '/'; targetlen--;
 			}
@@ -1853,7 +1849,7 @@ udf_readlink(void *v)
 			}
 			memcpy(targetpos, tmpname, namelen);
 			targetpos += namelen; targetlen -= namelen;
-			if (vattr.va_size-pathlen > UDF_PATH_COMP_SIZE+l_ci) {
+			if (filesize-pathlen > UDF_PATH_COMP_SIZE+l_ci) {
 				/* more follows, so must be directory */
 				*targetpos++ = '/'; targetlen--;
 			}
@@ -1870,17 +1866,54 @@ udf_readlink(void *v)
 
 	}
 	/* all processed? */
-	if (vattr.va_size - pathlen > 0)
+	if (filesize - pathlen > 0)
 		error = EINVAL;
 
+	free(pathbuf, M_UDFTEMP);
+	free(tmpname, M_UDFTEMP);
+
+	*length = PATH_MAX - targetlen;
+	return error;
+}
+
+
+int
+udf_readlink(void *v)
+{
+	struct vop_readlink_args /* {
+		struct vnode *a_vp;
+		struct uio *a_uio;
+		kauth_cred_t a_cred;
+	} */ *ap = v;
+	struct vnode *vp = ap->a_vp;
+	struct udf_node *udf_node = VTOI(vp);
+	struct file_entry    *fe  = udf_node->fe;
+	struct extfile_entry *efe = udf_node->efe;
+	struct uio *uio = ap->a_uio;
+	uint64_t filesize;
+	uint8_t *targetbuf;
+	int length;
+	int error;
+
+	DPRINTF(CALL, ("udf_readlink called\n"));
+
+	if (fe) {
+		filesize = udf_rw64(fe->inf_len);
+	} else {
+		assert(udf_node->efe);
+		filesize = udf_rw64(efe->inf_len);
+	}
+
+	/* claim temporary buffers for translation */
+	targetbuf = malloc(PATH_MAX+1, M_UDFTEMP, M_WAITOK);
+
+	error = udf_do_readlink(udf_node, filesize, targetbuf, &length);
+
 	/* uiomove() to destination */
 	if (!error)
-		uiomove(targetbuf, PATH_MAX - targetlen, uio);
+		uiomove(targetbuf, length, uio);
 
-	free(pathbuf, M_UDFTEMP);
 	free(targetbuf, M_UDFTEMP);
-	free(tmpname, M_UDFTEMP);
-
 	return error;
 }
 
@@ -2143,6 +2176,8 @@ const struct vnodeopv_entry_desc udf_vno
 	{ &vop_setattr_desc, udf_setattr },	/* setattr */	/* TODO chflags */
 	{ &vop_read_desc, udf_read },		/* read */
 	{ &vop_write_desc, udf_write },		/* write */	/* WRITE */
+	{ &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */
 	{ &vop_fcntl_desc, genfs_fcntl },	/* fcntl */	/* TODO? */
 	{ &vop_ioctl_desc, genfs_enoioctl },	/* ioctl */	/* TODO? */
 	{ &vop_poll_desc, genfs_poll },		/* poll */	/* TODO/OK? */

Index: src/sys/fs/union/union_subr.c
diff -u src/sys/fs/union/union_subr.c:1.63 src/sys/fs/union/union_subr.c:1.63.2.1
--- src/sys/fs/union/union_subr.c:1.63	Sun Feb 16 09:50:25 2014
+++ src/sys/fs/union/union_subr.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: union_subr.c,v 1.63 2014/02/16 09:50:25 hannken Exp $	*/
+/*	$NetBSD: union_subr.c,v 1.63.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 1994
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.63 2014/02/16 09:50:25 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.63.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -811,6 +811,7 @@ union_mkshadow(struct union_mount *um, s
 	va.va_type = VDIR;
 	va.va_mode = um->um_cmode;
 
+	KASSERT(*vpp == NULL);
 	error = VOP_MKDIR(dvp, vpp, &cn, &va);
 	VOP_UNLOCK(dvp);
 	PNBUF_PUT(pnbuf);
@@ -889,11 +890,15 @@ union_vn_create(struct vnode **vpp, stru
 	vap->va_type = VREG;
 	vap->va_mode = cmode;
 	vref(un->un_dirvp);
+	vp = NULL;
 	error = VOP_CREATE(un->un_dirvp, &vp, &cn, vap);
-	if (error)
+	if (error) {
+		VOP_UNLOCK(un->un_dirvp);
 		return error;
+	}
 
 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+	VOP_UNLOCK(un->un_dirvp);
 	error = VOP_OPEN(vp, fmode, cred);
 	if (error) {
 		vput(vp);

Index: src/sys/fs/union/union_vfsops.c
diff -u src/sys/fs/union/union_vfsops.c:1.71 src/sys/fs/union/union_vfsops.c:1.71.2.1
--- src/sys/fs/union/union_vfsops.c:1.71	Sun Mar 23 15:21:16 2014
+++ src/sys/fs/union/union_vfsops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: union_vfsops.c,v 1.71 2014/03/23 15:21:16 hannken Exp $	*/
+/*	$NetBSD: union_vfsops.c,v 1.71.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 1994 The Regents of the University of California.
@@ -77,7 +77,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_vfsops.c,v 1.71 2014/03/23 15:21:16 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_vfsops.c,v 1.71.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -119,6 +119,8 @@ union_mount(struct mount *mp, const char
 	int len;
 	size_t size;
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 

Index: src/sys/fs/union/union_vnops.c
diff -u src/sys/fs/union/union_vnops.c:1.59 src/sys/fs/union/union_vnops.c:1.59.2.1
--- src/sys/fs/union/union_vnops.c:1.59	Mon Mar 24 13:42:40 2014
+++ src/sys/fs/union/union_vnops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: union_vnops.c,v 1.59 2014/03/24 13:42:40 hannken Exp $	*/
+/*	$NetBSD: union_vnops.c,v 1.59.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993, 1994, 1995
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.59 2014/03/24 13:42:40 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.59.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -155,6 +155,8 @@ const struct vnodeopv_entry_desc union_v
 	{ &vop_setattr_desc, union_setattr },		/* setattr */
 	{ &vop_read_desc, union_read },			/* read */
 	{ &vop_write_desc, union_write },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_ioctl_desc, union_ioctl },		/* ioctl */
 	{ &vop_poll_desc, union_poll },			/* select */
 	{ &vop_revoke_desc, union_revoke },		/* revoke */
@@ -517,6 +519,8 @@ union_create(void *v)
 		struct mount *mp;
 
 		mp = ap->a_dvp->v_mount;
+
+		vp = NULL;
 		error = VOP_CREATE(dvp, &vp, cnp, ap->a_vap);
 		if (error)
 			return (error);
@@ -1383,6 +1387,7 @@ union_mkdir(void *v)
 		int error;
 		struct vnode *vp;
 
+		vp = NULL;
 		error = VOP_MKDIR(dvp, &vp, cnp, ap->a_vap);
 		if (error) {
 			vrele(ap->a_dvp);

Index: src/sys/fs/unionfs/unionfs_vfsops.c
diff -u src/sys/fs/unionfs/unionfs_vfsops.c:1.12 src/sys/fs/unionfs/unionfs_vfsops.c:1.12.2.1
--- src/sys/fs/unionfs/unionfs_vfsops.c:1.12	Sun Mar 23 15:21:16 2014
+++ src/sys/fs/unionfs/unionfs_vfsops.c	Sun Aug 10 06:55:54 2014
@@ -89,6 +89,8 @@ unionfs_mount(struct mount *mp, const ch
 	const char	*cp;
 	char		*xp;
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof *args)
 		return EINVAL;
 

Index: src/sys/fs/unionfs/unionfs_vnops.c
diff -u src/sys/fs/unionfs/unionfs_vnops.c:1.7 src/sys/fs/unionfs/unionfs_vnops.c:1.7.10.1
--- src/sys/fs/unionfs/unionfs_vnops.c:1.7	Mon Nov  5 17:27:39 2012
+++ src/sys/fs/unionfs/unionfs_vnops.c	Sun Aug 10 06:55:54 2014
@@ -1820,6 +1820,8 @@ const struct vnodeopv_entry_desc unionfs
 	{ &vop_setattr_desc, unionfs_setattr },		/* setattr */
 	{ &vop_read_desc, unionfs_read },		/* read */
 	{ &vop_write_desc, unionfs_write },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_ioctl_desc, unionfs_ioctl },		/* ioctl */
 	{ &vop_poll_desc, unionfs_poll },		/* select */
 	{ &vop_revoke_desc, unionfs_revoke },		/* revoke */

Index: src/sys/fs/v7fs/v7fs_extern.c
diff -u src/sys/fs/v7fs/v7fs_extern.c:1.2 src/sys/fs/v7fs/v7fs_extern.c:1.2.2.1
--- src/sys/fs/v7fs/v7fs_extern.c:1.2	Sun Mar 23 15:21:16 2014
+++ src/sys/fs/v7fs/v7fs_extern.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: v7fs_extern.c,v 1.2 2014/03/23 15:21:16 hannken Exp $	*/
+/*	$NetBSD: v7fs_extern.c,v 1.2.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*-
  * Copyright (c) 2004, 2011 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: v7fs_extern.c,v 1.2 2014/03/23 15:21:16 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: v7fs_extern.c,v 1.2.2.1 2014/08/10 06:55:54 tls Exp $");
 
 #if defined _KERNEL_OPT
 #include "opt_v7fs.h"
@@ -65,6 +65,8 @@ const struct vnodeopv_entry_desc v7fs_vn
 	{ &vop_setattr_desc, v7fs_setattr },		/* setattr */
 	{ &vop_read_desc, v7fs_read },			/* read */
 	{ &vop_write_desc, v7fs_write },		/* write */
+	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
+	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
 	{ &vop_fcntl_desc, genfs_fcntl },		/* fcntl */
 	{ &vop_ioctl_desc, genfs_enoioctl },		/* ioctl */
 	{ &vop_poll_desc, genfs_poll },			/* poll */
@@ -112,6 +114,8 @@ const struct vnodeopv_entry_desc v7fs_sp
 	{ &vop_setattr_desc, v7fs_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_ioctl_desc, spec_ioctl },		/* ioctl */
 	{ &vop_fcntl_desc, genfs_fcntl },		/* fcntl */
 	{ &vop_poll_desc, spec_poll },			/* poll */
@@ -158,6 +162,8 @@ const struct vnodeopv_entry_desc v7fs_fi
 	{ &vop_setattr_desc, v7fs_setattr },		/* setattr */
 	{ &vop_read_desc, vn_fifo_bypass },		/* read */
 	{ &vop_write_desc, vn_fifo_bypass },		/* write */
+	{ &vop_fallocate_desc, vn_fifo_bypass },	/* fallocate */
+	{ &vop_fdiscard_desc, vn_fifo_bypass },		/* fdiscard */
 	{ &vop_ioctl_desc, vn_fifo_bypass },		/* ioctl */
 	{ &vop_fcntl_desc, genfs_fcntl },		/* fcntl */
 	{ &vop_poll_desc, vn_fifo_bypass },		/* poll */

Index: src/sys/fs/v7fs/v7fs_vfsops.c
diff -u src/sys/fs/v7fs/v7fs_vfsops.c:1.9 src/sys/fs/v7fs/v7fs_vfsops.c:1.9.2.1
--- src/sys/fs/v7fs/v7fs_vfsops.c:1.9	Sat Nov 23 13:35:36 2013
+++ src/sys/fs/v7fs/v7fs_vfsops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: v7fs_vfsops.c,v 1.9 2013/11/23 13:35:36 christos Exp $	*/
+/*	$NetBSD: v7fs_vfsops.c,v 1.9.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*-
  * Copyright (c) 2004, 2011 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: v7fs_vfsops.c,v 1.9 2013/11/23 13:35:36 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: v7fs_vfsops.c,v 1.9.2.1 2014/08/10 06:55:54 tls Exp $");
 #if defined _KERNEL_OPT
 #include "opt_v7fs.h"
 #endif
@@ -88,6 +88,8 @@ v7fs_mount(struct mount *mp, const char 
 
 	DPRINTF("mnt_flag=%x %s\n", mp->mnt_flag, update ? "update" : "");
 
+	if (args == NULL)
+		return EINVAL;
 	if (*data_len < sizeof(*args))
 		return EINVAL;
 

Index: src/sys/fs/v7fs/v7fs_vnops.c
diff -u src/sys/fs/v7fs/v7fs_vnops.c:1.16 src/sys/fs/v7fs/v7fs_vnops.c:1.16.2.1
--- src/sys/fs/v7fs/v7fs_vnops.c:1.16	Fri Feb  7 15:29:22 2014
+++ src/sys/fs/v7fs/v7fs_vnops.c	Sun Aug 10 06:55:54 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: v7fs_vnops.c,v 1.16 2014/02/07 15:29:22 hannken Exp $	*/
+/*	$NetBSD: v7fs_vnops.c,v 1.16.2.1 2014/08/10 06:55:54 tls Exp $	*/
 
 /*-
  * Copyright (c) 2004, 2011 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: v7fs_vnops.c,v 1.16 2014/02/07 15:29:22 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: v7fs_vnops.c,v 1.16.2.1 2014/08/10 06:55:54 tls Exp $");
 #if defined _KERNEL_OPT
 #include "opt_v7fs.h"
 #endif
@@ -587,7 +587,7 @@ v7fs_read(void *v)
 	}
 	v7node->update_atime = true;
 
-	return  error;
+	return error;
 }
 
 int

Reply via email to