Another follow-up to r291460. Only access vp->v_rdev for VCHR vnodes

in devfs_reclaim().

Reported and tested by:	pho
Sponsored by:	The FreeBSD Foundation
Approved by:	re (gjb)
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2016-06-15 15:55:14 +00:00
parent 1201d0bc46
commit 2d5bba3ae3

View File

@ -1360,10 +1360,10 @@ devfs_readlink(struct vop_readlink_args *ap)
static int static int
devfs_reclaim(struct vop_reclaim_args *ap) devfs_reclaim(struct vop_reclaim_args *ap)
{ {
struct vnode *vp = ap->a_vp; struct vnode *vp;
struct devfs_dirent *de; struct devfs_dirent *de;
struct cdev *dev;
vp = ap->a_vp;
mtx_lock(&devfs_de_interlock); mtx_lock(&devfs_de_interlock);
de = vp->v_data; de = vp->v_data;
if (de != NULL) { if (de != NULL) {
@ -1371,23 +1371,30 @@ devfs_reclaim(struct vop_reclaim_args *ap)
vp->v_data = NULL; vp->v_data = NULL;
} }
mtx_unlock(&devfs_de_interlock); mtx_unlock(&devfs_de_interlock);
vnode_destroy_vobject(vp); vnode_destroy_vobject(vp);
return (0);
}
static int
devfs_reclaim_vchr(struct vop_reclaim_args *ap)
{
struct vnode *vp;
struct cdev *dev;
vp = ap->a_vp;
MPASS(vp->v_type == VCHR);
devfs_reclaim(ap);
VI_LOCK(vp); VI_LOCK(vp);
dev_lock(); dev_lock();
dev = vp->v_rdev; dev = vp->v_rdev;
vp->v_rdev = NULL; vp->v_rdev = NULL;
if (dev != NULL)
if (dev == NULL) {
dev_unlock();
VI_UNLOCK(vp);
return (0);
}
dev->si_usecount -= vp->v_usecount; dev->si_usecount -= vp->v_usecount;
dev_unlock(); dev_unlock();
VI_UNLOCK(vp); VI_UNLOCK(vp);
if (dev != NULL)
dev_rel(dev); dev_rel(dev);
return (0); return (0);
} }
@ -1898,7 +1905,7 @@ static struct vop_vector devfs_specops = {
.vop_readdir = VOP_PANIC, .vop_readdir = VOP_PANIC,
.vop_readlink = VOP_PANIC, .vop_readlink = VOP_PANIC,
.vop_reallocblks = VOP_PANIC, .vop_reallocblks = VOP_PANIC,
.vop_reclaim = devfs_reclaim, .vop_reclaim = devfs_reclaim_vchr,
.vop_remove = devfs_remove, .vop_remove = devfs_remove,
.vop_rename = VOP_PANIC, .vop_rename = VOP_PANIC,
.vop_revoke = devfs_revoke, .vop_revoke = devfs_revoke,