diff options
author | jg <none@none> | 2007-03-16 14:05:13 -0700 |
---|---|---|
committer | jg <none@none> | 2007-03-16 14:05:13 -0700 |
commit | 6b9384783302cfb5bb67d617114d5a4e1dc3d609 (patch) | |
tree | fd5909fc8b993502a6d00aabd0f8805b666efe8f /usr/src | |
parent | f809017faca98a3dcfb58911112992cfdee29853 (diff) | |
download | illumos-joyent-6b9384783302cfb5bb67d617114d5a4e1dc3d609.tar.gz |
6502778 devnames has some problems with node creation and deletion
6529779 subdirectories under /dev get created too late
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/fs/dev/sdev_subr.c | 48 | ||||
-rw-r--r-- | usr/src/uts/common/fs/dev/sdev_vfsops.c | 5 | ||||
-rw-r--r-- | usr/src/uts/common/fs/dev/sdev_vnops.c | 64 | ||||
-rw-r--r-- | usr/src/uts/common/sys/fs/sdev_impl.h | 3 |
4 files changed, 80 insertions, 40 deletions
diff --git a/usr/src/uts/common/fs/dev/sdev_subr.c b/usr/src/uts/common/fs/dev/sdev_subr.c index 58e7aea741..d6d92c2621 100644 --- a/usr/src/uts/common/fs/dev/sdev_subr.c +++ b/usr/src/uts/common/fs/dev/sdev_subr.c @@ -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 @@ done: return (error); } -static int +void sdev_filldir_dynamic(struct sdev_node *ddv) { int error; @@ -1603,31 +1603,25 @@ sdev_filldir_dynamic(struct sdev_node *ddv) 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 @@ devname_readdir_func(vnode_t *vp, uio_t *uiop, cred_t *cred, int *eofp, /* * 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 @@ devname_readdir_func(vnode_t *vp, uio_t *uiop, cred_t *cred, int *eofp, 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; } } diff --git a/usr/src/uts/common/fs/dev/sdev_vfsops.c b/usr/src/uts/common/fs/dev/sdev_vfsops.c index 38bbafe4de..5baf66ea1d 100644 --- a/usr/src/uts/common/fs/dev/sdev_vfsops.c +++ b/usr/src/uts/common/fs/dev/sdev_vfsops.c @@ -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 @@ sdev_mount(struct vfs *vfsp, struct vnode *mvp, struct mounta *uap, 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, diff --git a/usr/src/uts/common/fs/dev/sdev_vnops.c b/usr/src/uts/common/fs/dev/sdev_vnops.c index 9103a538c1..4cad8b53e8 100644 --- a/usr/src/uts/common/fs/dev/sdev_vnops.c +++ b/usr/src/uts/common/fs/dev/sdev_vnops.c @@ -370,11 +370,16 @@ static int 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 @@ sdev_create(struct vnode *dvp, char *nm, struct vattr *vap, vcexcl_t excl, } 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 @@ sdev_remove(struct vnode *dvp, char *nm, struct cred *cred) 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 @@ sdev_remove(struct vnode *dvp, char *nm, struct cred *cred) 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 @@ sdev_rename(struct vnode *odvp, char *onm, struct vnode *ndvp, char *nnm, 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 @@ sdev_symlink(struct vnode *dvp, char *lnm, struct vattr *tva, } 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 @@ sdev_symlink(struct vnode *dvp, char *lnm, struct vattr *tva, 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 @@ sdev_mkdir(struct vnode *dvp, char *nm, struct vattr *va, struct vnode **vpp, } 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 @@ sdev_rmdir(struct vnode *dvp, char *nm, struct vnode *cdir, struct cred *cred) } 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 @@ sdev_rmdir(struct vnode *dvp, char *nm, struct vnode *cdir, struct cred *cred) 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 @@ static int 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)) diff --git a/usr/src/uts/common/sys/fs/sdev_impl.h b/usr/src/uts/common/sys/fs/sdev_impl.h index 5b0a8b8426..4083fd382d 100644 --- a/usr/src/uts/common/sys/fs/sdev_impl.h +++ b/usr/src/uts/common/sys/fs/sdev_impl.h @@ -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_init(void); 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 **, |