summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorjg <none@none>2007-03-16 14:05:13 -0700
committerjg <none@none>2007-03-16 14:05:13 -0700
commit6b9384783302cfb5bb67d617114d5a4e1dc3d609 (patch)
treefd5909fc8b993502a6d00aabd0f8805b666efe8f /usr/src
parentf809017faca98a3dcfb58911112992cfdee29853 (diff)
downloadillumos-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.c48
-rw-r--r--usr/src/uts/common/fs/dev/sdev_vfsops.c5
-rw-r--r--usr/src/uts/common/fs/dev/sdev_vnops.c64
-rw-r--r--usr/src/uts/common/sys/fs/sdev_impl.h3
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 **,