PSARC/2008/412 Properties and Devinfo Snapshots
authorcth
Wed, 30 Jul 2008 10:30:05 -0700
changeset 7224 19ff3ecd90c2
parent 7223 c6e51d0e2b43
child 7225 b1baea26c8f4
PSARC/2008/412 Properties and Devinfo Snapshots 5034258 device size should be available in devinfo snapshots that request properties 5100405 Deadlock can occur due to the devinfo driver holding devi_lock 6276452 ddi_append_minor_node() and ddi_remove_minor_node() use the extra code to protect the critical code. 6588656 ddi_prop_op_size() should not check callers *lengthp on PROP_LEN_AND_VAL_ALLOC call 6720361 missing locks on devi_minor list traversal 6729639 scsi_hba code should not use DDI_MAJOR_T_UNKNOWN for properties
usr/src/cmd/mdb/common/modules/genunix/devinfo.c
usr/src/cmd/prtconf/pdevinfo.c
usr/src/uts/common/fs/devfs/devfs_subr.c
usr/src/uts/common/io/cmlb.c
usr/src/uts/common/io/devinfo.c
usr/src/uts/common/io/scsi/impl/scsi_hba.c
usr/src/uts/common/io/scsi/targets/sd.c
usr/src/uts/common/os/devcfg.c
usr/src/uts/common/os/devid_cache.c
usr/src/uts/common/os/modctl.c
usr/src/uts/common/os/sunddi.c
usr/src/uts/common/os/sunndi.c
usr/src/uts/common/pcmcia/nexus/pcmcia.c
usr/src/uts/common/sys/cmlb.h
usr/src/uts/common/sys/ddi_impldefs.h
usr/src/uts/common/sys/devinfo_impl.h
usr/src/uts/common/sys/sunddi.h
usr/src/uts/common/xen/io/xdf.c
usr/src/uts/intel/io/dktp/disk/cmdk.c
usr/src/uts/sun/io/dada/targets/dad.c
usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf.c
--- a/usr/src/cmd/mdb/common/modules/genunix/devinfo.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/cmd/mdb/common/modules/genunix/devinfo.c	Wed Jul 30 10:30:05 2008 -0700
@@ -1110,7 +1110,6 @@
 	    { "S_OFFLINING",	DEVI_S_OFFLINING,	DEVI_S_OFFLINING },
 	    { "S_INVOKING_DACF", DEVI_S_INVOKING_DACF,	DEVI_S_INVOKING_DACF },
 	    { "S_UNBOUND",	DEVI_S_UNBOUND,		DEVI_S_UNBOUND },
-	    { "S_MD_UPDATE",	DEVI_S_MD_UPDATE,	DEVI_S_MD_UPDATE },
 	    { "S_REPORT",	DEVI_S_REPORT,		DEVI_S_REPORT },
 	    { "S_EVADD",	DEVI_S_EVADD,		DEVI_S_EVADD },
 	    { "S_EVREMOVE",	DEVI_S_EVREMOVE,	DEVI_S_EVREMOVE },
--- a/usr/src/cmd/prtconf/pdevinfo.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/cmd/prtconf/pdevinfo.c	Wed Jul 30 10:30:05 2008 -0700
@@ -128,10 +128,10 @@
 #define	NUM_ELEMENTS(A) (sizeof (A) / sizeof (A[0]))
 
 static int prop_type_guess(const dumpops_t *, void *, void **, int *);
-static void dump_prop_list_common(const dumpops_t *, int, void *);
 static void walk_driver(di_node_t, di_devlink_handle_t);
 static int dump_devs(di_node_t, void *);
-static int dump_prop_list(const dumpops_t *, const char *, int, di_node_t);
+static int dump_prop_list(const dumpops_t *, const char *,
+				int, void *, dev_t);
 static int _error(const char *, ...);
 static int is_openprom();
 static void walk(uchar_t *, uint_t, int);
@@ -415,7 +415,6 @@
 	di_minor_private_set(minor, (void *)data);
 }
 
-
 /*
  * In this comment typed properties are those of type DI_PROP_TYPE_UNDEF_IT,
  * DI_PROP_TYPE_BOOLEAN, DI_PROP_TYPE_INT, DI_PROP_TYPE_INT64,
@@ -502,18 +501,80 @@
 	return (len);
 }
 
-static void
-dump_prop_list_common(const dumpops_t *dumpops, int ilev, void *node)
+/*
+ * Returns 0 if nothing is printed, 1 otherwise
+ */
+static int
+dump_prop_list(const dumpops_t *dumpops, const char *name, int ilev,
+    void *node, dev_t dev)
 {
-	void *prop = DI_PROP_NIL, *prop_data;
-	char *p;
-	int i, prop_type, nitems;
+	void		*prop = DI_PROP_NIL, *prop_data;
+	di_minor_t	minor;
+	char		*p;
+	int		i, prop_type, nitems;
+	dev_t		pdev;
+	int		nprop = 0;
 
 	while ((prop = NEXTPROP(dumpops)(node, prop)) != DI_PROP_NIL) {
-		nitems = prop_type_guess(dumpops, prop, &prop_data, &prop_type);
+
+		/* Skip properties a dev_t oriented caller is not requesting */
+		if (PROPDEVT(dumpops)) {
+			pdev = PROPDEVT(dumpops)(prop);
+
+			if (dev == DDI_DEV_T_ANY) {
+				/*
+				 * Caller requesting print all properties
+				 */
+				goto print;
+			} else if (dev == DDI_DEV_T_NONE) {
+				/*
+				 * Caller requesting print of properties
+				 * associated with devinfo (not minor).
+				 */
+				if ((pdev == DDI_DEV_T_ANY) ||
+				    (pdev == DDI_DEV_T_NONE))
+					goto print;
+
+				/*
+				 * Property has a minor association, see if
+				 * we have a minor with this dev_t. If there
+				 * is no such minor we print the property now
+				 * so it gets displayed.
+				 */
+				minor = DI_MINOR_NIL;
+				while ((minor = di_minor_next((di_node_t)node,
+				    minor)) != DI_MINOR_NIL) {
+					if (di_minor_devt(minor) == pdev)
+						break;
+				}
+				if (minor == DI_MINOR_NIL)
+					goto print;
+			} else if (dev == pdev) {
+				/*
+				 * Caller requesting print of properties
+				 * associated with a specific matching minor
+				 * node.
+				 */
+				goto print;
+			}
+
+			/* otherwise skip print */
+			continue;
+		}
+
+print:		nitems = prop_type_guess(dumpops, prop, &prop_data, &prop_type);
 		if (nitems < 0)
 			continue;
 
+		if (nprop == 0) {
+			if (name) {
+				indent_to_level(ilev);
+				(void) printf("%s properties:\n", name);
+			}
+			ilev++;
+		}
+		nprop++;
+
 		indent_to_level(ilev);
 		(void) printf("name='%s' type=", PROPNAME(dumpops)(prop));
 
@@ -548,15 +609,13 @@
 			(void) printf(" items=%i", nitems);
 
 		/* print the major and minor numbers for a device property */
-		if (PROPDEVT(dumpops) != NULL) {
-			dev_t dev;
-
-			dev = PROPDEVT(dumpops)(prop);
-			if (dev != DDI_DEV_T_NONE) {
+		if (PROPDEVT(dumpops)) {
+			if ((pdev == DDI_DEV_T_NONE) ||
+			    (pdev == DDI_DEV_T_ANY)) {
+				(void) printf(" dev=none");
+			} else {
 				(void) printf(" dev=(%u,%u)",
-				    (uint_t)major(dev), (uint_t)minor(dev));
-			} else {
-				(void) printf(" dev=none");
+				    (uint_t)major(pdev), (uint_t)minor(pdev));
 			}
 		}
 
@@ -598,6 +657,8 @@
 
 		(void) putchar('\n');
 	}
+
+	return (nprop ? 1 : 0);
 }
 
 /*
@@ -682,17 +743,17 @@
 
 	if (opts.o_verbose)  {
 		if (dump_prop_list(&sysprop_dumpops, "System", ilev + 1,
-		    node)) {
+		    node, DDI_DEV_T_ANY)) {
 			(void) dump_prop_list(&globprop_dumpops, NULL, ilev + 1,
-			    node);
+			    node, DDI_DEV_T_ANY);
 		} else {
 			(void) dump_prop_list(&globprop_dumpops,
-			    "System software", ilev + 1, node);
+			    "System software", ilev + 1, node, DDI_DEV_T_ANY);
 		}
 		(void) dump_prop_list(&drvprop_dumpops, "Driver", ilev + 1,
-		    node);
+		    node, DDI_DEV_T_NONE);
 		(void) dump_prop_list(&hwprop_dumpops, "Hardware", ilev + 1,
-		    node);
+		    node, DDI_DEV_T_ANY);
 		dump_priv_data(ilev + 1, node);
 		dump_pathing_data(ilev + 1, node);
 		dump_link_data(ilev + 1, node, devlink_hdl);
@@ -708,26 +769,6 @@
 	return (DI_WALK_CONTINUE);
 }
 
-/*
- * Returns 0 if nothing is printed, 1 otherwise
- */
-static int
-dump_prop_list(const dumpops_t *dumpops, const char *name, int ilev,
-    di_node_t node)
-{
-	if (NEXTPROP(dumpops)(node, DI_PROP_NIL) == DI_PROP_NIL)
-		return (0);
-
-	if (name != NULL)  {
-		indent_to_level(ilev);
-		(void) printf("%s properties:\n", name);
-	}
-
-	dump_prop_list_common(dumpops, ilev + 1, node);
-	return (1);
-}
-
-
 /* _error([no_perror, ] fmt [, arg ...]) */
 static int
 _error(const char *opt_noperror, ...)
@@ -979,8 +1020,8 @@
 		indent_to_level(ilev);
 		(void) printf("%s#%d (%s)\n", di_driver_name(phci_node),
 		    di_instance(phci_node), path_state_name(di_path_state(pi)));
-
-		dump_prop_list_common(&pathprop_dumpops, ilev + 1, pi);
+		(void) dump_prop_list(&pathprop_dumpops, NULL, ilev + 1,
+		    pi, DDI_DEV_T_ANY);
 	}
 }
 
@@ -1325,6 +1366,10 @@
 
 		/* display who has this device minor node open */
 		dump_minor_link_data(ilev + 1, node, devt, devlink_hdl);
+
+		/* display properties associated with this devt */
+		(void) dump_prop_list(&drvprop_dumpops, "Minor",
+		    ilev + 1, node, devt);
 	}
 
 	/*
--- a/usr/src/uts/common/fs/devfs/devfs_subr.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/fs/devfs/devfs_subr.c	Wed Jul 30 10:30:05 2008 -0700
@@ -268,7 +268,8 @@
 static int
 dv_compare_nodes(const struct dv_node *dv1, const struct dv_node *dv2)
 {
-	int rv;
+	int	rv;
+
 	if ((rv = strcmp(dv1->dv_name, dv2->dv_name)) == 0)
 		return (0);
 	return ((rv < 0) ? -1 : 1);
@@ -282,8 +283,8 @@
 struct dv_node *
 dv_mkroot(struct vfs *vfsp, dev_t devfsdev)
 {
-	struct dv_node *dv;
-	struct vnode *vp;
+	struct dv_node	*dv;
+	struct vnode	*vp;
 
 	ASSERT(ddi_root_node() != NULL);
 	ASSERT(dv_node_cache != NULL);
@@ -332,9 +333,9 @@
 struct dv_node *
 dv_mkdir(struct dv_node *ddv, dev_info_t *devi, char *nm)
 {
-	struct dv_node *dv;
-	struct vnode *vp;
-	size_t nmlen;
+	struct dv_node	*dv;
+	struct vnode	*vp;
+	size_t		nmlen;
 
 	ASSERT((devi));
 	dcmn_err4(("dv_mkdir: %s\n", nm));
@@ -384,9 +385,9 @@
 dv_mknod(struct dv_node *ddv, dev_info_t *devi, char *nm,
 	struct ddi_minor_data *dmd)
 {
-	struct dv_node *dv;
-	struct vnode *vp;
-	size_t nmlen;
+	struct dv_node	*dv;
+	struct vnode	*vp;
+	size_t		nmlen;
 
 	dcmn_err4(("dv_mknod: %s\n", nm));
 
@@ -405,9 +406,12 @@
 	vn_setops(vp, vn_getops(DVTOV(ddv)));
 	vn_exists(vp);
 
-	ASSERT(MUTEX_HELD(&DEVI(devi)->devi_lock));
+	/* increment dev_ref with devi_lock held */
+	ASSERT(DEVI_BUSY_OWNED(devi));
+	mutex_enter(&DEVI(devi)->devi_lock);
 	dv->dv_devi = devi;
 	DEVI(devi)->devi_ref++;
+	mutex_exit(&DEVI(devi)->devi_lock);
 
 	dv->dv_ino = dv_mkino(devi, vp->v_type, vp->v_rdev);
 	dv->dv_nlink = 0;		/* updated on insert */
@@ -518,7 +522,7 @@
 void
 dv_insert(struct dv_node *ddv, struct dv_node *dv)
 {
-	avl_index_t where;
+	avl_index_t	where;
 
 	ASSERT(RW_WRITE_HELD(&ddv->dv_contents));
 	ASSERT(DVTOV(ddv)->v_type == VDIR);
@@ -577,7 +581,7 @@
 void
 dv_vattr_merge(struct dv_node *dv, struct vattr *vap)
 {
-	struct vnode *vp = DVTOV(dv);
+	struct vnode	*vp = DVTOV(dv);
 
 	vap->va_nodeid = dv->dv_ino;
 	vap->va_nlink = dv->dv_nlink;
@@ -608,8 +612,8 @@
 void
 devfs_get_defattr(struct vnode *vp, struct vattr *vap, int *no_fs_perm)
 {
-	mperm_t	mp;
-	struct dv_node *dv;
+	mperm_t		mp;
+	struct dv_node	*dv;
 
 	/* If vp isn't a dv_node, return something sensible */
 	if (!vn_matchops(vp, dv_vnodeops)) {
@@ -837,12 +841,12 @@
 static int
 dv_find_leafnode(dev_info_t *devi, char *minor_nm, struct ddi_minor_data *r_mi)
 {
-	struct ddi_minor_data *dmd;
+	struct ddi_minor_data	*dmd;
 
 	ASSERT(i_ddi_devi_attached(devi));
-	ASSERT(MUTEX_HELD(&DEVI(devi)->devi_lock));
 
 	dcmn_err3(("dv_find_leafnode: %s\n", minor_nm));
+	ASSERT(DEVI_BUSY_OWNED(devi));
 	for (dmd = DEVI(devi)->devi_minor; dmd; dmd = dmd->next) {
 
 		/*
@@ -880,10 +884,10 @@
 static struct dv_node *
 dv_clone_mknod(struct dv_node *ddv, char *drvname)
 {
-	major_t	major;
-	struct dv_node *dvp;
-	char *devnm;
-	struct ddi_minor_data *dmd;
+	major_t			major;
+	struct dv_node		*dvp;
+	char			*devnm;
+	struct ddi_minor_data	*dmd;
 
 	/*
 	 * Make sure drvname is a STREAMS driver. We load the driver,
@@ -926,12 +930,13 @@
 {
 	extern int isminiroot;	/* see modctl.c */
 
-	int rv = 0, was_busy = 0, nmlen, write_held = 0;
-	struct vnode *vp;
-	struct dv_node *dv, *dup;
-	dev_info_t *pdevi, *devi = NULL;
-	char *mnm;
-	struct ddi_minor_data *dmd;
+	int			circ;
+	int			rv = 0, was_busy = 0, nmlen, write_held = 0;
+	struct vnode		*vp;
+	struct dv_node		*dv, *dup;
+	dev_info_t		*pdevi, *devi = NULL;
+	char			*mnm;
+	struct ddi_minor_data	*dmd;
 
 	dcmn_err3(("dv_find %s\n", nm));
 
@@ -1119,24 +1124,29 @@
 		dv = dv_mkdir(ddv, devi, nm);
 	} else {
 		/*
-		 * For clone minors, load the driver indicated by minor name.
+		 * Allocate dmd first to avoid KM_SLEEP with active
+		 * ndi_devi_enter.
 		 */
-		mutex_enter(&DEVI(devi)->devi_lock);
+		dmd = kmem_zalloc(sizeof (*dmd), KM_SLEEP);
+		ndi_devi_enter(devi, &circ);
 		if (devi == clone_dip) {
+			/*
+			 * For clone minors, load the driver indicated by
+			 * minor name.
+			 */
 			dv = dv_clone_mknod(ddv, mnm + 1);
 		} else {
 			/*
 			 * Find minor node and make a dv_node
 			 */
-			dmd = kmem_zalloc(sizeof (*dmd), KM_SLEEP);
 			if (dv_find_leafnode(devi, mnm + 1, dmd) == 0) {
 				dv = dv_mknod(ddv, devi, nm, dmd);
 				if (dmd->ddm_node_priv)
 					dpfree(dmd->ddm_node_priv);
 			}
-			kmem_free(dmd, sizeof (*dmd));
 		}
-		mutex_exit(&DEVI(devi)->devi_lock);
+		ndi_devi_exit(devi, circ);
+		kmem_free(dmd, sizeof (*dmd));
 	}
 	/*
 	 * Release hold from ndi_devi_config_one()
@@ -1213,11 +1223,11 @@
 void
 dv_filldir(struct dv_node *ddv)
 {
-	struct dv_node *dv;
-	dev_info_t *devi, *pdevi;
-	struct ddi_minor_data *dmd;
-	char devnm[MAXNAMELEN];
-	int circ;
+	struct dv_node		*dv;
+	dev_info_t		*devi, *pdevi;
+	struct ddi_minor_data	*dmd;
+	char			devnm[MAXNAMELEN];
+	int			circ, ccirc;
 
 	ASSERT(DVTOV(ddv)->v_type == VDIR);
 	ASSERT(RW_WRITE_HELD(&ddv->dv_contents));
@@ -1240,7 +1250,7 @@
 
 		dcmn_err3(("dv_filldir: node %s\n", ddi_node_name(devi)));
 
-		mutex_enter(&DEVI(devi)->devi_lock);
+		ndi_devi_enter(devi, &ccirc);
 		for (dmd = DEVI(devi)->devi_minor; dmd; dmd = dmd->next) {
 			char *addr;
 
@@ -1272,7 +1282,7 @@
 			dv_insert(ddv, dv);
 			VN_RELE(DVTOV(dv));
 		}
-		mutex_exit(&DEVI(devi)->devi_lock);
+		ndi_devi_exit(devi, ccirc);
 
 		(void) ddi_deviname(devi, devnm);
 		if ((dv = dv_findbyname(ddv, devnm + 1)) == NULL) {
@@ -1300,10 +1310,10 @@
 int
 dv_cleandir(struct dv_node *ddv, char *devnm, uint_t flags)
 {
-	struct dv_node *dv;
-	struct dv_node *next;
-	struct vnode *vp;
-	int busy = 0;
+	struct dv_node	*dv;
+	struct dv_node	*next;
+	struct vnode	*vp;
+	int		busy = 0;
 
 	/*
 	 * We should always be holding the tsd_clean_key here: dv_cleandir()
@@ -1428,15 +1438,15 @@
 static int
 dv_reset_perm_dir(struct dv_node *ddv, uint_t flags)
 {
-	struct dv_node *dv;
-	struct vnode *vp;
-	int retval = 0;
-	struct vattr *attrp;
-	mperm_t mp;
-	char *nm;
-	uid_t old_uid;
-	gid_t old_gid;
-	mode_t old_mode;
+	struct dv_node	*dv;
+	struct vnode	*vp;
+	int		retval = 0;
+	struct vattr	*attrp;
+	mperm_t		mp;
+	char		*nm;
+	uid_t		old_uid;
+	gid_t		old_gid;
+	mode_t		old_mode;
 
 	rw_enter(&ddv->dv_contents, RW_WRITER);
 	for (dv = DV_FIRST_ENTRY(ddv); dv; dv = DV_NEXT_ENTRY(ddv, dv)) {
@@ -1524,8 +1534,8 @@
 int
 devfs_reset_perm(uint_t flags)
 {
-	struct dv_node *dvp;
-	int rval;
+	struct dv_node	*dvp;
+	int		rval;
 
 	if ((dvp = devfs_dip_to_dvnode(ddi_root_node())) == NULL)
 		return (0);
@@ -1555,17 +1565,17 @@
 static int
 devfs_remdrv_rmdir(vnode_t *dirvp, const char *dir, vnode_t *rvp)
 {
-	int error;
-	vnode_t *vp;
-	int eof;
-	struct iovec iov;
-	struct uio uio;
-	struct dirent64 *dp;
-	dirent64_t *dbuf;
-	size_t dlen;
-	size_t dbuflen;
-	int ndirents = 64;
-	char *nm;
+	int		error;
+	vnode_t		*vp;
+	int		eof;
+	struct iovec	iov;
+	struct uio	uio;
+	struct dirent64	*dp;
+	dirent64_t	*dbuf;
+	size_t		dlen;
+	size_t		dbuflen;
+	int		ndirents = 64;
+	char		*nm;
 
 	VN_HOLD(dirvp);
 
@@ -1651,21 +1661,21 @@
 int
 devfs_remdrv_cleanup(const char *dir, const char *nodename)
 {
-	int error;
-	vnode_t *vp;
-	vnode_t *dirvp;
-	int eof;
-	struct iovec iov;
-	struct uio uio;
-	struct dirent64 *dp;
-	dirent64_t *dbuf;
-	size_t dlen;
-	size_t dbuflen;
-	int ndirents = 64;
-	int nodenamelen = strlen(nodename);
-	char *nm;
-	struct pathname pn;
-	vnode_t *rvp;		/* root node of the underlying attribute fs */
+	int		error;
+	vnode_t		*vp;
+	vnode_t		*dirvp;
+	int		eof;
+	struct iovec	iov;
+	struct uio	uio;
+	struct dirent64	*dp;
+	dirent64_t	*dbuf;
+	size_t		dlen;
+	size_t		dbuflen;
+	int		ndirents = 64;
+	int		nodenamelen = strlen(nodename);
+	char		*nm;
+	struct pathname	pn;
+	vnode_t		*rvp;	/* root node of the underlying attribute fs */
 
 	dcmn_err5(("devfs_remdrv_cleanup: %s %s\n", dir, nodename));
 
--- a/usr/src/uts/common/io/cmlb.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/io/cmlb.c	Wed Jul 30 10:30:05 2008 -0700
@@ -41,6 +41,7 @@
 #include <sys/efi_partition.h>
 #include <sys/cmlb.h>
 #include <sys/cmlb_impl.h>
+#include <sys/ddi_impldefs.h>
 
 /*
  * Driver minor node structure and data table
@@ -139,6 +140,18 @@
 	{0}
 };
 
+/*
+ * Declare the dynamic properties implemented in prop_op(9E) implementation
+ * that we want to have show up in a di_init(3DEVINFO) device tree snapshot
+ * of drivers that call cmlb_attach().
+ */
+static i_ddi_prop_dyn_t cmlb_prop_dyn[] = {
+	{"Nblocks",		DDI_PROP_TYPE_INT64,	S_IFBLK},
+	{"Size",		DDI_PROP_TYPE_INT64,	S_IFCHR},
+	{"device-nblocks",	DDI_PROP_TYPE_INT64},
+	{"device-blksize",	DDI_PROP_TYPE_INT},
+	{NULL}
+};
 
 /*
  * External kernel interfaces
@@ -595,6 +608,9 @@
 		return (ENXIO);
 	}
 
+	/* Define the dynamic properties for devinfo spapshots. */
+	i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), cmlb_prop_dyn);
+
 	cl->cl_state = CMLB_ATTACHED;
 
 	mutex_exit(CMLB_MUTEX(cl));
@@ -624,6 +640,7 @@
 	cl->cl_def_labeltype = CMLB_LABEL_UNDEF;
 	cl->cl_f_geometry_is_valid = FALSE;
 	ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL);
+	i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), NULL);
 	cl->cl_state = CMLB_INITED;
 	mutex_exit(CMLB_MUTEX(cl));
 }
@@ -1162,6 +1179,25 @@
 		err = ENOTTY;
 
 	}
+
+	/*
+	 * An ioctl that succeeds and changed ('set') size(9P) information
+	 * needs to invalidate the cached devinfo snapshot to avoid having
+	 * old information being returned in a snapshots.
+	 *
+	 * NB: When available, call ddi_change_minor_node() to clear
+	 * SSIZEVALID in specfs vnodes via spec_size_invalidate().
+	 */
+	if (err == 0) {
+		switch (cmd) {
+		case DKIOCSGEOM:
+		case DKIOCSAPART:
+		case DKIOCSVTOC:
+		case DKIOCSETEFI:
+			i_ddi_prop_dyn_cache_invalidate(CMLB_DEVINFO(cl),
+			    i_ddi_prop_dyn_driver_get(CMLB_DEVINFO(cl)));
+		}
+	}
 	return (err);
 }
 
@@ -2737,7 +2773,7 @@
 		/*
 		 * Refer to comments related to off-by-1 at the
 		 * header of this file.
-		 * Before caculating geometry, capacity should be
+		 * Before calculating geometry, capacity should be
 		 * decreased by 1.
 		 */
 
@@ -4735,3 +4771,106 @@
 	return (err);
 }
 #endif
+
+int
+cmlb_prop_op(cmlb_handle_t cmlbhandle,
+    dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
+    char *name, caddr_t valuep, int *lengthp, int part, void *tg_cookie)
+{
+	struct cmlb_lun	*cl;
+	diskaddr_t	capacity;
+	uint32_t	lbasize;
+	enum		dp { DP_NBLOCKS, DP_BLKSIZE } dp;
+	int		callers_length;
+	caddr_t		buffer;
+	uint64_t	nblocks64;
+	uint_t		dblk;
+
+	/* Always fallback to ddi_prop_op... */
+	cl = (struct cmlb_lun *)cmlbhandle;
+	if (cl == NULL) {
+fallback:	return (ddi_prop_op(dev, dip, prop_op, mod_flags,
+		    name, valuep, lengthp));
+	}
+
+	/* Pick up capacity and blocksize information. */
+	capacity = cl->cl_blockcount;
+	if (capacity == 0)
+		goto fallback;
+	lbasize = cl->cl_tgt_blocksize;
+	if (lbasize == 0)
+		lbasize = DEV_BSIZE;	/* 0 -> DEV_BSIZE units */
+
+	/* Check for dynamic property of whole device. */
+	if (dev == DDI_DEV_T_ANY) {
+		/* Fallback to ddi_prop_op if we don't understand.  */
+		if (strcmp(name, "device-nblocks") == 0)
+			dp = DP_NBLOCKS;
+		else if (strcmp(name, "device-blksize") == 0)
+			dp = DP_BLKSIZE;
+		else
+			goto fallback;
+
+		/* get callers length, establish length of our dynamic prop */
+		callers_length = *lengthp;
+		if (dp == DP_NBLOCKS)
+			*lengthp = sizeof (uint64_t);
+		else if (dp == DP_BLKSIZE)
+			*lengthp = sizeof (uint32_t);
+
+		/* service request for the length of the property */
+		if (prop_op == PROP_LEN)
+			return (DDI_PROP_SUCCESS);
+
+		switch (prop_op) {
+		case PROP_LEN_AND_VAL_ALLOC:
+			if ((buffer = kmem_alloc(*lengthp,
+			    (mod_flags & DDI_PROP_CANSLEEP) ?
+			    KM_SLEEP : KM_NOSLEEP)) == NULL)
+				return (DDI_PROP_NO_MEMORY);
+			*(caddr_t *)valuep = buffer;	/* set callers buf */
+			break;
+
+		case PROP_LEN_AND_VAL_BUF:
+			/* the length of the prop and the request must match */
+			if (callers_length != *lengthp)
+				return (DDI_PROP_INVAL_ARG);
+			buffer = valuep;		/* get callers buf */
+			break;
+
+		default:
+			return (DDI_PROP_INVAL_ARG);
+		}
+
+		/* transfer the value into the buffer */
+		if (dp == DP_NBLOCKS)
+			*((uint64_t *)buffer) = capacity;
+		else if (dp == DP_BLKSIZE)
+			*((uint32_t *)buffer) = lbasize;
+
+		return (DDI_PROP_SUCCESS);
+	}
+
+	/*
+	 * Support dynamic size oriented properties of partition. Requests
+	 * issued under conditions where size is valid are passed to
+	 * ddi_prop_op_nblocks with the size information, otherwise the
+	 * request is passed to ddi_prop_op. Size depends on valid geometry.
+	 */
+	if (!cmlb_is_valid(cmlbhandle))
+		goto fallback;
+
+	/* Get partition nblocks value. */
+	(void) cmlb_partinfo(cmlbhandle, part,
+	    (diskaddr_t *)&nblocks64, NULL, NULL, NULL, tg_cookie);
+
+	/*
+	 * Assume partition information is in DEV_BSIZE units, compute
+	 * divisor for size(9P) property representation.
+	 */
+	dblk = lbasize / DEV_BSIZE;
+
+	/* Now let ddi_prop_op_nblocks_blksize() handle the request. */
+	return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op, mod_flags,
+	    name, valuep, lengthp, nblocks64 / dblk, lbasize));
+}
--- a/usr/src/uts/common/io/devinfo.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/io/devinfo.c	Wed Jul 30 10:30:05 2008 -0700
@@ -32,6 +32,7 @@
 #include <sys/pathname.h>
 #include <sys/debug.h>
 #include <sys/autoconf.h>
+#include <sys/vmsystm.h>
 #include <sys/conf.h>
 #include <sys/file.h>
 #include <sys/kmem.h>
@@ -74,6 +75,8 @@
  */
 static int di_max_opens = 32;
 
+static int di_prop_dyn = 1;		/* enable dynamic property support */
+
 #define	DI_FULL_PARENT		0
 #define	DI_READONLY_PARENT	1
 #define	DI_NODE_SPECIES		2
@@ -85,7 +88,12 @@
 #define	IOC_COPY	3	/* copyout in progress */
 
 /*
- * Keep max alignment so we can move snapshot to different platforms
+ * Keep max alignment so we can move snapshot to different platforms.
+ *
+ * NOTE: Most callers should rely on the di_checkmem return value
+ * being aligned, and reestablish *off_p with aligned value, instead
+ * of trying to align size of their allocations: this approach will
+ * minimize memory use.
  */
 #define	DI_ALIGN(addr)	((addr + 7l) & ~7l)
 
@@ -94,10 +102,10 @@
  * Size of each chunk is buf_size.
  */
 struct di_mem {
-	struct di_mem *next;	/* link to next chunk */
-	char *buf;		/* contiguous kernel memory */
-	size_t buf_size;	/* size of buf in bytes */
-	devmap_cookie_t cook;	/* cookie from ddi_umem_alloc */
+	struct di_mem	*next;		/* link to next chunk */
+	char		*buf;		/* contiguous kernel memory */
+	size_t		buf_size;	/* size of buf in bytes */
+	devmap_cookie_t	cook;		/* cookie from ddi_umem_alloc */
 };
 
 /*
@@ -124,15 +132,15 @@
 		(stack)->circ[(stack)->depth - 1]); \
 	((stack)->depth--); \
 }
-#define	PUSH_STACK(stack, node, offp)	{ \
+#define	PUSH_STACK(stack, node, off_p)	{ \
 	ASSERT(node != NULL); \
 	ndi_devi_enter((dev_info_t *)node, &(stack)->circ[(stack)->depth]); \
 	(stack)->dip[(stack)->depth] = (node); \
-	(stack)->offset[(stack)->depth] = (void *)(offp); \
+	(stack)->offset[(stack)->depth] = (void *)(off_p); \
 	((stack)->depth)++; \
 }
 
-#define	DI_ALL_PTR(s)	((struct di_all *)(intptr_t)di_mem_addr((s), 0))
+#define	DI_ALL_PTR(s)	DI_ALL(di_mem_addr((s), 0))
 
 /*
  * With devfs, the device tree has no global locks. The device tree is
@@ -228,17 +236,17 @@
  * Soft state associated with each instance of driver open.
  */
 static struct di_state {
-	di_off_t mem_size;	/* total # bytes in memlist	*/
-	struct di_mem *memlist;	/* head of memlist		*/
-	uint_t command;		/* command from ioctl		*/
-	int di_iocstate;	/* snapshot ioctl state		*/
-	mod_hash_t *reg_dip_hash;
-	mod_hash_t *reg_pip_hash;
-	int lnode_count;
-	int link_count;
-
-	mod_hash_t *lnode_hash;
-	mod_hash_t *link_hash;
+	di_off_t	mem_size;	/* total # bytes in memlist */
+	struct di_mem	*memlist;	/* head of memlist */
+	uint_t		command;	/* command from ioctl */
+	int		di_iocstate;	/* snapshot ioctl state	*/
+	mod_hash_t	*reg_dip_hash;
+	mod_hash_t	*reg_pip_hash;
+	int		lnode_count;
+	int		link_count;
+
+	mod_hash_t	*lnode_hash;
+	mod_hash_t	*link_hash;
 } **di_states;
 
 static kmutex_t di_lock;	/* serialize instance assignment */
@@ -285,18 +293,19 @@
 static di_off_t di_snapshot_and_clean(struct di_state *);
 static di_off_t di_copydevnm(di_off_t *, struct di_state *);
 static di_off_t di_copytree(struct dev_info *, di_off_t *, struct di_state *);
-static di_off_t di_copynode(struct di_stack *, struct di_state *);
+static di_off_t di_copynode(struct dev_info *, struct di_stack *,
+    struct di_state *);
 static di_off_t di_getmdata(struct ddi_minor_data *, di_off_t *, di_off_t,
     struct di_state *);
 static di_off_t di_getppdata(struct dev_info *, di_off_t *, struct di_state *);
 static di_off_t di_getdpdata(struct dev_info *, di_off_t *, struct di_state *);
-static di_off_t di_getprop(struct ddi_prop *, di_off_t *,
-    struct di_state *, struct dev_info *, int);
+static di_off_t di_getprop(int, struct ddi_prop **, di_off_t *,
+    struct di_state *, struct dev_info *);
 static void di_allocmem(struct di_state *, size_t);
 static void di_freemem(struct di_state *);
 static void di_copymem(struct di_state *st, caddr_t buf, size_t bufsiz);
 static di_off_t di_checkmem(struct di_state *, di_off_t, size_t);
-static caddr_t di_mem_addr(struct di_state *, di_off_t);
+static void *di_mem_addr(struct di_state *, di_off_t);
 static int di_setstate(struct di_state *, int);
 static void di_register_dip(struct di_state *, dev_info_t *, di_off_t);
 static void di_register_pip(struct di_state *, mdi_pathinfo_t *, di_off_t);
@@ -310,8 +319,14 @@
 static int di_cache_lookup(struct di_state *st);
 static int di_cache_update(struct di_state *st);
 static void di_cache_print(di_cache_debug_t msglevel, char *fmt, ...);
-int build_vhci_list(dev_info_t *vh_devinfo, void *arg);
-int build_phci_list(dev_info_t *ph_devinfo, void *arg);
+static int build_vhci_list(dev_info_t *vh_devinfo, void *arg);
+static int build_phci_list(dev_info_t *ph_devinfo, void *arg);
+
+extern int modrootloaded;
+extern void mdi_walk_vhcis(int (*)(dev_info_t *, void *), void *);
+extern void mdi_vhci_walk_phcis(dev_info_t *,
+	int (*)(dev_info_t *, void *), void *);
+
 
 static struct cb_ops di_cb_ops = {
 	di_open,		/* open */
@@ -401,7 +416,7 @@
 static int
 di_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
 {
-	int error = DDI_FAILURE;
+	int	error = DDI_FAILURE;
 
 	switch (infocmd) {
 	case DDI_INFO_DEVT2DEVINFO:
@@ -425,7 +440,7 @@
 static int
 di_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 {
-	int error = DDI_FAILURE;
+	int	error = DDI_FAILURE;
 
 	switch (cmd) {
 	case DDI_ATTACH:
@@ -458,7 +473,7 @@
 static int
 di_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 {
-	int error = DDI_FAILURE;
+	int	error = DDI_FAILURE;
 
 	switch (cmd) {
 	case DDI_DETACH:
@@ -487,8 +502,8 @@
 static int
 di_open(dev_t *devp, int flag, int otyp, cred_t *credp)
 {
-	int m;
-	minor_t minor_parent = getminor(*devp);
+	int	m;
+	minor_t	minor_parent = getminor(*devp);
 
 	if (minor_parent != DI_FULL_PARENT &&
 	    minor_parent != DI_READONLY_PARENT)
@@ -527,8 +542,8 @@
 static int
 di_close(dev_t dev, int flag, int otype, cred_t *cred_p)
 {
-	struct di_state *st;
-	int m = (int)getminor(dev) - DI_NODE_SPECIES;
+	struct di_state	*st;
+	int		m = (int)getminor(dev) - DI_NODE_SPECIES;
 
 	if (m < 0) {
 		cmn_err(CE_WARN, "closing non-existent devinfo minor %d",
@@ -559,17 +574,16 @@
 static int
 di_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
 {
-	int rv, error;
-	di_off_t off;
-	struct di_all *all;
-	struct di_state *st;
-	int m = (int)getminor(dev) - DI_NODE_SPECIES;
-
-	major_t i;
-	char *drv_name;
-	size_t map_size, size;
-	struct di_mem *dcp;
-	int ndi_flags;
+	int		rv, error;
+	di_off_t	off;
+	struct di_all	*all;
+	struct di_state	*st;
+	int		m = (int)getminor(dev) - DI_NODE_SPECIES;
+	major_t		i;
+	char		*drv_name;
+	size_t		map_size, size;
+	struct di_mem	*dcp;
+	int		ndi_flags;
 
 	if (m < 0 || m >= di_max_opens) {
 		return (ENXIO);
@@ -645,8 +659,7 @@
 		if (di_setstate(st, IOC_COPY) == -1)
 			return (EBUSY);
 
-		map_size = ((struct di_all *)
-		    (intptr_t)di_mem_addr(st, 0))->map_size;
+		map_size = DI_ALL_PTR(st)->map_size;
 		if (map_size == 0) {
 			(void) di_setstate(st, IOC_DONE);
 			return (EFAULT);
@@ -712,17 +725,22 @@
 	if (di_setstate(st, IOC_SNAP) == -1)
 		return (EBUSY);
 
+	/*
+	 * Initial memlist always holds di_all and the root_path - and
+	 * is at least a page and size.
+	 */
 	size = sizeof (struct di_all) +
 	    sizeof (((struct dinfo_io *)(NULL))->root_path);
 	if (size < PAGESIZE)
 		size = PAGESIZE;
-	di_allocmem(st, size);
-
-	all = (struct di_all *)(intptr_t)di_mem_addr(st, 0);
+	off = di_checkmem(st, 0, size);
+	all = DI_ALL_PTR(st);
+	off += sizeof (struct di_all);		/* real length of di_all */
+
 	all->devcnt = devcnt;
 	all->command = st->command;
 	all->version = DI_SNAPSHOT_VERSION;
-	all->top_vhci_devinfo = 0;	/* filled up by build_vhci_list. */
+	all->top_vhci_devinfo = 0;		/* filled by build_vhci_list. */
 
 	/*
 	 * Note the endianness in case we need to transport snapshot
@@ -741,6 +759,7 @@
 		(void) di_setstate(st, IOC_IDLE);
 		return (EFAULT);
 	}
+	off += size;				/* real length of root_path */
 
 	if ((st->command & DINFOCLEANUP) && !DEVICES_FILES_CLEANABLE(st)) {
 		di_freemem(st);
@@ -755,8 +774,6 @@
 		return (error);
 	}
 
-	off = DI_ALIGN(sizeof (struct di_all) + size);
-
 	/*
 	 * Only the fully enabled version may force load drivers or read
 	 * the parent private data from a driver.
@@ -834,8 +851,8 @@
 static void
 di_allocmem(struct di_state *st, size_t size)
 {
-	struct di_mem *mem = kmem_zalloc(sizeof (struct di_mem),
-	    KM_SLEEP);
+	struct di_mem	*mem = kmem_zalloc(sizeof (struct di_mem), KM_SLEEP);
+
 	/*
 	 * Round up size to nearest power of 2. If it is less
 	 * than st->mem_size, set it to st->mem_size (i.e.,
@@ -876,8 +893,8 @@
 static void
 di_copymem(struct di_state *st, caddr_t buf, size_t bufsiz)
 {
-	struct di_mem *dcp;
-	size_t copysz;
+	struct di_mem	*dcp;
+	size_t		copysz;
 
 	if (st->mem_size == 0) {
 		ASSERT(st->memlist == NULL);
@@ -910,7 +927,7 @@
 static void
 di_freemem(struct di_state *st)
 {
-	struct di_mem *dcp, *tmp;
+	struct di_mem	*dcp, *tmp;
 
 	dcmn_err2((CE_CONT, "di_freemem\n"));
 
@@ -980,7 +997,7 @@
 static size_t
 di_mem2cache(struct di_state *st, struct di_cache *cache)
 {
-	size_t map_size;
+	size_t	map_size;
 
 	ASSERT(cache->cache_size == 0);
 	ASSERT(cache->cache_data == NULL);
@@ -1040,6 +1057,8 @@
 		di_allocmem(st, size);
 	}
 
+	/* verify that return value is aligned */
+	ASSERT(off == DI_ALIGN(off));
 	return (off);
 }
 
@@ -1050,9 +1069,9 @@
 static di_off_t
 di_copyformat(di_off_t off, struct di_state *st, intptr_t arg, int mode)
 {
-	di_off_t size;
-	struct di_priv_data *priv;
-	struct di_all *all = (struct di_all *)(intptr_t)di_mem_addr(st, 0);
+	di_off_t		size;
+	struct di_priv_data	*priv;
+	struct di_all		*all = DI_ALL_PTR(st);
 
 	dcmn_err2((CE_CONT, "di_copyformat: off=%x, arg=%p mode=%x\n",
 	    off, (void *)arg, mode));
@@ -1083,8 +1102,7 @@
 		 * check memory
 		 */
 		size = all->n_ppdata * sizeof (struct di_priv_format);
-		off = di_checkmem(st, off, size);
-		all->ppdata_format = off;
+		all->ppdata_format = off = di_checkmem(st, off, size);
 		if (ddi_copyin(priv->parent, di_mem_addr(st, off), size,
 		    mode) != 0) {
 			kmem_free(priv, sizeof (struct di_priv_data));
@@ -1099,8 +1117,7 @@
 		 * check memory
 		 */
 		size = all->n_dpdata * sizeof (struct di_priv_format);
-		off = di_checkmem(st, off, size);
-		all->dpdata_format = off;
+		all->dpdata_format = off = di_checkmem(st, off, size);
 		if (ddi_copyin(priv->driver, di_mem_addr(st, off), size,
 		    mode) != 0) {
 			kmem_free(priv, sizeof (struct di_priv_data));
@@ -1117,10 +1134,10 @@
 /*
  * Return the real address based on the offset (off) within snapshot
  */
-static caddr_t
+static void *
 di_mem_addr(struct di_state *st, di_off_t off)
 {
-	struct di_mem *dcp = st->memlist;
+	struct di_mem	*dcp = st->memlist;
 
 	dcmn_err3((CE_CONT, "di_mem_addr: dcp=%p off=%x\n",
 	    (void *)dcp, off));
@@ -1147,9 +1164,9 @@
 static uint_t
 di_hash_byptr(void *arg, mod_hash_key_t key)
 {
-	struct di_key *dik = key;
-	size_t rshift;
-	void *ptr;
+	struct di_key	*dik = key;
+	size_t		rshift;
+	void		*ptr;
 
 	ASSERT(arg == NULL);
 
@@ -1215,8 +1232,8 @@
 static int
 di_pkey_cmp(struct di_pkey *pk1, struct di_pkey *pk2)
 {
-	char *p1, *p2;
-	int rv;
+	char	*p1, *p2;
+	int	rv;
 
 	if (pk1->pk_pip !=  pk2->pk_pip)
 		return (pk1->pk_pip > pk2->pk_pip ? 1 : -1);
@@ -1243,7 +1260,7 @@
 static int
 di_key_cmp(mod_hash_key_t key1, mod_hash_key_t key2)
 {
-	struct di_key *dik1, *dik2;
+	struct di_key	*dik1, *dik2;
 
 	dik1 = key1;
 	dik2 = key2;
@@ -1270,15 +1287,15 @@
 static di_off_t
 di_snapshot(struct di_state *st)
 {
-	di_off_t off;
-	struct di_all *all;
-	dev_info_t *rootnode;
-	char buf[80];
-	int plen;
-	char *path;
-	vnode_t *vp;
-
-	all = (struct di_all *)(intptr_t)di_mem_addr(st, 0);
+	di_off_t	off;
+	struct di_all	*all;
+	dev_info_t	*rootnode;
+	char		buf[80];
+	int		plen;
+	char		*path;
+	vnode_t		*vp;
+
+	all = DI_ALL_PTR(st);
 	dcmn_err((CE_CONT, "Taking a snapshot of devinfo tree...\n"));
 
 	/*
@@ -1411,20 +1428,19 @@
 /*
  * construct vhci linkage in the snapshot.
  */
-int
+static int
 build_vhci_list(dev_info_t *vh_devinfo, void *arg)
 {
-	struct di_all *all;
-	struct di_node *me;
-	struct di_state *st;
-	di_off_t off;
-	phci_walk_arg_t pwa;
+	struct di_all	*all;
+	struct di_node	*me;
+	struct di_state	*st;
+	di_off_t	off;
+	phci_walk_arg_t	pwa;
 
 	dcmn_err3((CE_CONT, "build_vhci list\n"));
 
-	dcmn_err3((CE_CONT, "vhci node %s, instance #%d\n",
-	    DEVI(vh_devinfo)->devi_node_name,
-	    DEVI(vh_devinfo)->devi_instance));
+	dcmn_err3((CE_CONT, "vhci node %s%d\n",
+	    ddi_driver_name(vh_devinfo), ddi_get_instance(vh_devinfo)));
 
 	st = (struct di_state *)arg;
 	if (di_dip_find(st, vh_devinfo, &off) != 0) {
@@ -1435,16 +1451,14 @@
 	dcmn_err3((CE_CONT, "st->mem_size: %d vh_devinfo off: 0x%x\n",
 	    st->mem_size, off));
 
-	all = (struct di_all *)(intptr_t)di_mem_addr(st, 0);
+	all = DI_ALL_PTR(st);
 	if (all->top_vhci_devinfo == 0) {
 		all->top_vhci_devinfo = off;
 	} else {
-		me = (struct di_node *)
-		    (intptr_t)di_mem_addr(st, all->top_vhci_devinfo);
+		me = DI_NODE(di_mem_addr(st, all->top_vhci_devinfo));
 
 		while (me->next_vhci != 0) {
-			me = (struct di_node *)
-			    (intptr_t)di_mem_addr(st, me->next_vhci);
+			me = DI_NODE(di_mem_addr(st, me->next_vhci));
 		}
 
 		me->next_vhci = off;
@@ -1460,41 +1474,37 @@
 /*
  * construct phci linkage for the given vhci in the snapshot.
  */
-int
+static int
 build_phci_list(dev_info_t *ph_devinfo, void *arg)
 {
-	struct di_node *vh_di_node;
-	struct di_node *me;
-	phci_walk_arg_t *pwa;
-	di_off_t off;
+	struct di_node	*vh_di_node;
+	struct di_node	*me;
+	phci_walk_arg_t	*pwa;
+	di_off_t	off;
 
 	pwa = (phci_walk_arg_t *)arg;
 
 	dcmn_err3((CE_CONT, "build_phci list for vhci at offset: 0x%x\n",
 	    pwa->off));
 
-	vh_di_node = (struct di_node *)(intptr_t)di_mem_addr(pwa->st, pwa->off);
-
+	vh_di_node = DI_NODE(di_mem_addr(pwa->st, pwa->off));
 	if (di_dip_find(pwa->st, ph_devinfo, &off) != 0) {
 		dcmn_err((CE_WARN, "di_dip_find error for the given node\n"));
 		return (DDI_WALK_TERMINATE);
 	}
 
-	dcmn_err3((CE_CONT, "phci node %s, instance #%d, at offset 0x%x\n",
-	    DEVI(ph_devinfo)->devi_node_name,
-	    DEVI(ph_devinfo)->devi_instance, off));
+	dcmn_err3((CE_CONT, "phci node %s%d, at offset 0x%x\n",
+	    ddi_driver_name(ph_devinfo), ddi_get_instance(ph_devinfo), off));
 
 	if (vh_di_node->top_phci == 0) {
 		vh_di_node->top_phci = off;
 		return (DDI_WALK_CONTINUE);
 	}
 
-	me = (struct di_node *)
-	    (intptr_t)di_mem_addr(pwa->st, vh_di_node->top_phci);
+	me = DI_NODE(di_mem_addr(pwa->st, vh_di_node->top_phci));
 
 	while (me->next_phci != 0) {
-		me = (struct di_node *)
-		    (intptr_t)di_mem_addr(pwa->st, me->next_phci);
+		me = DI_NODE(di_mem_addr(pwa->st, me->next_phci));
 	}
 	me->next_phci = off;
 
@@ -1505,11 +1515,11 @@
  * Assumes all devinfo nodes in device tree have been snapshotted
  */
 static void
-snap_driver_list(struct di_state *st, struct devnames *dnp, di_off_t *poff_p)
+snap_driver_list(struct di_state *st, struct devnames *dnp, di_off_t *off_p)
 {
-	struct dev_info *node;
-	struct di_node *me;
-	di_off_t off;
+	struct dev_info	*node;
+	struct di_node	*me;
+	di_off_t	off;
 
 	ASSERT(mutex_owned(&dnp->dn_lock));
 
@@ -1519,7 +1529,7 @@
 			continue;
 
 		ASSERT(off > 0);
-		me = (struct di_node *)(intptr_t)di_mem_addr(st, off);
+		me = DI_NODE(di_mem_addr(st, off));
 		ASSERT(me->next == 0 || me->next == -1);
 		/*
 		 * Only nodes which were BOUND when they were
@@ -1528,11 +1538,11 @@
 		if (me->next != -1)
 			continue;
 
-		*poff_p = off;
-		poff_p = &me->next;
+		*off_p = off;
+		off_p = &me->next;
 	}
 
-	*poff_p = 0;
+	*off_p = 0;
 }
 
 /*
@@ -1542,10 +1552,10 @@
 static di_off_t
 di_copydevnm(di_off_t *off_p, struct di_state *st)
 {
-	int i;
-	di_off_t off;
-	size_t size;
-	struct di_devnm *dnp;
+	int		i;
+	di_off_t	off;
+	size_t		size;
+	struct di_devnm	*dnp;
 
 	dcmn_err2((CE_CONT, "di_copydevnm: *off_p = %p\n", (void *)off_p));
 
@@ -1553,15 +1563,13 @@
 	 * make sure there is some allocated memory
 	 */
 	size = devcnt * sizeof (struct di_devnm);
-	off = di_checkmem(st, *off_p, size);
-	*off_p = off;
+	*off_p = off = di_checkmem(st, *off_p, size);
+	dnp = DI_DEVNM(di_mem_addr(st, off));
+	off += size;
 
 	dcmn_err((CE_CONT, "Start copying devnamesp[%d] at offset 0x%x\n",
 	    devcnt, off));
 
-	dnp = (struct di_devnm *)(intptr_t)di_mem_addr(st, off);
-	off += size;
-
 	for (i = 0; i < devcnt; i++) {
 		if (devnamesp[i].dn_name == NULL) {
 			continue;
@@ -1577,14 +1585,13 @@
 		 * the same problem.
 		 */
 		dcmn_err2((CE_CONT, "di_copydevnm: %s%d, off=%x\n",
-		    devnamesp[i].dn_name, devnamesp[i].dn_instance,
-		    off));
-
-		off = di_checkmem(st, off, strlen(devnamesp[i].dn_name) + 1);
-		dnp[i].name = off;
+		    devnamesp[i].dn_name, devnamesp[i].dn_instance, off));
+
+		size = strlen(devnamesp[i].dn_name) + 1;
+		dnp[i].name = off = di_checkmem(st, off, size);
 		(void) strcpy((char *)di_mem_addr(st, off),
 		    devnamesp[i].dn_name);
-		off += DI_ALIGN(strlen(devnamesp[i].dn_name) + 1);
+		off += size;
 
 		mutex_enter(&devnamesp[i].dn_lock);
 
@@ -1605,9 +1612,9 @@
 		if ((DINFOPROP & st->command) &&
 		    devnamesp[i].dn_global_prop_ptr) {
 			dnp[i].global_prop = off;
-			off = di_getprop(
-			    devnamesp[i].dn_global_prop_ptr->prop_list,
-			    &dnp[i].global_prop, st, NULL, DI_PROP_GLB_LIST);
+			off = di_getprop(DI_PROP_GLB_LIST,
+			    &devnamesp[i].dn_global_prop_ptr->prop_list,
+			    &dnp[i].global_prop, st, NULL);
 		}
 
 		/*
@@ -1639,8 +1646,9 @@
 static di_off_t
 di_copytree(struct dev_info *root, di_off_t *off_p, struct di_state *st)
 {
-	di_off_t off;
-	struct di_stack *dsp = kmem_zalloc(sizeof (struct di_stack), KM_SLEEP);
+	di_off_t	off;
+	struct dev_info	*node;
+	struct di_stack	*dsp = kmem_zalloc(sizeof (struct di_stack), KM_SLEEP);
 
 	dcmn_err((CE_CONT, "di_copytree: root = %p, *off_p = %x\n",
 	    (void *)root, *off_p));
@@ -1667,7 +1675,8 @@
 	 * child and sibling nodes on the stack.
 	 */
 	while (!EMPTY_STACK(dsp)) {
-		off = di_copynode(dsp, st);
+		node = TOP_NODE(dsp);
+		off = di_copynode(node, dsp, st);
 	}
 
 	/*
@@ -1684,24 +1693,23 @@
  * ioctl command.
  */
 static di_off_t
-di_copynode(struct di_stack *dsp, struct di_state *st)
+di_copynode(struct dev_info *node, struct di_stack *dsp, struct di_state *st)
 {
 	di_off_t	off;
 	struct di_node	*me;
-	struct dev_info	*node;
+	size_t		size;
 
 	dcmn_err2((CE_CONT, "di_copynode: depth = %x\n", dsp->depth));
-
-	node = TOP_NODE(dsp);
-
-	ASSERT(node != NULL);
+	ASSERT((node != NULL) && (node == TOP_NODE(dsp)));
 
 	/*
 	 * check memory usage, and fix offsets accordingly.
 	 */
-	off = di_checkmem(st, *(TOP_OFFSET(dsp)), sizeof (struct di_node));
-	*(TOP_OFFSET(dsp)) = off;
+	size = sizeof (struct di_node);
+	*(TOP_OFFSET(dsp)) = off = di_checkmem(st, *(TOP_OFFSET(dsp)), size);
 	me = DI_NODE(di_mem_addr(st, off));
+	me->self = off;
+	off += size;
 
 	dcmn_err((CE_CONT, "copy node %s, instance #%d, at offset 0x%x\n",
 	    node->devi_node_name, node->devi_instance, off));
@@ -1711,9 +1719,8 @@
 	 * self		-- offset of current node within snapshot
 	 * nodeid	-- pointer to PROM node (tri-valued)
 	 * state	-- hot plugging device state
-	 * node_state	-- devinfo node state (CF1, CF2, etc.)
+	 * node_state	-- devinfo node state
 	 */
-	me->self = off;
 	me->instance = node->devi_instance;
 	me->nodeid = node->devi_nodeid;
 	me->node_class = node->devi_node_class;
@@ -1745,16 +1752,10 @@
 	 */
 	di_register_dip(st, (dev_info_t *)node, me->self);
 
-	/*
-	 * increment offset
-	 */
-	off += sizeof (struct di_node);
-
 #ifdef	DEVID_COMPATIBILITY
 	/* check for devid as property marker */
 	if (node->devi_devid_str) {
 		ddi_devid_t	devid;
-		int		devid_size;
 
 		/*
 		 * The devid is now represented as a property. For
@@ -1765,44 +1766,43 @@
 		 */
 		if (ddi_devid_str_decode(node->devi_devid_str, &devid, NULL) ==
 		    DDI_SUCCESS) {
-			devid_size = ddi_devid_sizeof(devid);
-			off = di_checkmem(st, off, devid_size);
+			size = ddi_devid_sizeof(devid);
+			off = di_checkmem(st, off, size);
 			me->devid = off;
-			bcopy(devid, di_mem_addr(st, off), devid_size);
-			off += devid_size;
+			bcopy(devid, di_mem_addr(st, off), size);
+			off += size;
 			ddi_devid_free(devid);
 		}
 	}
 #endif	/* DEVID_COMPATIBILITY */
 
 	if (node->devi_node_name) {
-		off = di_checkmem(st, off, strlen(node->devi_node_name) + 1);
-		me->node_name = off;
+		size = strlen(node->devi_node_name) + 1;
+		me->node_name = off = di_checkmem(st, off, size);
 		(void) strcpy(di_mem_addr(st, off), node->devi_node_name);
-		off += strlen(node->devi_node_name) + 1;
+		off += size;
 	}
 
 	if (node->devi_compat_names && (node->devi_compat_length > 1)) {
-		off = di_checkmem(st, off, node->devi_compat_length);
-		me->compat_names = off;
-		me->compat_length = node->devi_compat_length;
-		bcopy(node->devi_compat_names, di_mem_addr(st, off),
-		    node->devi_compat_length);
-		off += node->devi_compat_length;
+		size = node->devi_compat_length;
+		me->compat_names = off = di_checkmem(st, off, size);
+		me->compat_length = (int)size;
+		bcopy(node->devi_compat_names, di_mem_addr(st, off), size);
+		off += size;
 	}
 
 	if (node->devi_addr) {
-		off = di_checkmem(st, off, strlen(node->devi_addr) + 1);
-		me->address = off;
+		size = strlen(node->devi_addr) + 1;
+		me->address = off = di_checkmem(st, off, size);
 		(void) strcpy(di_mem_addr(st, off), node->devi_addr);
-		off += strlen(node->devi_addr) + 1;
+		off += size;
 	}
 
 	if (node->devi_binding_name) {
-		off = di_checkmem(st, off, strlen(node->devi_binding_name) + 1);
-		me->bind_name = off;
+		size = strlen(node->devi_binding_name) + 1;
+		me->bind_name = off = di_checkmem(st, off, size);
 		(void) strcpy(di_mem_addr(st, off), node->devi_binding_name);
-		off += strlen(node->devi_binding_name) + 1;
+		off += size;
 	}
 
 	me->drv_major = node->devi_major;
@@ -1826,17 +1826,17 @@
 	}
 
 	/*
-	 * Grab current per dev_info node lock to
-	 * get minor data and properties.
+	 * LOCKING: We already have an active ndi_devi_enter to gather the
+	 * minor data, and we will take devi_lock to gather properties as
+	 * needed off di_getprop.
 	 */
-	mutex_enter(&(node->devi_lock));
-
 	if (!(DINFOMINOR & st->command)) {
 		goto path;
 	}
 
+	ASSERT(DEVI_BUSY_OWNED(node));
 	if (node->devi_minor) {		/* minor data */
-		me->minor_data = DI_ALIGN(off);
+		me->minor_data = off;
 		off = di_getmdata(node->devi_minor, &me->minor_data,
 		    me->self, st);
 	}
@@ -1852,7 +1852,7 @@
 
 	if (MDI_CLIENT(node)) {
 		me->multipath_component = MULTIPATH_COMPONENT_CLIENT;
-		me->multipath_client = DI_ALIGN(off);
+		me->multipath_client = off;
 		off = di_getpath_data((dev_info_t *)node, &me->multipath_client,
 		    me->self, st, 1);
 		dcmn_err((CE_WARN, "me->multipath_client = %x for node %p "
@@ -1863,7 +1863,7 @@
 
 	if (MDI_PHCI(node)) {
 		me->multipath_component = MULTIPATH_COMPONENT_PHCI;
-		me->multipath_phci = DI_ALIGN(off);
+		me->multipath_phci = off;
 		off = di_getpath_data((dev_info_t *)node, &me->multipath_phci,
 		    me->self, st, 0);
 		dcmn_err((CE_WARN, "me->multipath_phci = %x for node %p "
@@ -1874,25 +1874,25 @@
 
 property:
 	if (!(DINFOPROP & st->command)) {
-		goto unlock;
+		goto priv_data;
 	}
 
 	if (node->devi_drv_prop_ptr) {	/* driver property list */
-		me->drv_prop = DI_ALIGN(off);
-		off = di_getprop(node->devi_drv_prop_ptr, &me->drv_prop, st,
-		    node, DI_PROP_DRV_LIST);
+		me->drv_prop = off;
+		off = di_getprop(DI_PROP_DRV_LIST, &node->devi_drv_prop_ptr,
+		    &me->drv_prop, st, node);
 	}
 
 	if (node->devi_sys_prop_ptr) {	/* system property list */
-		me->sys_prop = DI_ALIGN(off);
-		off = di_getprop(node->devi_sys_prop_ptr, &me->sys_prop, st,
-		    node, DI_PROP_SYS_LIST);
+		me->sys_prop = off;
+		off = di_getprop(DI_PROP_SYS_LIST, &node->devi_sys_prop_ptr,
+		    &me->sys_prop, st, node);
 	}
 
 	if (node->devi_hw_prop_ptr) {	/* hardware property list */
-		me->hw_prop = DI_ALIGN(off);
-		off = di_getprop(node->devi_hw_prop_ptr, &me->hw_prop, st,
-		    node, DI_PROP_HW_LIST);
+		me->hw_prop = off;
+		off = di_getprop(DI_PROP_HW_LIST, &node->devi_hw_prop_ptr,
+		    &me->hw_prop, st, node);
 	}
 
 	if (node->devi_global_prop_list == NULL) {
@@ -1907,39 +1907,37 @@
 		ASSERT(me->drv_major != -1);
 		if (node->devi_global_prop_list !=
 		    devnamesp[me->drv_major].dn_global_prop_ptr) {
-			me->glob_prop = DI_ALIGN(off);
-			off = di_getprop(node->devi_global_prop_list->prop_list,
-			    &me->glob_prop, st, node, DI_PROP_GLB_LIST);
+			me->glob_prop = off;
+			off = di_getprop(DI_PROP_GLB_LIST,
+			    &node->devi_global_prop_list->prop_list,
+			    &me->glob_prop, st, node);
 		}
 	}
 
-unlock:
-	/*
-	 * release current per dev_info node lock
-	 */
-	mutex_exit(&(node->devi_lock));
-
 priv_data:
 	if (!(DINFOPRIVDATA & st->command)) {
 		goto pm_info;
 	}
 
 	if (ddi_get_parent_data((dev_info_t *)node) != NULL) {
-		me->parent_data = DI_ALIGN(off);
+		me->parent_data = off;
 		off = di_getppdata(node, &me->parent_data, st);
 	}
 
 	if (ddi_get_driver_private((dev_info_t *)node) != NULL) {
-		me->driver_data = DI_ALIGN(off);
+		me->driver_data = off;
 		off = di_getdpdata(node, &me->driver_data, st);
 	}
 
 pm_info: /* NOT implemented */
 
 subtree:
+	/* keep the stack aligned */
+	off = DI_ALIGN(off);
+
 	if (!(DINFOSUBTREE & st->command)) {
 		POP_STACK(dsp);
-		return (DI_ALIGN(off));
+		return (off);
 	}
 
 child:
@@ -1948,7 +1946,7 @@
 	 * Hold the parent busy while doing so.
 	 */
 	if (node->devi_child) {
-		me->child = DI_ALIGN(off);
+		me->child = off;
 		PUSH_STACK(dsp, node->devi_child, &me->child);
 		return (me->child);
 	}
@@ -1969,7 +1967,7 @@
 		/*
 		 * a sibling is found, replace top of stack by its sibling
 		 */
-		me->sibling = DI_ALIGN(off);
+		me->sibling = off;
 		PUSH_STACK(dsp, node->devi_sibling, &me->sibling);
 		return (me->sibling);
 	}
@@ -1977,7 +1975,7 @@
 	/*
 	 * DONE with all nodes
 	 */
-	return (DI_ALIGN(off));
+	return (off);
 }
 
 static i_lnode_t *
@@ -2015,7 +2013,7 @@
 static i_link_t *
 i_link_alloc(int spec_type)
 {
-	i_link_t *i_link;
+	i_link_t	*i_link;
 
 	i_link = kmem_zalloc(sizeof (i_link_t), KM_SLEEP);
 	i_link->spec_type = spec_type;
@@ -2096,7 +2094,7 @@
 
 	/*
 	 * if the source or target of this device usage information doesn't
-	 * corrospond to a device node then we don't report it via
+	 * correspond to a device node then we don't report it via
 	 * libdevinfo so return.
 	 */
 	if ((ldi_usage->src_dip == NULL) || (ldi_usage->tgt_dip == NULL))
@@ -2125,7 +2123,7 @@
 	 * operations - so it may already be in the hash.
 	 */
 	i_lnode = i_lnode_alloc(ldi_usage->src_modid);
-	i_lnode->di_node = (struct di_node *)(intptr_t)di_mem_addr(st, soff);
+	i_lnode->di_node = DI_NODE(di_mem_addr(st, soff));
 	i_lnode->devt = ldi_usage->src_devt;
 
 	res = mod_hash_find(st->lnode_hash, i_lnode, &nodep);
@@ -2148,7 +2146,7 @@
 	 * allocate a tgt i_lnode and add it to the lnode hash
 	 */
 	i_lnode = i_lnode_alloc(ldi_usage->tgt_modid);
-	i_lnode->di_node = (struct di_node *)(intptr_t)di_mem_addr(st, toff);
+	i_lnode->di_node = DI_NODE(di_mem_addr(st, toff));
 	i_lnode->devt = ldi_usage->tgt_devt;
 
 	res = mod_hash_find(st->lnode_hash, i_lnode, &nodep);
@@ -2238,7 +2236,7 @@
 	ASSERT(data->link_count <= data->st->link_count);
 
 	/* fill in fields for the di_link snapshot */
-	me = (struct di_link *)(intptr_t)di_mem_addr(data->st, i_link->self);
+	me = DI_LINK(di_mem_addr(data->st, i_link->self));
 	me->self = i_link->self;
 	me->spec_type = i_link->spec_type;
 
@@ -2256,16 +2254,14 @@
 	 * Save this link's offset in the src_lnode snapshot's link_out
 	 * field
 	 */
-	melnode = (struct di_lnode *)
-	    (intptr_t)di_mem_addr(data->st, me->src_lnode);
+	melnode = DI_LNODE(di_mem_addr(data->st, me->src_lnode));
 	me->src_link_next = melnode->link_out;
 	melnode->link_out = me->self;
 
 	/*
 	 * Put this link on the tgt_lnode's link_in field
 	 */
-	melnode = (struct di_lnode *)
-	    (intptr_t)di_mem_addr(data->st, me->tgt_lnode);
+	melnode = DI_LNODE(di_mem_addr(data->st, me->tgt_lnode));
 	me->tgt_link_next = melnode->link_in;
 	melnode->link_in = me->self;
 
@@ -2311,7 +2307,7 @@
 	ASSERT(data->lnode_count <= data->st->lnode_count);
 
 	/* fill in fields for the di_lnode snapshot */
-	me = (struct di_lnode *)(intptr_t)di_mem_addr(data->st, i_lnode->self);
+	me = DI_LNODE(di_mem_addr(data->st, i_lnode->self));
 	me->self = i_lnode->self;
 
 	if (i_lnode->devt == DDI_DEV_T_NONE) {
@@ -2354,8 +2350,8 @@
 static di_off_t
 di_getlink_data(di_off_t off, struct di_state *st)
 {
-	struct i_layer_data data = {0};
-	size_t size;
+	struct i_layer_data	data = {0};
+	size_t			size;
 
 	dcmn_err2((CE_CONT, "di_copylyr: off = %x\n", off));
 
@@ -2380,12 +2376,12 @@
 	/* get a pointer to snapshot memory for all the di_lnodes */
 	size = sizeof (struct di_lnode) * st->lnode_count;
 	data.lnode_off = off = di_checkmem(st, off, size);
-	off += DI_ALIGN(size);
+	off += size;
 
 	/* get a pointer to snapshot memory for all the di_links */
 	size = sizeof (struct di_link) * st->link_count;
 	data.link_off = off = di_checkmem(st, off, size);
-	off += DI_ALIGN(size);
+	off += size;
 
 	data.lnode_count = data.link_count = 0;
 	data.st = st;
@@ -2415,14 +2411,16 @@
 
 /*
  * Copy all minor data nodes attached to a devinfo node into the snapshot.
- * It is called from di_copynode with devi_lock held.
+ * It is called from di_copynode with active ndi_devi_enter to protect
+ * the list of minor nodes.
  */
 static di_off_t
 di_getmdata(struct ddi_minor_data *mnode, di_off_t *off_p, di_off_t node,
 	struct di_state *st)
 {
-	di_off_t off;
-	struct di_minor *me;
+	di_off_t	off;
+	struct di_minor	*me;
+	size_t		size;
 
 	dcmn_err2((CE_CONT, "di_getmdata:\n"));
 
@@ -2433,13 +2431,13 @@
 	*off_p = off;
 
 	do {
-		me = (struct di_minor *)(intptr_t)di_mem_addr(st, off);
+		me = DI_MINOR(di_mem_addr(st, off));
 		me->self = off;
 		me->type = mnode->type;
 		me->node = node;
 		me->user_private_data = NULL;
 
-		off += DI_ALIGN(sizeof (struct di_minor));
+		off += sizeof (struct di_minor);
 
 		/*
 		 * Split dev_t to major/minor, so it works for
@@ -2450,20 +2448,18 @@
 		me->spec_type = mnode->ddm_spec_type;
 
 		if (mnode->ddm_name) {
-			off = di_checkmem(st, off,
-			    strlen(mnode->ddm_name) + 1);
-			me->name = off;
+			size = strlen(mnode->ddm_name) + 1;
+			me->name = off = di_checkmem(st, off, size);
 			(void) strcpy(di_mem_addr(st, off), mnode->ddm_name);
-			off += DI_ALIGN(strlen(mnode->ddm_name) + 1);
+			off += size;
 		}
 
 		if (mnode->ddm_node_type) {
-			off = di_checkmem(st, off,
-			    strlen(mnode->ddm_node_type) + 1);
-			me->node_type = off;
+			size = strlen(mnode->ddm_node_type) + 1;
+			me->node_type = off = di_checkmem(st, off, size);
 			(void) strcpy(di_mem_addr(st, off),
 			    mnode->ddm_node_type);
-			off += DI_ALIGN(strlen(mnode->ddm_node_type) + 1);
+			off += size;
 		}
 
 		off = di_checkmem(st, off, sizeof (struct di_minor));
@@ -2485,9 +2481,9 @@
 static void
 di_register_dip(struct di_state *st, dev_info_t *dip, di_off_t off)
 {
-	struct dev_info *node = DEVI(dip);
-	struct di_key *key = kmem_zalloc(sizeof (*key), KM_SLEEP);
-	struct di_dkey *dk;
+	struct dev_info	*node = DEVI(dip);
+	struct di_key	*key = kmem_zalloc(sizeof (*key), KM_SLEEP);
+	struct di_dkey	*dk;
 
 	ASSERT(dip);
 	ASSERT(off > 0);
@@ -2639,12 +2635,18 @@
 
 
 static di_off_t
-di_path_getprop(mdi_pathinfo_t *pip, di_off_t off, di_off_t *off_p,
+di_path_getprop(mdi_pathinfo_t *pip, di_off_t *off_p,
     struct di_state *st)
 {
-	nvpair_t *prop = NULL;
-	struct di_path_prop *me;
-
+	nvpair_t		*prop = NULL;
+	struct di_path_prop	*me;
+	int			off;
+	size_t			size;
+	char			*str;
+	uchar_t			*buf;
+	uint_t			nelems;
+
+	off = *off_p;
 	if (mdi_pi_get_next_prop(pip, NULL) == NULL) {
 		*off_p = 0;
 		return (off);
@@ -2654,19 +2656,17 @@
 	*off_p = off;
 
 	while (prop = mdi_pi_get_next_prop(pip, prop)) {
-		int delta = 0;
-
-		me = (struct di_path_prop *)(intptr_t)di_mem_addr(st, off);
+		me = DI_PATHPROP(di_mem_addr(st, off));
 		me->self = off;
 		off += sizeof (struct di_path_prop);
 
 		/*
 		 * property name
 		 */
-		off = di_checkmem(st, off, strlen(nvpair_name(prop)) + 1);
-		me->prop_name = off;
+		size = strlen(nvpair_name(prop)) + 1;
+		me->prop_name = off = di_checkmem(st, off, size);
 		(void) strcpy(di_mem_addr(st, off), nvpair_name(prop));
-		off += strlen(nvpair_name(prop)) + 1;
+		off += size;
 
 		switch (nvpair_type(prop)) {
 		case DATA_TYPE_BYTE:
@@ -2674,32 +2674,30 @@
 		case DATA_TYPE_UINT16:
 		case DATA_TYPE_INT32:
 		case DATA_TYPE_UINT32:
-			delta = sizeof (int32_t);
 			me->prop_type = DDI_PROP_TYPE_INT;
-			off = di_checkmem(st, off, delta);
+			size = sizeof (int32_t);
+			off = di_checkmem(st, off, size);
 			(void) nvpair_value_int32(prop,
-			    (int32_t *)(intptr_t)di_mem_addr(st, off));
+			    (int32_t *)di_mem_addr(st, off));
 			break;
 
 		case DATA_TYPE_INT64:
 		case DATA_TYPE_UINT64:
-			delta = sizeof (int64_t);
 			me->prop_type = DDI_PROP_TYPE_INT64;
-			off = di_checkmem(st, off, delta);
+			size = sizeof (int64_t);
+			off = di_checkmem(st, off, size);
 			(void) nvpair_value_int64(prop,
-			    (int64_t *)(intptr_t)di_mem_addr(st, off));
+			    (int64_t *)di_mem_addr(st, off));
 			break;
 
 		case DATA_TYPE_STRING:
-		{
-			char *str;
+			me->prop_type = DDI_PROP_TYPE_STRING;
 			(void) nvpair_value_string(prop, &str);
-			delta = strlen(str) + 1;
-			me->prop_type = DDI_PROP_TYPE_STRING;
-			off = di_checkmem(st, off, delta);
+			size = strlen(str) + 1;
+			off = di_checkmem(st, off, size);
 			(void) strcpy(di_mem_addr(st, off), str);
 			break;
-		}
+
 		case DATA_TYPE_BYTE_ARRAY:
 		case DATA_TYPE_INT16_ARRAY:
 		case DATA_TYPE_UINT16_ARRAY:
@@ -2707,30 +2705,26 @@
 		case DATA_TYPE_UINT32_ARRAY:
 		case DATA_TYPE_INT64_ARRAY:
 		case DATA_TYPE_UINT64_ARRAY:
-		{
-			uchar_t *buf;
-			uint_t nelems;
+			me->prop_type = DDI_PROP_TYPE_BYTE;
 			(void) nvpair_value_byte_array(prop, &buf, &nelems);
-			delta = nelems;
-			me->prop_type = DDI_PROP_TYPE_BYTE;
+			size = nelems;
 			if (nelems != 0) {
-				off = di_checkmem(st, off, delta);
-				bcopy(buf, di_mem_addr(st, off), nelems);
+				off = di_checkmem(st, off, size);
+				bcopy(buf, di_mem_addr(st, off), size);
 			}
 			break;
+
+		default:	/* Unknown or unhandled type; skip it */
+			size = 0;
+			break;
 		}
 
-		default:	/* Unknown or unhandled type; skip it */
-			delta = 0;
-			break;
-		}
-
-		if (delta > 0) {
+		if (size > 0) {
 			me->prop_data = off;
 		}
 
-		me->prop_len = delta;
-		off += delta;
+		me->prop_len = (int)size;
+		off += size;
 
 		off = di_checkmem(st, off, sizeof (struct di_path_prop));
 		me->prop_next = off;
@@ -2763,18 +2757,19 @@
 }
 
 /*
- * poff_p: pointer to the linkage field. This links pips along the client|phci
+ * off_p: pointer to the linkage field. This links pips along the client|phci
  *	   linkage list.
  * noff  : Offset for the endpoint dip snapshot.
  */
 static di_off_t
-di_getpath_data(dev_info_t *dip, di_off_t *poff_p, di_off_t noff,
+di_getpath_data(dev_info_t *dip, di_off_t *off_p, di_off_t noff,
     struct di_state *st, int get_client)
 {
-	di_off_t off;
-	mdi_pathinfo_t *pip;
-	struct di_path *me;
-	mdi_pathinfo_t *(*next_pip)(dev_info_t *, mdi_pathinfo_t *);
+	di_off_t	off;
+	mdi_pathinfo_t	*pip;
+	struct di_path	*me;
+	mdi_pathinfo_t	*(*next_pip)(dev_info_t *, mdi_pathinfo_t *);
+	size_t		size;
 
 	dcmn_err2((CE_WARN, "di_getpath_data: client = %d", get_client));
 
@@ -2789,7 +2784,7 @@
 	else
 		next_pip = &mdi_get_next_client_path;
 
-	off = *poff_p;
+	off = *off_p;
 
 	pip = NULL;
 	while (pip = (*next_pip)(dip, pip)) {
@@ -2809,12 +2804,10 @@
 			 * first snapshotted i.e. when the other endpoint dip
 			 * was snapshotted.
 			 */
-			me = (struct di_path *)(intptr_t)
-			    di_mem_addr(st, stored_offset);
-
-			*poff_p = stored_offset;
-
-			di_path_one_endpoint(me, noff, &poff_p, get_client);
+			me = DI_PATH(di_mem_addr(st, stored_offset));
+			*off_p = stored_offset;
+
+			di_path_one_endpoint(me, noff, &off_p, get_client);
 
 			/*
 			 * The other endpoint and linkage were set when this
@@ -2833,11 +2826,11 @@
 		/*
 		 * Now that we need to snapshot this pip, check memory
 		 */
-		off = di_checkmem(st, off, sizeof (struct di_path));
-		me = (struct di_path *)(intptr_t)di_mem_addr(st, off);
+		size = sizeof (struct di_path);
+		*off_p = off = di_checkmem(st, off, size);
+		me = DI_PATH(di_mem_addr(st, off));
 		me->self = off;
-		*poff_p = off;
-		off += sizeof (struct di_path);
+		off += size;
 
 		me->path_snap_state =
 		    DI_PATH_SNAP_NOCLINK | DI_PATH_SNAP_NOPLINK;
@@ -2851,7 +2844,7 @@
 		me->path_client = me->path_phci = 0;
 		me->path_c_link = me->path_p_link = 0;
 
-		di_path_one_endpoint(me, noff, &poff_p, get_client);
+		di_path_one_endpoint(me, noff, &off_p, get_client);
 
 		/*
 		 * Note the existence of this pathinfo
@@ -2866,17 +2859,18 @@
 		/*
 		 * Get intermediate addressing info.
 		 */
-		off = di_checkmem(st, off, strlen(mdi_pi_get_addr(pip)) + 1);
-		me->path_addr = off;
+		size = strlen(mdi_pi_get_addr(pip)) + 1;
+		me->path_addr = off = di_checkmem(st, off, size);
 		(void) strcpy(di_mem_addr(st, off), mdi_pi_get_addr(pip));
-		off += strlen(mdi_pi_get_addr(pip)) + 1;
+		off += size;
 
 		/*
 		 * Get path properties if props are to be included in the
 		 * snapshot
 		 */
 		if (DINFOPROP & st->command) {
-			off = di_path_getprop(pip, off, &me->path_prop, st);
+			me->path_prop = off;
+			off = di_path_getprop(pip, &me->path_prop, st);
 		} else {
 			me->path_prop = 0;
 		}
@@ -2884,234 +2878,285 @@
 		mdi_pi_unlock(pip);
 	}
 
-	*poff_p = 0;
-
+	*off_p = 0;
 	return (off);
 }
 
 /*
+ * Return driver prop_op entry point for the specified devinfo node.
+ *
+ * To return a non-NULL value:
+ * - driver must be attached and held:
+ *   If driver is not attached we ignore the driver property list.
+ *   No one should rely on such properties.
+ * - driver "cb_prop_op != ddi_prop_op":
+ *   If "cb_prop_op == ddi_prop_op", framework does not need to call driver.
+ *   XXX or parent's bus_prop_op != ddi_bus_prop_op
+ */
+static int
+(*di_getprop_prop_op(struct dev_info *dip))
+	(dev_t, dev_info_t *, ddi_prop_op_t, int, char *, caddr_t, int *)
+{
+	struct dev_ops	*ops;
+
+	/* If driver is not attached we ignore the driver property list. */
+	if ((dip == NULL) || !i_ddi_devi_attached((dev_info_t *)dip))
+		return (NULL);
+
+	/*
+	 * Some nexus drivers incorrectly set cb_prop_op to nodev, nulldev,
+	 * or even NULL.
+	 */
+	ops = dip->devi_ops;
+	if (ops && ops->devo_cb_ops &&
+	    (ops->devo_cb_ops->cb_prop_op != ddi_prop_op) &&
+	    (ops->devo_cb_ops->cb_prop_op != nodev) &&
+	    (ops->devo_cb_ops->cb_prop_op != nulldev) &&
+	    (ops->devo_cb_ops->cb_prop_op != NULL))
+		return (ops->devo_cb_ops->cb_prop_op);
+	return (NULL);
+}
+
+static di_off_t
+di_getprop_add(int list, int dyn, struct di_state *st, struct dev_info *dip,
+    int (*prop_op)(),
+    char *name, dev_t devt, int aflags, int alen, caddr_t aval,
+    di_off_t off, di_off_t **off_pp)
+{
+	int		need_free = 0;
+	dev_t		pdevt;
+	int		pflags;
+	int		rv;
+	caddr_t		val;
+	int		len;
+	size_t		size;
+	struct di_prop	*pp;
+
+	/* If we have prop_op function, ask driver for latest value */
+	if (prop_op) {
+		ASSERT(dip);
+
+		/* Must search DDI_DEV_T_NONE with DDI_DEV_T_ANY */
+		pdevt = (devt == DDI_DEV_T_NONE) ? DDI_DEV_T_ANY : devt;
+
+		/*
+		 * We have type information in flags, but are invoking an
+		 * old non-typed prop_op(9E) interface. Since not all types are
+		 * part of DDI_PROP_TYPE_ANY (example is DDI_PROP_TYPE_INT64),
+		 * we set DDI_PROP_CONSUMER_TYPED - causing the framework to
+		 * expand type bits beyond DDI_PROP_TYPE_ANY.  This allows us
+		 * to use the legacy prop_op(9E) interface to obtain updates
+		 * non-DDI_PROP_TYPE_ANY dynamic properties.
+		 */
+		pflags = aflags & ~DDI_PROP_TYPE_MASK;
+		pflags |= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM |
+		    DDI_PROP_CONSUMER_TYPED;
+		rv = (*prop_op)(pdevt, (dev_info_t)dip, PROP_LEN_AND_VAL_ALLOC,
+		    pflags, name, &val, &len);
+
+		if (rv == DDI_PROP_SUCCESS) {
+			need_free = 1;		/* dynamic prop obtained */
+		} else if (dyn) {
+			/*
+			 * A dynamic property must succeed prop_op(9E) to show
+			 * up in the snapshot - that is the only source of its
+			 * value.
+			 */
+			return (off);		/* dynamic prop not supported */
+		} else {
+			/*
+			 * In case calling the driver caused an update off
+			 * prop_op(9E) of a non-dynamic property (code leading
+			 * to ddi_prop_change), we defer picking up val and
+			 * len informatiojn until after prop_op(9E) to ensure
+			 * that we snapshot the latest value.
+			 */
+			val = aval;
+			len = alen;
+
+		}
+	} else {
+		val = aval;
+		len = alen;
+	}
+
+	dcmn_err((CE_CONT, "di_getprop_add: list %d %s len %d val %p\n",
+	    list, name ? name : "NULL", len, (void *)val));
+
+	size = sizeof (struct di_prop);
+	**off_pp = off = di_checkmem(st, off, size);
+	pp = DI_PROP(di_mem_addr(st, off));
+	pp->self = off;
+	off += size;
+
+	pp->dev_major = getmajor(devt);
+	pp->dev_minor = getminor(devt);
+	pp->prop_flags = aflags;
+	pp->prop_list = list;
+
+	/* property name */
+	if (name) {
+		size = strlen(name) + 1;
+		pp->prop_name = off = di_checkmem(st, off, size);
+		(void) strcpy(di_mem_addr(st, off), name);
+		off += size;
+	} else {
+		pp->prop_name = -1;
+	}
+
+	pp->prop_len = len;
+	if (val == NULL) {
+		pp->prop_data = -1;
+	} else if (len != 0) {
+		size = len;
+		pp->prop_data = off = di_checkmem(st, off, size);
+		bcopy(val, di_mem_addr(st, off), size);
+		off += size;
+	}
+
+	pp->next = 0;			/* assume tail for now */
+	*off_pp = &pp->next;		/* return pointer to our next */
+
+	if (need_free)			/* free PROP_LEN_AND_VAL_ALLOC alloc */
+		kmem_free(val, len);
+	return (off);
+}
+
+
+/*
  * Copy a list of properties attached to a devinfo node. Called from
- * di_copynode with devi_lock held. The major number is passed in case
+ * di_copynode with active ndi_devi_enter. The major number is passed in case
  * we need to call driver's prop_op entry. The value of list indicates
  * which list we are copying. Possible values are:
  * DI_PROP_DRV_LIST, DI_PROP_SYS_LIST, DI_PROP_GLB_LIST, DI_PROP_HW_LIST
  */
 static di_off_t
-di_getprop(struct ddi_prop *prop, di_off_t *off_p, struct di_state *st,
-	struct dev_info *dip, int list)
+di_getprop(int list, struct ddi_prop **pprop, di_off_t *off_p,
+    struct di_state *st, struct dev_info *dip)
 {
-	dev_t dev;
-	int (*prop_op)();
-	int off, need_prop_op = 0;
-	int prop_op_fail = 0;
-	ddi_prop_t *propp = NULL;
-	struct di_prop *pp;
-	struct dev_ops *ops = NULL;
-	int prop_len;
-	caddr_t prop_val;
-
-
-	dcmn_err2((CE_CONT, "di_getprop:\n"));
+	struct ddi_prop		*prop;
+	int			(*prop_op)();
+	int			off;
+	struct ddi_minor_data	*mn;
+	i_ddi_prop_dyn_t	*dp;
+	struct plist {
+		struct plist	*pl_next;
+		char		*pl_name;
+		int		pl_flags;
+		dev_t		pl_dev;
+		int		pl_len;
+		caddr_t		pl_val;
+	}			*pl, *pl0, **plp;
 
 	ASSERT(st != NULL);
 
-	dcmn_err((CE_CONT, "copy property list at addr %p\n", (void *)prop));
+	off = *off_p;
+	*off_p = 0;
+	dcmn_err((CE_CONT, "di_getprop: copy property list %d at addr %p\n",
+	    list, (void *)*pprop));
+
+	/* get pointer to driver's prop_op(9E) implementation if DRV_LIST */
+	prop_op = (list == DI_PROP_DRV_LIST) ? di_getprop_prop_op(dip) : NULL;
 
 	/*
-	 * Figure out if we need to call driver's prop_op entry point.
-	 * The conditions are:
-	 *	-- driver property list
-	 *	-- driver must be attached and held
-	 *	-- driver's cb_prop_op != ddi_prop_op
-	 *		or parent's bus_prop_op != ddi_bus_prop_op
+	 * Form private list of properties, holding devi_lock for properties
+	 * than hang off the dip.
 	 */
-
-	if (list != DI_PROP_DRV_LIST) {
-		goto getprop;
+	if (dip)
+		mutex_enter(&(dip->devi_lock));
+	for (plp = &pl0, prop = *pprop;
+	    prop; plp = &pl->pl_next, prop = prop->prop_next) {
+		pl = kmem_alloc(sizeof (*pl), KM_SLEEP);
+		*plp = pl;
+		pl->pl_next = NULL;
+		if (prop->prop_name)
+			pl->pl_name = i_ddi_strdup(prop->prop_name, KM_SLEEP);
+		else
+			pl->pl_name = NULL;
+		pl->pl_flags = prop->prop_flags;
+		pl->pl_dev = prop->prop_dev;
+		if (prop->prop_len) {
+			pl->pl_len = prop->prop_len;
+			pl->pl_val = kmem_alloc(pl->pl_len, KM_SLEEP);
+			bcopy(prop->prop_val, pl->pl_val, pl->pl_len);
+		} else {
+			pl->pl_len = 0;
+			pl->pl_val = NULL;
+		}
 	}
+	if (dip)
+		mutex_exit(&(dip->devi_lock));
 
 	/*
-	 * If driver is not attached or if major is -1, we ignore
-	 * the driver property list. No one should rely on such
-	 * properties.
+	 * Now that we have dropped devi_lock, perform a second-pass to
+	 * add properties to the snapshot.  We do this as a second pass
+	 * because we may need to call prop_op(9E) and we can't hold
+	 * devi_lock across that call.
 	 */
-	if (!i_ddi_devi_attached((dev_info_t *)dip)) {
-		off = *off_p;
-		*off_p = 0;
-		return (off);
+	for (pl = pl0; pl; pl = pl0) {
+		pl0 = pl->pl_next;
+		off = di_getprop_add(list, 0, st, dip, prop_op, pl->pl_name,
+		    pl->pl_dev, pl->pl_flags, pl->pl_len, pl->pl_val,
+		    off, &off_p);
+		if (pl->pl_val)
+			kmem_free(pl->pl_val, pl->pl_len);
+		if (pl->pl_name)
+			kmem_free(pl->pl_name, strlen(pl->pl_name) + 1);
+		kmem_free(pl, sizeof (*pl));
 	}
 
 	/*
-	 * Now we have a driver which is held. We can examine entry points
-	 * and check the condition listed above.
-	 */
-	ops = dip->devi_ops;
-
-	/*
-	 * Some nexus drivers incorrectly set cb_prop_op to nodev,
-	 * nulldev or even NULL.
-	 */
-	if (ops && ops->devo_cb_ops &&
-	    (ops->devo_cb_ops->cb_prop_op != ddi_prop_op) &&
-	    (ops->devo_cb_ops->cb_prop_op != nodev) &&
-	    (ops->devo_cb_ops->cb_prop_op != nulldev) &&
-	    (ops->devo_cb_ops->cb_prop_op != NULL)) {
-		need_prop_op = 1;
-	}
-
-getprop:
-	/*
-	 * check memory availability
-	 */
-	off = di_checkmem(st, *off_p, sizeof (struct di_prop));
-	*off_p = off;
-	/*
-	 * Now copy properties
+	 * If there is no prop_op or dynamic property support has been
+	 * disabled, we are done.
 	 */
-	do {
-		pp = (struct di_prop *)(intptr_t)di_mem_addr(st, off);
-		pp->self = off;
-		/*
-		 * Split dev_t to major/minor, so it works for
-		 * both ILP32 and LP64 model
-		 */
-		pp->dev_major = getmajor(prop->prop_dev);
-		pp->dev_minor = getminor(prop->prop_dev);
-		pp->prop_flags = prop->prop_flags;
-		pp->prop_list = list;
-
-		/*
-		 * property name
-		 */
-		off += sizeof (struct di_prop);
-		if (prop->prop_name) {
-			off = di_checkmem(st, off, strlen(prop->prop_name)
-			    + 1);
-			pp->prop_name = off;
-			(void) strcpy(di_mem_addr(st, off), prop->prop_name);
-			off += strlen(prop->prop_name) + 1;
-		}
-
-		/*
-		 * Set prop_len here. This may change later
-		 * if cb_prop_op returns a different length.
-		 */
-		pp->prop_len = prop->prop_len;
-		if (!need_prop_op) {
-			if (prop->prop_val == NULL) {
-				dcmn_err((CE_WARN,
-				    "devinfo: property fault at %p",
-				    (void *)prop));
-				pp->prop_data = -1;
-			} else if (prop->prop_len != 0) {
-				off = di_checkmem(st, off, prop->prop_len);
-				pp->prop_data = off;
-				bcopy(prop->prop_val, di_mem_addr(st, off),
-				    prop->prop_len);
-				off += DI_ALIGN(pp->prop_len);
-			}
-		}
-
-		off = di_checkmem(st, off, sizeof (struct di_prop));
-		pp->next = off;
-		prop = prop->prop_next;
-	} while (prop);
-
-	pp->next = 0;
-
-	if (!need_prop_op) {
-		dcmn_err((CE_CONT, "finished property "
-		    "list at offset 0x%x\n", off));
+	if ((prop_op == NULL) || (di_prop_dyn == 0)) {
+		*off_p = 0;
 		return (off);
 	}
 
-	/*
-	 * If there is a need to call driver's prop_op entry,
-	 * we must release driver's devi_lock, because the
-	 * cb_prop_op entry point will grab it.
-	 *
-	 * The snapshot memory has already been allocated above,
-	 * which means the length of an active property should
-	 * remain fixed for this implementation to work.
-	 */
-
-
-	prop_op = ops->devo_cb_ops->cb_prop_op;
-	pp = (struct di_prop *)(intptr_t)di_mem_addr(st, *off_p);
-
-	mutex_exit(&dip->devi_lock);
-
-	do {
-		int err;
-		struct di_prop *tmp;
-
-		if (pp->next) {
-			tmp = (struct di_prop *)
-			    (intptr_t)di_mem_addr(st, pp->next);
+	/* Add dynamic driver properties to snapshot */
+	for (dp = i_ddi_prop_dyn_driver_get((dev_info_t *)dip);
+	    dp && dp->dp_name; dp++) {
+		if (dp->dp_spec_type) {
+			/* if spec_type, property of matching minor */
+			ASSERT(DEVI_BUSY_OWNED(dip));
+			for (mn = dip->devi_minor; mn; mn = mn->next) {
+				if (mn->ddm_spec_type != dp->dp_spec_type)
+					continue;
+				off = di_getprop_add(list, 1, st, dip, prop_op,
+				    dp->dp_name, mn->ddm_dev, dp->dp_type,
+				    0, NULL, off, &off_p);
+			}
 		} else {
-			tmp = NULL;
+			/* property of devinfo node */
+			off = di_getprop_add(list, 1, st, dip, prop_op,
+			    dp->dp_name, DDI_DEV_T_NONE, dp->dp_type,
+			    0, NULL, off, &off_p);
 		}
-
-		/*
-		 * call into driver's prop_op entry point
-		 *
-		 * Must search DDI_DEV_T_NONE with DDI_DEV_T_ANY
-		 */
-		dev = makedevice(pp->dev_major, pp->dev_minor);
-		if (dev == DDI_DEV_T_NONE)
-			dev = DDI_DEV_T_ANY;
-
-		dcmn_err((CE_CONT, "call prop_op"
-		    "(%lx, %p, PROP_LEN_AND_VAL_BUF, "
-		    "DDI_PROP_DONTPASS, \"%s\", %p, &%d)\n",
-		    dev,
-		    (void *)dip,
-		    (char *)di_mem_addr(st, pp->prop_name),
-		    (void *)di_mem_addr(st, pp->prop_data),
-		    pp->prop_len));
-
-		if ((err = (*prop_op)(dev, (dev_info_t)dip,
-		    PROP_LEN_AND_VAL_ALLOC, DDI_PROP_DONTPASS,
-		    (char *)di_mem_addr(st, pp->prop_name),
-		    &prop_val, &prop_len)) != DDI_PROP_SUCCESS) {
-			if ((propp = i_ddi_prop_search(dev,
-			    (char *)di_mem_addr(st, pp->prop_name),
-			    (uint_t)pp->prop_flags,
-			    &(DEVI(dip)->devi_drv_prop_ptr))) != NULL) {
-				pp->prop_len = propp->prop_len;
-				if (pp->prop_len != 0) {
-					off = di_checkmem(st, off,
-					    pp->prop_len);
-					pp->prop_data = off;
-					bcopy(propp->prop_val, di_mem_addr(st,
-					    pp->prop_data), propp->prop_len);
-					off += DI_ALIGN(pp->prop_len);
-				}
-			} else {
-				prop_op_fail = 1;
+	}
+
+	/* Add dynamic parent properties to snapshot */
+	for (dp = i_ddi_prop_dyn_parent_get((dev_info_t *)dip);
+	    dp && dp->dp_name; dp++) {
+		if (dp->dp_spec_type) {
+			/* if spec_type, property of matching minor */
+			ASSERT(DEVI_BUSY_OWNED(dip));
+			for (mn = dip->devi_minor; mn; mn = mn->next) {
+				if (mn->ddm_spec_type != dp->dp_spec_type)
+					continue;
+				off = di_getprop_add(list, 1, st, dip, prop_op,
+				    dp->dp_name, mn->ddm_dev, dp->dp_type,
+				    0, NULL, off, &off_p);
 			}
-		} else if (prop_len != 0) {
-			pp->prop_len = prop_len;
-			off = di_checkmem(st, off, prop_len);
-			pp->prop_data = off;
-			bcopy(prop_val, di_mem_addr(st, off), prop_len);
-			off += DI_ALIGN(prop_len);
-			kmem_free(prop_val, prop_len);
+		} else {
+			/* property of devinfo node */
+			off = di_getprop_add(list, 1, st, dip, prop_op,
+			    dp->dp_name, DDI_DEV_T_NONE, dp->dp_type,
+			    0, NULL, off, &off_p);
 		}
-
-		if (prop_op_fail) {
-			pp->prop_data = -1;
-			dcmn_err((CE_WARN, "devinfo: prop_op failure "
-			    "for \"%s\" err %d",
-			    di_mem_addr(st, pp->prop_name), err));
-		}
-
-		pp = tmp;
-
-	} while (pp);
-
-	mutex_enter(&dip->devi_lock);
-	dcmn_err((CE_CONT, "finished property list at offset 0x%x\n", off));
+	}
+
+	*off_p = 0;
 	return (off);
 }
 
@@ -3126,11 +3171,11 @@
 struct di_priv_format *
 di_match_drv_name(struct dev_info *node, struct di_state *st, int match)
 {
-	int i, count, len;
-	char *drv_name;
-	major_t major;
-	struct di_all *all;
-	struct di_priv_format *form;
+	int			i, count, len;
+	char			*drv_name;
+	major_t			major;
+	struct di_all		*all;
+	struct di_priv_format	*form;
 
 	dcmn_err2((CE_CONT, "di_match_drv_name: node = %s, match = %x\n",
 	    node->devi_node_name, match));
@@ -3157,16 +3202,13 @@
 	}
 
 	/* Now get the di_priv_format array */
-	all = (struct di_all *)(intptr_t)di_mem_addr(st, 0);
-
+	all = DI_ALL_PTR(st);
 	if (match == DI_MATCH_PARENT) {
 		count = all->n_ppdata;
-		form = (struct di_priv_format *)
-		    (intptr_t)(di_mem_addr(st, 0) + all->ppdata_format);
+		form = DI_PRIV_FORMAT(di_mem_addr(st, all->ppdata_format));
 	} else {
 		count = all->n_dpdata;
-		form = (struct di_priv_format *)
-		    (intptr_t)((caddr_t)all + all->dpdata_format);
+		form = DI_PRIV_FORMAT(di_mem_addr(st, all->dpdata_format));
 	}
 
 	len = strlen(drv_name);
@@ -3202,13 +3244,12 @@
 di_getprvdata(struct di_priv_format *pdp, struct dev_info *node,
     void *data, di_off_t *off_p, struct di_state *st)
 {
-	caddr_t pa;
-	void *ptr;
-	int i, size, repeat;
-	di_off_t off, off0, *tmp;
-	char *path;
-
-	label_t ljb;
+	caddr_t		pa;
+	void		*ptr;
+	int		i, size, repeat;
+	di_off_t	off, off0, *tmp;
+	char		*path;
+	label_t		ljb;
 
 	dcmn_err2((CE_CONT, "di_getprvdata:\n"));
 
@@ -3217,6 +3258,7 @@
 	 * limited to DI_MAX_PRIVDATA.
 	 */
 	off = di_checkmem(st, *off_p, DI_MAX_PRIVDATA);
+	*off_p = off;
 
 	if ((pdp->bytes == 0) || pdp->bytes > DI_MAX_PRIVDATA) {
 		goto failure;
@@ -3225,7 +3267,7 @@
 	if (!on_fault(&ljb)) {
 		/* copy the struct */
 		bcopy(data, di_mem_addr(st, off), pdp->bytes);
-		off0 = DI_ALIGN(pdp->bytes);
+		off0 = DI_ALIGN(pdp->bytes);	/* XXX remove DI_ALIGN */
 
 		/* dereferencing pointers */
 		for (i = 0; i < MAX_PTR_IN_PRV; i++) {
@@ -3238,8 +3280,7 @@
 			 * first, get the pointer content
 			 */
 			if ((pdp->ptr[i].offset < 0) ||
-			    (pdp->ptr[i].offset >
-			    pdp->bytes - sizeof (char *)))
+			    (pdp->ptr[i].offset > pdp->bytes - sizeof (char *)))
 				goto failure;	/* wrong offset */
 
 			pa = di_mem_addr(st, off + pdp->ptr[i].offset);
@@ -3295,7 +3336,7 @@
 			 */
 			*tmp = off0;
 			bcopy(ptr, di_mem_addr(st, off + off0), size);
-			off0 += DI_ALIGN(size);
+			off0 += DI_ALIGN(size);	/* XXX remove DI_ALIGN */
 		}
 	} else {
 		goto failure;
@@ -3306,8 +3347,6 @@
 	 * success if reached here
 	 */
 	no_fault();
-	*off_p = off;
-
 	return (off + off0);
 	/*NOTREACHED*/
 
@@ -3331,8 +3370,8 @@
 static di_off_t
 di_getppdata(struct dev_info *node, di_off_t *off_p, struct di_state *st)
 {
-	int off;
-	struct di_priv_format *ppdp;
+	int			off;
+	struct di_priv_format	*ppdp;
 
 	dcmn_err2((CE_CONT, "di_getppdata:\n"));
 
@@ -3353,8 +3392,8 @@
 static di_off_t
 di_getdpdata(struct dev_info *node, di_off_t *off_p, struct di_state *st)
 {
-	int off;
-	struct di_priv_format *dpdp;
+	int			off;
+	struct di_priv_format	*dpdp;
 
 	dcmn_err2((CE_CONT, "di_getdpdata:"));
 
@@ -3382,7 +3421,7 @@
 static int
 di_setstate(struct di_state *st, int new_state)
 {
-	int ret = 0;
+	int	ret = 0;
 
 	mutex_enter(&di_lock);
 	switch (new_state) {
@@ -3495,11 +3534,6 @@
 	return (error);
 }
 
-extern int modrootloaded;
-extern void mdi_walk_vhcis(int (*)(dev_info_t *, void *), void *);
-extern void mdi_vhci_walk_phcis(dev_info_t *,
-	int (*)(dev_info_t *, void *), void *);
-
 static void
 di_cache_write(struct di_cache *cache)
 {
@@ -3616,8 +3650,9 @@
 		buf += chunk;
 		map_size -= chunk;
 
-		/* Give pageout a chance to run */
-		delay(1);
+		/* If low on memory, give pageout a chance to run */
+		if (freemem < desfree)
+			delay(1);
 	}
 
 	/*
@@ -3877,14 +3912,12 @@
 
 		rval = 0;
 		if (di_cache2mem(&di_cache, st) > 0) {
-
-			ASSERT(DI_ALL_PTR(st));
-
 			/*
 			 * map_size is size of valid data in the
 			 * cached snapshot and may be less than
 			 * size of the cache.
 			 */
+			ASSERT(DI_ALL_PTR(st));
 			rval = DI_ALL_PTR(st)->map_size;
 
 			ASSERT(rval >= sizeof (struct di_all));
@@ -3922,9 +3955,9 @@
 static int
 di_cache_update(struct di_state *st)
 {
-	int rval;
-	uint32_t crc;
-	struct di_all *all;
+	int		rval;
+	uint32_t	crc;
+	struct di_all	*all;
 
 	ASSERT(DI_CACHE_LOCKED(di_cache));
 	ASSERT(snapshot_is_cacheable(st));
@@ -3950,7 +3983,6 @@
 	}
 
 	DI_ALL_PTR(st)->map_size = rval;
-
 	if (di_mem2cache(st, &di_cache) == 0) {
 		CACHE_DEBUG((DI_ERR, "can't update cache: copy failed"));
 		return (0);
--- a/usr/src/uts/common/io/scsi/impl/scsi_hba.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/io/scsi/impl/scsi_hba.c	Wed Jul 30 10:30:05 2008 -0700
@@ -474,7 +474,7 @@
 	if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN, 0, prop_name,
 	    NULL, &len) == DDI_PROP_NOT_FOUND) {
 		value = scsi_reset_delay;
-		if (ddi_prop_update_int(DDI_MAJOR_T_UNKNOWN, dip,
+		if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 		    prop_name, value) != DDI_PROP_SUCCESS) {
 			cmn_err(CE_CONT, errmsg, prop_name,
 			    ddi_driver_name(dip), ddi_get_instance(dip));
@@ -486,7 +486,7 @@
 	if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN, 0, prop_name,
 	    NULL, &len) == DDI_PROP_NOT_FOUND) {
 		value = scsi_tag_age_limit;
-		if (ddi_prop_update_int(DDI_MAJOR_T_UNKNOWN, dip,
+		if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 		    prop_name, value) != DDI_PROP_SUCCESS) {
 			cmn_err(CE_CONT, errmsg, prop_name,
 			    ddi_driver_name(dip), ddi_get_instance(dip));
@@ -498,7 +498,7 @@
 	if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN, 0, prop_name,
 	    NULL, &len) == DDI_PROP_NOT_FOUND) {
 		value = scsi_watchdog_tick;
-		if (ddi_prop_update_int(DDI_MAJOR_T_UNKNOWN, dip,
+		if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 		    prop_name, value) != DDI_PROP_SUCCESS) {
 			cmn_err(CE_CONT, errmsg, prop_name,
 			    ddi_driver_name(dip), ddi_get_instance(dip));
@@ -510,7 +510,7 @@
 	if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN, 0, prop_name,
 	    NULL, &len) == DDI_PROP_NOT_FOUND) {
 		value = scsi_options;
-		if (ddi_prop_update_int(DDI_MAJOR_T_UNKNOWN, dip,
+		if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 		    prop_name, value) != DDI_PROP_SUCCESS) {
 			cmn_err(CE_CONT, errmsg, prop_name,
 			    ddi_driver_name(dip), ddi_get_instance(dip));
@@ -522,7 +522,7 @@
 	if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN, 0, prop_name,
 	    NULL, &len) == DDI_PROP_NOT_FOUND) {
 		value = scsi_selection_timeout;
-		if (ddi_prop_update_int(DDI_MAJOR_T_UNKNOWN, dip,
+		if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 		    prop_name, value) != DDI_PROP_SUCCESS) {
 			cmn_err(CE_CONT, errmsg, prop_name,
 			    ddi_driver_name(dip), ddi_get_instance(dip));
@@ -537,7 +537,7 @@
 		    NULL, &len) == DDI_PROP_NOT_FOUND) {
 			value = hba_tran->tran_interconnect_type;
 			prop_value = interconnect[value];
-			if (ddi_prop_update_string(DDI_MAJOR_T_UNKNOWN, dip,
+			if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
 			    prop_name, (char *)prop_value)
 			    != DDI_PROP_SUCCESS) {
 				cmn_err(CE_CONT, errmsg, prop_name,
--- a/usr/src/uts/common/io/scsi/targets/sd.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/io/scsi/targets/sd.c	Wed Jul 30 10:30:05 2008 -0700
@@ -2174,7 +2174,7 @@
 
 	/*
 	 * Creating taskq before mod_install ensures that all callers (threads)
-	 * that enter the module after a successfull mod_install encounter
+	 * that enter the module after a successful mod_install encounter
 	 * a valid taskq.
 	 */
 	sd_taskq_create();
@@ -2601,36 +2601,15 @@
 sd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
 	char *name, caddr_t valuep, int *lengthp)
 {
-	int		instance = ddi_get_instance(dip);
 	struct sd_lun	*un;
-	uint64_t	nblocks64;
-	uint_t		dblk;
-
-	/*
-	 * Our dynamic properties are all device specific and size oriented.
-	 * Requests issued under conditions where size is valid are passed
-	 * to ddi_prop_op_nblocks with the size information, otherwise the
-	 * request is passed to ddi_prop_op. Size depends on valid geometry.
-	 */
-	un = ddi_get_soft_state(sd_state, instance);
-	if ((dev == DDI_DEV_T_ANY) || (un == NULL)) {
+
+	if ((un = ddi_get_soft_state(sd_state, ddi_get_instance(dip))) == NULL)
 		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
 		    name, valuep, lengthp));
-	} else if (!SD_IS_VALID_LABEL(un)) {
-		return (ddi_prop_op(dev, dip, prop_op, mod_flags, name,
-		    valuep, lengthp));
-	}
-
-	/* get nblocks value */
-	ASSERT(!mutex_owned(SD_MUTEX(un)));
-
-	(void) cmlb_partinfo(un->un_cmlbhandle, SDPART(dev),
-	    (diskaddr_t *)&nblocks64, NULL, NULL, NULL, (void *)SD_PATH_DIRECT);
-
-	/* report size in target size blocks */
-	dblk = un->un_tgt_blocksize / un->un_sys_blocksize;
-	return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op, mod_flags,
-	    name, valuep, lengthp, nblocks64 / dblk, un->un_tgt_blocksize));
+
+	return (cmlb_prop_op(un->un_cmlbhandle,
+	    dev, dip, prop_op, mod_flags, name, valuep, lengthp,
+	    SDPART(dev), (void *)SD_PATH_DIRECT));
 }
 
 /*
@@ -4592,8 +4571,6 @@
 static void
 sd_update_block_info(struct sd_lun *un, uint32_t lbasize, uint64_t capacity)
 {
-	uint_t		dblk;
-
 	if (lbasize != 0) {
 		un->un_tgt_blocksize = lbasize;
 		un->un_f_tgt_blocksize_is_valid	= TRUE;
@@ -4603,32 +4580,6 @@
 		un->un_blockcount		= capacity;
 		un->un_f_blockcount_is_valid	= TRUE;
 	}
-
-	/*
-	 * Update device capacity properties.
-	 *
-	 *   'device-nblocks'	number of blocks in target's units
-	 *   'device-blksize'	data bearing size of target's block
-	 *
-	 * NOTE: math is complicated by the fact that un_tgt_blocksize may
-	 * not be a power of two for checksumming disks with 520/528 byte
-	 * sectors.
-	 */
-	if (un->un_f_tgt_blocksize_is_valid &&
-	    un->un_f_blockcount_is_valid &&
-	    un->un_sys_blocksize) {
-		dblk = un->un_tgt_blocksize / un->un_sys_blocksize;
-		(void) ddi_prop_update_int64(DDI_DEV_T_NONE, SD_DEVINFO(un),
-		    "device-nblocks", un->un_blockcount / dblk);
-		/*
-		 * To save memory, only define "device-blksize" when its
-		 * value is differnet than the default DEV_BSIZE value.
-		 */
-		if ((un->un_sys_blocksize * dblk) != DEV_BSIZE)
-			(void) ddi_prop_update_int(DDI_DEV_T_NONE,
-			    SD_DEVINFO(un), "device-blksize",
-			    un->un_sys_blocksize * dblk);
-	}
 }
 
 
@@ -4706,11 +4657,11 @@
 	}
 
 	/*
-	 * We check the availibility of the World Wide Name (0x83) and Unit
+	 * We check the availability of the World Wide Name (0x83) and Unit
 	 * Serial Number (0x80) pages in sd_check_vpd_page_support(), and using
 	 * un_vpd_page_mask from them, we decide which way to get the WWN.  If
-	 * 0x83 is availible, that is the best choice.  Our next choice is
-	 * 0x80.  If neither are availible, we munge the devid from the device
+	 * 0x83 is available, that is the best choice.  Our next choice is
+	 * 0x80.  If neither are available, we munge the devid from the device
 	 * vid/pid/serial # for Sun qualified disks, or use the ddi framework
 	 * to fabricate a devid for non-Sun qualified disks.
 	 */
@@ -5044,7 +4995,7 @@
  *
  * Description: This routine sends an inquiry command with the EVPD bit set and
  *		a page code of 0x00 to the device. It is used to determine which
- *		vital product pages are availible to find the devid. We are
+ *		vital product pages are available to find the devid. We are
  *		looking for pages 0x83 or 0x80.  If we return a negative 1, the
  *		device does not support that command.
  *
@@ -5276,7 +5227,7 @@
 
 		/*
 		 * If the Log sense for Page( Start/stop cycle counter page)
-		 * succeeds, then power managment is supported and we can
+		 * succeeds, then power management is supported and we can
 		 * enable auto-pm.
 		 */
 		if (rval == 0)  {
@@ -6041,7 +5992,7 @@
 			 * To effect this behavior, call pm_busy_component to
 			 * indicate to the framework this device is busy.
 			 * By not adjusting un_pm_count the rest of PM in
-			 * the driver will function normally, and independant
+			 * the driver will function normally, and independent
 			 * of this but because the framework is told the device
 			 * is busy it won't attempt powering down until it gets
 			 * a matching idle. The timeout handler sends this.
@@ -6546,7 +6497,7 @@
 	 * Note: This driver is currently compiled as two binaries, a parallel
 	 * scsi version (sd) and a fibre channel version (ssd). All functional
 	 * differences are determined at compile time. In the future a single
-	 * binary will be provided and the inteconnect type will be used to
+	 * binary will be provided and the interconnect type will be used to
 	 * differentiate between fibre and parallel scsi behaviors. At that time
 	 * it will be necessary for all fibre channel HBAs to support this
 	 * property.
@@ -6808,7 +6759,7 @@
 	 * configuration file (.conf) for this unit and update the soft state
 	 * for the device as needed for the indicated properties.
 	 * Note: the property configuration needs to occur here as some of the
-	 * following routines may have dependancies on soft state flags set
+	 * following routines may have dependencies on soft state flags set
 	 * as part of the driver property configuration.
 	 */
 	sd_read_unit_properties(un);
@@ -7263,7 +7214,7 @@
 	 * "retry-on-reservation-conflict") (1189689)
 	 *
 	 * Note: The use of a global here can have unintended consequences. A
-	 * per instance variable is preferrable to match the capabilities of
+	 * per instance variable is preferable to match the capabilities of
 	 * different underlying hba's (4402600)
 	 */
 	sd_retry_on_reservation_conflict = ddi_getprop(DDI_DEV_T_ANY, devi,
@@ -7337,7 +7288,7 @@
 
 #if (defined(__fibre))
 	/*
-	 * Register callbacks for fibre only.  You can't do this soley
+	 * Register callbacks for fibre only.  You can't do this solely
 	 * on the basis of the devid_type because this is hba specific.
 	 * We need to query our hba capabilities to find out whether to
 	 * register or not.
@@ -26058,12 +26009,6 @@
 		stp = (struct sd_errstats *)un->un_errstats->ks_data;
 		stp->sd_capacity.value.ui64 = 0;
 	}
-
-	/* remove "capacity-of-device" properties */
-	(void) ddi_prop_remove(DDI_DEV_T_NONE, SD_DEVINFO(un),
-	    "device-nblocks");
-	(void) ddi_prop_remove(DDI_DEV_T_NONE, SD_DEVINFO(un),
-	    "device-blksize");
 }
 
 
@@ -28227,7 +28172,7 @@
 	case TG_GETPHYGEOM:
 	case TG_GETVIRTGEOM:
 	case TG_GETCAPACITY:
-	case  TG_GETBLOCKSIZE:
+	case TG_GETBLOCKSIZE:
 		mutex_enter(SD_MUTEX(un));
 
 		if ((un->un_f_blockcount_is_valid == TRUE) &&
--- a/usr/src/uts/common/os/devcfg.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/os/devcfg.c	Wed Jul 30 10:30:05 2008 -0700
@@ -946,7 +946,7 @@
 
 		/*
 		 * Release our initial hold. If ddi_initchild() was
-		 * successfull then it will return with the active hold.
+		 * successful then it will return with the active hold.
 		 */
 		ndi_rele_devi(pdip);
 		goto out;
@@ -1784,8 +1784,8 @@
 }
 
 /*
- * Single thread entry into devinfo node for modifying its children.
- * To verify in ASSERTS use DEVI_BUSY_OWNED macro.
+ * Single thread entry into devinfo node for modifying its children (devinfo,
+ * pathinfo, and minor). To verify in ASSERTS use DEVI_BUSY_OWNED macro.
  */
 void
 ndi_devi_enter(dev_info_t *dip, int *circular)
@@ -2588,6 +2588,7 @@
 	 * and copy properties.
 	 */
 	mutex_enter(&DEVI(dip)->devi_lock);
+	ASSERT(DEVI_BUSY_OWNED(pdip));
 	for (hwdip = ddi_get_child(pdip); hwdip;
 	    hwdip = ddi_get_next_sibling(hwdip)) {
 		/*
@@ -3654,15 +3655,16 @@
 resolve_pathname(char *pathname,
 	dev_info_t **dipp, dev_t *devtp, int *spectypep)
 {
-	int error;
-	dev_info_t *parent, *child;
-	struct pathname pn;
-	char *component, *config_name;
-	char *minorname = NULL;
-	char *prev_minor = NULL;
-	dev_t devt = NODEV;
-	int spectype;
-	struct ddi_minor_data *dmn;
+	int			error;
+	dev_info_t		*parent, *child;
+	struct pathname		pn;
+	char			*component, *config_name;
+	char			*minorname = NULL;
+	char			*prev_minor = NULL;
+	dev_t			devt = NODEV;
+	int			spectype;
+	struct ddi_minor_data	*dmn;
+	int			circ;
 
 	if (*pathname != '/')
 		return (EINVAL);
@@ -3740,8 +3742,11 @@
 
 	if (devtp || spectypep) {
 		if (minorname == NULL) {
-			/* search for a default entry */
-			mutex_enter(&(DEVI(parent)->devi_lock));
+			/*
+			 * Search for a default entry with an active
+			 * ndi_devi_enter to protect the devi_minor list.
+			 */
+			ndi_devi_enter(parent, &circ);
 			for (dmn = DEVI(parent)->devi_minor; dmn;
 			    dmn = dmn->next) {
 				if (dmn->type == DDM_DEFAULT) {
@@ -3768,7 +3773,7 @@
 					spectype = S_IFCHR;
 				}
 			}
-			mutex_exit(&(DEVI(parent)->devi_lock));
+			ndi_devi_exit(parent, circ);
 		}
 		if (devtp)
 			*devtp = devt;
@@ -3842,6 +3847,7 @@
 	char		*minor_name = NULL;
 	int		spectype;
 	int		error;
+	int		circ;
 
 	error = resolve_pathname(prompath, &dip, &devt, &spectype);
 	if (error)
@@ -3853,7 +3859,7 @@
 	 */
 	(void) ddi_pathname(dip, devfspath);
 
-	mutex_enter(&(DEVI(dip)->devi_lock));
+	ndi_devi_enter(dip, &circ);
 	minor_name = i_ddi_devtspectype_to_minorname(dip, devt, spectype);
 	if (minor_name) {
 		(void) strcat(devfspath, ":");
@@ -3866,7 +3872,7 @@
 		(void) snprintf(devfspath, MAXPATHLEN, "%s:%s",
 		    CLONE_PATH, ddi_driver_name(dip));
 	}
-	mutex_exit(&(DEVI(dip)->devi_lock));
+	ndi_devi_exit(dip, circ);
 
 	/* release hold from resolve_pathname() */
 	ndi_rele_devi(dip);
@@ -6641,14 +6647,16 @@
 int
 i_ddi_minor_node_count(dev_info_t *ddip, const char *node_type)
 {
-	struct ddi_minor_data *dp;
-	int count = 0;
-
-	mutex_enter(&(DEVI(ddip)->devi_lock));
-	for (dp = DEVI(ddip)->devi_minor; dp != NULL; dp = dp->next)
+	int			circ;
+	struct ddi_minor_data	*dp;
+	int			count = 0;
+
+	ndi_devi_enter(ddip, &circ);
+	for (dp = DEVI(ddip)->devi_minor; dp != NULL; dp = dp->next) {
 		if (strcmp(dp->ddm_node_type, node_type) == 0)
 			count++;
-	mutex_exit(&(DEVI(ddip)->devi_lock));
+	}
+	ndi_devi_exit(ddip, circ);
 	return (count);
 }
 
--- a/usr/src/uts/common/os/devid_cache.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/os/devid_cache.c	Wed Jul 30 10:30:05 2008 -0700
@@ -680,6 +680,7 @@
 	int		*devtcntp,
 	dev_t		*devtsp)
 {
+	int			circ;
 	struct ddi_minor_data	*dmdp;
 	int			minor_all = 0;
 	int			ndevts = *devtcntp;
@@ -692,9 +693,8 @@
 	    (minor_name == DEVID_MINOR_NAME_ALL_BLK))
 		minor_all = 1;
 
-	mutex_enter(&(DEVI(dip)->devi_lock));
-
 	/* Find matching minor names */
+	ndi_devi_enter(dip, &circ);
 	for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) {
 
 		/* Skip non-minors, and non matching minor names */
@@ -714,8 +714,7 @@
 			devtsp[ndevts] = dmdp->ddm_dev;
 		ndevts++;
 	}
-
-	mutex_exit(&(DEVI(dip)->devi_lock));
+	ndi_devi_exit(dip, circ);
 
 	*devtcntp = ndevts;
 }
--- a/usr/src/uts/common/os/modctl.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/os/modctl.c	Wed Jul 30 10:30:05 2008 -0700
@@ -1099,6 +1099,7 @@
 	int		devid_len;
 	char		*minor_name = NULL;
 	dev_info_t	*dip = NULL;
+	int		circ;
 	struct ddi_minor_data   *dmdp;
 	char		*path = NULL;
 	int		ulens;
@@ -1185,6 +1186,7 @@
 			continue;
 
 		/* loop over all the minor nodes, skipping ones we don't want */
+		ndi_devi_enter(dip, &circ);
 		for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) {
 			if ((dmdp->ddm_dev != devlist[i]) ||
 			    (dmdp->type != DDM_MINOR))
@@ -1227,6 +1229,7 @@
 				upaths += len;
 			}
 		}
+		ndi_devi_exit(dip, circ);
 		ddi_release_devi(dip);
 		dip = NULL;
 	}
@@ -1239,8 +1242,10 @@
 	}
 	ret = 0;
 
-out:	if (dip)
+out:	if (dip) {
+		ndi_devi_exit(dip, circ);
 		ddi_release_devi(dip);
+	}
 	if (path)
 		kmem_free(path, MAXPATHLEN);
 	if (devlist)
@@ -4323,12 +4328,13 @@
 static int
 dev_alias_minorperm(dev_info_t *dip, char *minor_name, mperm_t *rmp)
 {
-	major_t major;
-	struct devnames *dnp;
-	mperm_t *mp;
-	char *alias = NULL;
-	dev_info_t *cdevi;
-	struct ddi_minor_data *dmd;
+	major_t			major;
+	struct devnames		*dnp;
+	mperm_t			*mp;
+	char			*alias = NULL;
+	dev_info_t		*cdevi;
+	int			circ;
+	struct ddi_minor_data	*dmd;
 
 	major = ddi_name_to_major(minor_name);
 
@@ -4347,14 +4353,14 @@
 	LOCK_DEV_OPS(&dnp->dn_lock);
 
 	if ((cdevi = dnp->dn_head) != NULL) {
-		mutex_enter(&DEVI(cdevi)->devi_lock);
+		ndi_devi_enter(cdevi, &circ);
 		for (dmd = DEVI(cdevi)->devi_minor; dmd; dmd = dmd->next) {
 			if (dmd->type == DDM_ALIAS) {
 				alias = i_ddi_strdup(dmd->ddm_name, KM_SLEEP);
 				break;
 			}
 		}
-		mutex_exit(&DEVI(cdevi)->devi_lock);
+		ndi_devi_exit(cdevi, circ);
 	}
 
 	UNLOCK_DEV_OPS(&dnp->dn_lock);
--- a/usr/src/uts/common/os/sunddi.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/os/sunddi.c	Wed Jul 30 10:30:05 2008 -0700
@@ -1894,6 +1894,21 @@
 	caddr_t	buffer;
 	int	blkshift;
 
+	/*
+	 * This is a kludge to support capture of size(9P) pure dynamic
+	 * properties in snapshots for non-cmlb code (without exposing
+	 * i_ddi_prop_dyn changes). When everyone uses cmlb, this code
+	 * should be removed.
+	 */
+	if (i_ddi_prop_dyn_driver_get(dip) == NULL) {
+		static i_ddi_prop_dyn_t prop_dyn_size[] = {
+		    {"Size",		DDI_PROP_TYPE_INT64,	S_IFCHR},
+		    {"Nblocks",		DDI_PROP_TYPE_INT64,	S_IFBLK},
+		    {NULL}
+		};
+		i_ddi_prop_dyn_driver_set(dip, prop_dyn_size);
+	}
+
 	/* convert block size to shift value */
 	ASSERT(BIT_ONLYONESET(blksize));
 	blkshift = highbit(blksize) - 1;
@@ -1924,10 +1939,6 @@
 	if (prop_op == PROP_LEN)
 		return (DDI_PROP_SUCCESS);
 
-	/* the length of the property and the request must match */
-	if (callers_length != *lengthp)
-		return (DDI_PROP_INVAL_ARG);
-
 	switch (prop_op) {
 	case PROP_LEN_AND_VAL_ALLOC:
 		if ((buffer = kmem_alloc(*lengthp,
@@ -1939,6 +1950,10 @@
 		break;
 
 	case PROP_LEN_AND_VAL_BUF:
+		/* the length of the property and the request must match */
+		if (callers_length != *lengthp)
+			return (DDI_PROP_INVAL_ARG);
+
 		buffer = valuep;		/* get callers buf ptr */
 		break;
 
@@ -3842,8 +3857,8 @@
 #endif /* DDI_PROP_DEBUG */
 	}
 	flag &= ~DDI_PROP_SYSTEM_DEF;
-	return (ddi_prop_update_common(dev, dip,
-	    (flag | DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY), name,
+	flag |= DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY;
+	return (ddi_prop_update_common(dev, dip, flag, name,
 	    value, length, ddi_prop_fm_encode_bytes));
 }
 
@@ -3853,9 +3868,8 @@
 {
 	if (!(flag & DDI_PROP_CANSLEEP))
 		flag |= DDI_PROP_DONTSLEEP;
-	return (ddi_prop_update_common(dev, dip,
-	    (flag | DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE |
-	    DDI_PROP_TYPE_ANY),
+	flag |= DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY;
+	return (ddi_prop_update_common(dev, dip, flag,
 	    name, value, length, ddi_prop_fm_encode_bytes));
 }
 
@@ -4501,6 +4515,7 @@
 void
 ddi_prop_remove_all(dev_info_t *dip)
 {
+	i_ddi_prop_dyn_driver_set(dip, NULL);
 	ddi_prop_remove_all_common(dip, 0);
 }
 
@@ -4531,9 +4546,9 @@
 {
 	if (!(flag & DDI_PROP_CANSLEEP))
 		flag |= DDI_PROP_DONTSLEEP;
-	return (ddi_prop_update_common(dev, dip,
-	    (flag | DDI_PROP_STACK_CREATE | DDI_PROP_UNDEF_IT |
-	    DDI_PROP_TYPE_ANY), name, NULL, 0, ddi_prop_fm_encode_bytes));
+	flag |= DDI_PROP_STACK_CREATE | DDI_PROP_UNDEF_IT | DDI_PROP_TYPE_ANY;
+	return (ddi_prop_update_common(dev, dip, flag,
+	    name, NULL, 0, ddi_prop_fm_encode_bytes));
 }
 
 int
@@ -4541,13 +4556,57 @@
 {
 	if (!(flag & DDI_PROP_CANSLEEP))
 		flag |= DDI_PROP_DONTSLEEP;
-	return (ddi_prop_update_common(dev, dip,
-	    (flag | DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE |
-	    DDI_PROP_UNDEF_IT | DDI_PROP_TYPE_ANY),
+	flag |= DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE |
+	    DDI_PROP_UNDEF_IT | DDI_PROP_TYPE_ANY;
+	return (ddi_prop_update_common(dev, dip, flag,
 	    name, NULL, 0, ddi_prop_fm_encode_bytes));
 }
 
 /*
+ * Support for gathering dynamic properties in devinfo snapshot.
+ */
+void
+i_ddi_prop_dyn_driver_set(dev_info_t *dip, i_ddi_prop_dyn_t *dp)
+{
+	DEVI(dip)->devi_prop_dyn_driver = dp;
+}
+
+i_ddi_prop_dyn_t *
+i_ddi_prop_dyn_driver_get(dev_info_t *dip)
+{
+	return (DEVI(dip)->devi_prop_dyn_driver);
+}
+
+void
+i_ddi_prop_dyn_parent_set(dev_info_t *dip, i_ddi_prop_dyn_t *dp)
+{
+	DEVI(dip)->devi_prop_dyn_parent = dp;
+}
+
+i_ddi_prop_dyn_t *
+i_ddi_prop_dyn_parent_get(dev_info_t *dip)
+{
+	return (DEVI(dip)->devi_prop_dyn_parent);
+}
+
+void
+i_ddi_prop_dyn_cache_invalidate(dev_info_t *dip, i_ddi_prop_dyn_t *dp)
+{
+	/* for now we invalidate the entire cached snapshot */
+	if (dip && dp)
+		i_ddi_di_cache_invalidate(KM_SLEEP);
+}
+
+/* ARGSUSED */
+void
+ddi_prop_cache_invalidate(dev_t dev, dev_info_t *dip, char *name, int flags)
+{
+	/* for now we invalidate the entire cached snapshot */
+	i_ddi_di_cache_invalidate(KM_SLEEP);
+}
+
+
+/*
  * Code to search hardware layer (PROM), if it exists, on behalf of child.
  *
  * if input dip != child_dip, then call is on behalf of child
@@ -5639,11 +5698,10 @@
 static void
 ddi_append_minor_node(dev_info_t *ddip, struct ddi_minor_data *dmdp)
 {
-	struct ddi_minor_data *dp;
-
-	mutex_enter(&(DEVI(ddip)->devi_lock));
-	i_devi_enter(ddip, DEVI_S_MD_UPDATE, DEVI_S_MD_UPDATE, 1);
-
+	int			circ;
+	struct ddi_minor_data	*dp;
+
+	ndi_devi_enter(ddip, &circ);
 	if ((dp = DEVI(ddip)->devi_minor) == (struct ddi_minor_data *)NULL) {
 		DEVI(ddip)->devi_minor = dmdp;
 	} else {
@@ -5651,9 +5709,7 @@
 			dp = dp->next;
 		dp->next = dmdp;
 	}
-
-	i_devi_exit(ddip, DEVI_S_MD_UPDATE, 1);
-	mutex_exit(&(DEVI(ddip)->devi_lock));
+	ndi_devi_exit(ddip, circ);
 }
 
 /*
@@ -6094,12 +6150,11 @@
 void
 ddi_remove_minor_node(dev_info_t *dip, char *name)
 {
-	struct ddi_minor_data *dmdp, *dmdp1;
-	struct ddi_minor_data **dmdp_prev;
-
-	mutex_enter(&(DEVI(dip)->devi_lock));
-	i_devi_enter(dip, DEVI_S_MD_UPDATE, DEVI_S_MD_UPDATE, 1);
-
+	int			circ;
+	struct ddi_minor_data	*dmdp, *dmdp1;
+	struct ddi_minor_data	**dmdp_prev;
+
+	ndi_devi_enter(dip, &circ);
 	dmdp_prev = &DEVI(dip)->devi_minor;
 	dmdp = DEVI(dip)->devi_minor;
 	while (dmdp != NULL) {
@@ -6134,9 +6189,7 @@
 		}
 		dmdp = dmdp1;
 	}
-
-	i_devi_exit(dip, DEVI_S_MD_UPDATE, 1);
-	mutex_exit(&(DEVI(dip)->devi_lock));
+	ndi_devi_exit(dip, circ);
 }
 
 
@@ -6650,6 +6703,7 @@
 int
 ddi_dev_pathname(dev_t devt, int spec_type, char *path)
 {
+	int		circ;
 	major_t		major = getmajor(devt);
 	int		instance;
 	dev_info_t	*dip;
@@ -6682,14 +6736,14 @@
 			goto fail;
 
 		/* Add minorname to path. */
-		mutex_enter(&(DEVI(dip)->devi_lock));
+		ndi_devi_enter(dip, &circ);
 		minorname = i_ddi_devtspectype_to_minorname(dip,
 		    devt, spec_type);
 		if (minorname) {
 			(void) strcat(path, ":");
 			(void) strcat(path, minorname);
 		}
-		mutex_exit(&(DEVI(dip)->devi_lock));
+		ndi_devi_exit(dip, circ);
 		ddi_release_devi(dip);
 		if (minorname == NULL)
 			goto fail;
@@ -7359,8 +7413,8 @@
 	 */
 	ASSERT((ddi_driver_major(dip) == getmajor(dev)) ||
 	    (strcmp(ddi_major_to_name(getmajor(dev)), "did") == 0));
-	ASSERT(MUTEX_HELD(&(DEVI(dip)->devi_lock)));
-
+
+	ASSERT(DEVI_BUSY_OWNED(dip));
 	for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) {
 		if (((dmdp->type == DDM_MINOR) ||
 		    (dmdp->type == DDM_INTERNAL_PATH) ||
@@ -7383,6 +7437,7 @@
 i_ddi_minorname_to_devtspectype(dev_info_t *dip, char *minor_name,
 	dev_t *devtp, int *spectypep)
 {
+	int			circ;
 	struct ddi_minor_data	*dmdp;
 
 	/* deal with clone minor nodes */
@@ -7415,9 +7470,7 @@
 		return (DDI_SUCCESS);
 	}
 
-	ASSERT(!MUTEX_HELD(&(DEVI(dip)->devi_lock)));
-	mutex_enter(&(DEVI(dip)->devi_lock));
-
+	ndi_devi_enter(dip, &circ);
 	for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) {
 		if (((dmdp->type != DDM_MINOR) &&
 		    (dmdp->type != DDM_INTERNAL_PATH) &&
@@ -7431,11 +7484,11 @@
 		if (spectypep)
 			*spectypep = dmdp->ddm_spec_type;
 
-		mutex_exit(&(DEVI(dip)->devi_lock));
+		ndi_devi_exit(dip, circ);
 		return (DDI_SUCCESS);
 	}
-
-	mutex_exit(&(DEVI(dip)->devi_lock));
+	ndi_devi_exit(dip, circ);
+
 	return (DDI_FAILURE);
 }
 
@@ -7792,54 +7845,38 @@
 int
 ddi_lyr_get_minor_name(dev_t dev, int spec_type, char **minor_name)
 {
+	char		*buf;
+	int		circ;
 	dev_info_t	*dip;
 	char		*nm;
-	size_t		alloc_sz, sz;
-
-	if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
-		return (DDI_FAILURE);
-
-	mutex_enter(&(DEVI(dip)->devi_lock));
-
-	if ((nm = i_ddi_devtspectype_to_minorname(dip,
-	    dev, spec_type)) == NULL) {
-		mutex_exit(&(DEVI(dip)->devi_lock));
-		ddi_release_devi(dip);	/* e_ddi_hold_devi_by_dev() */
+	int		rval;
+
+	if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) {
+		*minor_name = NULL;
 		return (DDI_FAILURE);
 	}
 
-	/* make a copy */
-	alloc_sz = strlen(nm) + 1;
-retry:
-	/* drop lock to allocate memory */
-	mutex_exit(&(DEVI(dip)->devi_lock));
-	*minor_name = kmem_alloc(alloc_sz, KM_SLEEP);
-	mutex_enter(&(DEVI(dip)->devi_lock));
-
-	/* re-check things, since we dropped the lock */
-	if ((nm = i_ddi_devtspectype_to_minorname(dip,
-	    dev, spec_type)) == NULL) {
-		mutex_exit(&(DEVI(dip)->devi_lock));
-		kmem_free(*minor_name, alloc_sz);
+	/* Find the minor name and copy into max size buf */
+	buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
+	ndi_devi_enter(dip, &circ);
+	nm = i_ddi_devtspectype_to_minorname(dip, dev, spec_type);
+	if (nm)
+		(void) strcpy(buf, nm);
+	ndi_devi_exit(dip, circ);
+	ddi_release_devi(dip);	/* e_ddi_hold_devi_by_dev() */
+
+	if (nm) {
+		/* duplicate into min size buf for return result */
+		*minor_name = i_ddi_strdup(buf, KM_SLEEP);
+		rval = DDI_SUCCESS;
+	} else {
 		*minor_name = NULL;
-		ddi_release_devi(dip);	/* e_ddi_hold_devi_by_dev() */
-		return (DDI_FAILURE);
-	}
-
-	/* verify size is the same */
-	sz = strlen(nm) + 1;
-	if (alloc_sz != sz) {
-		kmem_free(*minor_name, alloc_sz);
-		alloc_sz = sz;
-		goto retry;
-	}
-
-	/* sz == alloc_sz - make a copy */
-	(void) strcpy(*minor_name, nm);
-
-	mutex_exit(&(DEVI(dip)->devi_lock));
-	ddi_release_devi(dip);	/* e_ddi_hold_devi_by_dev() */
-	return (DDI_SUCCESS);
+		rval = DDI_FAILURE;
+	}
+
+	/* free max size buf and return */
+	kmem_free(buf, MAXNAMELEN);
+	return (rval);
 }
 
 int
@@ -7948,48 +7985,6 @@
 }
 
 /*
- * single thread access to dev_info node and set state
- */
-void
-i_devi_enter(dev_info_t *dip, uint_t s_mask, uint_t w_mask, int has_lock)
-{
-	if (!has_lock)
-		mutex_enter(&(DEVI(dip)->devi_lock));
-
-	ASSERT(mutex_owned(&(DEVI(dip)->devi_lock)));
-
-	/*
-	 * wait until state(s) have been changed
-	 */
-	while ((DEVI(dip)->devi_state & w_mask) != 0) {
-		cv_wait(&(DEVI(dip)->devi_cv), &(DEVI(dip)->devi_lock));
-	}
-	DEVI(dip)->devi_state |= s_mask;
-
-	if (!has_lock)
-		mutex_exit(&(DEVI(dip)->devi_lock));
-}
-
-void
-i_devi_exit(dev_info_t *dip, uint_t c_mask, int has_lock)
-{
-	if (!has_lock)
-		mutex_enter(&(DEVI(dip)->devi_lock));
-
-	ASSERT(mutex_owned(&(DEVI(dip)->devi_lock)));
-
-	/*
-	 * clear the state(s) and wakeup any threads waiting
-	 * for state change
-	 */
-	DEVI(dip)->devi_state &= ~c_mask;
-	cv_broadcast(&(DEVI(dip)->devi_cv));
-
-	if (!has_lock)
-		mutex_exit(&(DEVI(dip)->devi_lock));
-}
-
-/*
  * This procedure is provided as the general callback function when
  * umem_lockmemory calls as_add_callback for long term memory locking.
  * When as_unmap, as_setprot, or as_free encounter segments which have
--- a/usr/src/uts/common/os/sunndi.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/os/sunndi.c	Wed Jul 30 10:30:05 2008 -0700
@@ -163,6 +163,7 @@
 void
 ndi_prop_remove_all(dev_info_t *dip)
 {
+	i_ddi_prop_dyn_parent_set(dip, NULL);
 	ddi_prop_remove_all_common(dip, (int)DDI_PROP_HW_DEF);
 }
 
@@ -202,7 +203,7 @@
 	 * post the event to the responsible ancestor
 	 */
 	return ((*(DEVI(ddip)->devi_ops->devo_bus_ops->bus_post_event))
-		(ddip, rdip, cookie, impl_data));
+	    (ddip, rdip, cookie, impl_data));
 }
 
 /*
@@ -225,7 +226,7 @@
 	 * request responsible nexus to remove the eventcall
 	 */
 	return ((*(DEVI(ddip)->devi_ops->devo_bus_ops->bus_remove_eventcall))
-		(ddip, id));
+	    (ddip, id));
 }
 
 /*
@@ -256,7 +257,7 @@
 	 * request responsible ancestor to add the eventcall
 	 */
 	return ((*(DEVI(ddip)->devi_ops->devo_bus_ops->bus_add_eventcall))
-		(ddip, rdip, cookie, callback, arg, cb_id));
+	    (ddip, rdip, cookie, callback, arg, cb_id));
 }
 
 /*
@@ -294,11 +295,11 @@
 #endif /* DEBUG */
 
 		return (ndi_busop_get_eventcookie(pdip, rdip, name,
-			    event_cookiep));
+		    event_cookiep));
 	}
 
 	return ((*(DEVI(pdip)->devi_ops->devo_bus_ops->bus_get_eventcookie))
-		(pdip, rdip, name, event_cookiep));
+	    (pdip, rdip, name, event_cookiep));
 }
 
 /*
@@ -466,7 +467,7 @@
 
 	name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 	(void) snprintf(name, MAXNAMELEN, "%s@%s",
-		ndi_dc_getname(dcp), ndi_dc_getaddr(dcp));
+	    ndi_dc_getname(dcp), ndi_dc_getaddr(dcp));
 
 	if ((rval = ndi_devi_config_one(dip, name, &rdip,
 	    flags | NDI_DEVI_ONLINE | NDI_CONFIG)) == NDI_SUCCESS) {
@@ -486,8 +487,8 @@
 	}
 
 	NDI_DEBUG(flags, (CE_CONT, "%s%d: online: %s: %s\n",
-		ddi_driver_name(dip), ddi_get_instance(dip), name,
-		((rval == NDI_SUCCESS) ? "ok" : "failed")));
+	    ddi_driver_name(dip), ddi_get_instance(dip), name,
+	    ((rval == NDI_SUCCESS) ? "ok" : "failed")));
 
 	kmem_free(name, MAXNAMELEN);
 
@@ -510,7 +511,7 @@
 
 	name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 	(void) snprintf(name, MAXNAMELEN, "%s@%s",
-		ndi_dc_getname(dcp), ndi_dc_getaddr(dcp));
+	    ndi_dc_getname(dcp), ndi_dc_getaddr(dcp));
 
 	(void) devfs_clean(dip, name, DV_CLEAN_FORCE);
 	rval = ndi_devi_unconfig_one(dip, name, NULL,
@@ -523,8 +524,8 @@
 	}
 
 	NDI_DEBUG(flags, (CE_CONT, "%s%d: offline: %s: %s\n",
-		ddi_driver_name(dip), ddi_get_instance(dip), name,
-		(rval == NDI_SUCCESS) ? "ok" : "failed"));
+	    ddi_driver_name(dip), ddi_get_instance(dip), name,
+	    (rval == NDI_SUCCESS) ? "ok" : "failed"));
 
 	kmem_free(name, MAXNAMELEN);
 
@@ -547,7 +548,7 @@
 
 	name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 	(void) snprintf(name, MAXNAMELEN, "%s@%s",
-		ndi_dc_getname(dcp), ndi_dc_getaddr(dcp));
+	    ndi_dc_getname(dcp), ndi_dc_getaddr(dcp));
 
 	(void) devfs_clean(dip, name, DV_CLEAN_FORCE);
 
@@ -560,8 +561,8 @@
 	}
 
 	NDI_DEBUG(flags, (CE_CONT, "%s%d: remove: %s: %s\n",
-		ddi_driver_name(dip), ddi_get_instance(dip), name,
-		(rval == NDI_SUCCESS) ? "ok" : "failed"));
+	    ddi_driver_name(dip), ddi_get_instance(dip), name,
+	    (rval == NDI_SUCCESS) ? "ok" : "failed"));
 
 	kmem_free(name, MAXNAMELEN);
 
@@ -765,8 +766,8 @@
 
 	if (get_udatamodel() == DATAMODEL_NATIVE) {
 		if (copyout(ap, dcp->cpyout_buf,
-			sizeof (devctl_ap_state_t)) != 0)
-		    return (NDI_FAULT);
+		    sizeof (devctl_ap_state_t)) != 0)
+			return (NDI_FAULT);
 	}
 #ifdef _SYSCALL32_IMPL
 	else {
@@ -779,8 +780,8 @@
 		ap_state32.ap_in_transition = ap->ap_in_transition;
 		ap_state32.ap_last_change = (time32_t)ap->ap_last_change;
 		if (copyout(&ap_state32, dcp->cpyout_buf,
-			sizeof (devctl_ap_state32_t)) != 0)
-		    return (NDI_FAULT);
+		    sizeof (devctl_ap_state32_t)) != 0)
+			return (NDI_FAULT);
 	}
 #endif
 
@@ -1209,7 +1210,7 @@
 	struct ndi_event_hdl *ndi_event_hdl;
 
 	ndi_event_hdl = kmem_zalloc(sizeof (struct ndi_event_hdl),
-		((flag & NDI_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP));
+	    ((flag & NDI_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP));
 
 	if (!ndi_event_hdl) {
 		return (NDI_FAILURE);
@@ -1487,12 +1488,12 @@
 			if (strncmp(NDI_EVENT_NAME(cookie_list),
 			    ndi_event_defs[i].ndi_event_name, len) == 0) {
 
-			    ASSERT(cookie_list->callback_list == NULL);
-			    if (cookie_list->callback_list) {
-				    rval = NDI_FAILURE;
-				    goto done;
-			    }
-			    break;
+				ASSERT(cookie_list->callback_list == NULL);
+				if (cookie_list->callback_list) {
+					rval = NDI_FAILURE;
+					goto done;
+				}
+				break;
 			} else {
 				cookie_list = cookie_list->next_cookie;
 			}
@@ -1633,8 +1634,7 @@
 	 */
 	if ((flag & NDI_EVENT_NOPASS) == 0) {
 		return (ndi_busop_get_eventcookie(
-			ndi_event_hdl->ndi_evthdl_dip, rdip,
-			eventname, cookiep));
+		    ndi_event_hdl->ndi_evthdl_dip, rdip, eventname, cookiep));
 	} else {
 		return (NDI_FAILURE);
 	}
@@ -2113,25 +2113,19 @@
 	list = hdl->ndi_evthdl_cookie_list;
 
 	cmn_err(CE_CONT, "%s: event handle (%p): dip = %p (%s%d)\n",
-		location, (void *)hdl,
-		(void *)hdl->ndi_evthdl_dip,
-		ddi_node_name(hdl->ndi_evthdl_dip),
-		ddi_get_instance(hdl->ndi_evthdl_dip));
+	    location, (void *)hdl, (void *)hdl->ndi_evthdl_dip,
+	    ddi_node_name(hdl->ndi_evthdl_dip),
+	    ddi_get_instance(hdl->ndi_evthdl_dip));
 	cmn_err(CE_CONT, "\thigh=%d other=%d n=%d\n",
-		hdl->ndi_evthdl_high_plevels,
-		hdl->ndi_evthdl_other_plevels,
-		hdl->ndi_evthdl_n_events);
-
+	    hdl->ndi_evthdl_high_plevels, hdl->ndi_evthdl_other_plevels,
+	    hdl->ndi_evthdl_n_events);
 
 	cmn_err(CE_CONT, "\tevent cookies:\n");
 	while (list) {
-		cmn_err(CE_CONT,
-			"\t\ttag=%d name=%s p=%d a=%x dd=%p\n",
-			NDI_EVENT_TAG(list),
-			NDI_EVENT_NAME(list),
-			NDI_EVENT_PLEVEL(list),
-			NDI_EVENT_ATTRIBUTES(list),
-			(void *)NDI_EVENT_DDIP(list));
+		cmn_err(CE_CONT, "\t\ttag=%d name=%s p=%d a=%x dd=%p\n",
+		    NDI_EVENT_TAG(list), NDI_EVENT_NAME(list),
+		    NDI_EVENT_PLEVEL(list), NDI_EVENT_ATTRIBUTES(list),
+		    (void *)NDI_EVENT_DDIP(list));
 		cmn_err(CE_CONT, "\t\tcallbacks:\n");
 		for (next = list->callback_list; next != NULL;
 		    next = next->ndi_evtcb_next) {
@@ -2355,15 +2349,13 @@
 	}
 
 	cmn_err(level, "!%s%d: %s %s device; service %s%s"+(bad|changed),
-		ddi_driver_name(fedp->f_dip),
-		ddi_get_instance(fedp->f_dip),
-		bad ? "invalid report of fault" : action,
-		location, still ? "still " : "", servstate);
+	    ddi_driver_name(fedp->f_dip), ddi_get_instance(fedp->f_dip),
+	    bad ? "invalid report of fault" : action,
+	    location, still ? "still " : "", servstate);
 
 	cmn_err(level, "!%s%d: %s"+(bad|changed),
-		ddi_driver_name(fedp->f_dip),
-		ddi_get_instance(fedp->f_dip),
-		fedp->f_message);
+	    ddi_driver_name(fedp->f_dip), ddi_get_instance(fedp->f_dip),
+	    fedp->f_message);
 }
 
 /*
@@ -2425,7 +2417,7 @@
 	if (rootnex_event_hdl == NULL)
 		return (NDI_FAILURE);
 	return (ndi_event_retrieve_cookie(rootnex_event_hdl, rdip, eventname,
-		cookiep, NDI_EVENT_NOPASS));
+	    cookiep, NDI_EVENT_NOPASS));
 }
 
 /*ARGSUSED*/
@@ -2438,7 +2430,7 @@
 	if (rootnex_event_hdl == NULL)
 		return (NDI_FAILURE);
 	return (ndi_event_add_callback(rootnex_event_hdl, rdip,
-		eventid, handler, arg, NDI_SLEEP, cb_id));
+	    eventid, handler, arg, NDI_SLEEP, cb_id));
 }
 
 /*ARGSUSED*/
@@ -2467,7 +2459,7 @@
 		(*plat_fault_logger)(rdip, impl_data);
 	}
 	return (ndi_event_run_callbacks(rootnex_event_hdl, rdip,
-		eventid, impl_data));
+	    eventid, impl_data));
 }
 
 /*
--- a/usr/src/uts/common/pcmcia/nexus/pcmcia.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/pcmcia/nexus/pcmcia.c	Wed Jul 30 10:30:05 2008 -0700
@@ -1565,7 +1565,7 @@
 	char bf[256];
 	struct pcmcia_parent_private *ppd;
 	dev_info_t *dip;
-	int circular;
+	int circ;
 
 #if defined(PCMCIA_DEBUG)
 	if (pcmcia_debug)
@@ -1575,7 +1575,7 @@
 		    info->pd_vers1_name, info->pd_flags);
 #endif
 
-	ndi_devi_enter(self, &circular);
+	ndi_devi_enter(self, &circ);
 	/* do searches in compatible property order */
 	for (dip = (dev_info_t *)DEVI(self)->devi_child;
 	    dip != NULL;
@@ -1644,7 +1644,7 @@
 				break;
 		}
 	}
-	ndi_devi_exit(self, circular);
+	ndi_devi_exit(self, circ);
 	return (dip);
 }
 
@@ -3996,6 +3996,7 @@
 int
 pcmcia_get_minors(dev_info_t *dip, struct pcm_make_dev **minors)
 {
+	int circ;
 	int count = 0;
 	struct ddi_minor_data *dp;
 	struct pcm_make_dev *md;
@@ -4005,7 +4006,7 @@
 
 	socket = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 	    PCM_DEV_SOCKET, -1);
-	mutex_enter(&(DEVI(dip)->devi_lock));
+	ndi_devi_enter(dip, &circ);
 	if (DEVI(dip)->devi_minor != (struct ddi_minor_data *)NULL) {
 		for (dp = DEVI(dip)->devi_minor;
 			dp != (struct ddi_minor_data *)NULL;
@@ -4060,7 +4061,7 @@
 			count = 0;
 		}
 	}
-	mutex_exit(&(DEVI(dip)->devi_lock));
+	ndi_devi_exit(dip, circ);
 	return (count);
 }
 
@@ -4070,6 +4071,7 @@
 static void
 pcmcia_dump_minors(dev_info_t *dip)
 {
+	int circ;
 	int count = 0;
 	struct ddi_minor_data *dp;
 	int unit, major;
@@ -4093,7 +4095,7 @@
 			cmn_err(CE_CONT, "\tsibs: %s %s %s\n",
 				ddi_binding_name(np), cf2, cur);
 
-			mutex_enter(&(DEVI(np)->devi_lock));
+			ndi_devi_enter(np, &circ);
 			if (DEVI(np)->devi_minor !=
 			    (struct ddi_minor_data *)NULL) {
 				for (dp = DEVI(np)->devi_minor;
@@ -4117,7 +4119,7 @@
 						ddi_binding_name(np));
 				}
 			}
-			mutex_exit(&(DEVI(np)->devi_lock));
+			ndi_devi_exit(np, circ);
 		}
 	}
 }
@@ -4639,9 +4641,9 @@
 	struct regspec *assigned;
 	int len;
 	dev_info_t *dip;
-	int circular;
-
-	ndi_devi_enter(self, &circular);
+	int circ;
+
+	ndi_devi_enter(self, &circ);
 	/* do searches in compatible property order */
 	for (dip = (dev_info_t *)DEVI(self)->devi_child;
 	    dip != NULL;
@@ -4660,7 +4662,7 @@
 			kmem_free(assigned, len);
 		}
 	}
-	ndi_devi_exit(self, circular);
+	ndi_devi_exit(self, circ);
 }
 
 /*
--- a/usr/src/uts/common/sys/cmlb.h	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/sys/cmlb.h	Wed Jul 30 10:30:05 2008 -0700
@@ -184,7 +184,7 @@
 	 *			In case of TG_GETCAP, this return code
 	 *			indicates no media in the drive.
 	 *
-	 *	EIO		An error occured during obtaining info
+	 *	EIO		An error occurred during obtaining info
 	 *			from device/media.
 	 *
 	 *	ENOTSUP		In case of TG_GETCAP, target does not
@@ -483,6 +483,28 @@
     intptr_t arg, int flag, cred_t *cred_p, int *rval_p, void *tg_cookie);
 
 /*
+ * cmlb_prop_op:
+ *	provide common label prop_op(9E) implementation that understands the
+ *	size(9p) properties.
+ *
+ * Arguments:
+ *	cmlbhandle	cmlb handle associated with device.
+ *	dev		See prop_op(9E)
+ *	dip		"
+ *	prop_op		"
+ *	mod_flags	"
+ *	name		"
+ *	valuep		"
+ *	lengthp		"
+ *	part		partition number
+ *	tg_cookie 	cookie from target driver to be passed back to target
+ */
+int
+cmlb_prop_op(cmlb_handle_t cmlbhandle,
+    dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
+    char *name, caddr_t valuep, int *lengthp, int part, void *tg_cookie);
+
+/*
  * cmlb_get_devid_block:
  *	 get the block number where device id is stored.
  *
--- a/usr/src/uts/common/sys/ddi_impldefs.h	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/sys/ddi_impldefs.h	Wed Jul 30 10:30:05 2008 -0700
@@ -219,6 +219,10 @@
 
 	/* owned by bus framework */
 	devi_bus_priv_t	devi_bus;		/* bus private data */
+
+	/* Declarations of the pure dynamic properties to snapshot */
+	struct i_ddi_prop_dyn	*devi_prop_dyn_driver;	/* prop_op */
+	struct i_ddi_prop_dyn	*devi_prop_dyn_parent;	/* bus_prop_op */
 };
 
 #define	DEVI(dev_info_type)	((struct dev_info *)(dev_info_type))
@@ -258,7 +262,7 @@
  * Device state information is stored in bits [0-7], bus state in bits
  * [8-15].
  *
- * NOTE: all devi_state updates shoule be protected by devi_lock.
+ * NOTE: all devi_state updates should be protected by devi_lock.
  */
 #define	DEVI_DEVICE_OFFLINE	0x00000001
 #define	DEVI_DEVICE_DOWN	0x00000002
@@ -277,7 +281,6 @@
 #define	DEVI_S_INVOKING_DACF	0x00100000 /* busy invoking a dacf task */
 
 #define	DEVI_S_UNBOUND		0x00200000
-#define	DEVI_S_MD_UPDATE	0x00400000
 #define	DEVI_S_REPORT		0x08000000 /* report status change */
 
 #define	DEVI_S_EVADD		0x10000000 /* state of devfs event */
@@ -525,13 +528,10 @@
 	DEVI(dip)->devi_state &= ~DEVI_S_NEED_RESET;			\
 	}
 
-void	i_devi_enter(dev_info_t *, uint_t s_mask, uint_t w_mask, int has_lock);
-void	i_devi_exit(dev_info_t *, uint_t c_mask, int has_lock);
-
 /*
  * devi_flags bits
  *
- * NOTE: all devi_state updates shoule be protected by devi_lock.
+ * NOTE: all devi_state updates should be protected by devi_lock.
  */
 #define	DEVI_BUSY		0x00000001 /* busy configuring children */
 #define	DEVI_MADE_CHILDREN	0x00000002 /* children made from specs */
@@ -878,6 +878,55 @@
 	size_t			c_size;
 };
 
+/*
+ * Pure dynamic property declaration. A pure dynamic property is a property
+ * for which a driver's prop_op(9E) implementation will return a value on
+ * demand, but the property name does not exist on a property list (global,
+ * driver, system, or hardware) - the person asking for the value must know
+ * the name and type information.
+ *
+ * For a pure dynamic property to show up in a di_init() devinfo shapshot, the
+ * devinfo driver must know name and type. The i_ddi_prop_dyn_t mechanism
+ * allows a driver to define an array of the name/type information of its
+ * dynamic properties. When a driver declares its dynamic properties in a
+ * i_ddi_prop_dyn_t array, and registers that array using
+ * i_ddi_prop_dyn_driver_set() the devinfo driver has sufficient information
+ * to represent the properties in a snapshot - calling the driver's
+ * prop_op(9E) to obtain values.
+ *
+ * The last element of a i_ddi_prop_dyn_t is detected via a NULL dp_name value.
+ *
+ * A pure dynamic property name associated with a minor_node/dev_t should be
+ * defined with a dp_spec_type of S_IFCHR or S_IFBLK, as appropriate.  The
+ * driver's prop_op(9E) entry point will be called for all
+ * ddi_create_minor_node(9F) nodes of the specified spec_type. For a driver
+ * where not all minor_node/dev_t combinations support the same named
+ * properties, it is the responsibility of the prop_op(9E) implementation to
+ * sort out what combinations are appropriate.
+ *
+ * A pure dynamic property of a devinfo node should be defined with a
+ * dp_spec_type of 0.
+ *
+ * NB: Public DDI property interfaces no longer support pure dynamic
+ * properties, but they are still still used.  A prime example is the cmlb
+ * implementation of size(9P) properties. Using pure dynamic properties
+ * reduces the space required to maintain per-partition information. Since
+ * there are no public interfaces to create pure dynamic properties,
+ * the i_ddi_prop_dyn_t mechanism should remain private.
+ */
+typedef struct i_ddi_prop_dyn {
+	char	*dp_name;		/* name of dynamic property */
+	int	dp_type;		/* DDI_PROP_TYPE_ of property */
+	int	dp_spec_type;		/* 0, S_IFCHR, S_IFBLK */
+} i_ddi_prop_dyn_t;
+void			i_ddi_prop_dyn_driver_set(dev_info_t *,
+			    i_ddi_prop_dyn_t *);
+i_ddi_prop_dyn_t	*i_ddi_prop_dyn_driver_get(dev_info_t *);
+void			i_ddi_prop_dyn_parent_set(dev_info_t *,
+			    i_ddi_prop_dyn_t *);
+i_ddi_prop_dyn_t	*i_ddi_prop_dyn_parent_get(dev_info_t *);
+void			i_ddi_prop_dyn_cache_invalidate(dev_info_t *,
+			    i_ddi_prop_dyn_t *);
 
 /*
  * Device id - Internal definition.
--- a/usr/src/uts/common/sys/devinfo_impl.h	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/sys/devinfo_impl.h	Wed Jul 30 10:30:05 2008 -0700
@@ -118,15 +118,7 @@
 #define	DI_DEVNM(addr)		((struct di_devnm *)((void *)(addr)))
 #define	DI_LINK(addr)		((struct di_link *)((void *)(addr)))
 #define	DI_LNODE(addr)		((struct di_lnode *)((void *)(addr)))
-
-/*
- * For compatibility only
- */
-#define	DINO(addr)		DI_NODE(addr)
-#define	DIMI(addr)		DI_MINOR(addr)
-#define	DIPROP(addr)		DI_PROP(addr)
-#define	DIPATH(addr)		DI_PATH(addr)
-#define	DIPATHPROP(addr)	DI_PATHPROP(addr)
+#define	DI_PRIV_FORMAT(addr)	((struct di_priv_format *)((void *)(addr)))
 
 /*
  * multipath component definitions:  Follows the registered component of
@@ -360,9 +352,9 @@
 	di_off_t	prop_data;	/* property data */
 	major_t		dev_major;	/* dev_t can be 64 bit */
 	minor_t		dev_minor;
-	int	prop_flags;	/* mark prop value types & more */
-	int	prop_len;	/* prop length in bytes (boolean if 0) */
-	int	prop_list;	/* which list (DI_PROP_SYS_LIST), etc */
+	int		prop_flags;	/* mark prop value types & more */
+	int		prop_len;	/* prop len in bytes (boolean if 0) */
+	int		prop_list;	/* which list (DI_PROP_SYS_LIST), etc */
 };
 
 /*
--- a/usr/src/uts/common/sys/sunddi.h	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/sys/sunddi.h	Wed Jul 30 10:30:05 2008 -0700
@@ -924,6 +924,15 @@
 
 
 /*
+ * ddi_prop_cache_invalidate
+ *			Invalidate a property in the current cached
+ *			devinfo snapshot - next cached snapshot will
+ *			return the latest property value available.
+ */
+void
+ddi_prop_cache_invalidate(dev_t dev, dev_info_t *dip, char *name, int flags);
+
+/*
  * The default ddi_bus_prop_op wrapper...
  */
 
--- a/usr/src/uts/common/xen/io/xdf.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/common/xen/io/xdf.c	Wed Jul 30 10:30:05 2008 -0700
@@ -301,19 +301,9 @@
 xdf_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
 	char *name, caddr_t valuep, int *lengthp)
 {
-	int instance = ddi_get_instance(dip);
-	xdf_t *vdp;
-	diskaddr_t p_blkcnt;
-
-	/*
-	 * xdf dynamic properties are device specific and size oriented.
-	 * Requests issued under conditions where size is valid are passed
-	 * to ddi_prop_op_nblocks with the size information, otherwise the
-	 * request is passed to ddi_prop_op.
-	 */
-	vdp = ddi_get_soft_state(vbd_ss, instance);
-
-	if ((dev == DDI_DEV_T_ANY) || (vdp == NULL))
+	xdf_t	*vdp;
+
+	if ((vdp = ddi_get_soft_state(vbd_ss, ddi_get_instance(dip))) == NULL)
 		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
 		    name, valuep, lengthp));
 
@@ -321,18 +311,14 @@
 	mutex_enter(&vdp->xdf_dev_lk);
 	if (xdf_connect(vdp, B_TRUE) != XD_READY) {
 		mutex_exit(&vdp->xdf_dev_lk);
-		goto out;
+		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
+		    name, valuep, lengthp));
 	}
 	mutex_exit(&vdp->xdf_dev_lk);
 
-	if (cmlb_partinfo(vdp->xdf_vd_lbl, XDF_PART(getminor(dev)), &p_blkcnt,
-	    NULL, NULL, NULL, NULL) == 0)
-		return (ddi_prop_op_nblocks(dev, dip, prop_op, mod_flags,
-		    name, valuep, lengthp, (uint64_t)p_blkcnt));
-
-out:
-	return (ddi_prop_op(dev, dip, prop_op, mod_flags, name, valuep,
-	    lengthp));
+	return (cmlb_prop_op(vdp->xdf_vd_lbl,
+	    dev, dip, prop_op, mod_flags, name, valuep, lengthp,
+	    XDF_PART(getminor(dev)), NULL));
 }
 
 static int
--- a/usr/src/uts/intel/io/dktp/disk/cmdk.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/intel/io/dktp/disk/cmdk.c	Wed Jul 30 10:30:05 2008 -0700
@@ -684,8 +684,6 @@
     char *name, caddr_t valuep, int *lengthp)
 {
 	struct	cmdk	*dkp;
-	diskaddr_t	p_lblksrt;
-	diskaddr_t	p_lblkcnt;
 
 #ifdef CMDK_DEBUG
 	if (cmdk_debug & DENT)
@@ -693,31 +691,13 @@
 #endif
 
 	dkp = ddi_get_soft_state(cmdk_state, ddi_get_instance(dip));
+	if (dkp == NULL)
+		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
+		    name, valuep, lengthp));
 
-	/*
-	 * Our dynamic properties are all device specific and size oriented.
-	 * Requests issued under conditions where size is valid are passed
-	 * to ddi_prop_op_nblocks with the size information, otherwise the
-	 * request is passed to ddi_prop_op. Size depends on valid label.
-	 */
-	if ((dev != DDI_DEV_T_ANY) && (dkp != NULL)) {
-		if (!cmlb_partinfo(
-		    dkp->dk_cmlbhandle,
-		    CMDKPART(dev),
-		    &p_lblkcnt,
-		    &p_lblksrt,
-		    NULL,
-		    NULL,
-		    0))
-			return (ddi_prop_op_nblocks(dev, dip,
-			    prop_op, mod_flags,
-			    name, valuep, lengthp,
-			    (uint64_t)p_lblkcnt));
-	}
-
-	return (ddi_prop_op(dev, dip,
-	    prop_op, mod_flags,
-	    name, valuep, lengthp));
+	return (cmlb_prop_op(dkp->dk_cmlbhandle,
+	    dev, dip, prop_op, mod_flags, name, valuep, lengthp,
+	    CMDKPART(dev), NULL));
 }
 
 /*
--- a/usr/src/uts/sun/io/dada/targets/dad.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/sun/io/dada/targets/dad.c	Wed Jul 30 10:30:05 2008 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -419,8 +419,7 @@
 		dcd_max_instance = instance;
 	mutex_exit(&dcd_attach_mutex);
 
-	DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG,
-		    "dcdprobe:\n");
+	DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG, "dcdprobe:\n");
 
 	if (ddi_get_soft_state(dcd_state, instance) != NULL)
 		return (DDI_PROBE_PARTIAL);
@@ -586,14 +585,14 @@
 	cmlb_alloc_handle(&un->un_dklbhandle);
 
 	if (cmlb_attach(devi,
-		&dcd_lb_ops,
-		0,
-		0,
-		0,
-		DDI_NT_BLOCK_CHAN,
-		CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8,
-		un->un_dklbhandle,
-		0) != 0) {
+	    &dcd_lb_ops,
+	    0,
+	    0,
+	    0,
+	    DDI_NT_BLOCK_CHAN,
+	    CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8,
+	    un->un_dklbhandle,
+	    0) != 0) {
 		cmlb_free_handle(&un->un_dklbhandle);
 		dcd_free_softstate(un, devi);
 		return (DDI_FAILURE);
@@ -705,7 +704,7 @@
 		 */
 		wait_cmds_complete = ddi_get_lbolt();
 		wait_cmds_complete +=
-			DCD_WAIT_CMDS_COMPLETE * drv_usectohz(1000000);
+		    DCD_WAIT_CMDS_COMPLETE * drv_usectohz(1000000);
 
 		while (un->un_ncmds) {
 			if (cv_timedwait(&un->un_disk_busy_cv,
@@ -820,8 +819,8 @@
 	instance = ddi_get_instance(devi);
 
 	if (!(un = ddi_get_soft_state(dcd_state, instance)) ||
-		(DCD_DEVICE_STANDBY > level) || (level > DCD_DEVICE_ACTIVE) ||
-		component != 0) {
+	    (DCD_DEVICE_STANDBY > level) || (level > DCD_DEVICE_ACTIVE) ||
+	    component != 0) {
 		return (DDI_FAILURE);
 	}
 
@@ -1189,8 +1188,8 @@
 
 	if (un->un_state == DCD_STATE_PM_SUSPENDED) {
 		mutex_exit(DCD_MUTEX);
-		if (pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE)
-			!= DDI_SUCCESS) {
+		if (pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE) !=
+		    DDI_SUCCESS) {
 			mutex_enter(DCD_MUTEX);
 			return (DCD_BAD_LABEL);
 		}
@@ -1638,40 +1637,15 @@
 dcd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
     char *name, caddr_t valuep, int *lengthp)
 {
-	int		instance = ddi_get_instance(dip);
 	struct dcd_disk	*un;
-	uint64_t	nblocks64;
-	diskaddr_t lblocks;
-
-	/*
-	 * Our dynamic properties are all device specific and size oriented.
-	 * Requests issued under conditions where size is valid are passed
-	 * to ddi_prop_op_nblocks with the size information, otherwise the
-	 * request is passed to ddi_prop_op. Size depends on valid geometry.
-	 */
-	un = ddi_get_soft_state(dcd_state, instance);
-	if ((dev == DDI_DEV_T_ANY) || (un == NULL)) {
+
+	if ((un = ddi_get_soft_state(dcd_state, ddi_get_instance(dip))) == NULL)
 		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
 		    name, valuep, lengthp));
-	} else {
-		if (cmlb_partinfo(
-		    un->un_dklbhandle,
-		    DCDPART(dev),
-		    &lblocks,
-		    NULL,
-		    NULL,
-		    NULL,
-		    0)) {
-			return (ddi_prop_op(dev, dip, prop_op, mod_flags,
-			    name, valuep, lengthp));
-		}
-
-		/* get nblocks value */
-		nblocks64 = (ulong_t)lblocks;
-
-		return (ddi_prop_op_nblocks(dev, dip, prop_op, mod_flags,
-		    name, valuep, lengthp, nblocks64));
-	}
+
+	return (cmlb_prop_op(un->un_dklbhandle,
+	    dev, dip, prop_op, mod_flags, name, valuep, lengthp,
+	    DCDPART(dev), NULL));
 }
 
 /*
@@ -1858,7 +1832,7 @@
 		mutex_exit(DCD_MUTEX);
 		(void) pm_idle_component(DCD_DEVINFO, 0);
 		if (pm_raise_power(DCD_DEVINFO, 0,
-			DCD_DEVICE_ACTIVE) !=  DDI_SUCCESS) {
+		    DCD_DEVICE_ACTIVE) !=  DDI_SUCCESS) {
 			SET_BP_ERROR(bp, EIO);
 			goto error;
 		}
@@ -2744,7 +2718,7 @@
 		 */
 		DCD_DO_ERRSTATS(un, dcd_transerrs);
 		if ((pkt->pkt_reason != CMD_RESET) &&
-			(pkt->pkt_reason != CMD_ABORTED)) {
+		    (pkt->pkt_reason != CMD_ABORTED)) {
 			(void) dcd_reset_disk(un, pkt);
 		}
 		break;
@@ -2779,7 +2753,7 @@
 		 */
 		if (un->un_state != DCD_STATE_OFFLINE) {
 			dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
-			(const char *) notresp);
+			    (const char *) notresp);
 			New_state(un, DCD_STATE_OFFLINE);
 		}
 	} else if (pkt->pkt_reason == CMD_FATAL) {
@@ -2876,11 +2850,13 @@
 		} else if ((error &  ERR_UNC) == ERR_UNC) {
 			dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
 			    "Uncorrectable data Error: Block %x\n",
-		((struct dcd_cmd *)pkt->pkt_cdbp)->sector_num.lba_num);
+			    ((struct dcd_cmd *)pkt->pkt_cdbp)->
+			    sector_num.lba_num);
 		} else if ((error & ERR_BBK) == ERR_BBK) {
 			dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
 			    "Bad block detected: Block %x\n",
-			((struct dcd_cmd *)pkt->pkt_cdbp)->sector_num.lba_num);
+			    ((struct dcd_cmd *)pkt->pkt_cdbp)->
+			    sector_num.lba_num);
 		} else if ((error & ERR_ABORT) == ERR_ABORT) {
 			/* Aborted Command */
 			dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
@@ -3824,7 +3800,7 @@
 				 * }
 				 */
 				un->un_reissued_timeid =
-				timeout(dcdrestart, (caddr_t)un,
+				    timeout(dcdrestart, (caddr_t)un,
 				    DCD_BSY_TIMEOUT/500);
 				mutex_exit(DCD_MUTEX);
 				return;
@@ -3898,7 +3874,7 @@
 	}
 	if (!un->un_reissued_timeid) {
 		un->un_reissued_timeid =
-			timeout(dcdrestart, (caddr_t)un, DCD_BSY_TIMEOUT/500);
+		    timeout(dcdrestart, (caddr_t)un, DCD_BSY_TIMEOUT/500);
 	}
 }
 
@@ -4710,7 +4686,7 @@
 		if (un->un_diskcapacity <= 0) {
 			mutex_exit(DCD_MUTEX);
 			dcd_log(DCD_DEVINFO, dcd_label, CE_WARN,
-				"invalid disk capacity\n");
+			    "invalid disk capacity\n");
 			return (EIO);
 		}
 		if (cmd == TG_GETCAPACITY)
--- a/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf.c	Wed Jul 30 09:40:35 2008 -0700
+++ b/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf.c	Wed Jul 30 10:30:05 2008 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -240,6 +240,7 @@
 static boolean_t
 compatible_console(dev_t dev)
 {
+	int			circ;
 	boolean_t		compatible;
 	char *const		*nodetype;
 	struct ddi_minor_data	*dmdp;
@@ -261,6 +262,7 @@
 	compatible = B_FALSE;
 	len = sizeof (devtype);
 
+	ndi_devi_enter(dip, &circ);
 	for (dmdp = DEVI(dip)->devi_minor; dmdp != NULL; dmdp = dmdp->next) {
 		struct ddi_minor_data   *mdp = dmdp;
 
@@ -279,9 +281,9 @@
 				compatible = B_TRUE;
 			} else {
 				for (nodetype =
-					(char *const *)&supported_types[0];
-					*nodetype != (char *const)NULL;
-					nodetype++) {
+				    (char *const *)&supported_types[0];
+				    *nodetype != (char *const)NULL;
+				    nodetype++) {
 					if (strcmp(*nodetype,
 					    mdp->ddm_node_type) == 0) {
 						compatible = B_TRUE;
@@ -292,6 +294,7 @@
 			break;
 		}
 	}
+	ndi_devi_exit(dip, circ);
 	ddi_release_devi(dip);
 
 	/*
@@ -300,7 +303,7 @@
 	 */
 
 	ttymux_dprintf(DPRINT_L0, "%d:%d is %s\n", getmajor(dev),
-		getminor(dev), (compatible) ? "compatible" : "incompatible");
+	    getminor(dev), (compatible) ? "compatible" : "incompatible");
 
 	return (compatible);
 }
@@ -636,7 +639,7 @@
 	}
 
 	if ((rv = strioctl(mux_avp, I_PLINK, (intptr_t)lfd,
-		FREAD+FWRITE+FNOCTTY, K_TO_K, CRED(), &(cn->sm_muxid))) != 0) {
+	    FREAD+FWRITE+FNOCTTY, K_TO_K, CRED(), &(cn->sm_muxid))) != 0) {
 
 		ttymux_dprintf(DPRINT_L3,
 		    "Failed to link device: error %d", rv);
@@ -718,7 +721,7 @@
 			continue;
 		}
 		ttymux_dprintf(DPRINT_L0, "Enabling %d:%d\n",
-			getmajor(cn->sm_dev), getminor(cn->sm_dev));
+		    getmajor(cn->sm_dev), getminor(cn->sm_dev));
 
 		/*
 		 * Refuse requests to use devices as consoles which have an