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 **,