diff options
author | phk <phk@FreeBSD.org> | 2004-09-23 07:17:41 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2004-09-23 07:17:41 +0000 |
commit | 3947e54e89a67263df7cb82659d2a60b22e36d66 (patch) | |
tree | 7ba70387e941540c2b48f5f069c66f8c5b6d2f61 /sys | |
parent | a5b75e6c3853ff22f0202d48d68a4748e5391d42 (diff) | |
download | FreeBSD-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.c | 60 | ||||
-rw-r--r-- | sys/kern/kern_conf.c | 53 | ||||
-rw-r--r-- | sys/kern/vfs_bio.c | 16 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 41 | ||||
-rw-r--r-- | sys/sys/conf.h | 6 |
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); |