Fix the race between devfs_fp_check and devfs_reclaim. Derefence the
vnode' v_rdev and increment the dev threadcount , as well as clear it (in devfs_reclaim) under the dev_lock(). Reviewed by: tegge Approved by: pjd (mentor)
This commit is contained in:
parent
32c3bb77fa
commit
1663075c64
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=163529
@ -78,12 +78,14 @@ static int
|
||||
devfs_fp_check(struct file *fp, struct cdev **devp, struct cdevsw **dswp)
|
||||
{
|
||||
|
||||
*devp = fp->f_vnode->v_rdev;
|
||||
if (*devp != fp->f_data)
|
||||
*dswp = devvn_refthread(fp->f_vnode, devp);
|
||||
if (*devp != fp->f_data) {
|
||||
if (*dswp != NULL)
|
||||
dev_relthread(*devp);
|
||||
return (ENXIO);
|
||||
}
|
||||
KASSERT((*devp)->si_refcount > 0,
|
||||
("devfs: un-referenced struct cdev *(%s)", devtoname(*devp)));
|
||||
*dswp = dev_refthread(*devp);
|
||||
if (*dswp == NULL)
|
||||
return (ENXIO);
|
||||
return (0);
|
||||
@ -965,13 +967,15 @@ devfs_reclaim(struct vop_reclaim_args *ap)
|
||||
|
||||
vnode_destroy_vobject(vp);
|
||||
|
||||
dev_lock();
|
||||
dev = vp->v_rdev;
|
||||
vp->v_rdev = NULL;
|
||||
|
||||
if (dev == NULL)
|
||||
if (dev == NULL) {
|
||||
dev_unlock();
|
||||
return (0);
|
||||
}
|
||||
|
||||
dev_lock();
|
||||
dev->si_usecount -= vp->v_usecount;
|
||||
dev_unlock();
|
||||
dev_rel(dev);
|
||||
|
@ -125,6 +125,24 @@ dev_refthread(struct cdev *dev)
|
||||
return (csw);
|
||||
}
|
||||
|
||||
struct cdevsw *
|
||||
devvn_refthread(struct vnode *vp, struct cdev **devp)
|
||||
{
|
||||
struct cdevsw *csw;
|
||||
|
||||
mtx_assert(&devmtx, MA_NOTOWNED);
|
||||
csw = NULL;
|
||||
dev_lock();
|
||||
*devp = vp->v_rdev;
|
||||
if (*devp != NULL) {
|
||||
csw = (*devp)->si_devsw;
|
||||
if (csw != NULL)
|
||||
(*devp)->si_threadcount++;
|
||||
}
|
||||
dev_unlock();
|
||||
return (csw);
|
||||
}
|
||||
|
||||
void
|
||||
dev_relthread(struct cdev *dev)
|
||||
{
|
||||
|
@ -105,6 +105,7 @@ struct thread;
|
||||
struct uio;
|
||||
struct knote;
|
||||
struct clonedevs;
|
||||
struct vnode;
|
||||
|
||||
/*
|
||||
* Note: d_thread_t is provided as a transition aid for those drivers
|
||||
@ -244,6 +245,7 @@ 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 *dev_refthread(struct cdev *_dev);
|
||||
struct cdevsw *devvn_refthread(struct vnode *vp, struct cdev **devp);
|
||||
void dev_relthread(struct cdev *_dev);
|
||||
void dev_depends(struct cdev *_pdev, struct cdev *_cdev);
|
||||
void dev_ref(struct cdev *dev);
|
||||
|
Loading…
Reference in New Issue
Block a user