Module Name:    src
Committed By:   hannken
Date:           Mon Jun 16 09:55:49 UTC 2014

Modified Files:
        src/sys/fs/cd9660: cd9660_lookup.c cd9660_node.c cd9660_node.h
            cd9660_vfsops.c

Log Message:
Change cd9660 from hashlist to vcache.


To generate a diff of this commit:
cvs rdiff -u -r1.28 -r1.29 src/sys/fs/cd9660/cd9660_lookup.c
cvs rdiff -u -r1.32 -r1.33 src/sys/fs/cd9660/cd9660_node.c
cvs rdiff -u -r1.15 -r1.16 src/sys/fs/cd9660/cd9660_node.h
cvs rdiff -u -r1.86 -r1.87 src/sys/fs/cd9660/cd9660_vfsops.c

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

Modified files:

Index: src/sys/fs/cd9660/cd9660_lookup.c
diff -u src/sys/fs/cd9660/cd9660_lookup.c:1.28 src/sys/fs/cd9660/cd9660_lookup.c:1.29
--- src/sys/fs/cd9660/cd9660_lookup.c:1.28	Sat Jun 14 07:39:28 2014
+++ src/sys/fs/cd9660/cd9660_lookup.c	Mon Jun 16 09:55:49 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_lookup.c,v 1.28 2014/06/14 07:39:28 hannken Exp $	*/
+/*	$NetBSD: cd9660_lookup.c,v 1.29 2014/06/16 09:55:49 hannken Exp $	*/
 
 /*-
  * Copyright (c) 1989, 1993, 1994
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cd9660_lookup.c,v 1.28 2014/06/14 07:39:28 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cd9660_lookup.c,v 1.29 2014/06/16 09:55:49 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/namei.h>
@@ -107,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;
@@ -342,6 +341,7 @@ notfound:
 found:
 	if (numdirpasses == 2)
 		namecache_count_pass2();
+	brelse(bp, 0);
 
 	/*
 	 * Found component in pathname.
@@ -351,44 +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);
-		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);
+		error = vcache_get(vdp->v_mount,
+		    &dp->i_ino, sizeof(dp->i_ino), &tdp);
 		if (error)
 			return (error);
 		*vpp = tdp;
@@ -399,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;
 }
 

Index: src/sys/fs/cd9660/cd9660_node.c
diff -u src/sys/fs/cd9660/cd9660_node.c:1.32 src/sys/fs/cd9660/cd9660_node.c:1.33
--- src/sys/fs/cd9660/cd9660_node.c:1.32	Sat Jun 14 07:39:28 2014
+++ src/sys/fs/cd9660/cd9660_node.c	Mon Jun 16 09:55:49 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_node.c,v 1.32 2014/06/14 07:39:28 hannken Exp $	*/
+/*	$NetBSD: cd9660_node.c,v 1.33 2014/06/16 09:55:49 hannken Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1994
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cd9660_node.c,v 1.32 2014/06/14 07:39:28 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cd9660_node.c,v 1.33 2014/06/16 09:55:49 hannken 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,9 +137,9 @@ 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.
 	 */
@@ -438,7 +340,7 @@ isodirino(struct iso_directory_record *i
 
 	/*
 	 * Note there is an inverse calculation in
-	 * cd9660_vfsops.c:cd9660_vget_internal():
+	 * 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()

Index: src/sys/fs/cd9660/cd9660_node.h
diff -u src/sys/fs/cd9660/cd9660_node.h:1.15 src/sys/fs/cd9660/cd9660_node.h:1.16
--- src/sys/fs/cd9660/cd9660_node.h:1.15	Sat Jun 14 07:39:28 2014
+++ src/sys/fs/cd9660/cd9660_node.h	Mon Jun 16 09:55:49 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_node.h,v 1.15 2014/06/14 07:39:28 hannken Exp $	*/
+/*	$NetBSD: cd9660_node.h,v 1.16 2014/06/16 09:55:49 hannken 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,14 +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 **);
-
-extern kmutex_t cd9660_hashlock;
 
 #endif /* _KERNEL */
 #endif /* _ISOFS_CD9660_CD9660_NODE_H_ */

Index: src/sys/fs/cd9660/cd9660_vfsops.c
diff -u src/sys/fs/cd9660/cd9660_vfsops.c:1.86 src/sys/fs/cd9660/cd9660_vfsops.c:1.87
--- src/sys/fs/cd9660/cd9660_vfsops.c:1.86	Sat Jun 14 07:39:28 2014
+++ src/sys/fs/cd9660/cd9660_vfsops.c	Mon Jun 16 09:55:49 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_vfsops.c,v 1.86 2014/06/14 07:39:28 hannken Exp $	*/
+/*	$NetBSD: cd9660_vfsops.c,v 1.87 2014/06/16 09:55:49 hannken Exp $	*/
 
 /*-
  * Copyright (c) 1994
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cd9660_vfsops.c,v 1.86 2014/06/14 07:39:28 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cd9660_vfsops.c,v 1.87 2014/06/16 09:55:49 hannken 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,
@@ -677,77 +678,57 @@ cd9660_fhtovp(struct mount *mp, struct f
 int
 cd9660_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
 {
+	int error;
 
-	return cd9660_vget_internal(mp, ino, vpp);
+	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)
+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);
 
 	lbn = cd9660_lblkno(imp, ino);
 	if (lbn >= imp->volume_space_size) {
-		vput(vp);
+		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);
+		pool_put(&cd9660_node_pool, ip);
 		printf("fhtovp: crosses block boundary %d\n",
 		    off + ISO_DIRECTORY_RECORD_SIZE);
 		return (ESTALE);
@@ -757,14 +738,14 @@ cd9660_vget_internal(struct mount *mp, i
 		      lbn << (imp->im_bshift - DEV_BSHIFT),
 		      imp->logical_block_size, NOCRED, 0, &bp);
 	if (error) {
-		vput(vp);
+		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);
+		pool_put(&cd9660_node_pool, ip);
 		if (bp != 0)
 			brelse(bp, 0);
 		printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
@@ -776,6 +757,7 @@ cd9660_vget_internal(struct mount *mp, i
 #if 0
 	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);
 		printf("fhtovp: file start miss %d vs %d\n",
@@ -789,10 +771,14 @@ cd9660_vget_internal(struct mount *mp, i
 	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 */
 	    {
@@ -853,8 +839,8 @@ cd9660_vget_internal(struct mount *mp, i
 	 * XXX need generation number?
 	 */
 
-	*vpp = vp;
-	return (0);
+	*new_key = &ip->i_number;
+	return 0;
 }
 
 /*

Reply via email to