summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2004-10-01 06:33:39 +0000
committerphk <phk@FreeBSD.org>2004-10-01 06:33:39 +0000
commit2e5b8b98835509cddd3b2345fbdc9d31180a21d9 (patch)
treead89d4adcffc9a9b262d61d0ea417f468fc719ed
parentb360d8fe2f7a580cef467da8db8f763a30590de2 (diff)
downloadFreeBSD-src-2e5b8b98835509cddd3b2345fbdc9d31180a21d9.zip
FreeBSD-src-2e5b8b98835509cddd3b2345fbdc9d31180a21d9.tar.gz
Fix a LOR relating to freeing cdevs.
-rw-r--r--sys/kern/kern_conf.c18
-rw-r--r--sys/kern/vfs_subr.c10
-rw-r--r--sys/sys/conf.h2
3 files changed, 19 insertions, 11 deletions
diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c
index f5d6077..3f7bc44 100644
--- a/sys/kern/kern_conf.c
+++ b/sys/kern/kern_conf.c
@@ -98,17 +98,31 @@ dev_ref(struct cdev *dev)
}
void
-dev_rel(struct cdev *dev)
+dev_rel(struct vnode *vp)
{
+ struct cdev *dev;
+ int flag;
+ dev = vp->v_rdev;
+ mtx_assert(&devmtx, MA_NOTOWNED);
+ dev_lock();
+ SLIST_REMOVE(&dev->si_hlist, vp, vnode, v_specnext);
+ dev->si_usecount -= vp->v_usecount;
+ vp->v_rdev = NULL;
dev->si_refcount--;
KASSERT(dev->si_refcount >= 0,
("dev_rel(%s) gave negative count", devtoname(dev)));
+ flag = 0;
if (dev->si_devsw == NULL && dev->si_refcount == 0) {
LIST_REMOVE(dev, si_list);
- freedev(dev);
+ flag = 1;
}
+ dev_unlock();
+ if (flag)
+ freedev(dev);
+ return;
}
+
struct cdevsw *
dev_refthread(struct cdev *dev)
{
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 4f64313..71372da 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -2698,14 +2698,8 @@ vgonel(vp, td)
* if it is on one.
*/
VI_LOCK(vp);
- if (vp->v_type == VCHR && vp->v_rdev != NULL) {
- dev_lock();
- SLIST_REMOVE(&vp->v_rdev->si_hlist, vp, vnode, v_specnext);
- vp->v_rdev->si_usecount -= vp->v_usecount;
- dev_rel(vp->v_rdev);
- vp->v_rdev = NULL;
- dev_unlock();
- }
+ if (vp->v_type == VCHR && vp->v_rdev != NULL)
+ dev_rel(vp);
/*
* If it is on the freelist and not already at the head,
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index 33a2f70..6b26205 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -266,7 +266,7 @@ const char *devtoname(struct cdev *_dev);
int dev_named(struct cdev *_pdev, const char *_name);
void dev_depends(struct cdev *_pdev, struct cdev *_cdev);
void dev_ref(struct cdev *dev);
-void dev_rel(struct cdev *dev);
+void dev_rel(struct vnode *vp);
void dev_strategy(struct buf *bp);
struct cdev *makebdev(int _maj, int _min);
struct cdev *make_dev(struct cdevsw *_devsw, int _minor, uid_t _uid, gid_t _gid,
OpenPOWER on IntegriCloud