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;
}
/*