diff --git a/sys/fs/cd9660/cd9660_node.c b/sys/fs/cd9660/cd9660_node.c index f42945d6eb02..ed431af4bd61 100644 --- a/sys/fs/cd9660/cd9660_node.c +++ b/sys/fs/cd9660/cd9660_node.c @@ -1,4 +1,4 @@ -/* $NetBSD: cd9660_node.c,v 1.18 2007/11/26 19:01:42 pooka Exp $ */ +/* $NetBSD: cd9660_node.c,v 1.19 2007/12/08 14:41:11 ad Exp $ */ /*- * Copyright (c) 1982, 1986, 1989, 1994 @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: cd9660_node.c,v 1.18 2007/11/26 19:01:42 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cd9660_node.c,v 1.19 2007/12/08 14:41:11 ad Exp $"); #include #include @@ -64,13 +64,8 @@ __KERNEL_RCSID(0, "$NetBSD: cd9660_node.c,v 1.18 2007/11/26 19:01:42 pooka Exp $ LIST_HEAD(ihashhead, iso_node) *isohashtbl; u_long isohash; #define INOHASH(device, inum) (((device) + ((inum)>>12)) & isohash) -struct simplelock cd9660_ihash_slock; - -#ifdef ISODEVMAP -LIST_HEAD(idvhashhead, iso_dnode) *idvhashtbl; -u_long idvhash; -#define DNOHASH(device, inum) (((device) + ((inum)>>12)) & idvhash) -#endif +kmutex_t cd9660_ihash_lock; +kmutex_t cd9660_hashlock; extern int prtactive; /* 1 => print out reclaim of active vnodes */ @@ -90,11 +85,8 @@ cd9660_init() "cd9660nopl", &pool_allocator_nointr, IPL_NONE); isohashtbl = hashinit(desiredvnodes, HASH_LIST, M_ISOFSMNT, M_WAITOK, &isohash); - simple_lock_init(&cd9660_ihash_slock); -#ifdef ISODEVMAP - idvhashtbl = hashinit(desiredvnodes / 8, HASH_LIST, M_ISOFSMNT, - M_WAITOK, &idvhash); -#endif + mutex_init(&cd9660_ihash_lock, MUTEX_DEFAULT, IPL_NONE); + mutex_init(&cd9660_hashlock, MUTEX_DEFAULT, IPL_NONE); } /* @@ -107,38 +99,16 @@ cd9660_reinit() struct iso_node *ip; struct ihashhead *oldhash1, *hash1; u_long oldmask1, mask1, val; -#ifdef ISODEVMAP - struct iso_dnode *dp; - struct idvhashhead *oldhash2, *hash2; - u_long oldmask2, mask2; -#endif u_int i; hash1 = hashinit(desiredvnodes, HASH_LIST, M_ISOFSMNT, M_WAITOK, &mask1); -#ifdef ISODEVMAP - hash2 = hashinit(desiredvnodes / 8, HASH_LIST, M_ISOFSMNT, M_WAITOK, - &mask2); -#endif - simple_lock(&cd9660_ihash_slock); + mutex_enter(&cd9660_ihash_lock); oldhash1 = isohashtbl; oldmask1 = isohash; isohashtbl = hash1; isohash = mask1; -#ifdef ISODEVMAP - oldhash2 = idvhashtbl; - oldmask2 = idvhash; - idvhashtbl = hash2; - idvhash = mask2; - for (i = 0; i <= oldmask2; i++) { - while ((dp = LIST_FIRST(&oldhash2[i])) != NULL) { - LIST_REMOVE(dp, d_hash); - val = DNOHASH(dp->i_dev, dp->i_number); - LIST_INSERT_HEAD(&hash2[val], dp, d_hash); - } - } -#endif for (i = 0; i <= oldmask1; i++) { while ((ip = LIST_FIRST(&oldhash1[i])) != NULL) { LIST_REMOVE(ip, i_hash); @@ -146,11 +116,8 @@ cd9660_reinit() LIST_INSERT_HEAD(&hash1[val], ip, i_hash); } } - simple_unlock(&cd9660_ihash_slock); + mutex_exit(&cd9660_ihash_lock); hashdone(oldhash1, M_ISOFSMNT); -#ifdef ISODEVMAP - hashdone(oldhash2, M_ISOFSMNT); -#endif } /* @@ -160,87 +127,42 @@ void cd9660_done() { hashdone(isohashtbl, M_ISOFSMNT); -#ifdef ISODEVMAP - hashdone(idvhashtbl, M_ISOFSMNT); -#endif pool_destroy(&cd9660_node_pool); + mutex_destroy(&cd9660_ihash_lock); + mutex_destroy(&cd9660_hashlock); malloc_type_detach(M_ISOFSMNT); } -#ifdef ISODEVMAP -/* - * Enter a new node into the device hash list - */ -struct iso_dnode * -iso_dmap(device, inum, create) - dev_t device; - ino_t inum; - int create; -{ - struct iso_dnode *dp; - struct idvhashhead *hp; - - hp = &idvhashtbl[DNOHASH(device, inum)]; - LIST_FOREACH(dp, hp, d_hash) { - if (inum == dp->i_number && device == dp->i_dev) - return (dp); - } - - if (!create) - return (NULL); - - MALLOC(dp, struct iso_dnode *, sizeof(struct iso_dnode), M_CACHE, - M_WAITOK); - dp->i_dev = device; - dp->i_number = inum; - LIST_INSERT_HEAD(hp, dp, d_hash); - return (dp); -} - -void -iso_dunmap(device) - dev_t device; -{ - struct idvhashhead *dpp; - struct iso_dnode *dp, *dq; - - for (dpp = idvhashtbl; dpp <= idvhashtbl + idvhash; dpp++) { - for (dp = LIST_FIRST(dpp); dp != NULL; dp = dq) { - dq = LIST_NEXT(dp, d_hash); - if (device == dp->i_dev) { - LIST_REMOVE(dp, d_hash); - FREE(dp, M_CACHE); - } - } - } -} -#endif - /* * 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, inum) +cd9660_ihashget(dev, inum, flags) dev_t dev; ino_t inum; + int flags; { struct iso_node *ip; struct vnode *vp; loop: - simple_lock(&cd9660_ihash_slock); + 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); - simple_lock(&vp->v_interlock); - simple_unlock(&cd9660_ihash_slock); - if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) - goto loop; + if (flags == 0) { + mutex_exit(&cd9660_ihash_lock); + } else { + simple_lock(&vp->v_interlock); + mutex_exit(&cd9660_ihash_lock); + if (vget(vp, flags | LK_INTERLOCK)) + goto loop; + } return (vp); } } - simple_unlock(&cd9660_ihash_slock); + mutex_exit(&cd9660_ihash_lock); return (NULL); } @@ -255,10 +177,12 @@ cd9660_ihashins(ip) { struct ihashhead *ipp; - simple_lock(&cd9660_ihash_slock); + 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); - simple_unlock(&cd9660_ihash_slock); + mutex_exit(&cd9660_ihash_lock); lockmgr(&ip->i_vnode->v_lock, LK_EXCLUSIVE, &ip->i_vnode->v_interlock); } @@ -270,9 +194,9 @@ void cd9660_ihashrem(ip) struct iso_node *ip; { - simple_lock(&cd9660_ihash_slock); + mutex_enter(&cd9660_ihash_lock); LIST_REMOVE(ip, i_hash); - simple_unlock(&cd9660_ihash_slock); + mutex_exit(&cd9660_ihash_lock); } /* diff --git a/sys/fs/cd9660/cd9660_node.h b/sys/fs/cd9660/cd9660_node.h index f772c35e17f4..0f20e92b18df 100644 --- a/sys/fs/cd9660/cd9660_node.h +++ b/sys/fs/cd9660/cd9660_node.h @@ -1,4 +1,4 @@ -/* $NetBSD: cd9660_node.h,v 1.12 2005/12/03 22:16:16 christos Exp $ */ +/* $NetBSD: cd9660_node.h,v 1.13 2007/12/08 14:41:11 ad Exp $ */ /*- * Copyright (c) 1994 @@ -61,18 +61,6 @@ typedef struct { dev_t iso_rdev; /* Major/Minor number for special */ } ISO_RRIP_INODE; -#ifdef ISODEVMAP -/* - * FOr device# (major,minor) translation table - */ -struct iso_dnode { - LIST_ENTRY(iso_dnode) d_hash; - dev_t i_dev; /* device where dnode resides */ - ino_t i_number; /* the identity of the inode */ - dev_t d_dev; /* device # for translation */ -}; -#endif - struct iso_node { struct genfs_node i_gnode; LIST_ENTRY(iso_node) i_hash; @@ -140,16 +128,15 @@ void cd9660_defattr(struct iso_directory_record *, 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); +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(u_char *, struct timespec *); int cd9660_tstamp_conv17(u_char *, struct timespec *); int cd9660_vget_internal(struct mount *, ino_t, struct vnode **, int, struct iso_directory_record *); -#ifdef ISODEVMAP -struct iso_dnode *iso_dmap(dev_t, ino_t, int); -void iso_dunmap(dev_t); -#endif + +extern kmutex_t cd9660_hashlock; + #endif /* _KERNEL */ #endif /* _ISOFS_CD9660_CD9660_NODE_H_ */ diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c index fc9b0498dde5..d2484cb72ec3 100644 --- a/sys/fs/cd9660/cd9660_vfsops.c +++ b/sys/fs/cd9660/cd9660_vfsops.c @@ -1,4 +1,4 @@ -/* $NetBSD: cd9660_vfsops.c,v 1.50 2007/11/26 19:01:42 pooka Exp $ */ +/* $NetBSD: cd9660_vfsops.c,v 1.51 2007/12/08 14:41:12 ad Exp $ */ /*- * Copyright (c) 1994 @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: cd9660_vfsops.c,v 1.50 2007/11/26 19:01:42 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cd9660_vfsops.c,v 1.51 2007/12/08 14:41:12 ad Exp $"); #if defined(_KERNEL_OPT) #include "opt_compat_netbsd.h" @@ -539,11 +539,6 @@ cd9660_unmount(mp, mntflags) isomp = VFSTOISOFS(mp); -#ifdef ISODEVMAP - if (isomp->iso_ftype == ISO_FTYPE_RRIP) - iso_dunmap(isomp->im_dev); -#endif - if (isomp->im_devvp->v_type != VBAD) isomp->im_devvp->v_specmountpoint = NULL; @@ -700,9 +695,6 @@ cd9660_vget_internal(mp, ino, vpp, relocated, isodir) { struct iso_mnt *imp; struct iso_node *ip; -#ifdef ISODEVMAP - struct iso_dnode *dp; -#endif struct buf *bp; struct vnode *vp, *nvp; dev_t dev; @@ -710,7 +702,9 @@ cd9660_vget_internal(mp, ino, vpp, relocated, isodir) imp = VFSTOISOFS(mp); dev = imp->im_dev; - if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP) + + retry: + if ((*vpp = cd9660_ihashget(dev, ino, LK_EXCLUSIVE)) != NULLVP) return (0); /* Allocate a new vnode/iso_node. */ @@ -719,11 +713,27 @@ cd9660_vget_internal(mp, ino, vpp, relocated, isodir) 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 @@ -732,6 +742,7 @@ cd9660_vget_internal(mp, ino, vpp, relocated, isodir) * disk portion of this inode to be read. */ cd9660_ihashins(ip); + mutex_exit(&cd9660_hashlock); if (isodir == 0) { int lbn, off; @@ -787,8 +798,6 @@ cd9660_vget_internal(mp, ino, vpp, relocated, isodir) } else bp = 0; - ip->i_mnt = imp; - ip->i_devvp = imp->im_devvp; VREF(ip->i_devvp); if (relocated) { @@ -851,10 +860,6 @@ cd9660_vget_internal(mp, ino, vpp, relocated, isodir) /* * if device, look at device number table for translation */ -#ifdef ISODEVMAP - if ((dp = iso_dmap(dev, ino, 0)) != NULL) - ip->inode.iso_rdev = dp->d_dev; -#endif vp->v_op = cd9660_specop_p; if ((nvp = checkalias(vp, ip->inode.iso_rdev, mp)) != NULL) { /* @@ -897,7 +902,6 @@ cd9660_vget_internal(mp, ino, vpp, relocated, isodir) * XXX need generation number? */ - genfs_node_init(vp, &cd9660_genfsops); *vpp = vp; return (0); } diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c index 281427057f60..3ca39c8a4285 100644 --- a/sys/fs/cd9660/cd9660_vnops.c +++ b/sys/fs/cd9660/cd9660_vnops.c @@ -1,4 +1,4 @@ -/* $NetBSD: cd9660_vnops.c,v 1.30 2007/11/26 19:01:43 pooka Exp $ */ +/* $NetBSD: cd9660_vnops.c,v 1.31 2007/12/08 14:41:12 ad Exp $ */ /*- * Copyright (c) 1994 @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: cd9660_vnops.c,v 1.30 2007/11/26 19:01:43 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cd9660_vnops.c,v 1.31 2007/12/08 14:41:12 ad Exp $"); #include #include @@ -84,63 +84,6 @@ struct isoreaddir { int iso_uiodir(struct isoreaddir *, struct dirent *, off_t); int iso_shipdir(struct isoreaddir *); -#if 0 -/* - * Mknod vnode call - * Actually remap the device number - */ -int -cd9660_mknod(ndp, vap, cred, p) - struct nameidata *ndp; - kauth_cred_t cred; - struct vattr *vap; - struct proc *p; -{ -#ifndef ISODEVMAP - PNBUF_PUT(ndp->ni_pnbuf); - vput(ndp->ni_dvp); - vput(ndp->ni_vp); - return (EINVAL); -#else - struct vnode *vp; - struct iso_node *ip; - struct iso_dnode *dp; - - vp = ndp->ni_vp; - ip = VTOI(vp); - - if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP - || vap->va_type != vp->v_type - || (vap->va_type != VCHR && vap->va_type != VBLK)) { - PNBUF_PUT(ndp->ni_pnbuf); - vput(ndp->ni_dvp); - vput(ndp->ni_vp); - return (EINVAL); - } - - dp = iso_dmap(ip->i_dev, ip->i_number, 1); - if (ip->inode.iso_rdev == vap->va_rdev || - vap->va_rdev == (dev_t)VNOVAL) { - /* same as the unmapped one, delete the mapping */ - LIST_REMOVE(dp, d_hash); - FREE(dp, M_CACHE); - } else - /* enter new mapping */ - dp->d_dev = vap->va_rdev; - - /* - * Remove inode so that it will be reloaded by iget and - * checked to see if it is an alias of an existing entry - * in the inode cache. - */ - vput(vp); - vp->v_type = VNON; - vgone(vp); - return (0); -#endif -} -#endif - /* * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. * The mode is shifted to select the owner/group/other fields. The