Merge locking changes + fixes from the vmlocking branch.

This commit is contained in:
ad 2007-12-08 14:41:11 +00:00
parent e1d841a734
commit 6a3b582fe3
4 changed files with 57 additions and 199 deletions

View File

@ -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 <sys/cdefs.h>
__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 <sys/param.h>
#include <sys/systm.h>
@ -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);
}
/*

View File

@ -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_ */

View File

@ -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 <sys/cdefs.h>
__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);
}

View File

@ -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 <sys/cdefs.h>
__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 <sys/param.h>
#include <sys/systm.h>
@ -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