Fix a LOR relating to freeing cdevs.
This commit is contained in:
parent
b360d8fe2f
commit
2e5b8b9883
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user