Mercurial > illumos > illumos-gate
changeset 3843:6501a40c8d2a
6502778 devnames has some problems with node creation and deletion
6529779 subdirectories under /dev get created too late
author | jg |
---|---|
date | Fri, 16 Mar 2007 14:05:13 -0700 |
parents | e67ad389b114 |
children | 8c345d3f2fd4 |
files | usr/src/uts/common/fs/dev/sdev_subr.c usr/src/uts/common/fs/dev/sdev_vfsops.c usr/src/uts/common/fs/dev/sdev_vnops.c usr/src/uts/common/sys/fs/sdev_impl.h |
diffstat | 4 files changed, 80 insertions(+), 40 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fs/dev/sdev_subr.c Fri Mar 16 14:00:05 2007 -0700 +++ b/usr/src/uts/common/fs/dev/sdev_subr.c Fri Mar 16 14:05:13 2007 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1594,7 +1594,7 @@ return (error); } -static int +void sdev_filldir_dynamic(struct sdev_node *ddv) { int error; @@ -1603,31 +1603,25 @@ char *nm = NULL; struct sdev_node *dv = NULL; - if (!(ddv->sdev_flags & SDEV_BUILD)) { - return (0); - } - - ASSERT(RW_READ_HELD(&ddv->sdev_contents)); - if (!rw_tryupgrade(&ddv->sdev_contents)) { - rw_exit(&ddv->sdev_contents); - rw_enter(&ddv->sdev_contents, RW_WRITER); - } + ASSERT(RW_WRITE_HELD(&ddv->sdev_contents)); + ASSERT((ddv->sdev_flags & SDEV_BUILD)); vap = sdev_getdefault_attr(VDIR); for (i = 0; vtab[i].vt_name != NULL; i++) { nm = vtab[i].vt_name; ASSERT(RW_WRITE_HELD(&ddv->sdev_contents)); + dv = NULL; error = sdev_mknode(ddv, nm, &dv, vap, NULL, NULL, kcred, SDEV_READY); - if (error) - continue; - ASSERT(dv); - ASSERT(dv->sdev_state != SDEV_ZOMBIE); - SDEV_SIMPLE_RELE(dv); - dv = NULL; + if (error) { + cmn_err(CE_WARN, "%s/%s: error %d\n", + ddv->sdev_name, nm, error); + } else { + ASSERT(dv); + ASSERT(dv->sdev_state != SDEV_ZOMBIE); + SDEV_SIMPLE_RELE(dv); + } } - rw_downgrade(&ddv->sdev_contents); - return (0); } /* @@ -2782,7 +2776,7 @@ /* * release the contents lock so that - * the cache maybe updated by devfsadmd + * the cache may be updated by devfsadmd */ rw_exit(&ddv->sdev_contents); mutex_enter(&ddv->sdev_lookup_lock); @@ -2793,22 +2787,12 @@ sdcmn_err4(("readdir of directory %s by %s\n", ddv->sdev_name, curproc->p_user.u_comm)); - while (ddv->sdev_flags & SDEV_BUILD) { + if (ddv->sdev_flags & SDEV_BUILD) { if (SDEV_IS_PERSIST(ddv)) { error = sdev_filldir_from_store(ddv, alloc_count, cred); } - - /* - * pre-creating the directories - * defined in vtab - */ - if (SDEVTOV(ddv)->v_flag & VROOT) { - error = sdev_filldir_dynamic(ddv); - } - - if (!error) - ddv->sdev_flags &= ~SDEV_BUILD; + ddv->sdev_flags &= ~SDEV_BUILD; } }
--- a/usr/src/uts/common/fs/dev/sdev_vfsops.c Fri Mar 16 14:00:05 2007 -0700 +++ b/usr/src/uts/common/fs/dev/sdev_vfsops.c Fri Mar 16 14:05:13 2007 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -336,6 +336,9 @@ dv->sdev_origin = sdev_origins->sdev_root; } else { sdev_ncache_setup(); + rw_enter(&dv->sdev_contents, RW_WRITER); + sdev_filldir_dynamic(dv); + rw_exit(&dv->sdev_contents); } sdev_update_timestamps(dv->sdev_attrvp,
--- a/usr/src/uts/common/fs/dev/sdev_vnops.c Fri Mar 16 14:00:05 2007 -0700 +++ b/usr/src/uts/common/fs/dev/sdev_vnops.c Fri Mar 16 14:05:13 2007 -0700 @@ -370,11 +370,16 @@ sdev_lookup(struct vnode *dvp, char *nm, struct vnode **vpp, struct pathname *pnp, int flags, struct vnode *rdir, struct cred *cred) { - struct sdev_node *parent; + struct sdev_node *parent; + int error; parent = VTOSDEV(dvp); ASSERT(parent); + /* execute access is required to search the directory */ + if ((error = VOP_ACCESS(dvp, VEXEC, 0, cred)) != 0) + return (error); + if (!SDEV_IS_GLOBAL(parent)) return (prof_lookup(dvp, nm, vpp, cred)); return (devname_lookup_func(parent, nm, vpp, cred, NULL, 0)); @@ -414,7 +419,10 @@ } rw_exit(&parent->sdev_dotdot->sdev_contents); -again: + /* execute access is required to search the directory */ + if ((error = VOP_ACCESS(dvp, VEXEC|VWRITE, 0, cred)) != 0) + return (error); + /* check existing name */ error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cred); @@ -526,6 +534,12 @@ return (ENOTSUP); } + /* execute access is required to search the directory */ + if ((error = VOP_ACCESS(dvp, VEXEC, 0, cred)) != 0) { + rw_exit(&parent->sdev_contents); + return (error); + } + /* check existence first */ dv = sdev_cache_lookup(parent, nm); if (dv == NULL) { @@ -541,6 +555,13 @@ return (ENOENT); } + /* write access is required to remove an entry */ + if ((error = VOP_ACCESS(dvp, VWRITE, 0, cred)) != 0) { + rw_exit(&parent->sdev_contents); + VN_RELE(vp); + return (error); + } + /* the module may record/reject removing a device node */ map = sdev_get_map(parent, 0); dirops = map ? map->dir_ops : NULL; @@ -663,7 +684,7 @@ rw_exit(&toparent->sdev_dotdot->sdev_contents); /* - * grabbing the global lock to prevent + * acquire the global lock to prevent * mount/unmount/other rename activities. */ mutex_enter(&sdev_lock); @@ -885,6 +906,10 @@ } rw_exit(&parent->sdev_dotdot->sdev_contents); + /* execute access is required to search a directory */ + if ((error = VOP_ACCESS(dvp, VEXEC, 0, cred)) != 0) + return (error); + /* find existing name */ error = VOP_LOOKUP(dvp, lnm, &vp, NULL, 0, NULL, cred); if (error == 0) { @@ -893,10 +918,12 @@ sdcmn_err2(("sdev_symlink: node %s already exists\n", lnm)); return (EEXIST); } + if (error != ENOENT) + return (error); - if (error != ENOENT) { + /* write access is required to create a symlink */ + if ((error = VOP_ACCESS(dvp, VWRITE, 0, cred)) != 0) return (error); - } /* put it into memory cache */ rw_enter(&parent->sdev_contents, RW_WRITER); @@ -951,16 +978,25 @@ } rw_exit(&parent->sdev_dotdot->sdev_contents); + /* execute access is required to search the directory */ + if ((error = VOP_ACCESS(dvp, VEXEC, 0, cred)) != 0) { + return (error); + } + /* find existing name */ error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cred); if (error == 0) { VN_RELE(vp); return (EEXIST); } - if (error != ENOENT) return (error); + /* require write access to create a directory */ + if ((error = VOP_ACCESS(dvp, VWRITE, 0, cred)) != 0) { + return (error); + } + /* put it into memory */ rw_enter(&parent->sdev_contents, RW_WRITER); error = sdev_mknode(parent, nm, &self, @@ -1016,6 +1052,10 @@ } rw_exit(&parent->sdev_dotdot->sdev_contents); + /* execute access is required to search the directory */ + if ((error = VOP_ACCESS(dvp, VEXEC, 0, cred)) != 0) + return (error); + /* check existing name */ rw_enter(&parent->sdev_contents, RW_WRITER); self = sdev_cache_lookup(parent, nm); @@ -1032,6 +1072,13 @@ return (ENOENT); } + /* write access is required to remove a directory */ + if ((error = VOP_ACCESS(dvp, VWRITE, 0, cred)) != 0) { + rw_exit(&parent->sdev_contents); + VN_RELE(vp); + return (error); + } + /* some sanity checks */ if (vp == dvp || vp == cdir) { rw_exit(&parent->sdev_contents); @@ -1130,6 +1177,11 @@ sdev_readdir(struct vnode *dvp, struct uio *uiop, struct cred *cred, int *eofp) { struct sdev_node *parent = VTOSDEV(dvp); + int error; + + /* execute access is required to search the directory */ + if ((error = VOP_ACCESS(dvp, VEXEC, 0, cred)) != 0) + return (error); ASSERT(parent); if (!SDEV_IS_GLOBAL(parent))
--- a/usr/src/uts/common/sys/fs/sdev_impl.h Fri Mar 16 14:00:05 2007 -0700 +++ b/usr/src/uts/common/sys/fs/sdev_impl.h Fri Mar 16 14:05:13 2007 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -574,6 +574,7 @@ extern void sdev_node_cache_fini(void); extern struct sdev_node *sdev_mkroot(struct vfs *, dev_t, struct vnode *, struct vnode *, struct cred *); +extern void sdev_filldir_dynamic(struct sdev_node *); extern int sdev_mknode(struct sdev_node *, char *, struct sdev_node **, struct vattr *, struct vnode *, void *, struct cred *, sdev_node_state_t); extern int sdev_nodeinit(struct sdev_node *, char *, struct sdev_node **,