summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2004-09-23 07:17:41 +0000
committerphk <phk@FreeBSD.org>2004-09-23 07:17:41 +0000
commit3947e54e89a67263df7cb82659d2a60b22e36d66 (patch)
tree7ba70387e941540c2b48f5f069c66f8c5b6d2f61 /sys
parenta5b75e6c3853ff22f0202d48d68a4748e5391d42 (diff)
downloadFreeBSD-src-3947e54e89a67263df7cb82659d2a60b22e36d66.zip
FreeBSD-src-3947e54e89a67263df7cb82659d2a60b22e36d66.tar.gz
Do not refcount the cdevsw, but rather maintain a cdev->si_threadcount
of the number of threads which are inside whatever is behind the cdevsw for this particular cdev. Make the device mutex visible through dev_lock() and dev_unlock(). We may want finer granularity later. Replace spechash_mtx use with dev_lock()/dev_unlock().
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/specfs/spec_vnops.c60
-rw-r--r--sys/kern/kern_conf.c53
-rw-r--r--sys/kern/vfs_bio.c16
-rw-r--r--sys/kern/vfs_subr.c41
-rw-r--r--sys/sys/conf.h6
5 files changed, 90 insertions, 86 deletions
diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c
index 5133496..f1f8075 100644
--- a/sys/fs/specfs/spec_vnops.c
+++ b/sys/fs/specfs/spec_vnops.c
@@ -188,8 +188,9 @@ spec_open(ap)
vp->v_vflag |= VV_ISTTY;
VOP_UNLOCK(vp, 0, td);
- dev_ref(dev);
- cdevsw_ref(dsw);
+ dev_lock();
+ dev->si_threadcount++;
+ dev_unlock();
if(!(dsw->d_flags & D_NEEDGIANT)) {
DROP_GIANT();
if (dsw->d_fdopen != NULL)
@@ -201,9 +202,9 @@ spec_open(ap)
error = dsw->d_fdopen(dev, ap->a_mode, td, ap->a_fdidx);
else
error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td);
- cdevsw_rel(dsw);
- if (error != 0)
- dev_rel(dev);
+ dev_lock();
+ dev->si_threadcount--;
+ dev_unlock();
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (error)
@@ -260,14 +261,18 @@ spec_read(ap)
VOP_UNLOCK(vp, 0, td);
KASSERT(dev->si_refcount > 0,
("specread() on un-referenced struct cdev *(%s)", devtoname(dev)));
- cdevsw_ref(dsw);
+ dev_lock();
+ dev->si_threadcount++;
+ dev_unlock();
if (!(dsw->d_flags & D_NEEDGIANT)) {
DROP_GIANT();
error = dsw->d_read(dev, uio, ap->a_ioflag);
PICKUP_GIANT();
} else
error = dsw->d_read(dev, uio, ap->a_ioflag);
- cdevsw_rel(dsw);
+ dev_lock();
+ dev->si_threadcount--;
+ dev_unlock();
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (uio->uio_resid != resid || (error == 0 && resid != 0))
vfs_timestamp(&dev->si_atime);
@@ -304,14 +309,18 @@ spec_write(ap)
VOP_UNLOCK(vp, 0, td);
KASSERT(dev->si_refcount > 0,
("spec_write() on un-referenced struct cdev *(%s)", devtoname(dev)));
- cdevsw_ref(dsw);
+ dev_lock();
+ dev->si_threadcount++;
+ dev_unlock();
if (!(dsw->d_flags & D_NEEDGIANT)) {
DROP_GIANT();
error = dsw->d_write(dev, uio, ap->a_ioflag);
PICKUP_GIANT();
} else
error = dsw->d_write(dev, uio, ap->a_ioflag);
- cdevsw_rel(dsw);
+ dev_lock();
+ dev->si_threadcount--;
+ dev_unlock();
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (uio->uio_resid != resid || (error == 0 && resid != 0)) {
vfs_timestamp(&dev->si_ctime);
@@ -343,7 +352,9 @@ spec_ioctl(ap)
dsw = devsw(dev);
KASSERT(dev->si_refcount > 0,
("spec_ioctl() on un-referenced struct cdev *(%s)", devtoname(dev)));
- cdevsw_ref(dsw);
+ dev_lock();
+ dev->si_threadcount++;
+ dev_unlock();
if (!(dsw->d_flags & D_NEEDGIANT)) {
DROP_GIANT();
error = dsw->d_ioctl(dev, ap->a_command,
@@ -352,7 +363,9 @@ spec_ioctl(ap)
} else
error = dsw->d_ioctl(dev, ap->a_command,
ap->a_data, ap->a_fflag, ap->a_td);
- cdevsw_rel(dsw);
+ dev_lock();
+ dev->si_threadcount--;
+ dev_unlock();
if (error == ENOIOCTL)
error = ENOTTY;
return (error);
@@ -376,14 +389,18 @@ spec_poll(ap)
dsw = devsw(dev);
KASSERT(dev->si_refcount > 0,
("spec_poll() on un-referenced struct cdev *(%s)", devtoname(dev)));
- cdevsw_ref(dsw);
+ dev_lock();
+ dev->si_threadcount++;
+ dev_unlock();
if (!(dsw->d_flags & D_NEEDGIANT)) {
/* XXX: not yet DROP_GIANT(); */
error = dsw->d_poll(dev, ap->a_events, ap->a_td);
/* XXX: not yet PICKUP_GIANT(); */
} else
error = dsw->d_poll(dev, ap->a_events, ap->a_td);
- cdevsw_rel(dsw);
+ dev_lock();
+ dev->si_threadcount--;
+ dev_unlock();
return(error);
}
@@ -403,14 +420,18 @@ spec_kqfilter(ap)
dsw = devsw(dev);
KASSERT(dev->si_refcount > 0,
("spec_kqfilter() on un-referenced struct cdev *(%s)", devtoname(dev)));
- cdevsw_ref(dsw);
+ dev_lock();
+ dev->si_threadcount++;
+ dev_unlock();
if (!(dsw->d_flags & D_NEEDGIANT)) {
DROP_GIANT();
error = dsw->d_kqfilter(dev, ap->a_kn);
PICKUP_GIANT();
} else
error = dsw->d_kqfilter(dev, ap->a_kn);
- cdevsw_rel(dsw);
+ dev_lock();
+ dev->si_threadcount--;
+ dev_unlock();
return (error);
}
@@ -595,15 +616,18 @@ spec_close(ap)
VI_UNLOCK(vp);
KASSERT(dev->si_refcount > 0,
("spec_close() on un-referenced struct cdev *(%s)", devtoname(dev)));
- cdevsw_ref(dsw);
+ dev_lock();
+ dev->si_threadcount++;
+ dev_unlock();
if (!(dsw->d_flags & D_NEEDGIANT)) {
DROP_GIANT();
error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td);
PICKUP_GIANT();
} else
error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td);
- cdevsw_rel(dsw);
- dev_rel(dev);
+ dev_lock();
+ dev->si_threadcount--;
+ dev_unlock();
return (error);
}
diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c
index 2249f04..46fca85 100644
--- a/sys/kern/kern_conf.c
+++ b/sys/kern/kern_conf.c
@@ -73,16 +73,16 @@ static void freedev(struct cdev *dev);
static struct cdev *newdev(int x, int y);
-static void
-devlock(void)
+void
+dev_lock(void)
{
if (!mtx_initialized(&devmtx))
mtx_init(&devmtx, "cdev", NULL, MTX_DEF);
mtx_lock(&devmtx);
}
-static void
-devunlock(void)
+void
+dev_unlock(void)
{
mtx_unlock(&devmtx);
}
@@ -90,15 +90,15 @@ devunlock(void)
void
dev_ref(struct cdev *dev)
{
- devlock();
+ dev_lock();
dev->si_refcount++;
- devunlock();
+ dev_unlock();
}
void
dev_rel(struct cdev *dev)
{
- devlock();
+
dev->si_refcount--;
KASSERT(dev->si_refcount >= 0,
("dev_rel(%s) gave negative count", devtoname(dev)));
@@ -106,25 +106,6 @@ dev_rel(struct cdev *dev)
LIST_REMOVE(dev, si_list);
freedev(dev);
}
- devunlock();
-}
-
-void
-cdevsw_ref(struct cdevsw *csw)
-{
- devlock();
- csw->d_refcount++;
- devunlock();
-}
-
-void
-cdevsw_rel(struct cdevsw *csw)
-{
- devlock();
- csw->d_refcount--;
- KASSERT(csw->d_refcount >= 0,
- ("cdevsw_vrel(%s) gave negative count", csw->d_name));
- devunlock();
}
int
@@ -396,7 +377,7 @@ static void
prep_cdevsw(struct cdevsw *devsw)
{
- devlock();
+ dev_lock();
if (devsw->d_version != D_VERSION_00) {
printf(
@@ -451,7 +432,7 @@ prep_cdevsw(struct cdevsw *devsw)
reserved_majors[devsw->d_maj] = devsw->d_maj;
}
}
- devunlock();
+ dev_unlock();
}
struct cdev *
@@ -477,7 +458,7 @@ make_dev(struct cdevsw *devsw, int minornr, uid_t uid, gid_t gid, int perms, con
*/
return (dev);
}
- devlock();
+ dev_lock();
KASSERT(!(dev->si_flags & SI_NAMED),
("make_dev() by driver %s on pre-existing device (maj=%d, min=%d, name=%s)",
devsw->d_name, major(dev), minor(dev), devtoname(dev)));
@@ -497,7 +478,7 @@ make_dev(struct cdevsw *devsw, int minornr, uid_t uid, gid_t gid, int perms, con
LIST_INSERT_HEAD(&devsw->d_devs, dev, si_list);
devfs_create(dev);
- devunlock();
+ dev_unlock();
return (dev);
}
@@ -518,11 +499,11 @@ void
dev_depends(struct cdev *pdev, struct cdev *cdev)
{
- devlock();
+ dev_lock();
cdev->si_parent = pdev;
cdev->si_flags |= SI_CHILD;
LIST_INSERT_HEAD(&pdev->si_children, cdev, si_siblings);
- devunlock();
+ dev_unlock();
}
struct cdev *
@@ -533,7 +514,7 @@ make_dev_alias(struct cdev *pdev, const char *fmt, ...)
int i;
dev = allocdev();
- devlock();
+ dev_lock();
dev->si_flags |= SI_ALIAS;
dev->si_flags |= SI_NAMED;
va_start(ap, fmt);
@@ -545,7 +526,7 @@ make_dev_alias(struct cdev *pdev, const char *fmt, ...)
va_end(ap);
devfs_create(dev);
- devunlock();
+ dev_unlock();
dev_depends(pdev, dev);
return (dev);
}
@@ -606,9 +587,9 @@ void
destroy_dev(struct cdev *dev)
{
- devlock();
+ dev_lock();
idestroy_dev(dev);
- devunlock();
+ dev_unlock();
}
const char *
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 063e7d0..b2e73b9 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -3098,18 +3098,24 @@ void
dev_strategy(struct buf *bp)
{
struct cdevsw *csw;
+ struct cdev *dev;
if ((!bp->b_iocmd) || (bp->b_iocmd & (bp->b_iocmd - 1)))
panic("b_iocmd botch");
bp->b_io.bio_done = bufdonebio;
bp->b_io.bio_caller2 = bp;
- csw = devsw(bp->b_io.bio_dev);
- KASSERT(bp->b_io.bio_dev->si_refcount > 0,
+ dev = bp->b_io.bio_dev;
+ csw = devsw(dev);
+ KASSERT(dev->si_refcount > 0,
("dev_strategy on un-referenced struct cdev *(%s)",
- devtoname(bp->b_io.bio_dev)));
- cdevsw_ref(csw);
+ devtoname(dev)));
+ dev_lock();
+ dev->si_threadcount++;
+ dev_unlock();
(*devsw(bp->b_io.bio_dev)->d_strategy)(&bp->b_io);
- cdevsw_rel(csw);
+ dev_lock();
+ dev->si_threadcount--;
+ dev_unlock();
}
/*
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 5f1f2de..8908ec6 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -156,12 +156,6 @@ static struct mtx mntid_mtx;
*/
static struct mtx vnode_free_list_mtx;
-/*
- * For any iteration/modification of dev->si_hlist (linked through
- * v_specnext)
- */
-static struct mtx spechash_mtx;
-
/* Publicly exported FS */
struct nfs_public nfs_pub;
@@ -283,7 +277,6 @@ vntblinit(void *dummy __unused)
minvnodes = desiredvnodes / 4;
mtx_init(&mountlist_mtx, "mountlist", NULL, MTX_DEF);
mtx_init(&mntid_mtx, "mntid", NULL, MTX_DEF);
- mtx_init(&spechash_mtx, "spechash", NULL, MTX_DEF);
TAILQ_INIT(&vnode_free_list);
mtx_init(&vnode_free_list_mtx, "vnode_free_list", NULL, MTX_DEF);
vnode_zone = uma_zcreate("VNODE", sizeof (struct vnode), NULL, NULL,
@@ -1899,9 +1892,9 @@ v_incr_usecount(struct vnode *vp, int delta)
vp->v_usecount += delta;
if (vp->v_type == VCHR && vp->v_rdev != NULL) {
- mtx_lock(&spechash_mtx);
+ dev_lock();
vp->v_rdev->si_usecount += delta;
- mtx_unlock(&spechash_mtx);
+ dev_unlock();
}
}
@@ -1975,13 +1968,13 @@ addalias(nvp, dev)
{
KASSERT(nvp->v_type == VCHR, ("addalias on non-special vnode"));
- dev_ref(dev);
- nvp->v_rdev = dev;
VI_LOCK(nvp);
- mtx_lock(&spechash_mtx);
+ dev_lock();
+ dev->si_refcount++;
+ nvp->v_rdev = dev;
SLIST_INSERT_HEAD(&dev->si_hlist, nvp, v_specnext);
dev->si_usecount += nvp->v_usecount;
- mtx_unlock(&spechash_mtx);
+ dev_unlock();
VI_UNLOCK(nvp);
}
@@ -2585,9 +2578,9 @@ vop_revoke(ap)
VI_UNLOCK(vp);
dev = vp->v_rdev;
for (;;) {
- mtx_lock(&spechash_mtx);
+ dev_lock();
vq = SLIST_FIRST(&dev->si_hlist);
- mtx_unlock(&spechash_mtx);
+ dev_unlock();
if (vq == NULL)
break;
vgone(vq);
@@ -2706,12 +2699,12 @@ vgonel(vp, td)
*/
VI_LOCK(vp);
if (vp->v_type == VCHR && vp->v_rdev != NULL) {
- mtx_lock(&spechash_mtx);
+ dev_lock();
SLIST_REMOVE(&vp->v_rdev->si_hlist, vp, vnode, v_specnext);
vp->v_rdev->si_usecount -= vp->v_usecount;
- mtx_unlock(&spechash_mtx);
dev_rel(vp->v_rdev);
vp->v_rdev = NULL;
+ dev_unlock();
}
/*
@@ -2751,13 +2744,13 @@ vfinddev(dev, vpp)
{
struct vnode *vp;
- mtx_lock(&spechash_mtx);
+ dev_lock();
SLIST_FOREACH(vp, &dev->si_hlist, v_specnext) {
*vpp = vp;
- mtx_unlock(&spechash_mtx);
+ dev_unlock();
return (1);
}
- mtx_unlock(&spechash_mtx);
+ dev_unlock();
return (0);
}
@@ -2770,9 +2763,9 @@ vcount(vp)
{
int count;
- mtx_lock(&spechash_mtx);
+ dev_lock();
count = vp->v_rdev->si_usecount;
- mtx_unlock(&spechash_mtx);
+ dev_unlock();
return (count);
}
@@ -2785,9 +2778,9 @@ count_dev(dev)
{
int count;
- mtx_lock(&spechash_mtx);
+ dev_lock();
count = dev->si_usecount;
- mtx_unlock(&spechash_mtx);
+ dev_unlock();
return(count);
}
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index 20b4326..c714019 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -222,7 +222,7 @@ struct cdevsw {
/* These fields should not be messed with by drivers */
LIST_ENTRY(cdevsw) d_list;
LIST_HEAD(, cdev) d_devs;
- int d_refcount;
+ int d_spare3;
};
#endif /* _KERNEL */
@@ -263,8 +263,6 @@ int clone_create(struct clonedevs **, struct cdevsw *, int *unit, struct cdev **
int count_dev(struct cdev *_dev);
void destroy_dev(struct cdev *_dev);
struct cdevsw *devsw(struct cdev *_dev);
-void cdevsw_ref(struct cdevsw *);
-void cdevsw_rel(struct cdevsw *);
const char *devtoname(struct cdev *_dev);
int dev_named(struct cdev *_pdev, const char *_name);
void dev_depends(struct cdev *_pdev, struct cdev *_cdev);
@@ -276,6 +274,8 @@ struct cdev *make_dev(struct cdevsw *_devsw, int _minor, uid_t _uid, gid_t _gid,
int _perms, const char *_fmt, ...) __printflike(6, 7);
struct cdev *make_dev_alias(struct cdev *_pdev, const char *_fmt, ...) __printflike(2, 3);
int dev2unit(struct cdev *_dev);
+void dev_lock(void);
+void dev_unlock(void);
int unit2minor(int _unit);
void setconf(void);
struct cdev *getdiskbyname(char *_name);
OpenPOWER on IntegriCloud