Date: Sun, 22 Aug 2010 16:08:12 +0000 (UTC) From: Jaakko Heinonen <jh@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r211628 - head/sys/fs/devfs Message-ID: <201008221608.o7MG8C2d008409@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008221608.o7MG8C2d008409>