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