diff -Naur devfs/devfs.h devfsb/devfs.h --- fs/devfs/devfs.h 2006-08-18 17:23:00 +0000 +++ fs/devfsb/devfs.h 2006-09-03 19:34:57 +0000 @@ -163,7 +163,7 @@ void devfs_rules_apply(struct devfs_mount *dm, struct devfs_dirent *de); void devfs_rules_cleanup (struct devfs_mount *dm); int devfs_rules_ioctl(struct devfs_mount *dm, u_long cmd, caddr_t data, struct thread *td); -int devfs_allocv (struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, struct thread *td); +int devfs_allocv (struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, int *dm_unlock, struct thread *td); struct cdev **devfs_itod (int inode); struct devfs_dirent **devfs_itode (struct devfs_mount *dm, int inode); void devfs_delete(struct devfs_mount *dm, struct devfs_dirent *de); diff -Naur devfs/devfs_vfsops.c devfsb/devfs_vfsops.c --- fs/devfs/devfs_vfsops.c 2006-08-18 17:23:00 +0000 +++ fs/devfsb/devfs_vfsops.c 2006-09-03 19:34:57 +0000 @@ -139,9 +139,11 @@ int error; struct vnode *vp; struct devfs_mount *dmp; + int dm_unlock; dmp = VFSTODEVFS(mp); - error = devfs_allocv(dmp->dm_rootdir, mp, &vp, td); + dm_unlock = 0; + error = devfs_allocv(dmp->dm_rootdir, mp, &vp, &dm_unlock, td); if (error) return (error); vp->v_vflag |= VV_ROOT; diff -Naur devfs/devfs_vnops.c devfsb/devfs_vnops.c --- fs/devfs/devfs_vnops.c 2006-08-18 17:23:00 +0000 +++ fs/devfsb/devfs_vnops.c 2006-09-03 19:34:57 +0000 @@ -124,16 +124,23 @@ } int -devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, struct thread *td) +devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, + int *dm_unlock, struct thread *td) { int error; struct vnode *vp; struct cdev *dev; + struct devfs_mount *dmp; KASSERT(td == curthread, ("devfs_allocv: td != curthread")); + dmp = VFSTODEVFS(mp); loop: vp = de->de_vnode; if (vp != NULL) { + if (*dm_unlock) { + sx_xunlock(&dmp->dm_lock); + *dm_unlock = 0; + } if (vget(vp, LK_EXCLUSIVE, td)) goto loop; *vpp = vp; @@ -173,6 +180,10 @@ } vp->v_data = de; de->de_vnode = vp; + if (*dm_unlock) { + sx_xunlock(&dmp->dm_lock); + *dm_unlock = 0; + } vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); #ifdef MAC mac_associate_vnode_devfs(mp, de, vp); @@ -453,7 +464,7 @@ } static int -devfs_lookupx(struct vop_lookup_args *ap) +devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock) { struct componentname *cnp; struct vnode *dvp, **vpp; @@ -504,7 +515,7 @@ de = TAILQ_FIRST(&dd->de_dlist); /* "." */ de = TAILQ_NEXT(de, de_list); /* ".." */ de = de->de_dir; - error = devfs_allocv(de, dvp->v_mount, vpp, td); + error = devfs_allocv(de, dvp->v_mount, vpp, dm_unlock, td); vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); return (error); } @@ -561,7 +572,7 @@ return (0); } } - error = devfs_allocv(de, dvp->v_mount, vpp, td); + error = devfs_allocv(de, dvp->v_mount, vpp, dm_unlock, td); return (error); } @@ -570,11 +581,14 @@ { int j; struct devfs_mount *dmp; + int dm_unlock; dmp = VFSTODEVFS(ap->a_dvp->v_mount); + dm_unlock = 1; sx_xlock(&dmp->dm_lock); - j = devfs_lookupx(ap); - sx_xunlock(&dmp->dm_lock); + j = devfs_lookupx(ap, &dm_unlock); + if (dm_unlock == 1) + sx_xunlock(&dmp->dm_lock); return (j); } @@ -586,6 +600,7 @@ struct thread *td; struct devfs_dirent *dd, *de; struct devfs_mount *dmp; + int dm_unlock; int error; /* @@ -597,6 +612,7 @@ dvp = ap->a_dvp; dmp = VFSTODEVFS(dvp->v_mount); sx_xlock(&dmp->dm_lock); + dm_unlock = 1; cnp = ap->a_cnp; vpp = ap->a_vpp; @@ -617,9 +633,10 @@ if (de == NULL) goto notfound; de->de_flags &= ~DE_WHITEOUT; - error = devfs_allocv(de, dvp->v_mount, vpp, td); + error = devfs_allocv(de, dvp->v_mount, vpp, &dm_unlock, td); notfound: - sx_xunlock(&dmp->dm_lock); + if (dm_unlock == 1) + sx_xunlock(&dmp->dm_lock); return (error); } @@ -1101,6 +1118,7 @@ struct devfs_dirent *de; struct devfs_mount *dmp; struct thread *td; + int dm_unlock; td = ap->a_cnp->cn_thread; KASSERT(td == curthread, ("devfs_symlink: td != curthread")); @@ -1119,12 +1137,14 @@ de->de_symlink = malloc(i, M_DEVFS, M_WAITOK); bcopy(ap->a_target, de->de_symlink, i); sx_xlock(&dmp->dm_lock); + dm_unlock = 1; #ifdef MAC mac_create_devfs_symlink(ap->a_cnp->cn_cred, dmp->dm_mount, dd, de); #endif TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); - devfs_allocv(de, ap->a_dvp->v_mount, ap->a_vpp, td); - sx_xunlock(&dmp->dm_lock); + devfs_allocv(de, ap->a_dvp->v_mount, ap->a_vpp, &dm_unlock, td); + if (dm_unlock == 1) + sx_xunlock(&dmp->dm_lock); return (0); }