svn commit: r211628 - head/sys/fs/devfs
Jaakko Heinonen
jh at FreeBSD.org
Sun Aug 22 16:08:12 UTC 2010
Author: jh
Date: Sun Aug 22 16:08:12 2010
New Revision: 211628
URL: http://svn.freebsd.org/changeset/base/211628
Log:
Introduce and use devfs_populate_vp() to unlock a vnode before calling
devfs_populate(). This is a prerequisite for the automatic removal of
empty directories which will be committed in the future.
Reviewed by: kib (previous version)
Modified:
head/sys/fs/devfs/devfs_vnops.c
Modified: head/sys/fs/devfs/devfs_vnops.c
==============================================================================
--- head/sys/fs/devfs/devfs_vnops.c Sun Aug 22 16:06:07 2010 (r211627)
+++ head/sys/fs/devfs/devfs_vnops.c Sun Aug 22 16:08:12 2010 (r211628)
@@ -185,6 +185,43 @@ devfs_clear_cdevpriv(void)
devfs_fpdrop(fp);
}
+/*
+ * On success devfs_populate_vp() returns with dmp->dm_lock held.
+ */
+static int
+devfs_populate_vp(struct vnode *vp)
+{
+ struct devfs_mount *dmp;
+ int locked;
+
+ ASSERT_VOP_LOCKED(vp, "devfs_populate_vp");
+
+ dmp = VFSTODEVFS(vp->v_mount);
+ locked = VOP_ISLOCKED(vp);
+
+ sx_xlock(&dmp->dm_lock);
+ DEVFS_DMP_HOLD(dmp);
+
+ /* Can't call devfs_populate() with the vnode lock held. */
+ VOP_UNLOCK(vp, 0);
+ devfs_populate(dmp);
+
+ sx_xunlock(&dmp->dm_lock);
+ vn_lock(vp, locked | LK_RETRY);
+ sx_xlock(&dmp->dm_lock);
+ if (DEVFS_DMP_DROP(dmp)) {
+ sx_xunlock(&dmp->dm_lock);
+ devfs_unmount_final(dmp);
+ return (EBADF);
+ }
+ if (vp->v_iflag & VI_DOOMED) {
+ sx_xunlock(&dmp->dm_lock);
+ return (EBADF);
+ }
+
+ return (0);
+}
+
static int
devfs_vptocnp(struct vop_vptocnp_args *ap)
{
@@ -813,14 +850,6 @@ devfs_lookupx(struct vop_lookup_args *ap
return (error);
}
- DEVFS_DMP_HOLD(dmp);
- devfs_populate(dmp);
- if (DEVFS_DMP_DROP(dmp)) {
- *dm_unlock = 0;
- sx_xunlock(&dmp->dm_lock);
- devfs_unmount_final(dmp);
- return (ENOENT);
- }
dd = dvp->v_data;
de = devfs_find(dd, cnp->cn_nameptr, cnp->cn_namelen, 0);
while (de == NULL) { /* While(...) so we can use break */
@@ -843,7 +872,20 @@ devfs_lookupx(struct vop_lookup_args *ap
EVENTHANDLER_INVOKE(dev_clone,
td->td_ucred, pname, strlen(pname), &cdev);
sx_sunlock(&clone_drain_lock);
- sx_xlock(&dmp->dm_lock);
+
+ if (cdev == NULL)
+ sx_xlock(&dmp->dm_lock);
+ else if (devfs_populate_vp(dvp) != 0) {
+ *dm_unlock = 0;
+ sx_xlock(&dmp->dm_lock);
+ if (DEVFS_DMP_DROP(dmp)) {
+ sx_xunlock(&dmp->dm_lock);
+ devfs_unmount_final(dmp);
+ } else
+ sx_xunlock(&dmp->dm_lock);
+ dev_rel(cdev);
+ return (ENOENT);
+ }
if (DEVFS_DMP_DROP(dmp)) {
*dm_unlock = 0;
sx_xunlock(&dmp->dm_lock);
@@ -852,19 +894,10 @@ devfs_lookupx(struct vop_lookup_args *ap
dev_rel(cdev);
return (ENOENT);
}
+
if (cdev == NULL)
break;
- DEVFS_DMP_HOLD(dmp);
- devfs_populate(dmp);
- if (DEVFS_DMP_DROP(dmp)) {
- *dm_unlock = 0;
- sx_xunlock(&dmp->dm_lock);
- devfs_unmount_final(dmp);
- dev_rel(cdev);
- return (ENOENT);
- }
-
dev_lock();
dde = &cdev2priv(cdev)->cdp_dirents[dmp->dm_idx];
if (dde != NULL && *dde != NULL)
@@ -909,9 +942,11 @@ devfs_lookup(struct vop_lookup_args *ap)
struct devfs_mount *dmp;
int dm_unlock;
+ if (devfs_populate_vp(ap->a_dvp) != 0)
+ return (ENOTDIR);
+
dmp = VFSTODEVFS(ap->a_dvp->v_mount);
dm_unlock = 1;
- sx_xlock(&dmp->dm_lock);
j = devfs_lookupx(ap, &dm_unlock);
if (dm_unlock == 1)
sx_xunlock(&dmp->dm_lock);
@@ -1139,12 +1174,7 @@ devfs_readdir(struct vop_readdir_args *a
}
dmp = VFSTODEVFS(ap->a_vp->v_mount);
- sx_xlock(&dmp->dm_lock);
- DEVFS_DMP_HOLD(dmp);
- devfs_populate(dmp);
- if (DEVFS_DMP_DROP(dmp)) {
- sx_xunlock(&dmp->dm_lock);
- devfs_unmount_final(dmp);
+ if (devfs_populate_vp(ap->a_vp) != 0) {
if (tmp_ncookies != NULL)
ap->a_ncookies = tmp_ncookies;
return (EIO);
More information about the svn-src-all
mailing list