summaryrefslogtreecommitdiffstats
path: root/sys/fs/devfs
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2006-10-20 07:59:50 +0000
committerkib <kib@FreeBSD.org>2006-10-20 07:59:50 +0000
commit5f5bf9dadc00a7cc8dc6b37e8abf10a23ced17f4 (patch)
tree0c8a260910037a642d1dd98c671e553817da8b56 /sys/fs/devfs
parent5b6bf7eb1c1469a528a6e28e72f035a6aed74314 (diff)
downloadFreeBSD-src-5f5bf9dadc00a7cc8dc6b37e8abf10a23ced17f4.zip
FreeBSD-src-5f5bf9dadc00a7cc8dc6b37e8abf10a23ced17f4.tar.gz
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)
Diffstat (limited to 'sys/fs/devfs')
-rw-r--r--sys/fs/devfs/devfs_vnops.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index 4b348ec..55eaeb6 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -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);
OpenPOWER on IntegriCloud