changeset 1623:7bac4a816ebe

PSARC/2005/153 Bunnahabhain: Descriptive Name Support in SVM 4521995 Allow descriptive names for metadevices and hot spare pools 6396962 metareplace -c is obsolete and no longer needed.
author tw21770
date Tue, 14 Mar 2006 14:53:36 -0800
parents bda65fb11ddc
children 16ffeb79fcfc
files usr/src/cmd/devfsadm/Makefile.com usr/src/cmd/devfsadm/md_link.c usr/src/cmd/lvm/metassist/layout/layout_svm_util.c usr/src/cmd/lvm/rpc.metad/metad_svc_subr.c usr/src/cmd/lvm/util/metaclear.c usr/src/cmd/lvm/util/metaclust.c usr/src/cmd/lvm/util/metadb.c usr/src/cmd/lvm/util/metadetach.c usr/src/cmd/lvm/util/metahs.c usr/src/cmd/lvm/util/metainit.c usr/src/cmd/lvm/util/metaoffline.c usr/src/cmd/lvm/util/metaonline.c usr/src/cmd/lvm/util/metaparam.c usr/src/cmd/lvm/util/metarecover.c usr/src/cmd/lvm/util/metarename.c usr/src/cmd/lvm/util/metareplace.c usr/src/cmd/lvm/util/metaroot.c usr/src/cmd/lvm/util/metastat.c usr/src/cmd/lvm/util/metasync.c usr/src/cmd/lvm/util/metattach.c usr/src/cmd/rcm_daemon/common/svm_rcm.c usr/src/head/meta.h usr/src/lib/libdiskmgt/common/inuse_svm.c usr/src/lib/lvm/libmeta/common/meta_attach.c usr/src/lib/lvm/libmeta/common/meta_check.c usr/src/lib/lvm/libmeta/common/meta_db.c usr/src/lib/lvm/libmeta/common/meta_error.c usr/src/lib/lvm/libmeta/common/meta_getdevs.c usr/src/lib/lvm/libmeta/common/meta_hotspares.c usr/src/lib/lvm/libmeta/common/meta_init.c usr/src/lib/lvm/libmeta/common/meta_mirror.c usr/src/lib/lvm/libmeta/common/meta_mn_handlers.c usr/src/lib/lvm/libmeta/common/meta_mn_msg_table.c usr/src/lib/lvm/libmeta/common/meta_mn_subr.c usr/src/lib/lvm/libmeta/common/meta_mount.c usr/src/lib/lvm/libmeta/common/meta_name.c usr/src/lib/lvm/libmeta/common/meta_namespace.c usr/src/lib/lvm/libmeta/common/meta_raid.c usr/src/lib/lvm/libmeta/common/meta_rename.c usr/src/lib/lvm/libmeta/common/meta_replace.c usr/src/lib/lvm/libmeta/common/meta_se_notify.c usr/src/lib/lvm/libmeta/common/meta_set.c usr/src/lib/lvm/libmeta/common/meta_set_prv.c usr/src/lib/lvm/libmeta/common/meta_sp.c usr/src/lib/lvm/libmeta/common/meta_statconcise.c usr/src/lib/lvm/libmeta/common/meta_stripe.c usr/src/lib/lvm/libmeta/common/meta_tab.c usr/src/lib/lvm/libmeta/common/meta_trans.c usr/src/lib/lvm/libmeta/common/metagetroot.c usr/src/lib/lvm/libmeta/spec/meta.spec usr/src/lib/lvm/libpreen/common/mdpreen.c usr/src/lib/lvm/libsvm/common/metainterfaces.c usr/src/uts/common/io/lvm/hotspares/hotspares.c usr/src/uts/common/io/lvm/md/md.c usr/src/uts/common/io/lvm/md/md_ioctl.c usr/src/uts/common/io/lvm/md/md_mddb.c usr/src/uts/common/io/lvm/md/md_names.c usr/src/uts/common/io/lvm/md/md_rename.c usr/src/uts/common/io/lvm/md/md_subr.c usr/src/uts/common/io/lvm/mirror/mirror.c usr/src/uts/common/io/lvm/mirror/mirror_ioctl.c usr/src/uts/common/io/lvm/raid/raid.c usr/src/uts/common/io/lvm/raid/raid_ioctl.c usr/src/uts/common/io/lvm/raid/raid_replay.c usr/src/uts/common/io/lvm/softpart/sp.c usr/src/uts/common/io/lvm/softpart/sp_ioctl.c usr/src/uts/common/io/lvm/stripe/stripe.c usr/src/uts/common/io/lvm/stripe/stripe_ioctl.c usr/src/uts/common/io/lvm/trans/mdtrans.c usr/src/uts/common/sys/lvm/md_mddb.h usr/src/uts/common/sys/lvm/md_raid.h usr/src/uts/common/sys/lvm/mdio.h usr/src/uts/common/sys/lvm/mdiox.x usr/src/uts/common/sys/lvm/mdmn_commd.x usr/src/uts/common/sys/lvm/mdvar.h usr/src/uts/common/sys/lvm/meta_basic.x
diffstat 76 files changed, 4811 insertions(+), 2041 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/devfsadm/Makefile.com	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/devfsadm/Makefile.com	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
 #
 # CDDL HEADER END
 #
+
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -192,7 +192,7 @@
 	$(RM) $@; cat $(POFILES) > $@
 
 $(DEVFSADM_MOD): $(DEVFSADM_OBJ)
-	$(LINK.c) -o $@ $< $(DEVFSADM_OBJ) $(LDLIBS)
+	$(LINK.c) -o $@ $< $(DEVFSADM_OBJ) $(LDLIBS) -lmeta
 	$(POST_PROCESS)
 
 SUNW_%.so: %.o
--- a/usr/src/cmd/devfsadm/md_link.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/devfsadm/md_link.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,12 +19,13 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
+#include <meta.h>
 #include <regex.h>
 #include <devfsadm.h>
 #include <stdio.h>
@@ -34,8 +34,8 @@
 #include <limits.h>
 #include <sys/mkdev.h>
 
-#define	MD_LINK_RE_DEVICES	"^md/r?dsk/d[0-9]+$"
-#define	MD_LINK_RE_SHARED	"^md/shared/[0-9]+/r?dsk/d[0-9]+$"
+#define	MD_LINK_RE_DEVICES	"^md/r?dsk/.+$"
+#define	MD_LINK_RE_SHARED	"^md/shared/[0-9]+/r?dsk/.+$"
 #define	MD_LINK_RE_ADMIN	"^md/admin"
 
 /*
@@ -77,19 +77,25 @@
  * For the admin device:
  *	/dev/md/admin -> /devices/pseudo/md@0:admin
  *
- * For each other device
- *	/dev/md/dsk/dN -> /devices/pseudo/md@0:0,N,blk
- *	/dev/md/rdsk/dN -> /devices/pseudo/md@0:0,N,raw
- *	/dev/md/shared/M/dsk/dN /devices/pseudo/md@0:M,N,blk
- *	/dev/md/shared/M/rdsk/dN /devices/pseudo/md@0:M,N,raw
+ * For metadevice:
+ *	/dev/md/dsk/foobar --> /devices/pseudo/md@0:0,100,blk
+ *	/dev/md/rdsk/foobar --> /devices/pseudo/md@0:0,100,raw
+ *
+ * Where 'foobar' is user specified arbitrary name and '100'
+ * is the minor number returned by MD_IOCMAKE_DEV ioctl
+ *
  */
 static int
 md_create(di_minor_t minor, di_node_t node)
 {
 	char mn[MAXNAMELEN + 1];
 	char path[PATH_MAX + 1];
-	int set = -1, mdev = -1, ret;
+	int set = -1, ret;
 	char *type, *dir;
+	char *device_name;
+	dev_t minor_devt = di_minor_devt(minor);
+	int key;
+	md_error_t ep;
 
 	(void) strcpy(mn, di_minor_name(minor));
 
@@ -115,26 +121,38 @@
 		 * under the "shared" directory entry instead of linking
 		 * into the top level dsk/rdsk directories.
 		 */
-		ret = sscanf(mn, "%d,%d,", &set, &mdev);
-		if (ret == 2 && (type = strrchr(mn, ',')) != NULL) {
-			type ++;
+		ret = sscanf(mn, "%d,", &set);
+		if (ret == 1 && (type = strrchr(mn, ',')) != NULL) {
+			type++;
 			if (strcmp(type, "blk") == 0) {
 				dir = "dsk";
 			} else {
 				dir = "rdsk";
 			}
+
+			(void) memset(&ep, '\0', sizeof (ep));
+			if ((device_name = meta_getnmentbydev(set,
+			    MD_SIDEWILD, minor_devt, NULL, NULL,
+			    &key, &ep)) == NULL) {
+				(void) close_admin(&ep);
+				return (DEVFSADM_CONTINUE);
+			}
+
 			if (set == 0) {
 				/* this is a simple md */
 				(void) snprintf(path, sizeof (path),
-					"md/%s/d%d", dir, mdev);
+				"md/%s/%s", dir, basename(device_name));
 			} else {
 				/* this is a shared md */
 				(void) snprintf(path, sizeof (path),
-					"md/shared/%d/%s/d%d",
-					set, dir, mdev);
+				"md/shared/%d/%s/%s", set, dir,
+				basename(device_name));
 			}
 			(void) devfsadm_mklink(path, node, minor, 0);
+			Free(device_name);
 		}
 	}
+
+	(void) close_admin(&ep);
 	return (DEVFSADM_CONTINUE);
 }
--- a/usr/src/cmd/lvm/metassist/layout/layout_svm_util.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/metassist/layout/layout_svm_util.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1672,7 +1671,7 @@
 		mdname_t	*mdn;
 		md_raid_t	*raid;
 
-		mdn = metaname(&sp, nlp->namep->cname, &error);
+		mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, &error);
 		mdclrerror(&error);
 		if (mdn == NULL) {
 		    continue;
@@ -1704,7 +1703,7 @@
 		mdname_t	*mdn;
 		md_stripe_t	*stripe;
 
-		mdn = metaname(&sp, nlp->namep->cname, &error);
+		mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, &error);
 		mdclrerror(&error);
 		if (mdn == NULL) {
 		    continue;
@@ -1745,7 +1744,7 @@
 		mdname_t	*mdn;
 		md_sp_t		*soft_part;
 
-		mdn = metaname(&sp, nlp->namep->cname, &error);
+		mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, &error);
 		mdclrerror(&error);
 		if (mdn == NULL) {
 		    continue;
@@ -1901,8 +1900,13 @@
 {
 	mdname_t	*mdn;
 	md_error_t	 error = mdnullerror;
+	meta_device_type_t	uname_type = UNKNOWN;
 
-	mdn = metaname(&sp, slice_name, &error);
+	/* Determine the appropriate uname type for metaname */
+	if (type == SVM_MDB || type == SVM_DRIVE || type == SVM_TRANS)
+		uname_type = LOGICAL_DEVICE;
+
+	mdn = metaname(&sp, slice_name, uname_type, &error);
 	if (!mdisok(&error)) {
 	    mdn = NULL;
 	}
--- a/usr/src/cmd/lvm/rpc.metad/metad_svc_subr.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/rpc.metad/metad_svc_subr.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2140,7 +2140,7 @@
 	if ((np = metaslicename(dp, MD_SLICE0, ep)) == NULL)
 		return;
 
-	if ((real_np = metaname(&sp, np->bname, ep)) == NULL)
+	if ((real_np = metaname(&sp, np->bname, LOGICAL_DEVICE, ep)) == NULL)
 		return;
 
 	res->dev = real_np->dev;
@@ -2262,7 +2262,7 @@
 	if ((np = metaslicename(dp, MD_SLICE0, ep)) == NULL)
 		return;
 
-	if (metaname(&sp, np->bname, ep) == NULL)
+	if (metaname(&sp, np->bname, LOGICAL_DEVICE, ep) == NULL)
 		return;
 
 	res->enc_devid = meta_get_devid(np->rname);
@@ -2381,7 +2381,7 @@
 		return (TRUE);
 	}
 
-	np = metaname(&sp, disklist[0].devname, ep);
+	np = metaname(&sp, disklist[0].devname, LOGICAL_DEVICE, ep);
 	if (np != NULL) {
 		mdcinfo_t	*cinfo;
 		if ((cinfo = metagetcinfo(np, ep)) != NULL) {
@@ -2493,7 +2493,7 @@
 	if (disklist[i].dev == NODEV)
 		i = 0;
 
-	np = metaname(&sp, disklist[i].devname, ep);
+	np = metaname(&sp, disklist[i].devname, LOGICAL_DEVICE, ep);
 	if (np != NULL) {
 		mdcinfo_t	*cinfo;
 		if ((cinfo = metagetcinfo(np, ep)) != NULL) {
@@ -5138,9 +5138,9 @@
 		if (metaioctl(MD_MN_GET_MM_OWNER, ownpar, ep,
 		    "MD_MN_GET_MM_OWNER") != 0) {
 			mde_perror(ep, gettext(
-			    "Unable to get mirror owner for %s/d%u"),
+			    "Unable to get mirror owner for %s/%s"),
 			    local_sp->setname,
-			    (unsigned)MD_MIN2UNIT(ownpar->d.mnum));
+			    get_mdname(local_sp, ownpar->d.mnum));
 			goto out;
 		}
 
@@ -5160,9 +5160,9 @@
 				    MD_MN_MM_ALLOW_CHANGE) == -1) {
 					mde_perror(ep, gettext(
 					    "Unable to reset mirror owner for"
-					    " %s/d%u"), local_sp->setname,
-					    (unsigned)MD_MIN2UNIT(
-					    ownpar->d.mnum));
+					    " %s/%s"), local_sp->setname,
+					    get_mdname(local_sp,
+						    ownpar->d.mnum));
 					goto out;
 				}
 				break;
--- a/usr/src/cmd/lvm/util/metaclear.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metaclear.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -47,7 +46,7 @@
 {
 
 	/* clear hotspare pool */
-	if (is_hspname(uname)) {
+	if (is_existing_hsp(*spp, uname)) {
 		mdhspname_t	*hspnp;
 
 		/* get hotspare pool name */
@@ -71,8 +70,12 @@
 	else {
 		mdname_t	*np;
 
+		/* check for ownership */
+		if (meta_check_ownership(*spp, ep) != 0)
+			return (-1);
+
 		/* get metadevice name */
-		if (((np = metaname(spp, uname, ep)) == NULL) ||
+		if (((np = metaname(spp, uname, META_DEVICE, ep)) == NULL) ||
 		    (metachkmeta(np, ep) != 0)) {
 			return (-1);
 		}
@@ -82,10 +85,6 @@
 		if (meta_lock(*spp, TRUE, ep))
 			return (-1);
 
-		/* check for ownership */
-		if (meta_check_ownership(*spp, ep) != 0)
-			return (-1);
-
 		/* clear metadevice */
 		return (meta_reset_by_name(*spp, np, options, ep));
 	}
@@ -119,10 +118,11 @@
 	char		*argv[]
 )
 {
-	char		*sname = NULL;
+	char		*sname = MD_LOCAL_NAME;
 	mdsetname_t	*sp = NULL;
 	int		aflag = 0;
 	int		pflag = 0;
+	int		set_flag = 0;
 	mdcmdopts_t	options = (MDCMD_PRINT|MDCMD_DOIT);
 	int		c;
 	md_error_t	status = mdnullerror;
@@ -172,6 +172,7 @@
 
 		case 's':
 			sname = optarg;
+			set_flag++;
 			break;
 
 		case 'a':
@@ -201,30 +202,20 @@
 	argc -= optind;
 	argv += optind;
 
-	if (sname != NULL && (sp = metasetname(sname, ep)) == NULL) {
-		goto errout;
+	/* with mn sets if -a, set name must have been specified by -s */
+	if (called_thru_rpc && aflag && !set_flag) {
+		md_eprintf(gettext(
+		    "-a parameter requires the use of -s in multi-node sets"));
+		md_exit(sp, 1);
+	}
+
+	/* get set context */
+	if ((sp = metasetname(sname, ep)) == NULL) {
+		mde_perror(ep, "");
+		md_exit(sp, 1);
 	}
 
 	if (called_thru_rpc) {
-
-		if (aflag) {
-			/* if -a, set name must have been specified by -s */
-			if ((sp == NULL) ||
-			    (metaget_setdesc(sp, ep) == NULL))
-				goto errout;
-		} else {
-			/*
-			 * setname may be defined by setname in first arg
-			 * if sp is NULL, meta_is_mn_name() derives sp from
-			 * argv[0], eg from set/d10
-			 */
-			if (meta_is_mn_name(&sp, argv[0], ep)) {
-				if (metaget_setdesc(sp, ep) == NULL)
-					goto errout;
-			} else
-				goto errout;
-		}
-
 		/* Check if the device is open  on all nodes */
 		options |= MDCMD_MN_OPEN_CHECK;
 	}
@@ -233,12 +224,6 @@
 		if (argc != 0)
 			usage(sp, 1);
 
-		if (sp == NULL) {
-			/* Get sp for local set */
-			if ((sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
-				goto errout;
-		}
-
 		/*
 		 * If a MN set, we will generate a series of individual
 		 * metaclear commands which will each grab the set lock.
@@ -271,13 +256,12 @@
 		 */
 		if (argc <= 0)
 			usage(sp, 1);
+
 		if (meta_is_mn_name(&sp, argv[0], ep))
 			mnset = TRUE;
 		eval = 0;
 
 		for (; (argc > 0); --argc, ++argv) {
-			mdhspname_t	*hspnp;
-			mdname_t	*np;
 			char		*cname;
 
 			/*
@@ -287,45 +271,32 @@
 			 * deal with it.
 			 */
 			if (!called_thru_rpc && mnset) {
+				/* get the canonical name */
 				if (pflag) {
 					/*
 					 * If -p, set cname to the device
 					 * argument.
 					 */
-					cname = argv[0];
+					cname = Strdup(argv[0]);
 				} else {
 					/*
 					 * For hotspares and metadevices, set
 					 * cname to the full name,
 					 * setname/hspxxx or setname/dxxx
 					 */
-					if (is_hspname(argv[0])) {
-						/* get hotspare pool name */
-						if ((hspnp = metahspname(&sp,
-						    argv[0], ep)) == NULL) {
-							mde_perror(ep, "");
-							eval = 1;
-							continue;
-						}
-						cname = hspnp->hspname;
-					} else {
-						/* get metadevice name */
-						if (((np = metaname(&sp,
-						    argv[0], ep)) == NULL) ||
-						    (metachkmeta(np, ep)
-						    != 0)) {
-							mde_perror(ep, "");
-							eval = 1;
-							continue;
-						}
-						cname = np->cname;
+					cname = meta_name_getname(&sp,
+					    argv[0], META_DEVICE, ep);
+					if (cname == NULL) {
+						mde_perror(ep, "");
+						eval = 1;
+						continue;
 					}
 				}
 				if (meta_mn_send_metaclear_command(sp,
 				    cname, options, pflag, ep) != 0) {
 					eval = 1;
-					continue;
 				}
+				Free(cname);
 			} else {
 				if (pflag) {
 					/*
@@ -339,24 +310,34 @@
 						continue;
 					}
 				} else {
-					/* clear named devices */
-					if (clear_name(&sp, argv[0],
-					    options, ep) != 0) {
+					/*
+					 * get the canonical name and
+					 * setup sp if it has been
+					 * specified as part of the
+					 * metadevice/hsp name param
+					 */
+					cname = meta_name_getname(&sp,
+					    argv[0], META_DEVICE, ep);
+					if (cname == NULL) {
 						mde_perror(ep, "");
 						eval = 1;
 						continue;
 					}
+
+					/* clear named devices */
+					if (clear_name(&sp, cname,
+					    options, ep) != 0) {
+						mde_perror(ep, "");
+						eval = 1;
+						Free(cname);
+						continue;
+					}
+					Free(cname);
 				}
 			}
 		}
 	}
 	/* update md.cf */
-	if (sp == NULL) {
-		/* Get sp for local set */
-		if ((sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
-			goto errout;
-	}
-
 	if (meta_update_md_cf(sp, ep) != 0) {
 		mde_perror(ep, "");
 		eval = 1;
--- a/usr/src/cmd/lvm/util/metaclust.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metaclust.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -238,19 +237,25 @@
 compose_path(mdsetname_t *sp, int mnum, char *pathname, int pathlen)
 {
 	int	rtn;
+	mdname_t	*np;
+	md_error_t	status = mdnullerror;
 
 	if (MD_MIN2SET(mnum) != sp->setno) {
 		md_eprintf(gettext("minor number 0x%x invalid for set %d\n"),
 		    mnum, sp->setno);
 		return (-1);
 	}
-	rtn = snprintf(pathname, pathlen, "/dev/md/%s/rdsk/d%u",
-	    sp->setname, (unsigned)MD_MIN2UNIT(mnum));
+
+	if ((np = metamnumname(&sp, mnum, 0, &status)) == NULL) {
+		return (-1);
+	}
+
+	rtn = snprintf(pathname, pathlen, "%s", np->rname);
 
 	if ((pathname[0] == '\0') || (rtn >= pathlen)) {
 		md_eprintf(gettext(
-		    "Could not create path for device %s/d%u\n"),
-		    sp->setname, (unsigned)MD_MIN2UNIT(mnum));
+		    "Could not create path for device %s\n"),
+		    get_mdname(sp, mnum));
 		return (-1);
 	}
 	return (0);
@@ -328,15 +333,14 @@
 			mir_state->mnum = meta_getminor(devnp->dev);
 			MD_SETDRIVERNAME(mir_state, MD_MIRROR, sp->setno);
 			meta_mc_log(MC_LOG4, gettext("Getting mirror state"
-			    " for %s/d%u: %s"), sp->setname,
-			    (unsigned)MD_MIN2UNIT(mir_state->mnum),
+			    " for %s: %s"), get_mdname(sp, mir_state->mnum),
 			    meta_print_hrtime(gethrtime() - start_time));
 
 			if (metaioctl(MD_MN_GET_MIRROR_STATE, mir_state, ep,
 			    "MD_MN_GET_MIRROR_STATE") != 0) {
 				mde_perror(ep, gettext("Unable to get "
-				    "mirror state for %s/d%u"), sp->setname,
-				    (unsigned)MD_MIN2UNIT(mir_state->mnum));
+				    "mirror state for %s"),
+				    get_mdname(sp, mir_state->mnum));
 				goto out;
 			} else {
 				continue;
@@ -372,16 +376,15 @@
 			MD_SETDRIVERNAME(ownpar, MD_MIRROR, sp->setno);
 
 			meta_mc_log(MC_LOG4, gettext("Setting owner "
-			    "for %s/d%u: %s"), sp->setname,
-			    (unsigned)MD_MIN2UNIT(ownpar->d.mnum),
+			    "for %s: %s"), get_mdname(sp, ownpar->d.mnum),
 			    meta_print_hrtime(gethrtime() - start_time));
 
 			/* get the current owner id */
 			if (metaioctl(MD_MN_GET_MM_OWNER, ownpar, ep,
 			    "MD_MN_GET_MM_OWNER") != 0) {
 				mde_perror(ep, gettext("Unable to get "
-				    "mirror owner for %s/d%u"), sp->setname,
-				    (unsigned)MD_MIN2UNIT(ownpar->d.mnum));
+				    "mirror owner for %s"),
+				    get_mdname(sp, ownpar->d.mnum));
 				goto out;
 			}
 		}
@@ -407,18 +410,16 @@
 				    MD_MN_MM_ALLOW_CHANGE) == -1) {
 					md_eprintf(gettext(
 					    "Unable to reset mirror owner "
-					    "for %s/d%u\n"), sp->setname,
-					    (unsigned)MD_MIN2UNIT(
-					    ownpar->d.mnum));
+					    "for %s\n"),
+					    get_mdname(sp, ownpar->d.mnum));
 					goto out;
 				}
 				if (meta_mirror_resync(sp, devnp, 0, ep,
 				    MD_RESYNC_KILL_NO_WAIT) != 0) {
 					md_eprintf(gettext(
 					    "Unable to kill resync for"
-					    " %s/d%u\n"), sp->setname,
-					    (unsigned)MD_MIN2UNIT(
-					    ownpar->d.mnum));
+					    " %s\n"),
+					    get_mdname(sp, ownpar->d.mnum));
 					goto out;
 				}
 			}
@@ -441,8 +442,8 @@
 			    ownpar->d.mnum, ownpar->d.owner,
 			    MD_MN_MM_CHOOSE_OWNER) == -1) {
 				md_eprintf(gettext("Unable to choose "
-				    "mirror owner for %s/d%u\n"), sp->setname,
-				    (unsigned)MD_MIN2UNIT(ownpar->d.mnum));
+				    "mirror owner for %s\n"),
+				    get_mdname(sp, ownpar->d.mnum));
 				goto out;
 			}
 		}
@@ -465,7 +466,7 @@
 			 * cluster, ABR will be cleared on all nodes.
 			 */
 			char		*miscname;
-			char		name[MD_MAX_CTDLEN];
+			char		name[MAXPATHLEN];
 			int		mnum, fd;
 
 			name[0] = '\0';
@@ -483,8 +484,7 @@
 				continue;
 
 			meta_mc_log(MC_LOG4, gettext("Re-setting ABR state "
-			    "for %s/d%u: %s"), sp->setname,
-			    (unsigned)MD_MIN2UNIT(mnum),
+			    "for %s: %s"), get_mdname(sp, mnum),
 			    meta_print_hrtime(gethrtime() - start_time));
 
 			/* compose the absolute device path and open it */
@@ -507,7 +507,7 @@
 			 */
 
 			char		*miscname;
-			char		name[MD_MAX_CTDLEN];
+			char		name[MAXPATHLEN];
 			int		mnum, fd;
 			volcap_t	vc;
 			uint_t		tstate;
@@ -535,8 +535,7 @@
 				continue;
 
 			meta_mc_log(MC_LOG4, gettext("Updating ABR state "
-			    "for %s/d%u: %s"), sp->setname,
-			    (unsigned)MD_MIN2UNIT(mnum),
+			    "for %s: %s"), get_mdname(sp, mnum),
 			    meta_print_hrtime(gethrtime() - start_time));
 
 			/* compose the absolute device path and open it */
--- a/usr/src/cmd/lvm/util/metadb.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metadb.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -75,7 +74,7 @@
 {
 	mdname_t	*np;
 
-	if ((np = metaname(&sp, name, ep)) == NULL)
+	if ((np = metaname(&sp, name, LOGICAL_DEVICE, ep)) == NULL)
 		return (NULL);
 
 	return (metanamelist_append(nlp, np));
--- a/usr/src/cmd/lvm/util/metadetach.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metadetach.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -90,7 +89,7 @@
 		usage(*spp, 1);
 
 	/* get submirror */
-	if ((submirnp = metaname(spp, argv[1], ep)) == NULL)
+	if ((submirnp = metaname(spp, argv[1], META_DEVICE, ep)) == NULL)
 		return (-1);
 
 	/* detach submirror */
@@ -238,7 +237,7 @@
 	}
 
 	/* Get metadevice name */
-	if (((np = metaname(&sp, argv[optind], ep)) == NULL) ||
+	if (((np = metaname(&sp, argv[optind], META_DEVICE, ep)) == NULL) ||
 	    (metachkmeta(np, ep) != 0)) {
 		mde_perror(ep, "");
 		md_exit(sp, 1);
--- a/usr/src/cmd/lvm/util/metahs.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metahs.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -60,7 +59,7 @@
 
 	/* must have set */
 	assert(sp != NULL);
-	assert(sp->setno == HSP_SET(hspnp->hsp));
+	assert(hspnp->hsp == MD_HSP_NONE || sp->setno == HSP_SET(hspnp->hsp));
 
 	/* print status */
 	if (meta_hsp_print(sp, hspnp, &nlp, NULL, stdout, options, ep) != 0)
@@ -93,18 +92,6 @@
 }
 
 /*
- * check for "all"
- */
-static int
-is_all(char *s)
-{
-	if ((strcoll(s, gettext("all")) == 0) ||
-	    (strcoll(s, gettext("ALL")) == 0))
-		return (1);
-	return (0);
-}
-
-/*
  * parse args and add hotspares
  */
 static int
@@ -125,11 +112,7 @@
 	/* get hotspare pool name(s) */
 	if (argc < 1)
 		usage(*spp, 1);
-	if ((argc > 1) && is_all(argv[0])) {
-		if ((*spp == NULL) &&
-		    ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)) {
-			return (-1);
-		}
+	if ((argc > 1) && meta_is_all(argv[0])) {
 		/* check for ownership */
 		assert(*spp != NULL);
 		if (meta_check_ownership(*spp, ep) != 0)
@@ -140,9 +123,12 @@
 		} else if (cnt == 0) {
 			return (mderror(ep, MDE_NO_HSPS, NULL));
 		}
-	} else if ((cnt = metahspnamelist(spp, &hspnlp, 1, &argv[0],
-	    ep)) < 0) {
-		return (-1);
+	} else { /* create the hsp nmlist from the specified hsp name */
+		if (!is_hspname(argv[0]))
+			return (mderror(ep, MDE_NAME_ILLEGAL, argv[0]));
+
+		if ((cnt = metahspnamelist(spp, &hspnlp, 1, &argv[0], ep)) < 0)
+			return (-1);
 	}
 	assert(cnt > 0);
 	--argc, ++argv;
@@ -158,7 +144,8 @@
 		return (-1);
 
 	/* get hotspares */
-	if (metanamelist(spp, &nlp, argc, argv, ep) < 0) {
+	if (metanamelist(spp, &nlp, argc, argv,
+	    LOGICAL_DEVICE, ep) < 0) {
 		goto out;
 	}
 
@@ -201,11 +188,7 @@
 	/* get hotspare pool name(s) */
 	if (argc < 1)
 		usage(*spp, 1);
-	if ((argc > 1) && is_all(argv[0])) {
-		if ((*spp == NULL) &&
-		    ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)) {
-			return (-1);
-		}
+	if ((argc > 1) && meta_is_all(argv[0])) {
 		/* check for ownership */
 		assert(*spp != NULL);
 		if (meta_check_ownership(*spp, ep) != 0)
@@ -234,7 +217,8 @@
 		return (-1);
 
 	/* get hotspares */
-	if (metanamelist(spp, &nlp, argc, argv, ep) < 0) {
+	if (metanamelist(spp, &nlp, argc, argv,
+	    LOGICAL_DEVICE, ep) < 0) {
 		goto out;
 	}
 
@@ -292,7 +276,8 @@
 		usage(*spp, 1);
 
 	/* get list of hotspares */
-	if (metanamelist(spp, &nlp, argc, argv, ep) < 0)
+	if (metanamelist(spp, &nlp, argc, argv,
+	    LOGICAL_DEVICE, ep) < 0)
 		goto out;
 	assert(nlp != NULL);
 
@@ -337,11 +322,7 @@
 	/* get hotspare pool name(s) */
 	if (argc != 3)
 		usage(*spp, 1);
-	if (is_all(argv[0])) {
-		if ((*spp == NULL) &&
-		    ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)) {
-			return (-1);
-		}
+	if (meta_is_all(argv[0])) {
 		/* check for ownership */
 		assert(*spp != NULL);
 		if (meta_check_ownership(*spp, ep) != 0)
@@ -369,11 +350,11 @@
 		return (-1);
 
 	/* get old component */
-	if ((oldnp = metaname(spp, argv[1], ep)) == NULL)
+	if ((oldnp = metaname(spp, argv[1], LOGICAL_DEVICE, ep)) == NULL)
 		goto out;
 
 	/* get new component */
-	if ((newnp = metaname(spp, argv[2], ep)) == NULL)
+	if ((newnp = metaname(spp, argv[2], LOGICAL_DEVICE, ep)) == NULL)
 		goto out;
 
 	/* replace hotspares */
@@ -480,10 +461,6 @@
 
 	/* get hotspare pool name(s) */
 	if (argc == 0) {
-		if ((*spp == NULL) &&
-		    ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)) {
-			return (-1);
-		}
 		/* check for ownership */
 		assert(*spp != NULL);
 		if (meta_check_ownership(*spp, ep) != 0)
@@ -696,6 +673,24 @@
 	if (which_op == NONE)
 		usage(sp, 1);
 
+	/*
+	 * if a hot spare pool was specified by name then
+	 * get the canonical form of the name and set up
+	 * sp if the name was specified in the form 'set/hsp'
+	 * unless 'all' is specified or the request is made to
+	 * enable a hs which means that argv[0] will be a component
+	 */
+	if (argc > 0 && !meta_is_all(argv[0]) && which_op != ENABLE_A_HS) {
+		char *cname = NULL;
+
+		cname = meta_name_getname(&sp, argv[0], HSP_DEVICE, ep);
+		if (cname == NULL) {
+			mde_perror(ep, "");
+			md_exit(sp, 1);
+		}
+		Free(cname);
+	}
+
 	if (which_op == STATUS_A_HSP) {
 		if (status_hotspares(&sp, argc, argv, ep) != 0) {
 			mde_perror(ep, "");
--- a/usr/src/cmd/lvm/util/metainit.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metainit.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -128,14 +127,18 @@
 	/* for all matching entries, which haven't already been done */
 	for (line = 0; (line < tabp->nlines); ++line) {
 		md_tab_line_t	*linep = &tabp->lines[line];
+		char		*uname = linep->argv[0];
 
 		/* see if already done */
 		if (linep->flags != DO_AGAIN)
 			continue;
 
+		/* clear the metadev/hsp caches between inits */
+		metaflushmetanames();
+
 		/* try it */
 		if ((called_thru_rpc == FALSE) &&
-		    meta_is_mn_name(spp, linep->argv[0], ep)) {
+		    meta_is_mn_name(spp, uname, ep)) {
 			/*
 			 * MN set, send command to all nodes
 			 * Note that is sp is NULL, meta_is_mn_name() derives
@@ -144,15 +147,26 @@
 			ret = mn_send_command(spp, linep->argc, linep->argv,
 			    options, flags, linep->context, ep);
 		} else {
-			ret = meta_init_name(spp, linep->argc, linep->argv,
-			    options, ep);
-			if (ret != 0) {
-				if (!(flags & MD_IGNORE_STDERR)) {
-					mderrorextra(ep, linep->context);
-					mde_perror(ep, "");
-					rval = -1;
+			char		*cname = NULL;
+
+			cname = meta_name_getname(spp, uname, META_DEVICE, ep);
+			if (cname == NULL) {
+				mde_perror(ep, "");
+				mdclrerror(ep);
+			} else {
+
+				ret = meta_init_name(spp, linep->argc,
+				    linep->argv, cname, options, ep);
+				Free(cname);
+
+				if (ret != 0) {
+					if (!(flags & MD_IGNORE_STDERR)) {
+					    mderrorextra(ep, linep->context);
+					    mde_perror(ep, "");
+					    rval = -1;
+					}
+					mdclrerror(ep);
 				}
-				mdclrerror(ep);
 			}
 		}
 		if (ret == 0) {
@@ -184,16 +198,6 @@
 	int		done;
 	int		eval = -1;
 
-	/* create local set, if necessary */
-	if (*spp == NULL) {
-		if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL) {
-			mde_perror(ep, "");
-			mdclrerror(ep);
-			return (eval);
-		}
-	}
-	setlen = strlen((*spp)->setname);
-
 	/*
 	 * Only take the lock if this is not a MN set
 	 * We can only enter this code for a MN set if we are the initiator
@@ -225,6 +229,7 @@
 		return (eval);
 	}
 
+	setlen = strlen((*spp)->setname);
 	for (more = 0; (more < tabp->nlines); ++more) {
 		md_tab_line_t	*linep = &tabp->lines[more];
 		char		*cname = linep->cname;
@@ -290,11 +295,10 @@
 	md_tab_line_t	*linep = NULL;
 	int		rval = -1;
 	int		ret;
+	char		*uname = argv[0];
 
 	/* look in md.tab */
 	if (argc == 1) {
-		char		*name = argv[0];
-
 		/* get md.tab entries */
 		if ((tabp = meta_tab_parse(NULL, ep)) == NULL) {
 			if (! mdissyserror(ep, ENOENT))
@@ -302,7 +306,7 @@
 		}
 
 		/* look in md.tab */
-		if ((linep = meta_tab_find(*spp, tabp, name, TAB_MD_HSP))
+		if ((linep = meta_tab_find(*spp, tabp, uname, TAB_MD_HSP))
 								!= NULL) {
 			argc = linep->argc;
 			argv = linep->argv;
@@ -310,14 +314,29 @@
 	}
 
 	if ((called_thru_rpc == FALSE) &&
-	    meta_is_mn_name(spp, argv[0], ep)) {
+	    meta_is_mn_name(spp, uname, ep)) {
 		/*
 		 * MN set, send command to all nodes
 		 */
 		ret = mn_send_command(spp, argc, argv, options,
 		    MD_DISP_STDERR, NO_CONTEXT_STRING, ep);
-	} else
-		ret = meta_init_name(spp, argc, argv, options, ep);
+	} else {
+		char		*cname = NULL;
+
+		cname = meta_name_getname(spp, uname, META_DEVICE, ep);
+		if (cname == NULL) {
+			goto out;
+		}
+
+		/* check for ownership */
+		if (meta_check_ownership(*spp, ep) != 0) {
+			Free(cname);
+			goto out;
+		}
+
+		ret = meta_init_name(spp, argc, argv, cname, options, ep);
+		Free(cname);
+	}
 
 	if (ret != 0) {
 		if (linep != NULL)
@@ -687,7 +706,7 @@
 	char		*argv[]
 )
 {
-	char		*sname = NULL;
+	char		*sname = MD_LOCAL_NAME;
 	mdsetname_t	*sp = NULL;
 	enum action {
 		NONE,
@@ -784,12 +803,12 @@
 		}
 	}
 
-	if (sname != NULL) {
-		if ((sp = metasetname(sname, ep)) == NULL) {
-			mde_perror(ep, "");
-			md_exit(sp, 1);
-		}
+	/* sname is MD_LOCAL_NAME if not specified on the command line */
+	if ((sp = metasetname(sname, ep)) == NULL) {
+		mde_perror(ep, "");
+		md_exit(sp, 1);
 	}
+
 	argc -= optind;
 	argv += optind;
 	if (todo == NONE) {
--- a/usr/src/cmd/lvm/util/metaoffline.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metaoffline.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -139,8 +138,8 @@
 	}
 
 	/* get names */
-	if (((mirnp = metaname(&sp, argv[0], ep)) == NULL) ||
-	    ((submirnp = metaname(&sp, argv[1], ep)) == NULL)) {
+	if (((mirnp = metaname(&sp, argv[0], META_DEVICE, ep)) == NULL) ||
+	    ((submirnp = metaname(&sp, argv[1], META_DEVICE, ep)) == NULL)) {
 		mde_perror(ep, "");
 		md_exit(sp, 1);
 	}
--- a/usr/src/cmd/lvm/util/metaonline.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metaonline.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -135,8 +134,8 @@
 	}
 
 	/* get names */
-	if (((mirnp = metaname(&sp, argv[0], ep)) == NULL) ||
-	    ((submirnp = metaname(&sp, argv[1], ep)) == NULL)) {
+	if (((mirnp = metaname(&sp, argv[0], META_DEVICE, ep)) == NULL) ||
+	    ((submirnp = metaname(&sp, argv[1], META_DEVICE, ep)) == NULL)) {
 		mde_perror(ep, "");
 		md_exit(sp, 1);
 	}
--- a/usr/src/cmd/lvm/util/metaparam.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metaparam.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -35,18 +34,6 @@
 #include <sdssc.h>
 
 /*
- * check for "none"
- */
-static int
-is_none(char *s)
-{
-	if ((strcoll(s, gettext("none")) == 0) ||
-	    (strcoll(s, gettext("NONE")) == 0))
-		return (1);
-	return (0);
-}
-
-/*
  * print usage message
  */
 static void
@@ -202,7 +189,7 @@
 			break;
 
 		case 'h':
-			if (is_none(optarg)) {
+			if (meta_is_none(optarg)) {
 				msp.hsp_id = MD_HSP_NONE;
 			} else if ((hspnp = metahspname(&sp, optarg,
 			    ep)) == NULL) {
@@ -289,7 +276,7 @@
 			break;
 
 		case 'h':
-			if (is_none(optarg)) {
+			if (meta_is_none(optarg)) {
 				msp.hsp_id = MD_HSP_NONE;
 			} else if ((hspnp = metahspname(&sp, optarg,
 			    ep)) == NULL) {
@@ -442,7 +429,7 @@
 		md_exit(sp, result);
 	}
 
-	if ((np = metaname(&sp, argv[optind], ep)) == NULL) {
+	if ((np = metaname(&sp, argv[optind], META_DEVICE, ep)) == NULL) {
 		mde_perror(ep, "");
 		md_exit(sp, 1);
 	}
--- a/usr/src/cmd/lvm/util/metarecover.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metarecover.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -142,7 +141,7 @@
 	argv++;
 	argc--;
 
-	if ((namep = metaname(&sp, devname, ep)) == NULL) {
+	if ((namep = metaname(&sp, devname, UNKNOWN, ep)) == NULL) {
 		mde_perror(ep, "");
 		md_exit(sp, 1);
 	}
--- a/usr/src/cmd/lvm/util/metarename.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metarename.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -221,13 +220,14 @@
 		}
 		if (i == 1 && !xflag) {
 		    /* rename, create dest metadevice name */
-		    if (meta_init_make_device(&sp, argv[i], ep) != 0) {
+		    if (meta_init_make_device(&sp, argv[i], ep) <= 0) {
 			mde_perror(ep, argv[i]);
 			md_exit(sp, 1);
 		    }
 		}
 
-		if (NULL == (mdnms[i] = metaname(&sp, argv[i], ep))) {
+		if ((mdnms[i] = metaname(&sp, argv[i],
+		    META_DEVICE, ep)) == NULL) {
 			mde_perror(ep, argv[i]);
 			md_exit(sp, 1);
 		}
--- a/usr/src/cmd/lvm/util/metareplace.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metareplace.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -47,9 +46,8 @@
 usage:	%s [-s setname] mirror component-old component-new\n\
 	%s [-s setname] -e mirror component\n\
 	%s [-s setname] [-f] RAID component-old component-new\n\
-	%s [-s setname] [-f] -e RAID component\n\
-	%s [-s setname] -c metadevice component-old component-new\n"),
-	    myname, myname, myname, myname, myname);
+	%s [-s setname] [-f] -e RAID component\n"),
+	    myname, myname, myname, myname);
 	md_exit(sp, eval);
 }
 
@@ -67,7 +65,6 @@
 	mdcmdopts_t	options = (MDCMD_PRINT|MDCMD_DOIT);
 	mdname_t	*namep;
 	int		eflag = 0;
-	int		cflag = 0;
 	int		c;
 	md_error_t	status = mdnullerror;
 	md_error_t	*ep = &status;
@@ -111,7 +108,7 @@
 	/* parse arguments */
 	optind = 1;
 	opterr = 1;
-	while ((c = getopt(argc, argv, "hs:cefn?")) != -1) {
+	while ((c = getopt(argc, argv, "hs:efn?")) != -1) {
 		switch (c) {
 		case 'h':
 			usage(sp, 0);
@@ -137,11 +134,6 @@
 			}
 			break;
 
-		case 'c':
-			options |= MDCMD_CLUSTER_REPLACE;
-			++cflag;
-			break;
-
 		case '?':
 			if (optopt == '?')
 				usage(sp, 0);
@@ -167,30 +159,14 @@
 
 	uname = argv[0];
 
-	if (((namep = metaname(&sp, argv[0], ep)) == NULL)) {
+	if (((namep = metaname(&sp, uname, META_DEVICE, ep)) == NULL)) {
 		mde_perror(ep, "");
 		md_exit(sp, 1);
 	}
 
-	/*
-	 * This 'if' statement might look a little strange so I'll 'splain
-	 * a few things.
-	 *
-	 * If 'cflag' is not set then always do the metachkmeta.
-	 *    This is the normal behavior and you're not allowed to run
-	 *    metarplace on a hotspare. metachkmeta will barf.
-	 *
-	 * If 'cflag' and uname is not a hotspare do metachkmeta
-	 *    Still need to check out the metadevice as long as it's not
-	 *    a hotspare.
-	 *
-	 * Else we've got a hotspare so we can't call metachkmeta
-	 */
-	if ((!cflag) || (cflag && (!is_hspname(uname)))) {
-		if (metachkmeta(namep, ep) != 0) {
-			mde_perror(ep, "");
-			md_exit(sp, 1);
-		}
+	if (metachkmeta(namep, ep) != 0) {
+		mde_perror(ep, "");
+		md_exit(sp, 1);
 	}
 
 	assert(sp != NULL);
@@ -274,7 +250,7 @@
 		if (argc != 1)
 			usage(sp, 1);
 
-		if ((compnp = metaname(&sp, argv[0], ep)) == NULL) {
+		if ((compnp = metaname(&sp, argv[0], UNKNOWN, ep)) == NULL) {
 			mde_perror(ep, "");
 			md_exit(sp, 1);
 		}
@@ -290,26 +266,18 @@
 		if (argc != 2)
 			usage(sp, 1);
 
-		if ((oldnp = metaname(&sp, argv[0], ep)) == NULL) {
-			mde_perror(ep, "");
-			md_exit(sp, 1);
-		}
-		if ((newnp = metaname(&sp, argv[1], ep)) == NULL) {
+		if ((oldnp = metaname(&sp, argv[0], UNKNOWN, ep)) == NULL) {
 			mde_perror(ep, "");
 			md_exit(sp, 1);
 		}
-		if (cflag) {			/* new replace stuff */
-			if (meta_replace(sp, namep, oldnp, newnp, uname,
-			    options, ep) != 0) {
-				mde_perror(ep, "");
-				md_exit(sp, 1);
-			}
-		} else {
-			if (meta_replace_byname(sp, namep, oldnp, newnp,
-			    options, ep) != 0) {
-				mde_perror(ep, "");
-				md_exit(sp, 1);
-			}
+		if ((newnp = metaname(&sp, argv[1], UNKNOWN, ep)) == NULL) {
+			mde_perror(ep, "");
+			md_exit(sp, 1);
+		}
+		if (meta_replace_byname(sp, namep, oldnp, newnp,
+		    options, ep) != 0) {
+			mde_perror(ep, "");
+			md_exit(sp, 1);
 		}
 	}
 
--- a/usr/src/cmd/lvm/util/metaroot.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metaroot.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1992-2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -251,7 +250,7 @@
 		mde_perror(ep, "");
 		return (METAROOT_ERR);
 	}
-	if ((rootnp = metaname(&sp, curroot, ep)) == NULL) {
+	if ((rootnp = metaname(&sp, curroot, UNKNOWN, ep)) == NULL) {
 		mde_perror(ep, "");
 		return (METAROOT_ERR);
 	}
@@ -412,7 +411,7 @@
 	}
 
 	/* get device name */
-	if ((rootnp = metaname(&sp, argv[0], ep)) == NULL) {
+	if ((rootnp = metaname(&sp, argv[0], UNKNOWN, ep)) == NULL) {
 		mde_perror(ep, "");
 		md_exit(sp, 1);
 	}
@@ -425,7 +424,7 @@
 	 * mounted as happens if this command is part of the install
 	 * process, currootnp will be set to NULL.
 	 */
-	currootnp = metaname(&sp, curroot, ep);
+	currootnp = metaname(&sp, curroot, UNKNOWN, ep);
 	/*
 	 * If the argument is the name of the current root filesystem, then
 	 * the command is allowed, otherwise check that the argument is
--- a/usr/src/cmd/lvm/util/metastat.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metastat.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -110,7 +109,7 @@
 	options |= PRINT_SUBDEVS;
 
 	/* hotspare pool */
-	if (is_hspname(uname)) {
+	if (is_existing_hsp(*spp, uname)) {
 		mdhspname_t	*hspnamep;
 
 		/* get hotsparepool */
@@ -128,7 +127,7 @@
 	}
 
 	/* get metadevice */
-	if (((namep = metaname(spp, uname, ep)) == NULL) ||
+	if (((namep = metaname(spp, uname, META_DEVICE, ep)) == NULL) ||
 	    (metachkmeta(namep, ep) != 0))
 		return (-1);
 
@@ -162,20 +161,20 @@
 )
 {
 	int			rval = -1;
+	char			*cname = NULL;
 	char			*cp = NULL;
 	md_gs_stat_parm_t	gsp;
 
-	/* create local set, if necessary */
-	if (*spp == NULL) {
-		if (fname != NULL && (cp = strchr(fname, '/')) != NULL)
-			*cp = '\0';
 
-		if (fname != NULL && (*spp = metasetname(fname, ep)) != NULL) {
-			*cp = '/';
-		} else {
-			if ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)
-				return (rval);
+	if (fname != NULL && strchr(fname, '/') != NULL) {
+		/* get the canonical name */
+		cname = meta_name_getname(spp, fname, META_DEVICE, ep);
+		if (cname == NULL) {
+			mde_perror(ep, "");
+			mdclrerror(ep);
+			return (-1);
 		}
+		Free(cname);
 	}
 
 	if ((cp = getenv("MD_DEBUG")) == NULL)
@@ -264,7 +263,7 @@
 )
 {
 	(void) fprintf(stderr, gettext("\
-usage:	%s [-s setname] [-a][-c][-B][-r][-i][-p] [-t] [metadevice...]\n"),
+usage:	%s [-s setname] [-a][-c][-B][-D][-r][-i][-p] [-t] [metadevice...]\n"),
 	    myname);
 	md_exit(sp, eval);
 }
@@ -278,7 +277,7 @@
 	char	*argv[]
 )
 {
-	char		*sname = NULL;
+	char		*sname = MD_LOCAL_NAME;
 	mdsetname_t	*sp = NULL;
 	mdprtopts_t	options = PRINT_HEADER | PRINT_DEVID | PRINT_FAST;
 	int		c;
@@ -288,6 +287,7 @@
 	int		eval = 0;
 	int		inquire = 0;
 	int		quiet_flg = 0;
+	int		set_flg = 0;
 	int		error;
 	int		all_sets_flag = 0;
 	int		concise_flag = 0;
@@ -324,7 +324,7 @@
 	/* parse arguments */
 	optind = 1;
 	opterr = 1;
-	while ((c = getopt(argc, argv, "acSs:hpBrtiq?")) != -1) {
+	while ((c = getopt(argc, argv, "acSs:hpBDrtiq?")) != -1) {
 		switch (c) {
 		case 'a':
 			all_sets_flag++;
@@ -341,6 +341,7 @@
 
 		case 's':
 			sname = optarg;
+			set_flg++;
 			break;
 
 		case 'h':
@@ -363,6 +364,9 @@
 		case 'B':
 			options |= PRINT_LARGEDEVICES;
 			break;
+		case 'D':
+			options |= PRINT_FN;
+			break;
 		case 'r':		/* defunct option */
 			break;
 		case 'q':
@@ -380,23 +384,16 @@
 	argc -= optind;
 	argv += optind;
 
-	if (sname != NULL) {
-
-		if (all_sets_flag) {
-			fprintf(stderr, gettext("metastat: "
-			    "incompatible options: -a and -s\n"));
-			usage(sp, 1);
-		}
+	if (all_sets_flag && set_flg) {
+		fprintf(stderr, gettext("metastat: "
+		    "incompatible options: -a and -s\n"));
+		usage(sp, 1);
+	}
 
-		if ((sp = metasetname(sname, ep)) == NULL) {
-			mde_perror(ep, "");
-			md_exit(sp, 1);
-		}
-	} else {
-		if ((sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) {
-			mde_perror(ep, "");
-			md_exit(sp, 1);
-		}
+	/* get set context */
+	if ((sp = metasetname(sname, ep)) == NULL) {
+		mde_perror(ep, "");
+		md_exit(sp, 1);
 	}
 
 	/* make sure that the mddb is not stale. Else print a warning */
@@ -453,26 +450,39 @@
 	/* print named device types */
 	while (devcnt < argc) {
 		char	*uname = argv[devcnt];
+		char	*cname = NULL;
+
+		/* get the canonical name */
+		cname = meta_name_getname(&sp, uname, META_DEVICE, ep);
+		if (cname == NULL) {
+			/* already printed the error */
+			mdclrerror(ep);
+			eval = 1;
+			++devcnt;
+			continue;
+		}
 
 		if (concise_flag) {
 		    mdname_t *np;
 
-		    np = metaname(&sp, uname, ep);
+		    np = metaname(&sp, cname, META_DEVICE, ep);
 		    if (np == NULL) {
 			mde_perror(ep, "");
 			mdclrerror(ep);
+			eval = 1;
 		    } else {
 			print_concise_md(0, sp, np);
 		    }
 
 		} else {
-		    if (print_name(&sp, uname, &nlistp, NULL, stdout, options,
+		    if (print_name(&sp, cname, &nlistp, NULL, stdout, options,
 			&meta_print_trans_msg, &lognlp, ep) != 0) {
 			    mde_perror(ep, "");
 			    mdclrerror(ep);
 			    eval = 1;
 		    }
 		}
+		Free(cname);
 		++devcnt;
 	}
 
@@ -482,14 +492,24 @@
 
 		while (devcnt < argc) {
 			char	*uname = argv[devcnt];
+			char	*cname = NULL;
+
+			/* get the canonical name */
+			cname = meta_name_getname(&sp, uname, META_DEVICE, ep);
+			if (cname == NULL) {
+				mde_perror(ep, "");
+				mdclrerror(ep);
+				++devcnt;
+				continue;
+			}
 
 			/* hotspare pools */
-			if (is_hspname(uname)) {
+			if (is_existing_hsp(sp, cname)) {
 				mdhspname_t	*hspnamep;
 				md_hsp_t	*hsp;
 
 				/* get hotsparepool */
-				if ((hspnamep = metahspname(&sp, uname,
+				if ((hspnamep = metahspname(&sp, cname,
 					ep)) == NULL)
 					eval = 1;
 
@@ -504,7 +524,8 @@
 					namep = hsp->hotspares.
 					    hotspares_val[hsi].hsnamep;
 
-					if (!(options & PRINT_LARGEDEVICES)) {
+					if (!(options &
+					    (PRINT_LARGEDEVICES | PRINT_FN))) {
 						/* meta_getdevs populates the */
 						/* nlistp structure for use   */
 						if (meta_getdevs(sp, namep,
@@ -517,12 +538,13 @@
 			} else {
 
 				/* get metadevice */
-				if (((namep = metaname(&sp, uname,
-					ep)) == NULL) ||
+				if (((namep = metaname(&sp, cname,
+					META_DEVICE, ep)) == NULL) ||
 					(metachkmeta(namep, ep) != 0))
 					eval = 1;
 
-				if (!(options & PRINT_LARGEDEVICES)) {
+				if (!(options &
+				    (PRINT_LARGEDEVICES | PRINT_FN))) {
 					/* meta_getdevs populates the	*/
 					/* nlistp structure for use 	*/
 					if (meta_getdevs(sp, namep, &nlistp, ep)
@@ -530,7 +552,7 @@
 						eval =  1;
 				}
 			}
-
+			Free(cname);
 			++devcnt;
 		}
 		if (print_devid(sp, nlistp, stdout, ep) != 0)
@@ -602,12 +624,6 @@
 	md_error_t	*ep = &status;
 	int		meta_print_trans_msg = 0;
 
-	/* default to local set */
-	if ((sp == NULL) && ((sp = metasetname(MD_LOCAL_NAME, ep)) == NULL)) {
-	    mde_perror(ep, "");
-	    md_exit(sp, 1);
-	}
-
 	/* check for ownership */
 	assert(sp != NULL);
 	if (meta_check_ownership(sp, ep) != 0) {
@@ -638,7 +654,7 @@
 		 * upgrade.  Even if meta_getalldevs fails, the
 		 * data in nlistp is still valid.
 		 */
-		if (!(options & PRINT_LARGEDEVICES)) {
+		if (!(options & (PRINT_LARGEDEVICES | PRINT_FN))) {
 		    (void) meta_getalldevs(sp, &nlistp, 0, ep);
 		}
 		if (nlistp != NULL) {
@@ -1164,7 +1180,7 @@
 		md_sp_t		*soft_part;
 		mdnamelist_t	*tnlp;
 
-		mdn = metaname(&sp, nlp->namep->cname, &error);
+		mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, &error);
 		mdclrerror(&error);
 		if (mdn == NULL) {
 		    print_concise_entry(0, nlp->namep->cname, 0, 'p');
@@ -1195,7 +1211,9 @@
 		for (tnlp = nlp->next; tnlp != NULL; tnlp = tnlp->next) {
 		    md_sp_t		*part;
 
-		    mdn = metaname(&sp, tnlp->namep->cname, &error);
+		    mdn = metaname(&sp, tnlp->namep->cname,
+		    META_DEVICE, &error);
+
 		    mdclrerror(&error);
 		    if (mdn == NULL)
 			continue;
@@ -1287,7 +1305,7 @@
 	    mdname_t	*mdn;
 	    md_common_t	*u;
 
-	    mdn = metaname(&sp, nlp->namep->cname, &error);
+	    mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, &error);
 	    mdclrerror(&error);
 	    if (mdn == NULL) {
 		print_concise_entry(0, nlp->namep->cname, 0, mtype);
@@ -1672,7 +1690,7 @@
 
 		if (mirror_status & MD_UN_RESYNC_ACTIVE) {
 
-		    if (mirror->common.revision == MD_64BIT_META_DEV) {
+		    if (mirror->common.revision & MD_64BIT_META_DEV) {
 			(void) snprintf(buf, sizeof (buf),
 			    gettext("resync-%2d.%1d%%"),
 			    mirror->percent_done / 10,
--- a/usr/src/cmd/lvm/util/metasync.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metasync.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -236,7 +235,7 @@
 		int		result;
 
 		/* get device */
-		if ((np = metaname(&sp, argv[0], ep)) == NULL) {
+		if ((np = metaname(&sp, argv[0], META_DEVICE, ep)) == NULL) {
 			mde_perror(ep, "");
 			rval = -1;
 			continue;
--- a/usr/src/cmd/lvm/util/metattach.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/lvm/util/metattach.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -163,7 +162,8 @@
 		usage(*spp, 1);
 
 	/* get list of components */
-	if (metanamelist(spp, &compnlp, argc, argv, ep) < 0)
+	if (metanamelist(spp, &compnlp, argc, argv,
+	    UNKNOWN, ep) < 0)
 		return (-1);
 	assert(compnlp != NULL);
 	for (p = compnlp; (p != NULL); p = p->next) {
@@ -256,7 +256,8 @@
 		usage(*spp, 1);
 
 	/* get list of components */
-	if (metanamelist(spp, &compnlp, argc, argv, ep) < 0)
+	if (metanamelist(spp, &compnlp, argc, argv,
+	    UNKNOWN, ep) < 0)
 		return (-1);
 	assert(compnlp != NULL);
 	for (p = compnlp; (p != NULL); p = p->next) {
@@ -318,7 +319,8 @@
 
 	/* get submirror */
 	if (argc == 1) {
-		if (((submirnp = metaname(spp, argv[0], ep)) == NULL) ||
+		if (((submirnp = metaname(spp, argv[0], META_DEVICE,
+		    ep)) == NULL) ||
 		    (metachkmeta(submirnp, ep) != 0)) {
 			return (-1);
 		}
@@ -427,7 +429,7 @@
 		}
 	}
 
-	if (((np = metaname(&sp, argv[optind], ep)) == NULL) ||
+	if (((np = metaname(&sp, argv[optind], META_DEVICE, ep)) == NULL) ||
 	    (metachkmeta(np, ep) != 0)) {
 		mde_perror(ep, "");
 		md_exit(sp, 1);
--- a/usr/src/cmd/rcm_daemon/common/svm_rcm.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/cmd/rcm_daemon/common/svm_rcm.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -72,6 +71,7 @@
  */
 #define	MSG_UNRECOGNIZED	gettext("SVM: \"%s\" is not a SVM resource")
 #define	MSG_NODEPS		gettext("SVM: can't find dependents")
+#define	MSG_NORECACHE		gettext("SVM: WARNING: couldn't re-cache.")
 #define	MSG_OPENERR		gettext("SVM: can't open \"%s\"")
 #define	MSG_CACHEFAIL		gettext("SVM: can't malloc cache")
 
@@ -120,7 +120,8 @@
 	struct deventry		*next;		/* next entry with same hash */
 	svm_type_t		devtype;	/* device type */
 	dev_t			devkey;		/* key */
-	char			*devname;	/* name */
+	char			*devname;	/* name in /dev */
+	char			*devicesname;	/* name in /devices */
 	struct deventry		*dependent;	/* 1st dependent */
 	struct deventry		*next_dep;	/* next dependent */
 	struct deventry		*antecedent;	/* antecedent */
@@ -157,6 +158,7 @@
 
 static int svm_register(rcm_handle_t *hd);
 static int svm_unregister(rcm_handle_t *hd);
+static int svm_unregister_device(rcm_handle_t *hd, deventry_t *d);
 static deventry_t *cache_dependent(cache_t *cache, char *devname, int devflags,
     deventry_t *dependents);
 static deventry_t *cache_device(cache_t *cache, char *devname,
@@ -185,7 +187,7 @@
 static void free_cache(cache_t **cache);
 static void free_deventry(deventry_t **deventry);
 static uint32_t hash(uint32_t h, char *s);
-static void register_device(rcm_handle_t *hd, char *devname);
+static void svm_register_device(rcm_handle_t *hd, char *devname);
 static int add_dep(int *ndeps, char ***depsp, deventry_t *deventry);
 static int get_dependents(deventry_t *deventry, char *** dependentsp);
 char *add_to_usage(char ** usagep, char *string);
@@ -341,7 +343,7 @@
 
 	/* If not, register the whole cache and mark it as registered. */
 	while ((devicename = cache_walk(svm_cache, &i, &l)) != NULL) {
-			register_device(hd, devicename);
+			svm_register_device(hd, devicename);
 	}
 	svm_cache->registered = 1;
 
@@ -369,7 +371,6 @@
 {
 	deventry_t *l = NULL;
 	uint32_t i = 0;
-	char	    *devicename;
 
 	rcm_log_message(RCM_TRACE1, "SVM: unregister\n");
 	/* Guard against bad arguments */
@@ -378,8 +379,8 @@
 	/* Walk the cache, unregistering everything */
 	(void) mutex_lock(&svm_cache_lock);
 	if (svm_cache != NULL) {
-		while ((devicename = cache_walk(svm_cache, &i, &l)) != NULL) {
-			(void) rcm_unregister_interest(hd, devicename, 0);
+		while (cache_walk(svm_cache, &i, &l) != NULL) {
+			(void) svm_unregister_device(hd, l);
 		}
 		svm_cache->registered = 0;
 	}
@@ -1599,7 +1600,8 @@
 			mdname_t	*mdn;
 			md_trans_t	*trans;
 
-			mdn = metaname(&sp, nlp->namep->cname, &error);
+			mdn = metaname(&sp, nlp->namep->cname, META_DEVICE,
+			    &error);
 			if (mdn == NULL) {
 				continue;
 			}
@@ -1622,7 +1624,8 @@
 			mdname_t	*mdn;
 			md_mirror_t	*mirror;
 
-			mdn = metaname(&sp, nlp->namep->cname, &error);
+			mdn = metaname(&sp, nlp->namep->cname, META_DEVICE,
+			    &error);
 			if (mdn == NULL) {
 				continue;
 			}
@@ -1645,7 +1648,8 @@
 			mdname_t	*mdn;
 			md_raid_t	*raid;
 
-			mdn = metaname(&sp, nlp->namep->cname, &error);
+			mdn = metaname(&sp, nlp->namep->cname, META_DEVICE,
+			    &error);
 			if (mdn == NULL) {
 				continue;
 			}
@@ -1668,7 +1672,8 @@
 			mdname_t	*mdn;
 			md_stripe_t	*stripe;
 
-			mdn = metaname(&sp, nlp->namep->cname, &error);
+			mdn = metaname(&sp, nlp->namep->cname, META_DEVICE,
+			    &error);
 			if (mdn == NULL) {
 				continue;
 			}
@@ -1691,7 +1696,8 @@
 			mdname_t	*mdn;
 			md_sp_t		*soft_part;
 
-			mdn = metaname(&sp, nlp->namep->cname, &error);
+			mdn = metaname(&sp, nlp->namep->cname, META_DEVICE,
+			    &error);
 			if (mdn == NULL) {
 				continue;
 			}
@@ -1844,14 +1850,16 @@
 create_deventry(char *devname, svm_type_t devtype, md_dev64_t devkey,
     int devflags)
 {
-	deventry_t	*newdeventry;
-	char		*newdevname;
+	const char	*devprefix = "/dev/";
+	deventry_t	*newdeventry = NULL;
+	char		*newdevname = NULL;
+	char		*devicesname = NULL;
 
 	newdeventry = (deventry_t *)malloc(sizeof (*newdeventry));
 	if (newdeventry == NULL) {
 		rcm_log_message(RCM_ERROR,
 		    gettext("SVM: can't malloc deventrys"));
-		return (NULL);
+		goto errout;
 	}
 	(void) memset((char *)newdeventry, 0, sizeof (*newdeventry));
 
@@ -1859,16 +1867,55 @@
 	if (newdevname == NULL) {
 		rcm_log_message(RCM_ERROR,
 		    gettext("SVM: can't malloc devname"));
-		free(newdeventry);
-		return (NULL);
+		goto errout;
+	}
+
+	/*
+	 * When we register interest in a name starting with /dev/, RCM
+	 * will use realpath to convert the name to a /devices name before
+	 * storing it.  metaclear removes both the /dev and the /devices
+	 * form of the name of a metadevice from the file system.  Thus,
+	 * when we later call rcm_unregister_interest to get rid of a
+	 * metacleared device, RCM will not be able to derive the /devices
+	 * name for the /dev name.  Thus, to unregister we will need to use
+	 * the /devices name.  We will save it now, so that we have it when
+	 * it comes time to unregister.
+	 */
+	if (strncmp(devname, devprefix, strlen(devprefix)) == 0) {
+		devicesname = (char *)malloc(PATH_MAX);
+		if (devicesname == NULL) {
+			rcm_log_message(RCM_ERROR,
+			    gettext("SVM: can't malloc PATH_MAX bytes"));
+			goto errout;
+		}
+		if (realpath(devname, devicesname) == NULL) {
+			free(devicesname);
+			devicesname = NULL;
+		}
 	}
 	newdeventry->devname = newdevname;
+	newdeventry->devicesname = devicesname;
 	newdeventry->devtype = devtype;
 	newdeventry->devkey = meta_cmpldev(devkey);
 	newdeventry->flags = devflags;
-	rcm_log_message(RCM_TRACE1,
-	    "SVM created deventry for %s\n", newdeventry->devname);
+	if (newdeventry->devicesname == NULL) {
+		rcm_log_message(RCM_TRACE1,
+			"SVM created deventry for %s\n", newdeventry->devname);
+	} else {
+		rcm_log_message(RCM_TRACE1,
+			"SVM created deventry for %s (%s)\n",
+			newdeventry->devname, newdeventry->devicesname);
+	}
 	return (newdeventry);
+
+errout:
+	if (devicesname != NULL)
+		free(devicesname);
+	if (newdevname != NULL)
+		free(newdevname);
+	if (newdeventry != NULL)
+		free(newdeventry);
+	return (NULL);
 }
 
 /*
@@ -1991,7 +2038,40 @@
 /*
  *      cache_sync()
  *
- *      Resync cache with the svm database
+ *	Resync cache with the svm database.  First a new cache is created
+ *	that represents the current state of the SVM database.  The
+ *	function walks the new cache to look for new entries that must be
+ *	registered.  The new entries are kept in a list, because we cannot
+ *	register them at this point.  Entries that appear in both caches
+ *	are removed from the old cache.  Because of this at the end of the
+ *	walk, the old cache will only contain devices that have been
+ *	removed and need to be unregistered.
+ *
+ *	Next the old cache is walked, so that we can unregister the devices
+ *	that are no longer present.
+ *
+ *	Finally, we process the list of new devices that must be
+ *	registered.  There is a reason why we must unregister the removed
+ *	(metacleared) devices before registering the new ones.  It has to
+ *	do with the fact that rcm_register_interest calls realpath(3C) to
+ *	convert a /dev name to a /devices name.  It uses the /devices name
+ *	for storing the device information.
+ *
+ *	It can happen that between cache_syncs that the administrator
+ *	metaclears one metadevice and metacreates a new one.  For example,
+ *
+ *		metaclear acct
+ *		metainit engr 1 1 c1t12d0s0
+ *
+ *	The metaclear operation frees up the minor number that was being
+ *	used by acct.  The metainit operation can then reuse the minor
+ *	number.  This means that both metadevices would have the same
+ *	/devices name even though they had different /dev names.  Since
+ *	rcm_register_interest uses /devices names for storing records, we
+ *	need to unregister acct before registering engr.  Otherwise we
+ *	would get an EALREADY errno and a failed registration.  This is why
+ *	cache_sync creates a list of devices to be registered after all the
+ *	removed devices have been unregistered.
  *
  *      Input:
  *		rcm_handle_t	*hd		rcm handle
@@ -2009,17 +2089,24 @@
 	cache_t		*new_cache;
 	cache_t		*old_cache = *cachep;
 	deventry_t	*hashline = NULL;
+	deventry_t	**register_list = NULL;
+	deventry_t	*register_this;
+	uint32_t	register_count = 0;	/* # entrys in register_list */
+	uint32_t	allocated = 0;		/* # entrys allocated in */
+						/* register_list */
+	uint32_t	allocate_incr = 16;
 	uint32_t	i = 0;
 
 	/* Get a new cache */
 	if ((new_cache = create_cache()) == NULL) {
-		rcm_log_message(RCM_WARNING,
-		    gettext("SVM: WARNING: couldn't re-cache."));
+		rcm_log_message(RCM_WARNING, MSG_NORECACHE);
 		return;
 	}
 
 	/* For every entry in the new cache... */
 	while ((devicename = cache_walk(new_cache, &i, &hashline)) != NULL) {
+		register_this = NULL;
+
 		/* Look for this entry in the old cache */
 		deventry = cache_lookup(old_cache, devicename);
 		/*
@@ -2028,12 +2115,32 @@
 		 * again and remove it from the old cache
 		 */
 		if (deventry == NULL) {
-			register_device(hd, hashline->devname);
+			register_this = hashline;
 		} else {
 			if (deventry->flags&REMOVED)
-				register_device(hd, hashline->devname);
+				register_this = hashline;
 			cache_remove(old_cache, deventry);
 		}
+
+		/* Save this entry if we need to register it later. */
+		if (register_this) {
+			if (register_count >= allocated) {
+				/* Need to extend our array */
+				allocated += allocate_incr;
+				register_list =
+					(deventry_t **)realloc(register_list,
+					allocated * sizeof (*register_list));
+				if (register_list == NULL) {
+					/* Out of memory.  Give up. */
+					rcm_log_message(RCM_WARNING,
+						MSG_NORECACHE);
+					free(new_cache);
+					return;
+				}
+			}
+			*(register_list + register_count) = register_this;
+			register_count++;
+		}
 	}
 
 	/*
@@ -2044,10 +2151,18 @@
 	hashline = NULL;
 	while ((devicename = cache_walk(old_cache, &i, &hashline)) != NULL) {
 		if (!(hashline->flags&REMOVED)) {
-			(void) rcm_unregister_interest(hd, devicename, 0);
+			(void) svm_unregister_device(hd, hashline);
 		}
 	}
 
+	/* Register the new devices. */
+	for (i = 0; i < register_count; i++) {
+		deventry = *(register_list + i);
+		svm_register_device(hd, deventry->devname);
+	}
+	if (register_list)
+		free(register_list);
+
 	/* Swap pointers */
 	*cachep = new_cache;
 
@@ -2204,6 +2319,8 @@
 					free(oldhspentry);
 				}
 			}
+			if ((*deventry)->devicesname)
+				free((*deventry)->devicesname);
 			free((*deventry)->devname);
 			free (*deventry);
 			*deventry = olddeventry;
@@ -2240,7 +2357,7 @@
 }
 
 /*
- *      register_device()
+ *      svm_register_device()
  *
  *      Register a device
  *
@@ -2251,7 +2368,7 @@
  *      Locking: None
  */
 static void
-register_device(rcm_handle_t *hd, char *devname)
+svm_register_device(rcm_handle_t *hd, char *devname)
 {
 	/* Sanity check */
 	if (devname == NULL)
@@ -2840,7 +2957,6 @@
 	mdsetname_t	*sp;
 	md_error_t	error = mdnullerror;
 	char		sname[BUFSIZ+1];
-	uint32_t	d;
 	mdname_t	*np;
 	deventry_t	*dependent;
 	int		rval = NOTREDUNDANT;
@@ -2871,10 +2987,10 @@
 		 * it contains a setname.
 		 */
 		ret = sscanf(dependent->devname,
-		    "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/dsk/d%u",
-		    sname, &d);
+		    "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/dsk/",
+		    sname);
 
-		if (ret != 2)
+		if (ret != 1)
 			(void) strcpy(sname, MD_LOCAL_NAME);
 
 		if ((sp = metasetname(sname, &error)) == NULL) {
@@ -2887,7 +3003,7 @@
 		rcm_log_message(RCM_TRACE1, "SVM: processing: %s\n",
 		    dependent->devname);
 
-		np = metaname(&sp, dependent->devname, &error);
+		np = metaname(&sp, dependent->devname, META_DEVICE, &error);
 
 		switch (dependent->devtype) {
 		case SVM_TRANS:
@@ -2943,3 +3059,66 @@
 	rcm_log_message(RCM_TRACE1, "SVM: check_device return %d\n", rval);
 	return (rval);
 }
+
+/*
+ *	svm_unregister_device
+ *
+ *	Unregister the device specified by the deventry
+ *
+ *	Input:
+ *		rcm_handle_t *	information for RCM
+ *		deventry_t *	description of the device to be
+ *				unregistered
+ *
+ *	Return:
+ *		int		0	- successfully unregistered
+ *				!= 0	- failed to unregister
+ *
+ *	Locking:
+ *		None
+ *
+ * If the deventry_t has a devicesname, we will first attempt to unregister
+ * using that name.  If that fails then we'll attempt to unregister using
+ * devname.  The reason for this strategy has to do with the way that
+ * rcm_register_interest works.  If passed a /dev/ name,
+ * rcm_register_interest uses realpath() to convert it to a /devices name.
+ * Thus, we are more likely to succeed if we use devicesname first.
+ */
+
+static int
+svm_unregister_device(rcm_handle_t *hd, deventry_t *d)
+{
+	int	deleted;
+
+	if (d->devicesname) {
+		rcm_log_message(RCM_TRACE1, "SVM: unregister_device %s (%s)\n",
+			d->devname, d->devicesname);
+	} else {
+		rcm_log_message(RCM_TRACE1, "SVM: unregister_device %s\n",
+			d->devname);
+	}
+	deleted = -1;
+	if (d->devicesname != NULL) {
+		/*
+		 * Try to unregister via the /devices entry first.  RCM
+		 * converts /dev/ entries to /devices entries before
+		 * storing them.  Thus, if this item has a /devices name
+		 * available, we should use it for unregistering.
+		 */
+		deleted = rcm_unregister_interest(hd,
+			d->devicesname, 0);
+	}
+	if (deleted != 0) {
+		/*
+		 * Either we did not have a /devices name or the attempt to
+		 * unregister using the /devices name failed.  Either way
+		 * we'll now try to unregister using the conventional name.
+		 */
+		deleted = rcm_unregister_interest(hd, d->devname, 0);
+	}
+	if (deleted != 0) {
+		rcm_log_message(RCM_TRACE1, "SVM: unregister_device failed "
+			"for %s\n", d->devname);
+	}
+	return (deleted);
+}
--- a/usr/src/head/meta.h	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/head/meta.h	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -154,6 +153,7 @@
 #define	PRINT_FAST		0x00000080
 #define	PRINT_DEVID		0x00000100
 #define	PRINT_LARGEDEVICES	0x00000200
+#define	PRINT_FN		0x00000400
 
 /*
  * for meta_devadm options
@@ -218,7 +218,6 @@
 #define	MDCMD_INIT		0x0010	/* init operation */
 #define	MDCMD_UPDATE		0x0020	/* update sizes used w/o DOIT mostly */
 #define	MDCMD_NOLOCK		0x0040	/* lock already held, DONT acquire */
-#define	MDCMD_CLUSTER_REPLACE	0x0080	/* don't resync raid */
 #define	MDCMD_VERBOSE		0x0100	/* be verbose */
 #define	MDCMD_USE_WHOLE_DISK	0x0200	/* repartition disk */
 #define	MDCMD_DIRECT		0x0400	/* extents specified directly */
@@ -775,8 +774,8 @@
 extern	int		meta_adjust_geom(md_unit_t *md, mdname_t *np,
 			    uint_t write_reinstruct, uint_t read_reinstruct,
 			    uint_t round_cyl, md_error_t *ep);
-extern	int		meta_init_name(mdsetname_t **spp,
-			    int argc, char *argv[], mdcmdopts_t options,
+extern	int		meta_init_name(mdsetname_t **spp, int argc,
+			    char *argv[], char *cname, mdcmdopts_t options,
 			    md_error_t *ep);
 extern	int		meta_check_devicesize(diskaddr_t total_blocks);
 extern	int		meta_init_make_device(mdsetname_t **spp, char *uname,
@@ -1103,9 +1102,16 @@
 
 /* meta_name.c */
 extern  char		*meta_name_getname(mdsetname_t **spp, char *uname,
-			    md_error_t *ep);
+			    meta_device_type_t uname_type, md_error_t *ep);
 extern	char		*meta_canonicalize(mdsetname_t *sp, char *uname);
+extern	char		*meta_canonicalize_check_set(mdsetname_t **sp,
+			    char *uname, md_error_t *ep);
+extern	int		meta_is_all(char *uname);
+extern	int		is_existing_metadevice(mdsetname_t *sp, char *uname);
+extern	int		is_existing_hsp(mdsetname_t *sp, char *uname);
+extern	int		is_existing_meta_hsp(mdsetname_t *sp, char *uname);
 extern	int		is_metaname(char *uname);
+extern	int		meta_is_none(char *uname);
 extern	int		is_hspname(char *uname);
 extern	int		parse_ctd(char *uname, uint_t *slice);
 extern	md_set_desc	*sr2setdesc(md_set_record *sr);
@@ -1135,19 +1141,20 @@
 extern	int		meta_getdev(mdsetname_t *sp, mdname_t *np,
 			    md_error_t *ep);
 extern	mdname_t	*metaname_fast(mdsetname_t **spp, char *uname,
-			    md_error_t *ep);
+			    meta_device_type_t uname_type, md_error_t *ep);
 extern	mdname_t	*metaname(mdsetname_t **spp, char *uname,
-			    md_error_t *ep);
+			    meta_device_type_t uname_type, md_error_t *ep);
 extern	mdname_t	*metamnumname(mdsetname_t **spp, minor_t mnum,
 			    int fast, md_error_t *ep);
-extern	char		*get_mdname(minor_t mnum);
+extern	char		*get_mdname(mdsetname_t *sp, minor_t mnum);
 extern	int		metaismeta(mdname_t *np);
 extern	int		metachkmeta(mdname_t *np, md_error_t *ep);
 extern	int		metachkdisk(mdname_t *np, md_error_t *ep);
 extern	int		metachkcomp(mdname_t *np, md_error_t *ep);
 extern	void		metafreenamelist(mdnamelist_t *nlp);
 extern	int		metanamelist(mdsetname_t **spp, mdnamelist_t **nlpp,
-			    int argc, char *argv[], md_error_t *ep);
+			    int argc, char *argv[], meta_device_type_t type,
+			    md_error_t *ep);
 extern	mdname_t	*metanamelist_append(mdnamelist_t **nlpp,
 			    mdname_t *np);
 extern  mdnamelist_t	**meta_namelist_append_wrapper(mdnamelist_t **nlpp,
@@ -1156,7 +1163,7 @@
 			    char *uname, md_error_t *ep);
 extern	mdhspname_t	*metahsphspname(mdsetname_t **spp,
 			    hsp_t hsp, md_error_t *ep);
-extern	char		*get_hspname(hsp_t mnum);
+extern	char		*get_hspname(mdsetname_t *sp, hsp_t mnum);
 extern	void		metafreehspnamelist(mdhspnamelist_t *hspnlp);
 extern	int		metahspnamelist(mdsetname_t **spp,
 			    mdhspnamelist_t **hspnlpp,
@@ -1168,6 +1175,7 @@
 extern	char		*get_devname(set_t setno, md_dev64_t dev);
 extern	mdname_t	*metakeyname(mdsetname_t **spp,
 			    mdkey_t key, int fast, md_error_t *ep);
+extern	void		metaflushmetanames(void);
 extern	void		metaflushnames(int flush_sr_cache);
 extern	int		meta_get_hotspare_names(mdsetname_t *sp,
 			    mdnamelist_t **nlpp, int options, md_error_t *ep);
@@ -1213,6 +1221,10 @@
 extern	char		*meta_getnmentbydev(set_t setno, side_t sideno,
 			    md_dev64_t dev, char **drvnm, minor_t *mnum,
 			    mdkey_t *key, md_error_t *ep);
+extern	char		*meta_gethspnmentbyid(set_t setno, side_t sideno,
+			    hsp_t hspid, md_error_t *ep);
+extern	hsp_t		meta_gethspnmentbyname(set_t setno, side_t sideno,
+			    char *hspname, md_error_t *ep);
 extern	char		*meta_getdidminorbykey(set_t setno, side_t sideno,
 			    mdkey_t key, md_error_t *ep);
 extern	ddi_devid_t	meta_getdidbykey(set_t setno, side_t sideno,
@@ -1230,6 +1242,10 @@
 			    md_error_t *ep);
 extern	int		del_key_names(mdsetname_t *sp, mdnamelist_t *nlp,
 			    md_error_t *ep);
+extern	mdkey_t		add_self_name(mdsetname_t *, char *,
+			    md_mkdev_params_t *, md_error_t *);
+extern	int		del_self_name(mdsetname_t *, mdkey_t,
+			    md_error_t *);
 
 /* meta_patch.c */
 extern	int		meta_patch_vfstab(char *cmpname, mdname_t *fsnp,
@@ -1329,10 +1345,6 @@
 			    uint_t *slicep, md_error_t *ep);
 
 /* meta_replace.c */
-extern	int		meta_replace(mdsetname_t *sp, mdname_t *metanp,
-			    mdname_t *oldnp,
-			    mdname_t *newnp, char *uname, mdcmdopts_t options,
-			    md_error_t *ep);
 extern	int		meta_replace_byname(mdsetname_t *sp, mdname_t *namep,
 			    mdname_t *oldnp, mdname_t *newnp,
 			    mdcmdopts_t options, md_error_t *ep);
--- a/usr/src/lib/libdiskmgt/common/inuse_svm.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/libdiskmgt/common/inuse_svm.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -87,7 +86,7 @@
 static md_drive_desc	*(*mdl_metaget_drivedesc)(mdsetname_t *sp, int flags,
 			    md_error_t *ep);
 static mdname_t		*(*mdl_metaname)(mdsetname_t **spp, char *uname,
-			    md_error_t *ep);
+			    meta_device_type_t uname_type, md_error_t *ep);
 static int		(*mdl_metareplicalist)(mdsetname_t *sp, int flags,
 			    md_replicalist_t **rlpp, md_error_t *ep);
 static mdsetname_t	*(*mdl_metasetnosetname)(set_t setno, md_error_t *ep);
@@ -303,7 +302,8 @@
 		mdname_t	*mdn;
 		md_raid_t	*raid;
 
-		mdn = (mdl_metaname)(&sp, nlp->namep->cname, &error);
+		mdn = (mdl_metaname)(&sp, nlp->namep->cname,
+		    META_DEVICE, &error);
 		(mdl_mdclrerror)(&error);
 		if (mdn == NULL) {
 		    continue;
@@ -336,7 +336,8 @@
 		mdname_t	*mdn;
 		md_stripe_t	*stripe;
 
-		mdn = (mdl_metaname)(&sp, nlp->namep->cname, &error);
+		mdn = (mdl_metaname)(&sp, nlp->namep->cname,
+		    META_DEVICE, &error);
 		(mdl_mdclrerror)(&error);
 		if (mdn == NULL) {
 		    continue;
@@ -379,7 +380,8 @@
 		mdname_t	*mdn;
 		md_sp_t		*soft_part;
 
-		mdn = (mdl_metaname)(&sp, nlp->namep->cname, &error);
+		mdn = (mdl_metaname)(&sp, nlp->namep->cname,
+		    META_DEVICE, &error);
 		(mdl_mdclrerror)(&error);
 		if (mdn == NULL) {
 		    continue;
@@ -539,8 +541,8 @@
 	mdl_metaget_drivedesc = (md_drive_desc *(*)(mdsetname_t *, int,
 	    md_error_t *))dlsym(lh, "metaget_drivedesc");
 
-	mdl_metaname = (mdname_t *(*)(mdsetname_t **, char *, md_error_t *))
-	    dlsym(lh, "metaname");
+	mdl_metaname = (mdname_t *(*)(mdsetname_t **, char *,
+	    meta_device_type_t, md_error_t *))dlsym(lh, "metaname");
 
 	mdl_metareplicalist = (int (*)(mdsetname_t *, int, md_replicalist_t **,
 	    md_error_t *))dlsym(lh, "metareplicalist");
@@ -650,7 +652,7 @@
 	mdname_t	*mdn;
 	md_error_t	 error = *mdl_mdnullerror;
 
-	mdn = (mdl_metaname)(&sp, sname, &error);
+	mdn = (mdl_metaname)(&sp, sname, UNKNOWN, &error);
 	if (!mdisok(&error)) {
 	    (mdl_mdclrerror)(&error);
 	    return (0);
--- a/usr/src/lib/lvm/libmeta/common/meta_attach.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_attach.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,13 +20,12 @@
  */
 
 /*
- * Copyright 1992-2002 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
-
 /*
  * attach operations
  */
@@ -58,7 +56,7 @@
 
 	/* grow device */
 	(void) memset(&mgp, 0, sizeof (mgp));
-	if (big_or_little == MD_64BIT_META_DEV)
+	if (big_or_little & MD_64BIT_META_DEV)
 		mgp.options = MD_CRO_64BIT;
 	else
 		mgp.options = MD_CRO_32BIT;
--- a/usr/src/lib/lvm/libmeta/common/meta_check.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_check.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -152,7 +151,7 @@
 		mdname_t	*snp;
 
 		if ((snp = metaname(&sp, swtp->swt_ent[i].ste_path,
-		    ep)) == NULL) {
+		    UNKNOWN, ep)) == NULL) {
 			mdclrerror(ep);
 			continue;
 		}
@@ -201,7 +200,7 @@
 		mdname_t	*snp;
 
 		if ((snp = metaname(&sp, swtp->swt_ent[i].ste_path,
-		    ep)) == NULL) {
+		    LOGICAL_DEVICE, ep)) == NULL) {
 			mdclrerror(ep);
 			continue;
 		}
@@ -238,7 +237,7 @@
 	if (ioctl(dump_fd, DIOCGETDEV, device) != -1) {
 		mdname_t	*dump_np;
 
-		if ((dump_np = metaname(&sp, device, ep)) == NULL) {
+		if ((dump_np = metaname(&sp, device, UNKNOWN, ep)) == NULL) {
 			mdclrerror(ep);
 			(void) close(dump_fd);
 			return (0);
@@ -306,7 +305,7 @@
 		(void) strcpy(mountp, m.mnt_mountp);
 		(void) strcpy(mnt_special, m.mnt_special);
 
-		if ((mnp = metaname(&sp, mnt_special, ep)) == NULL) {
+		if ((mnp = metaname(&sp, mnt_special, UNKNOWN, ep)) == NULL) {
 			mdclrerror(ep);
 			continue;
 		}
@@ -372,7 +371,8 @@
 
 		(void) strcpy(mountp, m.mnt_mountp);
 		(void) strcpy(mnt_special, m.mnt_special);
-		if ((mnp = metaname(&sp, mnt_special, ep)) == NULL) {
+		if ((mnp = metaname(&sp, mnt_special,
+		    LOGICAL_DEVICE, ep)) == NULL) {
 			mdclrerror(ep);
 			continue;
 		}
@@ -525,15 +525,12 @@
 	 *
 	 * Case 1 - The filenames are identical
 	 *
-	 * Case 2 - Either name is a metadevice name.  If so then they
-	 *	are not the same drive.
-	 *
-	 * Case 3 - Both devices have a devid
+	 * Case 2 - Both devices have a devid
 	 * 	get and compare the devids for the devices. If both
 	 * 	devices have a devid then the compare will is all
 	 *	that is needed we are done.
 	 *
-	 * Case 4 - One or more devices does not have a devid
+	 * Case 3 - One or more devices does not have a devid
 	 *	start by doing a simple compare of the name, if they
 	 *	are the same just return.
 	 *
--- a/usr/src/lib/lvm/libmeta/common/meta_db.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_db.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -2076,13 +2075,15 @@
 	/* get device name */
 	devname = splicename(&c->c_devname);
 	if (flags & PRINT_FAST) {
-		if ((rp->r_namep = metaname_fast(&sp, devname, ep)) == NULL) {
+		if ((rp->r_namep = metaname_fast(&sp, devname,
+		    LOGICAL_DEVICE, ep)) == NULL) {
 			Free(devname);
 			Free(rp);
 			return (NULL);
 		}
 	} else {
-		if ((rp->r_namep = metaname(&sp, devname, ep)) == NULL) {
+		if ((rp->r_namep = metaname(&sp, devname,
+		    LOGICAL_DEVICE, ep)) == NULL) {
 			Free(devname);
 			Free(rp);
 			return (NULL);
--- a/usr/src/lib/lvm/libmeta/common/meta_error.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_error.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -71,10 +70,10 @@
 	char	*name;
 
 	/* get name, or fake it */
-	if ((name = get_mdname(mnum)) == NULL) {
+	if ((name = get_mdname(NULL, mnum)) == NULL) {
 		char	buf[40];
 
-		(void) sprintf(buf, "%lu/d%lu", MD_MIN2SET(mnum),
+		(void) sprintf(buf, "%lu/%lu", MD_MIN2SET(mnum),
 		    MD_MIN2UNIT(mnum));
 		return (Strdup(buf));
 	}
@@ -109,10 +108,10 @@
 {
 	char	*name;
 
-	if ((name = get_hspname(hsp)) == NULL) {
+	if ((name = get_hspname(NULL, hsp)) == NULL) {
 		char	buf[40];
 
-		(void) sprintf(buf, "%u/hsp%03u", HSP_SET(hsp), HSP_ID(hsp));
+		(void) sprintf(buf, "%u/%u", HSP_SET(hsp), HSP_ID(hsp));
 		return (Strdup(buf));
 	}
 	return (Strdup(name));
@@ -878,6 +877,18 @@
 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
 		    "service(s) not online in SMF"));
 		break;
+	case MDE_AMBIGUOUS_DEV:
+		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
+		    "Specify complete path to avoid ambiguity."));
+		break;
+	case MDE_NAME_IN_USE:
+		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
+		    "Name already in use for metadevice or hot spare pool."));
+		break;
+	case MDE_NAME_ILLEGAL:
+		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
+		    "Invalid name for metadevice or hot spare pool."));
+		break;
 	case MDE_ZONE_ADMIN:
 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
 		"Volume administration unavailable within non-global zones."));
--- a/usr/src/lib/lvm/libmeta/common/meta_getdevs.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_getdevs.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -129,6 +128,10 @@
 	/* must have local set */
 	assert(sp != NULL);
 
+	/* if no valid name then return an error */
+	if (namep == NULL)
+		return (-1);
+
 	/* just add regular devices */
 	if (! metaismeta(namep)) {
 		mdnamelist_t	*p;
--- a/usr/src/lib/lvm/libmeta/common/meta_hotspares.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_hotspares.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -42,7 +41,6 @@
 #include <sys/lvm/md_hotspares.h>
 #include <sys/lvm/md_convert.h>
 
-
 /*
  * FUNCTION:	meta_get_hsp_names()
  * INPUT:	sp	- the set name to get hotspares from
@@ -137,7 +135,7 @@
 
 	/* should have a set */
 	assert(sp != NULL);
-	assert(sp->setno == HSP_SET(hspnp->hsp));
+	assert(hspnp->hsp == MD_HSP_NONE || sp->setno == HSP_SET(hspnp->hsp));
 
 	/* get size of unit structure */
 	(void) memset(&mig, 0, sizeof (mig));
@@ -191,7 +189,7 @@
 
 	/* must have set */
 	assert(sp != NULL);
-	assert(sp->setno == HSP_SET(hspnp->hsp));
+	assert(hspnp->hsp == MD_HSP_NONE || sp->setno == HSP_SET(hspnp->hsp));
 
 	/* short circuit */
 	if (hspnp->unitp != NULL)
@@ -285,7 +283,7 @@
 
 	/* should be in the same set */
 	assert(sp != NULL);
-	assert(sp->setno == HSP_SET(hspnp->hsp));
+	assert(hspnp->hsp == MD_HSP_NONE || sp->setno == HSP_SET(hspnp->hsp));
 
 	/* get unit */
 	if ((hspp = meta_get_hsp(sp, hspnp, ep)) == NULL)
@@ -482,11 +480,12 @@
 	mdname_t	*didnp = NULL;
 	uint_t		len;
 	int		large_hs_dev_cnt = 0;
+	int		fn_hs_dev_cnt = 0;
 
 	if (options & PRINT_LARGEDEVICES) {
 		for (hsi = 0; (hsi < hspp->hotspares.hotspares_len); ++hsi) {
 			md_hs_t	*hsp = &hspp->hotspares.hotspares_val[hsi];
-			if (hsp->revision == MD_64BIT_META_DEV) {
+			if (hsp->revision & MD_64BIT_META_DEV) {
 				large_hs_dev_cnt += 1;
 				if (meta_getdevs(sp, hsp->hsnamep, nlpp, ep)
 				    != 0)
@@ -499,6 +498,21 @@
 			goto out;
 		}
 	}
+
+	if (options & PRINT_FN) {
+		if (!HSP_ID_IS_FN(hspp->hspnamep->hsp)) {
+			rval = 0;
+			goto out;
+		}
+		for (hsi = 0; (hsi < hspp->hotspares.hotspares_len); ++hsi) {
+			md_hs_t	*hsp = &hspp->hotspares.hotspares_val[hsi];
+			fn_hs_dev_cnt += 1;
+			if (meta_getdevs(sp, hsp->hsnamep, nlpp, ep)
+			    != 0)
+				goto out;
+		}
+	}
+
 	/* print header */
 	if (hspp->hotspares.hotspares_len == 0) {
 		if (fprintf(fp, dgettext(TEXT_DOMAIN, "%s: is empty\n"),
@@ -597,7 +611,7 @@
 		}
 
 		if (options & PRINT_LARGEDEVICES) {
-			if (hsp->revision != MD_64BIT_META_DEV)
+			if ((hsp->revision & MD_64BIT_META_DEV) == 0)
 				continue;
 		}
 		/* determine if devid does NOT exist */
@@ -668,7 +682,8 @@
 
 	/* should have same set */
 	assert(sp != NULL);
-	assert((hspnp == NULL) || (sp->setno == HSP_SET(hspnp->hsp)));
+	assert(hspnp == NULL || hspnp->hsp == MD_HSP_NONE ||
+	    sp->setno == HSP_SET(hspnp->hsp));
 
 	/* print all hsps */
 	if (hspnp == NULL) {
@@ -743,6 +758,309 @@
 }
 
 /*
+ * FUNCTION:	del_hsp_name_mn_sides()
+ * INPUT:	sp	- set name
+ *		curside	- side of this node
+ *		key	- key of records to delete
+ * OUTPUT:	ep	- error information
+ * RETURNS:	none.
+ * PURPOSE:	There are name records for each side in a set.  This
+ *		function deletes the records associated with the specified
+ *		key for all sides except curside.  This function is used
+ *		when the set is a multinode set.
+ */
+static void
+del_hsp_name_mn_sides(
+	mdsetname_t	*sp,
+	md_set_desc	*sd,
+	side_t		curside,
+	mdkey_t		key,
+	md_error_t	*ep
+)
+{
+	md_error_t	first_error = MDNULLERROR;
+	int		error_seen = FALSE;
+	md_mnnode_desc	*nd;
+
+	for (nd = sd->sd_nodelist; nd; nd = nd->nd_next) {
+		if (nd->nd_nodeid == curside)
+			continue;
+		if (del_name(sp, nd->nd_nodeid, key, &first_error) == -1) {
+			if (error_seen == FALSE) {
+				error_seen = TRUE;
+				(void) mdstealerror(ep, &first_error);
+			}
+		}
+	}
+}
+
+/*
+ * FUNCTION:	del_hsp_name_trad_sides()
+ * INPUT:	sp	- set name
+ *		curside	- side of this node
+ *		key	- key of records to delete
+ * OUTPUT:	ep	- error information
+ * RETURNS:	none.
+ * PURPOSE:	There are name records for each side in a set.  This
+ *		function deletes the records associated with the specified
+ *		key for all sides except curside.  This function is used
+ *		when the set is a traditional set.
+ */
+static void
+del_hsp_name_trad_sides(
+	mdsetname_t	*sp,
+	md_set_desc	*sd,
+	side_t		curside,
+	mdkey_t		key,
+	md_error_t	*ep
+)
+{
+	int		error_seen = FALSE;
+	md_error_t	first_error = MDNULLERROR;
+	int		i;
+
+	for (i = 0; i < MD_MAXSIDES; i++) {
+		if (i == curside)
+			continue;
+		if (sd->sd_nodes[i][0] != '\0') {
+			if (del_name(sp, i, key, &first_error) == -1) {
+				if (error_seen == FALSE) {
+					error_seen = TRUE;
+					(void) mdstealerror(ep, &first_error);
+				}
+			}
+		}
+	}
+}
+
+/*
+ * FUNCTION:	del_hsp_keys()
+ * INPUT:	sp	- set name
+ *		hspid	- ID of records to delete
+ * OUTPUT:	ep	- error information
+ * RETURNS:	0	- success
+ *		-1	- error
+ * PURPOSE:	Remove the NM records associated with hspid from all sides
+ *		of the set.  Missing records are not considered to be an
+ *		error.  The key associated with the current side is removed
+ *		last.
+ *
+ *		This function is very similar to del_key_name(), except it
+ *		does not require any device look up.  This is because the
+ *		hot spare pool is not a device.
+ */
+static int
+del_hsp_keys(mdsetname_t *sp, hsp_t hspid, md_error_t *ep)
+{
+	md_error_t	first_error = MDNULLERROR;
+	mdkey_t		key = HSP_ID_TO_KEY(hspid);
+	md_set_desc	*sd;
+	side_t		thisside;	/* Side # of this node. */
+
+	/*
+	 * If there is no key, this means that the hot spare was created
+	 * before the introduction of friendly names.  Thus, the is no NM
+	 * record and nothing for us to do in this function.
+	 */
+	if (key == MD_KEYBAD)
+		return (0);
+
+	/* Find our current side */
+	mdclrerror(ep);
+	thisside = getmyside(sp, ep);
+	if (! mdisok(ep))
+		return (-1);
+
+	/*
+	 * If not the local set, we need to process the non-local sides
+	 * first.
+	 */
+	if (!metaislocalset(sp)) {
+		if ((sd = metaget_setdesc(sp, ep)) == NULL)
+			return (-1);
+		if (MD_MNSET_DESC(sd)) {
+			/* Multinode set.  Sides are in a linked list. */
+			del_hsp_name_mn_sides(sp, sd, thisside, key,
+				&first_error);
+		} else {
+			/* Sides are in an array. */
+			del_hsp_name_trad_sides(sp, sd, thisside, key,
+				&first_error);
+		}
+	}
+
+	/* Now delete the name for the current side. */
+	(void) del_name(sp, thisside, key, ep);
+	if (! mdisok(&first_error))
+		(void) mdstealerror(ep, &first_error);
+	return (mdisok(ep) ? 0 : -1);
+}
+
+/*
+ * FUNCTION:	add_hsp_name_mn_sides()
+ * INPUT:	sp	- set name
+ *		curside	- side number for this node
+ *		key	- key to use for the name record
+ *		hsp_name - name of the hot spare
+ * OUTPUT:	ep	- error information
+ * RETURNS:	0 indicates success, and -1 indicates failure.
+ * PURPOSE:	Once the name record has been added for the current side,
+ *		this function adds the record to the remaining sides.  This
+ *		function is to be used when the set is a multinode set.
+ *		The side designated by curside will be ignored when adding
+ *		records.
+ */
+static int
+add_hsp_name_mn_sides(
+	mdsetname_t	*sp,
+	md_set_desc	*sd,
+	side_t		curside,
+	mdkey_t		key,
+	char		*hsp_name,
+	md_error_t	*ep
+)
+{
+	md_mnnode_desc	*nd;
+
+	for (nd = sd->sd_nodelist; nd; nd = nd->nd_next) {
+		if (nd->nd_nodeid == curside)
+			continue;
+		if (add_name(sp, nd->nd_nodeid, key, MD_HOTSPARES,
+			minor(NODEV), hsp_name, ep) == -1) {
+			return (-1);
+		}
+	}
+	return (0);
+}
+
+/*
+ * FUNCTION:	add_hsp_name_trad_sides()
+ * INPUT:	sp	- set name
+ *		curside	- side number for this node
+ *		key	- key to use for the name record
+ *		hsp_name - name of the hot spare
+ * OUTPUT:	ep	- error information
+ * RETURNS:	0 indicates success, and -1 indicates failure.
+ * PURPOSE:	Once the name record has been added for the current side,
+ *		this function adds the record to the remaining sides.  This
+ *		function is to be used when the set is a traditional set.
+ *		The side designated by curside will be ignored when adding
+ *		records.
+ */
+static int
+add_hsp_name_trad_sides(
+	mdsetname_t	*sp,
+	md_set_desc	*sd,
+	side_t		curside,
+	mdkey_t		key,
+	char		*hsp_name,
+	md_error_t	*ep
+)
+{
+	int		i;
+
+	for (i = 0; i < MD_MAXSIDES; i++) {
+		if (i == curside)
+			continue;
+		if (sd->sd_nodes[i][0] != '\0') {
+			if (add_name(sp, i, key, MD_HOTSPARES, minor(NODEV),
+				hsp_name, ep) == -1) {
+				return (-1);
+			}
+		}
+	}
+	return (0);
+}
+
+/*
+ * FUNCTION:	add_hsp_name()
+ * INPUT:	sp	- Name of the set containing the hsp
+ *		hsp_name - Hot spare pool name to be added
+ * OUTPUT:	ep	- Error information
+ * RETURNS:	If successful the key of the newly added record is
+ *		returned.  MD_KEYBAD is returned to indicate a failure.
+ * PURPOSE:	This function creates a new NM record containing the name
+ *		of the hotspare pool.  A record containing the name is
+ *		added to each active side, but the record is added first to
+ *		the current side.  This function is modeled on
+ *		add_key_name() in meta_namespace.  The difference is that
+ *		there is no device associated with a hot spare pool
+ */
+static hsp_t
+add_hsp_name(
+	mdsetname_t	*sp,
+	char		*hsp_name,
+	md_error_t	*ep
+)
+{
+	md_error_t	ignore_error = MDNULLERROR;
+	mdkey_t		key;
+	md_set_desc	*sd;
+	side_t		thisside;	/* Side # of this node. */
+
+	if (sp == NULL) {
+		(void) mderror(ep, MDE_NO_SET, NULL);
+		return (MD_KEYBAD);
+	}
+	if (hsp_name == NULL) {
+		(void) mderror(ep, MDE_INVAL_HSOP, NULL);
+		return (MD_KEYBAD);
+	}
+
+	mdclrerror(ep);
+	thisside = getmyside(sp, ep);
+	if (! mdisok(ep))
+		return (MD_HSPID_WILD);
+
+	/* First add the record for the side of the current node. */
+	key = add_name(sp, thisside, MD_KEYWILD, MD_HOTSPARES, minor(NODEV),
+		hsp_name, ep);
+	if (key == -1) {
+		goto cleanup;
+	}
+
+	/* Make sure that we can use the key */
+	if (!HSP_KEY_OK(key)) {
+		(void) mdhsperror(ep, MDE_HSP_CREATE_FAILURE, MD_HSPID_WILD,
+			hsp_name);
+		goto cleanup;
+	}
+
+	/*
+	 * Now that we have a key, we will use it to add a record to the
+	 * rest of the sides in the set.  For multinode sets, the sides are
+	 * in a linked list that is anchored on the set descriptor.  For
+	 * traditional sets the side information is in an array in the set
+	 * descriptor.
+	 */
+	if (!metaislocalset(sp)) {
+		if ((sd = metaget_setdesc(sp, ep)) == NULL) {
+			goto cleanup;
+		}
+		if (MD_MNSET_DESC(sd)) {
+			/* Multinode set.  Sides are in linked list. */
+			if (add_hsp_name_mn_sides(sp, sd, thisside, key,
+				hsp_name, ep) == -1) {
+				goto cleanup;
+			}
+		} else {
+			/* Traditional set.  Sides are in an array. */
+			if (add_hsp_name_trad_sides(sp, sd, thisside, key,
+				hsp_name, ep) == -1) {
+				goto cleanup;
+			}
+		}
+	}
+
+	return (KEY_TO_HSP_ID(sp->setno, key));
+
+cleanup:
+	/* Get rid records that we added. */
+	(void) del_hsp_keys(sp, KEY_TO_HSP_ID(sp->setno, key), &ignore_error);
+	return (MD_HSPID_WILD);
+}
+
+/*
  * add hotspares and/or hotspare pool
  */
 int
@@ -754,12 +1072,14 @@
 	md_error_t	*ep
 )
 {
+	md_error_t	ignore_error = MDNULLERROR;
 	mdnamelist_t	*p;
 	set_hs_params_t	shs;
+	side_t		thisside;
 
 	/* should have a set */
 	assert(sp != NULL);
-	assert(sp->setno == HSP_SET(hspnp->hsp));
+	assert(hspnp->hsp == MD_HSP_NONE || sp->setno == HSP_SET(hspnp->hsp));
 
 	/* clear cache */
 	meta_invalidate_hsp(hspnp);
@@ -767,9 +1087,39 @@
 	/* setup hotspare pool info */
 	(void) memset(&shs, 0, sizeof (shs));
 	shs.shs_cmd = ADD_HOT_SPARE;
-	shs.shs_hot_spare_pool = hspnp->hsp;
 	MD_SETDRIVERNAME(&shs, MD_HOTSPARES, sp->setno);
 
+	/* Get key for hot spare pool name record. */
+	if (options & MDCMD_DOIT) {
+		/* First see if the name record already exists. */
+		mdclrerror(ep);
+		thisside = getmyside(sp, ep);
+		if (! mdisok(ep))
+			return (-1);
+		shs.shs_hot_spare_pool =
+			meta_gethspnmentbyname(sp->setno, thisside,
+				hspnp->hspname, ep);
+		if (! mdisok(ep)) {
+			/*
+			 * If the error is ENOENT, then we will create a
+			 * hot spare pool name records.  For other types of
+			 * errors, however, we'll bail out.
+			 */
+			if (! mdissyserror(ep, ENOENT))
+				return (-1);
+			mdclrerror(ep);
+			/* make sure that the name isn't already in use */
+			if (is_existing_metadevice(sp, hspnp->hspname))
+				return (mderror(ep, MDE_NAME_IN_USE,
+					hspnp->hspname));
+			if ((shs.shs_hot_spare_pool =
+				add_hsp_name(sp, hspnp->hspname, ep)) ==
+				MD_HSPID_WILD) {
+				return (-1);
+			}
+		}
+	}
+
 	/* add empty hotspare pool */
 	if (hsnlp == NULL) {
 		shs.shs_options = HS_OPT_POOL;
@@ -778,8 +1128,14 @@
 			shs.shs_options |= HS_OPT_DRYRUN;
 		}
 		if (metaioctl(MD_IOCSET_HS, &shs, &shs.mde,
-		    hspnp->hspname) != 0)
+			hspnp->hspname) != 0) {
+			if (options & MDCMD_DOIT) {
+				(void) del_hsp_keys(sp,
+					shs.shs_hot_spare_pool,
+					&ignore_error);
+			}
 			return (mdstealerror(ep, &shs.mde));
+		}
 		goto success;
 	}
 
@@ -794,7 +1150,8 @@
 		diskaddr_t	size, label, start_blk;
 
 		/* should be in same set */
-		assert(sp->setno == HSP_SET(hspnp->hsp));
+		assert(hspnp->hsp == MD_HSP_NONE ||
+		    sp->setno == HSP_SET(hspnp->hsp));
 
 		/* check it out */
 		if (meta_check_hotspare(sp, hsnp, ep) != 0)
@@ -857,6 +1214,49 @@
 }
 
 /*
+ * FUNCTION:	meta_hsp_delete()
+ * INPUT:	sp	- Name of the set containing the hsp
+ *		hspnp	- Hot spare pool name information
+ *		options	- Options from command line
+ * OUTPUT:	ep	- Error information
+ * RETURNS:	0 on success and -1 on failure.
+ * PURPOSE:	Common code to delete an empty hot spare pool.
+ */
+static int
+meta_hsp_delete(
+	mdsetname_t	*sp,
+	mdhspname_t	*hspnp,
+	mdcmdopts_t	options,
+	md_error_t	*ep
+)
+{
+	set_hs_params_t	shs;
+
+	/* setup hotspare pool info */
+	(void) memset(&shs, 0, sizeof (shs));
+	shs.shs_hot_spare_pool = hspnp->hsp;
+	MD_SETDRIVERNAME(&shs, MD_HOTSPARES, sp->setno);
+	shs.shs_cmd = DELETE_HOT_SPARE;
+	shs.shs_options = HS_OPT_POOL;
+	/* If DOIT is not set, it's a dryrun */
+	if ((options & MDCMD_DOIT) == 0) {
+		shs.shs_options |= HS_OPT_DRYRUN;
+	}
+
+	/* Remove hsp record. */
+	if (metaioctl(MD_IOCSET_HS, &shs, &shs.mde,
+	    hspnp->hspname) != 0)
+		return (mdstealerror(ep, &shs.mde));
+
+	/* Get rid of hsp NM records */
+	if ((options & MDCMD_DOIT) &&
+		(del_hsp_keys(sp, hspnp->hsp, ep) == -1)) {
+		return (-1);
+	}
+	return (0);
+}
+
+/*
  * delete hotspares from pool
  */
 int
@@ -873,7 +1273,7 @@
 
 	/* should have a set */
 	assert(sp != NULL);
-	assert(sp->setno == HSP_SET(hspnp->hsp));
+	assert(hspnp->hsp == MD_HSP_NONE || sp->setno == HSP_SET(hspnp->hsp));
 
 	/* clear cache */
 	meta_invalidate_hsp(hspnp);
@@ -886,14 +1286,8 @@
 
 	/* delete empty hotspare pool */
 	if (hsnlp == NULL) {
-		shs.shs_options = HS_OPT_POOL;
-		/* If DOIT is not set, it's a dryrun */
-		if ((options & MDCMD_DOIT) == 0) {
-			shs.shs_options |= HS_OPT_DRYRUN;
-		}
-		if (metaioctl(MD_IOCSET_HS, &shs, &shs.mde,
-		    hspnp->hspname) != 0)
-			return (mdstealerror(ep, &shs.mde));
+		if (meta_hsp_delete(sp, hspnp, options, ep) != 0)
+			return (-1);
 		goto success;
 	}
 
@@ -907,7 +1301,8 @@
 		mdname_t	*hsnp = p->namep;
 
 		/* should be in same set */
-		assert(sp->setno == HSP_SET(hspnp->hsp));
+		assert(hspnp->hsp == MD_HSP_NONE ||
+		    sp->setno == HSP_SET(hspnp->hsp));
 
 		/* delete hotspare */
 		shs.shs_component_old = hsnp->dev;
@@ -963,7 +1358,7 @@
 
 	/* should be in same set */
 	assert(sp != NULL);
-	assert(sp->setno == HSP_SET(hspnp->hsp));
+	assert(hspnp->hsp == MD_HSP_NONE || sp->setno == HSP_SET(hspnp->hsp));
 
 	/* save new binding incase this is a rebind where oldnp==newnp */
 	new_dev = newnp->dev;
@@ -1436,7 +1831,8 @@
 
 	/* see if it exists already */
 	if (meta_get_hsp(*spp, hspnp, ep) != NULL) {
-		(void) mdhsperror(ep, MDE_HSP_ALREADY_SETUP, hspnp->hsp, uname);
+		(void) mdhsperror(ep, MDE_HSP_ALREADY_SETUP,
+		    hspnp->hsp, uname);
 		goto out;
 	} else if (! mdishsperror(ep, MDE_INVAL_HSP)) {
 		goto out;
@@ -1469,7 +1865,8 @@
 		mdname_t	*hsnamep;
 
 		/* parse hotspare name */
-		if ((hsnamep = metaname(spp, argv[0], ep)) == NULL)
+		if ((hsnamep = metaname(spp, argv[0],
+		    LOGICAL_DEVICE, ep)) == NULL)
 			goto out;
 		hsp->hsnamep = hsnamep;
 		--argc, ++argv;
@@ -1520,7 +1917,8 @@
 
 	/* should have the same set */
 	assert(sp != NULL);
-	assert((hspnp == NULL) || (sp->setno == HSP_SET(hspnp->hsp)));
+	assert(hspnp == NULL || hspnp->hsp == MD_HSP_NONE ||
+	    sp->setno == HSP_SET(hspnp->hsp));
 
 	/* reset all hotspares */
 	if (hspnp == NULL) {
@@ -1595,15 +1993,8 @@
 	}
 
 	/* clear hotspare pool */
-	shs.shs_options = HS_OPT_POOL;
-	/* If DOIT is not set, it's a dryrun */
-	if ((options & MDCMD_DOIT) == 0) {
-		shs.shs_options |= HS_OPT_DRYRUN;
-	}
-	if (metaioctl(MD_IOCSET_HS, &shs, &shs.mde, hspnp->hspname) != 0) {
-		(void) mdstealerror(ep, &shs.mde);
+	if (meta_hsp_delete(sp, hspnp, options, ep) != 0)
 		goto out;
-	}
 	rval = 0;	/* success */
 
 	/* let em know */
--- a/usr/src/lib/lvm/libmeta/common/meta_init.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_init.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -32,6 +31,7 @@
  */
 
 #include <meta.h>
+#include <sys/lvm/mdio.h>
 #include <libdevinfo.h>
 
 
@@ -209,10 +209,10 @@
  * Input:	spp	set structure
  *		uname	unit-name (fully qualified or relative)
  * Output:	ep	error return structure
- * Returns:	0	success
+ * Returns:	> 0	success and return 'key'
  *		-1	Error. <ep> contains error reason
  */
-int
+mdkey_t
 meta_init_make_device(
 	mdsetname_t	**spp,
 	char		*uname,
@@ -221,47 +221,29 @@
 {
 	di_devlink_handle_t	hdl;
 	md_mkdev_params_t	params;
-	int			rval = 0;
-	char			*p, *e = uname;
-	size_t			len = strlen(uname);
+	mdkey_t			rval = 0;
+	char			*p;
+	int			len = strlen(uname);
 
-	e += len;
 	(void) memset(&params, 0, sizeof (params));
 	MD_SETDRIVERNAME(&params, "md", (*spp)->setno);
 
 	/*
-	 * Find the start of the unit within <uname>.
+	 * This ioctl call causes kernel to allocate a unit number
+	 * and populate /devices for the named metadevice
 	 */
-	p = strrchr(uname, '/');
-	if (p == NULL) {
-		/* Relative name (e.g. d80) */
-		p = &uname[1];
-	} else {
-		/* qualified name (e.g. /dev/md/dsk/d80) */
-		p += 2;
-		if (p >= e) {
-			/* Invalid drive name */
-			p = Malloc(len + 3);
-			(void) snprintf(p, len + 3, "\"%s\"", uname);
-			rval = mderror(ep, MDE_NOT_DRIVENAME, p);
-			Free(p);
-			return (rval);
-		}
-	}
-	e = NULL;
-	params.mnum = strtoul(p, &e, 10);
-	if (e == p) {
-		/* Invalid drive name */
-		p = Malloc(len + 3);
-		(void) snprintf(p, len + 3, "\"%s\"", uname);
-		rval = mderror(ep, MDE_NOT_DRIVENAME, p);
-		Free(p);
-		return (rval);
-	}
-
 	if (metaioctl(MD_IOCMAKE_DEV, &params, &params.mde, NULL) != 0) {
 		return (mdstealerror(ep, &params.mde));
 	}
+
+	/*
+	 * Now we have minor number so add it to the namespace
+	 * and return the key
+	 */
+	if ((rval = add_self_name(*spp, uname, &params, ep)) <= 0) {
+		return (mderror(ep, MDE_UNIT_NOT_FOUND, NULL));
+	}
+
 	/*
 	 * Wait until device appears in namespace. di_devlink_init() returns
 	 * once the /dev links have been created. If NULL is returned the
@@ -274,6 +256,10 @@
 	if (hdl != NULL) {
 		(void) di_devlink_fini(&hdl);
 	} else {
+		/*
+		 * Delete name entry we just created
+		 */
+		(void) del_self_name(*spp, rval, ep);
 		p = Malloc(len + 3);
 		(void) snprintf(p, len + 3, "\"%s\"", uname);
 		rval = mderror(ep, MDE_UNIT_NOT_FOUND, p);
@@ -382,6 +368,7 @@
 	mdsetname_t	**spp,
 	int		argc,
 	char		*argv[],
+	char		*cname, /* canonical name */
 	mdcmdopts_t	options,
 	md_error_t	*ep
 )
@@ -390,56 +377,98 @@
 	char		*p;
 	int		rval;
 	char		*uname = argv[0];
+	mdkey_t		key = MD_KEYWILD;
+	minor_t		mnum;
+	md_error_t	t_e = mdnullerror;
 
 	assert(argc > 0);
+	assert(*spp != NULL);
 
 	/* determine type of metadevice or hot spare pool being created */
 	init_type = meta_get_init_type(argc, argv);
 
+	/*
+	 * Metatrans is eof
+	 */
+	if (init_type == TAB_TRANS)
+		return (mderror(ep, MDE_EOF_TRANS, NULL));
+
 	/* hotspare pool */
 	if (init_type == TAB_HSP)
 		return (meta_init_hsp(spp, argc, argv, options, ep));
 
+	/*
+	 * We are creating metadevice so make sure the name
+	 * has not been used
+	 */
+	if (is_existing_meta_hsp(*spp, cname)) {
+		/*
+		 * The name has been used by hsp
+		 */
+		if (is_existing_hsp(*spp, cname)) {
+			return (mderror(ep, MDE_NAME_IN_USE, cname));
+		}
+
+		/*
+		 * If path exists but unit is not created
+		 * then meta_init_make_device will correct
+		 * that.  If unit also exists then it
+		 * will return a conflict error
+		 */
+		if (init_type != TAB_UNKNOWN) {
+		    /* Create device node */
+		    if ((key = meta_init_make_device(spp, uname,
+			&t_e)) <= 0) {
+			return (mdstealerror(ep, &t_e));
+		    }
+		}
+	}
+
 	/* metadevice */
 	if (argc >= 2 && init_type != TAB_UNKNOWN) {
-		md_error_t	t_e = mdnullerror;
-		char	*cname;
-
 		/*
 		 * We need to create the device node if the specified metadevice
 		 * does not already exist in the database. The actual creation
 		 * is undertaken by the md driver and the links propagated by
 		 * devfsadm.
 		 */
-
-		/* initialize the spp properly */
-		if ((cname = meta_name_getname(spp, uname, &t_e)) != NULL)
-			Free(cname);
-		if (! mdisok(&t_e))
-			return (mdstealerror(ep, &t_e));
-
-		/* Create device node */
-		if (meta_init_make_device(spp, uname, &t_e) != 0) {
-			return (mdstealerror(ep, &t_e));
+		if (key == MD_KEYWILD) {
+			if ((key = meta_init_make_device(spp, uname,
+			    &t_e)) <= 0)
+				return (mdstealerror(ep, &t_e));
 		}
 
 		switch (init_type) {
 		case TAB_MIRROR:
-			return (meta_init_mirror(spp, argc, argv, options, ep));
+			rval = meta_init_mirror(spp, argc, argv, options, ep);
 			break;
 		case TAB_RAID:
-			return (meta_init_raid(spp, argc, argv, options, ep));
+			rval = meta_init_raid(spp, argc, argv, options, ep);
 			break;
 		case TAB_SP:
-			return (meta_init_sp(spp, argc, argv, options, ep));
-			break;
-		case TAB_TRANS:
-			return (mderror(ep, MDE_EOF_TRANS, NULL));
+			rval = meta_init_sp(spp, argc, argv, options, ep);
 			break;
 		case TAB_STRIPE:
-			return (meta_init_stripe(spp, argc, argv, options, ep));
+			rval = meta_init_stripe(spp, argc, argv, options, ep);
 			break;
 		}
+
+		if (rval == -1 || !(options & MDCMD_DOIT)) {
+			/*
+			 * Remove the device node created before
+			 */
+			if ((meta_getnmentbykey((*spp)->setno, MD_SIDEWILD,
+			    key, NULL, &mnum, NULL, ep) != NULL) &&
+			    MD_MIN2UNIT(mnum) < MD_MAXUNITS) {
+			    (void) metaioctl(MD_IOCREM_DEV, &mnum, &t_e, NULL);
+			}
+
+			/*
+			 * Del what we added before
+			 */
+			(void) del_self_name(*spp, key, &t_e);
+		}
+		return (rval);
 	}
 
 	/* unknown type */
--- a/usr/src/lib/lvm/libmeta/common/meta_mirror.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_mirror.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -314,14 +313,19 @@
 	 * is net mounted as happens if we're part of the
 	 * install process, rootnp will be set to NULL and we
 	 * return success.
+	 *
+	 * Since curroot should be a complete path, we only
+	 * need to check whether the device is a logical device.
+	 * The metaname below returns NULL if curroot is not a logical
+	 * device.
 	 */
-	if ((rootnp = metaname(&sp, curroot, ep)) == NULL)
+	if ((rootnp = metaname(&sp, curroot, LOGICAL_DEVICE, ep)) == NULL)
 		return (0);
 	/*
-	 * If the currently mounted root slice is not a
-	 * ctds, we don't bother checking
+	 * If we're here, the curroot is a mounted on a logical device.
+	 * Make sure this mirror is not on the root logical device.
 	 */
-	if ((!metaismeta(rootnp)) && metaismeta(mirnp)) {
+	if (metaismeta(mirnp)) {
 		if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL)
 			return (-1);
 
@@ -597,7 +601,14 @@
 
 
 	if (options & PRINT_LARGEDEVICES) {
-		if (mirrorp->common.revision != MD_64BIT_META_DEV) {
+		if ((mirrorp->common.revision & MD_64BIT_META_DEV) == 0) {
+			rval = 0;
+			goto out;
+		}
+	}
+
+	if (options & PRINT_FN) {
+		if ((mirrorp->common.revision & MD_FN_META_DEV) == 0) {
 			rval = 0;
 			goto out;
 		}
@@ -619,7 +630,7 @@
 		}
 
 		/* print submirror */
-		if (fprintf(fp, " %s", submirnamep->cname) == EOF)
+		if (fprintf(fp, " %s", submirnamep->rname) == EOF)
 			goto out;
 	}
 
@@ -908,7 +919,40 @@
 	 * level and print there if appropriate.
 	 */
 	if (options & PRINT_LARGEDEVICES) {
-		if (mirrorp->common.revision != MD_64BIT_META_DEV) {
+		if ((mirrorp->common.revision & MD_64BIT_META_DEV) == 0) {
+			for (smi = 0; (smi < NMIRROR); ++smi) {
+				md_submirror_t	*mdsp =
+				    &mirrorp->submirrors[smi];
+				mdname_t	*submirnamep =
+				    mdsp->submirnamep;
+				if (submirnamep == NULL) {
+					continue;
+				}
+				if ((metaismeta(submirnamep)) &&
+				    (meta_print_name(sp, submirnamep, nlpp,
+				    fname, fp, options | PRINT_SUBDEVS, NULL,
+				    ep) != 0)) {
+					return (-1);
+				}
+			}
+			rval = 0;
+			goto out;
+		} else {
+			if (meta_getdevs(sp, mirrorp->common.namep,
+			    nlpp, ep) != 0)
+				goto out;
+		}
+	}
+
+	/*
+	 * check for the -D option. If -D and the name is
+	 * a descriptive name, get the dev for relocation information
+	 * printout. If not a descriptive name, don't print this
+	 * information out but you need to go down to the subdevice
+	 * level and print there if appropriate.
+	 */
+	if (options & PRINT_FN) {
+		if ((mirrorp->common.revision & MD_FN_META_DEV) == 0) {
 			for (smi = 0; (smi < NMIRROR); ++smi) {
 				md_submirror_t	*mdsp =
 				    &mirrorp->submirrors[smi];
@@ -987,7 +1031,7 @@
 	/* print resync status */
 	if (status & MD_UN_RESYNC_CANCEL) {
 		/* Resync was cancelled but is restartable */
-		if (mirrorp->common.revision == MD_64BIT_META_DEV) {
+		if (mirrorp->common.revision & MD_64BIT_META_DEV) {
 			if (fprintf(fp, dgettext(TEXT_DOMAIN,
 			    "    Resync cancelled: %2d.%1d %% done\n"),
 			    mirrorp->percent_done/10,
@@ -1002,7 +1046,7 @@
 			}
 		}
 	} else if (status & MD_UN_RESYNC_ACTIVE) {
-		if (mirrorp->common.revision == MD_64BIT_META_DEV) {
+		if (mirrorp->common.revision & MD_64BIT_META_DEV) {
 			if (fprintf(fp, dgettext(TEXT_DOMAIN,
 			    "    Resync in progress: %2d.%1d %% done\n"),
 			    mirrorp->percent_done/10,
@@ -1136,6 +1180,7 @@
 		char		*sm_state;
 		md_timeval32_t	tv;
 		char		*timep;
+		md_stripe_t	*stripep;
 
 		/* skip unused submirrors */
 		if (submirnamep == NULL) {
@@ -1143,6 +1188,17 @@
 			continue;
 		}
 
+		if (options & PRINT_FN) {
+			/* get unit structure */
+			if ((stripep = meta_get_stripe_common(sp, submirnamep,
+			    ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL)
+				goto out;
+
+			if ((stripep->common.revision & MD_FN_META_DEV)
+			    == 0)
+				continue;
+		}
+
 		/* add extra line */
 		if (fprintf(fp, "\n") == EOF)
 			goto out;
@@ -2384,10 +2440,10 @@
 	/* did the user tell us to generate a large device? */
 	create_flag = meta_check_devicesize(mm->c.un_total_blocks);
 	if (create_flag == MD_CRO_64BIT) {
-		mm->c.un_revision = MD_64BIT_META_DEV;
+		mm->c.un_revision |= MD_64BIT_META_DEV;
 		set_params.options = MD_CRO_64BIT;
 	} else {
-		mm->c.un_revision = MD_32BIT_META_DEV;
+		mm->c.un_revision &= ~MD_64BIT_META_DEV;
 		set_params.options = MD_CRO_32BIT;
 	}
 	set_params.mnum = MD_SID(mm);
@@ -2441,7 +2497,7 @@
 	assert(argc > 0);
 	if (argc < 1)
 		goto syntax;
-	if ((mirnp = metaname(spp, uname, ep)) == NULL)
+	if ((mirnp = metaname(spp, uname, META_DEVICE, ep)) == NULL)
 		goto out;
 	assert(*spp != NULL);
 	uname = mirnp->cname;
@@ -2504,7 +2560,8 @@
 		}
 
 		/* parse submirror name */
-		if ((submirnamep = metaname(spp, argv[0], ep)) == NULL)
+		if ((submirnamep = metaname(spp, argv[0],
+		    META_DEVICE, ep)) == NULL)
 			goto out;
 		mdsm->submirnamep = submirnamep;
 		--argc, ++argv;
--- a/usr/src/lib/lvm/libmeta/common/meta_mn_handlers.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_mn_handlers.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1149,8 +1148,9 @@
 	}
 
 	name = splicename(&d->msg_splitname);
-	if ((np = metaname(&sp, name, &ep)) == NULL) {
-		Free(name);
+	np = metaname(&sp, name, LOGICAL_DEVICE, &ep);
+	Free(name);
+	if (np == NULL) {
 		(void) mdstealerror(&(resp->mmr_ep), &ep);
 		resp->mmr_exitval = -1;
 		return;
@@ -1192,7 +1192,7 @@
 		}
 	}
 	add_name = splicename(&d->msg_splitname);
-	if ((np = metaname(&sp, add_name, &ep)) != NULL) {
+	if ((np = metaname(&sp, add_name, LOGICAL_DEVICE, &ep)) != NULL) {
 		meta_invalidate_name(np);
 	} else {
 		ret = -1;
@@ -1268,7 +1268,7 @@
 		}
 		/* Not incrementing "i" intentionally (dbcnt is changed) */
 	}
-	if ((np = metaname(&sp, del_name, &ep)) != NULL) {
+	if ((np = metaname(&sp, del_name, LOGICAL_DEVICE, &ep)) != NULL) {
 		meta_invalidate_name(np);
 	} else {
 		ret = -1;
@@ -1673,6 +1673,9 @@
 		return;
 	}
 
+	/*
+	 * Device should be in the namespace already
+	 */
 	if ((np = metamnumname(&sp, d->iocset_params.mnum, 1, &mde)) == NULL) {
 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
 		    "MD_MN_MSG_IOCSET: Invalid mnum %d\n"),
@@ -1681,14 +1684,9 @@
 		return;
 	}
 
-	if (meta_init_make_device(&sp, np->cname, &mde) == -1) {
-		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
-		    "MD_MN_MSG_IOCSET: Invalid metadevice name %s\n"),
-		    np->cname);
-		resp->mmr_exitval = 1;
-		return;
-	}
-
+	/*
+	 * Create unit structure
+	 */
 	d->iocset_params.mdp = (uintptr_t)&d->unit; /* set pointer to unit */
 	ret = metaioctl(MD_IOCSET, &(d->iocset_params), &mde, np->cname);
 	resp->mmr_exitval = ret;
@@ -1757,7 +1755,7 @@
 		return;
 	}
 
-	compnp = metaname(&sp, d->addkeyname_name, &mde);
+	compnp = metaname(&sp, d->addkeyname_name, UNKNOWN, &mde);
 	if (compnp != NULL) {
 		ret = add_key_name(sp, compnp, NULL, &mde);
 		if (ret < 0)
@@ -1955,3 +1953,69 @@
 	resp->mmr_exitval = metaioctl(MD_MN_POKE_HOTSPARES, &pokehsp,
 	    &pokehsp.mde, NULL);
 }
+
+/*
+ * Called to create a softpart during a metarecover operation
+ */
+/*ARGSUSED*/
+void
+mdmn_do_addmdname(md_mn_msg_t *msg, uint_t flags, md_mn_result_t *resp)
+{
+	md_mn_msg_addmdname_t	*d;
+	md_error_t		mde = mdnullerror;
+	mdsetname_t		*sp;
+	int			init = 0;
+	mdkey_t			key;
+	minor_t			mnum;
+
+	resp->mmr_comm_state = MDMNE_ACK; /* Ok state */;
+	resp->mmr_out_size = 0;
+	resp->mmr_err_size = 0;
+	resp->mmr_out = NULL;
+	resp->mmr_err = NULL;
+	d = (md_mn_msg_addmdname_t *)(void *)msg->msg_event_data;
+
+	if ((sp = metasetnosetname(d->addmdname_setno, &mde)) == NULL) {
+		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
+		    "MD_MN_MSG_ADDMDNAME: Invalid setno %d\n"),
+		    d->addmdname_setno);
+		resp->mmr_exitval = 1;
+		return;
+	}
+
+	/*
+	 * If device node does not exist then init it
+	 */
+	if (!is_existing_meta_hsp(sp, d->addmdname_name)) {
+	    if ((key = meta_init_make_device(&sp, d->addmdname_name,
+		&mde)) <= 0) {
+		    syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
+			"MD_MN_MSG_ADDMDNAME: Invalid name %s\n"),
+			d->addmdname_name);
+		    resp->mmr_exitval = 1;
+		    return;
+		}
+
+		init = 1;
+	}
+
+	/*
+	 * We should have it
+	 */
+	if (metaname(&sp, d->addmdname_name, META_DEVICE, &mde) == NULL) {
+
+	    if (init) {
+		if (meta_getnmentbykey(sp->setno, MD_SIDEWILD,
+		    key, NULL, &mnum, NULL, &mde) != NULL) {
+			(void) metaioctl(MD_IOCREM_DEV, &mnum,
+				&mde, NULL);
+		}
+		(void) del_self_name(sp, key, &mde);
+	    }
+
+	    resp->mmr_exitval = 1;
+	    return;
+	}
+
+	resp->mmr_exitval = 0;
+}
--- a/usr/src/lib/lvm/libmeta/common/meta_mn_msg_table.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_mn_msg_table.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -56,6 +55,7 @@
 extern void mdmn_do_delkeyname(HANDLER_PARMS);
 extern void mdmn_do_get_tstate(HANDLER_PARMS);
 extern void mdmn_do_get_mirstate(HANDLER_PARMS);
+extern void mdmn_do_addmdname(HANDLER_PARMS);
 
 extern int mdmn_smgen_test6(SMGEN_PARMS);
 extern int mdmn_smgen_state_upd(SMGEN_PARMS);
@@ -687,4 +687,16 @@
 		UINT_MAX, 100	/* comm fail retry / time delta */
 	},
 
+	{
+	/*
+	 * MD_MN_MSG_ADDMDNAME
+	 * Add metadevice name into replica
+	 */
+		MD_MSG_CLASS1,		/* message class */
+		mdmn_do_addmdname,	/* add ,etadevice name */
+		NULL,			/* submessage generator */
+		90,			/* times out in 90 secs */
+		10000, 2,		/* class busy retry / time delta */
+		10, 1000		/* comm fail retry / time delta */
+	},
 };
--- a/usr/src/lib/lvm/libmeta/common/meta_mn_subr.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_mn_subr.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -76,7 +75,7 @@
  * FUNCTION:	meta_is_mn_name()
  * INPUT:       spp     - ptr to the set name, if NULL the setname is derived
  *			  from the metadevice name (eg set/d10 )
- *		name	- the metadevice name
+ *		name	- the metadevice/hsp name
  * OUTPUT:	ep	- return error pointer
  * RETURNS:	int	- 1 if MultiNode set else 0
  * PURPOSE:	checks if the metadevice is in a MultiNode set
@@ -88,23 +87,23 @@
 	md_error_t	*ep
 )
 {
-	md_error_t	t_e = mdnullerror;
-	char		*cname;
+	if (*spp == NULL) {
+		char		*cname;
 
-	if (*spp == NULL) {
-		if (is_hspname(name)) {
-			if (metahspname(spp, name, ep) == NULL)
-				return (0);
-		} else if (is_metaname(name)) {
-			/* Will fill in *spp based on name */
-			if ((cname = meta_name_getname(spp, name, &t_e))
-			    != NULL)
-				Free(cname);
-			if (! mdisok(&t_e)) {
-				(void) mdstealerror(ep, &t_e);
-				return (0);
-			}
-		} else return (0);
+		/*
+		 * if the setname is specified in uname and *spp is
+		 * not set, then it is setup using that set name value.
+		 * If *spp is set and a setname specified in uname and
+		 * the set names don't agree then cname will be
+		 * returned as NULL
+		 */
+		cname = meta_canonicalize_check_set(spp, name, ep);
+		if (cname == NULL) {
+			mdclrerror(ep);
+			return (0);
+		}
+
+		Free(cname);
 	}
 
 	if ((strcmp((*spp)->setname, MD_LOCAL_NAME) != 0) &&
--- a/usr/src/lib/lvm/libmeta/common/meta_mount.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_mount.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -82,7 +81,7 @@
 
 		(void) strcpy(mnt_mountp, m.mnt_mountp);
 		(void) strcpy(mnt_special, m.mnt_special);
-		if ((mnp = metaname(&sp, mnt_special, ep)) == NULL) {
+		if ((mnp = metaname(&sp, mnt_special, UNKNOWN, ep)) == NULL) {
 			mdclrerror(ep);
 			continue;
 		}
--- a/usr/src/lib/lvm/libmeta/common/meta_name.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_name.c	Tue Mar 14 14:53:36 2006 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -30,6 +30,7 @@
 
 #include <ctype.h>
 #include <string.h>
+#include <sys/fs/ufs_fsdir.h>
 
 /*
  * Just in case we're not in a build environment, make sure that
@@ -60,6 +61,11 @@
 static	mdhspnamelist_t		*hsplistp = NULL;
 
 /*
+ * Static definitions
+ */
+static int chksetname(mdsetname_t **spp, char *sname, md_error_t *ep);
+
+/*
  * leak proof name conversion
  */
 static char *
@@ -122,102 +128,15 @@
 }
 
 /*
- * parse up metadevice name
- */
-static int
-parse_metadevice(
-	char		*uname,
-	char		**snamep,
-	unit_t		*unitp
-)
-{
-	char		*sname = Malloc(strlen(uname) + 1);
-	char		*tname = Malloc(strlen(uname) + 1);
-
-	unit_t		unit;
-	int		len;
-	char *up;
-	char *tp;
-	int lcws;	/* last character was slash */
-
-	/* handle dont cares */
-	if (unitp == NULL)
-		unitp = &unit;
-
-	/* Now copy uname to tname by throwing away any duplicate '/' */
-	for (lcws = 0, tp = tname, up = uname; *up; up++) {
-		if (lcws) {
-			if (*up == '/') {
-				continue;
-			} else {
-				lcws = 0;
-			}
-		}
-		if (*up == '/') {
-			lcws = 1;
-		}
-		*tp++ = *up; /* ++ is done by for loop */
-	}
-	*tp = '\0';
-
-	/* without set */
-	if ((sscanf(tname, "d%lu%n", unitp, &len) == 1) &&
-	    (strlen(tname) == len) && ((long)*unitp >= 0)) {
-		if (snamep != NULL)
-			*snamep = NULL;
-		Free(sname);
-		Free(tname);
-		return (0);
-	}
-
-	/* fully-qualified without set */
-	if (((sscanf(tname, "/dev/md/dsk/d%lu%n", unitp, &len) == 1) &&
-	    (strlen(tname) == len) && ((long)*unitp >= 0)) ||
-	    ((sscanf(tname, "/dev/md/rdsk/d%lu%n", unitp, &len) == 1) &&
-	    (strlen(tname) == len) && ((long)*unitp >= 0))) {
-		if (snamep != NULL)
-			*snamep = Strdup(MD_LOCAL_NAME);
-		Free(sname);
-		Free(tname);
-		return (0);
-	}
-
-	/* with set */
-	if (((sscanf(tname, "%[^/]/d%lu%n", sname, unitp, &len) == 2) &&
-	    (strlen(tname) == len) && ((long)*unitp >= 0)) ||
-	    ((sscanf(tname, "/dev/md/%[^/]/dsk/d%lu%n", sname,
-	    unitp, &len) == 2) &&
-	    (strlen(tname) == len) && ((long)*unitp >= 0)) ||
-	    ((sscanf(tname, "/dev/md/%[^/]/rdsk/d%lu%n", sname,
-	    unitp, &len) == 2) &&
-	    (strlen(tname) == len) && ((long)*unitp >= 0))) {
-		if (snamep != NULL) {
-			*snamep = sname;
-		} else {
-			Free(sname);
-		}
-		Free(tname);
-		return (0);
-	}
-
-	/* no match */
-	if (snamep != NULL)
-		*snamep = NULL;
-	Free(sname);
-	Free(tname);
-	return (-1);
-}
-
-/*
  * FUNCTION:	parse_device()
  * INPUT:	sp - pointer to setname struct
  *		uname - Name of either a hotspare pool or metadevice
  *			This can either be a fully qualified path or
  *			in the form [set name/]device
- * OUTPUT:	setnamep - name of the set that uname is in
- *		uname - name of the hotspare pools or metadevice
- *			only contains the name of the device with all
- *			other path information stripped off.
+ * OUTPUT:	snamep - name of the set that uname is in
+ *		fnamep - metadevice or hsp with path and set name info stripped
+ *		    This parameter is dynamically allocated and must be
+ *		    freed by the calling function.
  * PURPOSE:	Parse uname and sp into the set name and device name strings.
  *		If the set name is specified as part of uname then use that
  *		otherwise attempt to get the set name from sp.
@@ -226,10 +145,12 @@
 parse_device(
 	mdsetname_t	*sp,
 	char		*uname,
-	char		**setnamep /* dynamically alloced - caller must free */
+	char		**fnamep, /* dynamically alloced - caller must free */
+	char		**snamep  /* dynamically alloced - caller must free */
 )
 {
 	char		setname[FILENAME_MAX+1];
+	char		devname[FILENAME_MAX+1];
 	char		*tname = Malloc(strlen(uname) + 1);
 
 	int		len;
@@ -255,139 +176,94 @@
 
 	/* fully-qualified  - local set */
 	if (((sscanf(tname, "/dev/md/dsk/%" VAL2STR(FILENAME_MAX) "s%n",
-			uname, &len) == 1) && (strlen(tname) == len)) ||
+			devname, &len) == 1) && (strlen(tname) == len)) ||
 	    ((sscanf(tname, "/dev/md/rdsk/%" VAL2STR(FILENAME_MAX) "s%n",
-			uname, &len) == 1) && (strlen(tname) == len))) {
-		if (setnamep != NULL)
-			*setnamep = NULL;
+			devname, &len) == 1) && (strlen(tname) == len))) {
+		*snamep = Strdup(MD_LOCAL_NAME);
+		*fnamep = Strdup(devname);
 		Free(tname);
 		return;
 	}
 
 	/* with setname specified - either fully qualified and relative spec */
-	if (((sscanf(tname, "%" VAL2STR(FILENAME_MAX) "s/%"
-	    VAL2STR(FILENAME_MAX) "s%n", setname, uname, &len) == 2) &&
-			(strlen(tname) == len)) ||
+	if (((sscanf(tname, "%[^/]/%" VAL2STR(FILENAME_MAX) "s%n",
+		setname, devname, &len) == 2) && (strlen(tname) == len)) ||
 	    ((sscanf(tname, "/dev/md/%[^/]/dsk/%" VAL2STR(FILENAME_MAX) "s%n",
-		setname, uname, &len) == 2) && (strlen(tname) == len)) ||
+		setname, devname, &len) == 2) && (strlen(tname) == len)) ||
 	    ((sscanf(tname, "/dev/md/%[^/]/rdsk/%" VAL2STR(FILENAME_MAX) "s%n",
-		setname, uname, &len) == 2) && (strlen(tname) == len))) {
-
-		if (setnamep != NULL) {
-			*setnamep = Strdup(setname);
-		}
+		setname, devname, &len) == 2) && (strlen(tname) == len))) {
+
+		*snamep = Strdup(setname);
+		*fnamep = Strdup(devname);
 		Free(tname);
 		return;
 	}
 
 	/* without setname specified */
-	(void) strcpy(uname, tname);
-	if (setnamep != NULL) {
-		if (sp != NULL && !metaislocalset(sp))
-			*setnamep = Strdup(sp->setname);
-		else
-			*setnamep = NULL;
-	}
-	Free(tname);
+	*fnamep = tname;
+	if (sp != NULL && !metaislocalset(sp))
+		*snamep = Strdup(sp->setname);
+	else
+		*snamep = NULL;
+}
+
+/*
+ * check for "all"
+ */
+int
+meta_is_all(char *s)
+{
+	if ((strcoll(s, gettext("all")) == 0) ||
+	    (strcoll(s, gettext("ALL")) == 0))
+		return (1);
+	return (0);
 }
 
 /*
- * parse up hotspare pool name
+ * check for "none"
  */
+int
+meta_is_none(char *s)
+{
+	if ((strcoll(s, gettext("none")) == 0) ||
+	    (strcoll(s, gettext("NONE")) == 0))
+		return (1);
+	return (0);
+}
+
 static int
-parse_hsp(
-	char		*uname,
-	char		**snamep,
-	hsp_t		*hspp
-)
+valid_name_syntax(char *uname)
 {
-	char		*sname = Malloc(strlen(uname) + 1);
-	hsp_t		hsp;
-	int		len;
-
-	/* handle dont cares */
-	if (hspp == NULL)
-		hspp = &hsp;
-
-	/* without set */
-	if ((sscanf(uname, "hsp%03u%n", hspp, &len) == 1) &&
-	    (strlen(uname) == len) && ((long)*hspp >= 0)) {
-		if (snamep != NULL)
-			*snamep = NULL;
-		Free(sname);
+	int	i;
+	int	uname_len;
+
+	if (uname == NULL || !isalpha(uname[0]))
+		return (0);
+
+	uname_len = strlen(uname);
+	if (uname_len > MAXNAMLEN)
 		return (0);
+
+	/* 'all' and 'none' are reserved */
+	if (meta_is_all(uname) || meta_is_none(uname))
+		return (0);
+
+	for (i = 1; i < uname_len; i++) {
+		if ((isalnum(uname[i]) || uname[i] == '-' ||
+		    uname[i] == '_' || uname[i] == '.'))
+			continue;
+		break;
 	}
 
-	/* with set */
-	if ((sscanf(uname, "%[^/]/hsp%03u%n", sname,
-	    hspp, &len) == 2) &&
-	    (strlen(uname) == len) && ((long)*hspp >= 0)) {
-		if (snamep != NULL) {
-			*snamep = sname;
-		} else {
-			Free(sname);
-		}
+	if (i < uname_len)
 		return (0);
-	}
-
-	/* no match */
-	Free(sname);
-	return (-1);
+
+	return (1);
+
 }
 
 /*
- * canonicalize metadevice name
- */
-static char *
-canon_metadevice(
-	char	*sname,
-	unit_t	unit
-)
-{
-	char	*cname;
-	size_t	len;
-
-	if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) {
-		len = strlen("d") + 20 + 1;
-		cname = Malloc(len);
-		(void) snprintf(cname, len, "d%lu", unit);
-	} else {
-		len = strlen(sname) + strlen("/d") + 20 + 1;
-		cname = Malloc(len);
-		(void) snprintf(cname, len, "%s/d%lu", sname, unit);
-	}
-
-	return (cname);
-}
-
-/*
- * canonicalize hotspare pool name
- */
-static char *
-canon_hsp(
-	char	*sname,
-	hsp_t	hsp
-)
-{
-	char	*cname;
-	size_t	len;
-
-	if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0)) {
-		cname = Malloc(strlen("hsp000") + 1);
-		(void) sprintf(cname, "hsp%03u", hsp);
-	} else {
-		len = strlen(sname) + strlen("/hsp000") + 1;
-		cname = Malloc(len);
-		(void) snprintf(cname, len, "%s/hsp%03lu", sname, hsp);
-	}
-
-	return (cname);
-}
-
-/*
- * canonicalize name, return type
- *
- * NOTE: this is really only for use by meta_tab*
+ * canonicalize name
  */
 char *
 meta_canonicalize(
@@ -396,23 +272,106 @@
 )
 {
 	char	*sname = NULL;
+	char	*tname = NULL;
 	char	*cname;
 
-	/* return the set name and dev name */
-	parse_device(sp, uname, &sname);
-
-	if (sname == NULL)
-		cname = Strdup(uname);
+	/* return the dev name and set name */
+	parse_device(sp, uname, &tname, &sname);
+
+	if (!valid_name_syntax(tname)) {
+		Free(tname);
+		if (sname != NULL)
+		    Free(sname);
+		return (NULL);
+	}
+
+	if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0))
+		cname = tname;
 	else {
 		size_t	cname_len;
 
-		cname_len = strlen(uname) + strlen(sname) + 2;
+		cname_len = strlen(tname) + strlen(sname) + 2;
 		cname = Malloc(cname_len);
 		(void) snprintf(
-		    cname, cname_len, "%s/%s", sname, uname);
+		    cname, cname_len, "%s/%s", sname, tname);
+		Free(tname);
+	}
+
+	if (sname != NULL)
+	    Free(sname);
+
+	return (cname);
+}
+
+/*
+ * canonicalize name and check the set
+ */
+char *
+meta_canonicalize_check_set(
+	mdsetname_t	**spp,
+	char		*uname,
+	md_error_t	*ep
+)
+{
+	char		*sname = NULL;
+	char		*tname = NULL;
+	char		*cname;
+
+	/* return the dev name and set name */
+	parse_device(*spp, uname, &tname, &sname);
+
+	if (!valid_name_syntax(tname)) {
+		(void) mderror(ep, MDE_NAME_ILLEGAL, tname);
+		if (sname != NULL)
+			Free(sname);
+		Free(tname);
+		return (NULL);
+	}
+
+	/* check the set name returned from the name for validity */
+	if (chksetname(spp, sname, ep) != 0) {
+		Free(tname);
+		if (sname != NULL)
+		    Free(sname);
+		return (NULL);
+	}
+
+	if ((sname == NULL) || (strcmp(sname, MD_LOCAL_NAME) == 0))
+		cname = tname;
+	else {
+		size_t	cname_len;
+
+		cname_len = strlen(tname) + strlen(sname) + 2;
+		cname = Malloc(cname_len);
+		(void) snprintf(
+		    cname, cname_len, "%s/%s", sname, tname);
+		Free(tname);
+	}
+
+	if (sname != NULL)
+	    Free(sname);
+
+	return (cname);
+}
+
+/*
+ * Verify that the name is a valid hsp/metadevice name
+ */
+static int
+parse_meta_hsp_name(char *uname)
+{
+	char	*sname = NULL;
+	char	*tname = NULL;
+	int	ret;
+
+	/* return the dev name and set name */
+	parse_device(NULL, uname, &tname, &sname);
+
+	ret = valid_name_syntax(tname);
+	if (sname != NULL)
 		Free(sname);
-	}
-	return (cname);
+	Free(tname);
+	return (ret);
 }
 
 /*
@@ -423,10 +382,7 @@
 	char	*uname
 )
 {
-	if (parse_metadevice(uname, NULL, NULL) == 0)
-		return (1);
-	else
-		return (0);
+	return (parse_meta_hsp_name(uname));
 }
 
 /*
@@ -437,10 +393,108 @@
 	char	*uname
 )
 {
-	if (parse_hsp(uname, NULL, NULL) == 0)
+	return (parse_meta_hsp_name(uname));
+}
+
+/*
+ * check to verify that name is an existing metadevice
+ */
+int
+is_existing_metadevice(
+	mdsetname_t	*sp,
+	char		*uname
+)
+{
+	char		*raw_name;
+	char		*set_name;
+	char		*full_path;
+	char		*fname = NULL;
+	int		pathlen;
+	int		retval = 0;
+
+	assert(uname != NULL);
+	/*
+	 * If it is an absolute name of a metadevice, then just call rawname
+	 * on the input
+	 */
+	if (uname[0] == '/') {
+		if (strncmp("/dev/md", uname, strlen("/dev/md")) == 0 &&
+			(raw_name = rawname(uname)) != NULL) {
+		    Free(raw_name);
+		    return (1);
+		}
+		return (0);
+	}
+
+	/* create a fully specified path from the parsed string */
+	parse_device(sp, uname, &fname, &set_name);
+
+	if ((set_name == NULL) || (strcmp(set_name, MD_LOCAL_NAME) == 0)) {
+		pathlen = strlen("/dev/md/rdsk/") + strlen(fname) + 1;
+		full_path = Zalloc(pathlen);
+		(void) snprintf(full_path, pathlen, "/dev/md/rdsk/%s", fname);
+	} else {
+		pathlen = strlen("/dev/md//rdsk/") + strlen(fname) +
+		    strlen(set_name) + 1;
+		full_path = Zalloc(pathlen);
+		(void) snprintf(full_path, pathlen, "/dev/md/%s/rdsk/%s",
+		    set_name, fname);
+	}
+
+	if ((raw_name = rawname(full_path)) != NULL) {
+	    Free(raw_name);
+	    retval = 1;
+	}
+
+	if (set_name != NULL)
+		Free(set_name);
+
+	Free(fname);
+	Free(full_path);
+	return (retval);
+}
+
+/*
+ * check to verify that name is an existing hsp
+ */
+int
+is_existing_hsp(
+	mdsetname_t	*sp,
+	char		*uname
+)
+{
+	md_error_t	status = mdnullerror;
+	hsp_t		hsp;
+	set_t		cur_set;
+
+	if (sp != NULL)
+		cur_set = sp->setno;
+	else
+		cur_set = 0;
+
+	hsp = meta_gethspnmentbyname(cur_set, MD_SIDEWILD, uname, &status);
+
+	if (hsp == MD_HSP_NONE) {
+		mdclrerror(&status);
+		return (0);
+	}
+	return (1);
+}
+
+/*
+ * check to verify that name is an existing metadevice or hotspare pool
+ */
+int
+is_existing_meta_hsp(
+	mdsetname_t	*sp,
+	char		*uname
+)
+{
+	if (is_existing_metadevice(sp, uname) ||
+	    is_existing_hsp(sp, uname))
 		return (1);
-	else
-		return (0);
+
+	return (0);
 }
 
 /*
@@ -851,7 +905,7 @@
 )
 {
 	/* if we already have a set, make sure it's the same */
-	if (*spp != NULL) {
+	if (*spp != NULL && !metaislocalset(*spp)) {
 		if ((*spp)->setname != sname &&
 				strcmp((*spp)->setname, sname) != 0) {
 			return (mderror(ep, MDE_SET_DIFF, sname));
@@ -881,7 +935,7 @@
 	/* default to *spp's setname, or if that is NULL to MD_LOCAL_NAME */
 	if (sname == NULL) {
 		if (*spp) {
-			sname = (*spp)->setname;
+			return (0);
 		} else {
 			sname = MD_LOCAL_NAME;
 		}
@@ -1044,9 +1098,6 @@
 	int	l = 0;
 	int	cl = strlen(name);
 
-	if (is_metaname(name))
-	    return (Strdup(name));
-
 	/*
 	 * Handle old style names, which are of the form /dev/rXXNN[a-h].
 	 */
@@ -1193,40 +1244,42 @@
 
 /*
  * check set and get comparison name
+ *
+ * NOTE: This function has a side effect of setting *spp if the setname
+ * has been specified and *spp is not already set.
  */
 char *
 meta_name_getname(
-	mdsetname_t	**spp,
-	char		*uname,
-	md_error_t	*ep
+	mdsetname_t		**spp,
+	char			*uname,
+	meta_device_type_t	uname_type,
+	md_error_t		*ep
 )
 {
-	char		*sname = NULL;
-	int		ismeta = 0;
-	unit_t		unit;
-
-	/* check set name */
-	if (parse_metadevice(uname, &sname, &unit) == 0)
-		ismeta = 1;
-	if (chksetname(spp, sname, ep) != 0) {
-		if (sname != NULL)
-			Free(sname);
+	if (uname_type == META_DEVICE || uname_type == HSP_DEVICE ||
+	    (uname_type == UNKNOWN && is_existing_metadevice(*spp, uname))) {
+
+		/*
+		 * if the setname is specified in uname, *spp is set,
+		 * and the set names don't agree then canonical name will be
+		 * returned as NULL
+		 */
+		return (meta_canonicalize_check_set(spp, uname, ep));
+	}
+
+	/* if it is not a meta/hsp and *spp is not set then set it to local */
+	if (chksetname(spp, NULL, ep) != 0)
 		return (NULL);
-	}
-	if (sname != NULL)
-		Free(sname);
-
-	/* return comparison name */
-	if (ismeta)
-		return (canon_metadevice((*spp)->setname, unit));
-	else
-		return (Strdup(uname));
+
+	/* if it is not a meta/hsp name then just return uname */
+	return (Strdup(uname));
 }
 
 /*
  * FUNCTION:	getrname()
  * INPUT:	spp	- the setname struct
  *		uname	- the possibly unqualified device name
+ *		type 	- ptr to the device type of uname
  * OUTPUT:	ep	- return error pointer
  * RETURNS:	char*	- character string containing the fully
  *			qualified raw device name
@@ -1234,20 +1287,44 @@
  *		unqualified device name.  If uname is an absolute
  *		path the raw name is derived from the input string.
  *		Otherwise, an attempt is made to get the rawname by
- *		catting "/dev/md/rdsk" and "/dev/rdsk".
+ *		catting "/dev/md/rdsk" and "/dev/rdsk". If the input
+ *		value of type is UNKNOWN and it can be successfully
+ *		determined then update type to the correct value.
  */
-static char *
-getrname(mdsetname_t **spp, char *uname, md_error_t *ep)
+static	char *
+getrname(mdsetname_t **spp, char *uname,
+    meta_device_type_t *type, md_error_t *ep)
 {
-	char	*rname,
-		*fname;
-	int	constructed = 0;
+	char			*rname,
+				*fname;
+	int			i;
+	int 			rname_cnt = 0;
+	char			*rname_list[3];
+	meta_device_type_t	tmp_type;
 
 	assert(uname != NULL);
 	/* if it is an absolute name then just call rawname on the input */
 	if (uname[0] == '/') {
-	    if ((rname = rawname(uname)) != NULL)
+	    if ((rname = rawname(uname)) != NULL) {
+		/*
+		 * If the returned rname does not match with
+		 * the specified uname type, we'll return null.
+		 */
+		if (strncmp(rname, "/dev/md", strlen("/dev/md")) == 0) {
+			if (*type == LOGICAL_DEVICE) {
+				(void) mdsyserror(ep, ENOENT, uname);
+				return (NULL);
+			}
+			*type = META_DEVICE;
+		} else {
+			if (*type == META_DEVICE) {
+				(void) mdsyserror(ep, ENOENT, uname);
+				return (NULL);
+			}
+			*type = LOGICAL_DEVICE;
+		}
 		return (rname);
+	    }
 
 	    /* out of luck */
 	    (void) mdsyserror(ep, ENOENT, uname);
@@ -1255,57 +1332,84 @@
 	}
 
 	/*
+	 * Get device that matches the requested type. If
+	 * a match is found, return immediately. If type is
+	 * UNKNOWN, save all the found devices in rname_list
+	 * so we can determine later whether the input uname
+	 * is ambiguous.
+	 *
 	 * Check for metadevice before physical device.
 	 * With the introduction of softpartitions it is more
 	 * likely to be a metadevice.
 	 */
 
 	/* metadevice short form */
-	if (metaislocalset(*spp)) {
-		fname = Malloc(strlen(uname) + strlen("/dev/md/rdsk/") + 1);
-		(void) strcpy(fname, "/dev/md/rdsk/");
-		(void) strcat(fname, uname);
-		if (*uname == 'd')
-			constructed = 1;
-	} else {
-		char	*p;
-		size_t	len;
-
-		if ((p = strchr(uname, '/')) != NULL) {
-			++p;
+	if (*type == META_DEVICE || *type == UNKNOWN) {
+		if (metaislocalset(*spp)) {
+			fname = Malloc(strlen(uname) +
+			    strlen("/dev/md/rdsk/") + 1);
+			(void) strcpy(fname, "/dev/md/rdsk/");
+			(void) strcat(fname, uname);
 		} else {
-			p = uname;
+			char	*p;
+			size_t	len;
+
+			if ((p = strchr(uname, '/')) != NULL) {
+				++p;
+			} else {
+				p = uname;
+			}
+			len = strlen((*spp)->setname) + strlen(p) +
+			    strlen("/dev/md//rdsk/") + 1;
+			fname = Malloc(len);
+			(void) snprintf(fname, len, "/dev/md/%s/rdsk/%s",
+			    (*spp)->setname, p);
 		}
-		len = strlen((*spp)->setname) + strlen(p) +
-		    strlen("/dev/md//rdsk/") + 1;
-		fname = Malloc(len);
-		(void) snprintf(fname, len, "/dev/md/%s/rdsk/%s",
-		    (*spp)->setname, p);
-		if (*p == 'd')
-			constructed = 1;
+		rname = rawname(fname);
+
+		if (*type == META_DEVICE) {
+			/*
+			 * Handle the case where we have a new metadevice
+			 * that does not yet exist in the name-space(e.g
+			 * metarecover in MN sets where /dev/md entry is
+			 * not yet created in the non-master nodes). In
+			 * this case we return the constructed metadevice
+			 * name as that will exist after the metainit call
+			 * has created it.
+			 */
+			if (rname == NULL) {
+				rname = Strdup(fname);
+			}
+
+			Free(fname);
+			return (rname);
+		}
+
+		Free(fname);
+		if ((rname != NULL) && (*type == UNKNOWN)) {
+			/* Save this result */
+			rname_list[rname_cnt] = rname;
+			rname_cnt ++;
+		}
 	}
-	rname = rawname(fname);
-
-	/*
-	 * Handle the case where we have a new metadevice that does not yet
-	 * exist in the name-space. In this case we return the constructed
-	 * metadevice name as that will exist after the metainit call has
-	 * created it.
-	 */
-	if ((rname == NULL) && constructed) {
-		rname = Strdup(fname);
+
+	if (*type == LOGICAL_DEVICE || *type == UNKNOWN) {
+		fname = Malloc(strlen(uname) + strlen("/dev/rdsk/") + 1);
+		(void) strcpy(fname, "/dev/rdsk/");
+		(void) strcat(fname, uname);
+		rname = rawname(fname);
+
+		Free(fname);
+		if (rname != NULL) {
+			/* Simply return if a logical device was requested */
+			if (*type == LOGICAL_DEVICE) {
+				return (rname);
+			} else {
+				rname_list[rname_cnt] = rname;
+				rname_cnt ++;
+			}
+		}
 	}
-	Free(fname);
-	if (rname != NULL)
-		return (rname);
-
-	fname = Malloc(strlen(uname) + strlen("/dev/rdsk/") + 1);
-	(void) strcpy(fname, "/dev/rdsk/");
-	(void) strcat(fname, uname);
-	rname = rawname(fname);
-	Free(fname);
-	if (rname != NULL)
-		return (rname);
 
 	/*
 	 * If all else fails try the straight uname.
@@ -1317,19 +1421,93 @@
 	 *	fubar/d10 -m fubar/d0 fubar/d1
 	 *	mount /dev/md/fubar/dsk/d10 /fubar
 	 *
-	 * When the system was booted DiskSuite would try to take ownership
+	 * When the system was booted SVM would try to take ownership
 	 * of diskset fubar. This would cause rawname("fubar/d10") to be
 	 * called. rawname() stats the string which caused the cluster
 	 * reservation code to try and take ownership which it was already
 	 * doing and a deadlock would occur. By moving this final attempt
 	 * at resolving the rawname to the end we avoid this deadlock.
 	 */
-	if (rname = rawname(uname))
+	if (rname = rawname(uname)) {
+		/*
+		 * It's only possible to get a logical device from this
+		 * rawname call since a metadevice would have been
+		 * detected earlier.
+		 */
+		if (*type == LOGICAL_DEVICE &&
+		    (strncmp(rname, "/dev/md/", strlen("/dev/md"))) != 1)
+			return (rname);
+		else {
+			rname_list[rname_cnt] = rname;
+			rname_cnt++;
+		}
+	}
+
+	/*
+	 * At this point, we've searched /dev/md/rdsk, /dev/rdsk and
+	 * ./ for the specified device. rname_list contains all
+	 * the matches we've found and rname_cnt is the number of
+	 * matches.
+	 *
+	 * We know that either we don't have a match if a specific
+	 * type was given, in which case we simply return NULL or
+	 * we have an UNKNOWN device with 1-3 entries in rname_list.
+	 *
+	 * If we get 3 entries, rname_cnt == 3, it's ambiguous.
+	 * If we only get 1 entry, rname_cnt == 1, return rname_list[0].
+	 * If we get 2 entries that are not the same, it's ambigous.
+	 */
+	rname = NULL;
+	if (rname_cnt == 0 || *type != UNKNOWN) {
+		/* out of luck */
+		(void) mdsyserror(ep, ENOENT, uname);
+		return (NULL);
+	} else {
+		if (rname_cnt == 3) {
+			(void) mderror(ep, MDE_AMBIGUOUS_DEV, uname);
+			(void) printf(dgettext(TEXT_DOMAIN,
+			    "Error: ambiguous device name.\n%s %s %s\n\n"),
+			    rname_list[0], rname_list[1], rname_list[2]);
+			rname = NULL;
+		}
+
+		/* grab the type in case it is not ambiguous */
+		if (strncmp(rname_list[0], "/dev/md", strlen("/dev/md")) == 0)
+			tmp_type =  META_DEVICE;
+		else
+			tmp_type =  LOGICAL_DEVICE;
+
+		if (rname_cnt == 1) {
+			rname = Strdup(rname_list[0]);
+			*type = tmp_type;
+		} else {
+			/*
+			 * Prevent the case where the command is run in
+			 * either /dev/md/rdsk or /dev/rdsk so the both
+			 * rname_list[0] and rname_list[1] are the same.
+			 */
+			if (strcmp(rname_list[0], rname_list[1]) != 0) {
+				(void) mderror(ep, MDE_AMBIGUOUS_DEV, uname);
+				if (rname_cnt != 3) {
+					/*
+					 * For the rname_cnt == 3 case, the
+					 * error was printed above.
+					 */
+					(void) printf(dgettext(TEXT_DOMAIN,
+						"Error: ambiguous device "
+						"name.\n%s %s\n\n"),
+						rname_list[0], rname_list[1]);
+				}
+				rname = NULL;
+			} else {
+				rname = Strdup(rname_list[0]);
+				*type = tmp_type;
+			}
+		}
+		for (i = 0; i < rname_cnt; i++)
+			Free(rname_list[i]);
 		return (rname);
-
-	/* out of luck */
-	(void) mdsyserror(ep, ENOENT, uname);
-	return (NULL);
+	}
 }
 
 /*
@@ -1337,20 +1515,26 @@
  */
 static char *
 getrawnames(
-	mdsetname_t	**spp,
-	char		*uname,
-	char		**dnamep,
-	md_error_t	*ep
+	mdsetname_t		**spp,
+	char			*uname,
+	char			**dnamep,
+	meta_device_type_t	*uname_type,
+	md_error_t		*ep
 )
 {
-	char		*rname;
+	char		*rname = NULL;
 	size_t		len;
 
+	/*
+	 * Incorrect code path if type is HSP_DEVICE
+	 */
+	assert(*uname_type != HSP_DEVICE);
+
 	/* initialize */
 	*dnamep = NULL;
 
 	/* get slice name */
-	if ((rname = getrname(spp, uname, ep)) != NULL) {
+	if ((rname = getrname(spp, uname, uname_type, ep)) != NULL) {
 		*dnamep = metadiskname(rname);
 		return (rname);
 	}
@@ -1358,9 +1542,11 @@
 	/*
 	 * If name cannot be found, if may be because is is not accessible.
 	 * If it is an absolute name, try all possible disk name formats and
-	 * if it is device name, assume it is /dev/rdsk/...
+	 * if it is device name, assume it is /dev/rdsk/..
+	 * Since the code below assumes logical devices, if the given
+	 * uname_type is META_DEVICE, there's nothing to do.
 	 */
-	if (mdissyserror(ep, ENOENT)) {
+	if (mdissyserror(ep, ENOENT) && *uname_type != META_DEVICE) {
 		if (uname[0] == '/') {
 			/* Absolute name */
 			char			*p;
@@ -1378,6 +1564,7 @@
 				mdclrerror(ep);
 				rname = Strdup(uname);
 				*dnamep = metadiskname(rname);
+				*uname_type = LOGICAL_DEVICE;
 				return (rname);
 			}
 
@@ -1393,6 +1580,7 @@
 				(void) snprintf(rname, len, "/dev/r%s%u%s",
 				    onmb, d, snm);
 				*dnamep = metadiskname(rname);
+				*uname_type = LOGICAL_DEVICE;
 				return (rname);
 			}
 
@@ -1405,6 +1593,7 @@
 				rname[(p - uname)] = 'r';
 				(void) strcpy(&rname[(p - uname) + 1], p);
 				*dnamep = metadiskname(rname);
+				*uname_type = LOGICAL_DEVICE;
 				return (rname);
 			}
 
@@ -1413,6 +1602,7 @@
 				mdclrerror(ep);
 				rname = Strdup(uname);
 				*dnamep = metadiskname(rname);
+				*uname_type = LOGICAL_DEVICE;
 				return (rname);
 			}
 		} else {
@@ -1427,12 +1617,15 @@
 				(void) snprintf(rname, len, "/dev/rdsk/%s",
 				    uname);
 				*dnamep = metadiskname(rname);
+				*uname_type = LOGICAL_DEVICE;
 				return (rname);
 			}
 		}
 	}
 
 	/* out of luck */
+	if (!mdiserror(ep, MDE_AMBIGUOUS_DEV))
+		(void) mderror(ep, MDE_UNIT_NOT_FOUND, uname);
 	return (NULL);
 }
 
@@ -1575,9 +1768,10 @@
  */
 static int
 uname2sliceno(
-	char		*uname,
-	uint_t		*slicep,
-	md_error_t	*ep
+	char			*uname,
+	meta_device_type_t	uname_type,
+	uint_t			*slicep,
+	md_error_t		*ep
 )
 {
 	uint_t			c = 0, t = 0, d = 0;
@@ -1587,7 +1781,8 @@
 	char			*p;
 	char			*rname = NULL;
 
-	if (is_metaname(uname))
+
+	if (uname_type == META_DEVICE)
 		return (*slicep = 0);
 
 	if ((p = strrchr(uname, '/')) != NULL)
@@ -1645,12 +1840,13 @@
  */
 static int
 getparts(
-	mddrivename_t	*dnp,
-	char		*rname,
-	char		*dname,
-	uint_t		*npartsp,
-	uint_t		*partnop,
-	md_error_t	*ep
+	mddrivename_t		*dnp,
+	char			*rname,
+	char			*dname,
+	meta_device_type_t	uname_type,
+	uint_t			*npartsp,
+	uint_t			*partnop,
+	md_error_t		*ep
 )
 {
 	int		nparts;
@@ -1659,7 +1855,7 @@
 	mdvtoc_t	*vtocp;
 
 	/* metadevice */
-	if (is_metaname(rname)) {
+	if (uname_type == META_DEVICE) {
 		dnp->type = MDT_META;
 		nparts = 1;
 		partno = 0;
@@ -1713,7 +1909,7 @@
 
 	mdclrerror(ep);
 	nparts = V_NUMPAR;
-	if (uname2sliceno(rname, &partno, ep) < 0) {
+	if (uname2sliceno(rname, uname_type, &partno, ep) < 0) {
 		mdclrerror(ep);
 		partno = 0;
 	}
@@ -1925,17 +2121,18 @@
 
 static mdname_t *
 setup_slice(
-	mdsetname_t	*sp,
-	mddrivename_t	*dnp,
-	char		*uname,
-	char		*rname,
-	char		*dname,
-	uint_t		partno,
-	md_error_t	*ep
+	mdsetname_t		*sp,
+	meta_device_type_t	uname_type,
+	mddrivename_t		*dnp,
+	char			*uname,
+	char			*rname,
+	char			*dname,
+	uint_t			partno,
+	md_error_t		*ep
 )
 {
-	char		*srname = NULL;
-	mdname_t	*np;
+	char			*srname = NULL;
+	mdname_t		*np;
 
 	/* must have a set */
 	assert(sp != NULL);
@@ -1946,7 +2143,7 @@
 
 	if (rname)
 		srname = rname;
-	else if (is_metaname(dname))
+	else if (uname_type == META_DEVICE)
 		srname = dname;
 	else {
 		char	onmb[BUFSIZ+1];
@@ -2072,9 +2269,8 @@
 	}
 	fastnmlp = NULL;
 }
-
 static char *
-getrname_fast(char *unm, md_error_t *ep)
+getrname_fast(char *unm, meta_device_type_t uname_type, md_error_t *ep)
 {
 	uint_t			d = 0;
 	int			l = 0;
@@ -2084,36 +2280,62 @@
 	char			*p;
 	size_t			len;
 
-	if (is_metaname(unm)) {
-		/* without set */
-		if (sscanf(unm, "d%u%n", &d, &l) == 1 && cl == l) {
-			rnm = Zalloc(14 + cl + 1);
-			(void) sprintf(rnm, "/dev/md/rdsk/d%u", d);
+	if (uname_type == META_DEVICE) {
+		/* fully qualified  - local set */
+		if (((sscanf(unm, "/dev/md/dsk/%" VAL2STR(BUFSIZ) "s%n",
+				onmb, &len) == 1) && (cl == len)) ||
+		    ((sscanf(unm, "/dev/md/rdsk/%" VAL2STR(BUFSIZ) "s%n",
+				onmb, &len) == 1) && (cl == len))) {
+			len = strlen("/dev/md/rdsk/") +	strlen(onmb) + 1;
+			rnm = Zalloc(len);
+			(void) snprintf(rnm, len, "/dev/md/rdsk/%s", onmb);
+			return (rnm);
+		}
+
+		/* fully qualified - setname specified */
+		if (((sscanf(unm, "/dev/md/%[^/]/dsk/%"
+				VAL2STR(BUFSIZ) "s%n",
+				snm, onmb, &len) == 2) && (cl == len)) ||
+		    ((sscanf(unm, "/dev/md/%[^/]/rdsk/%"
+				VAL2STR(BUFSIZ) "s%n",
+				snm, onmb, &len) == 2) && (cl == len))) {
+
+			len = strlen("/dev/md//rdsk/") + strlen(snm) +
+				strlen(onmb) + 1;
+			rnm = Zalloc(len);
+			(void) snprintf(rnm, len, "/dev/md/%s/rdsk/%s",
+			    snm, onmb);
 			return (rnm);
 		}
 
-		/* fully-qualified without set */
-		if ((sscanf(unm, "/dev/md/dsk/d%u%n", &d, &l) == 1 ||
-		    sscanf(unm, "/dev/md/rdsk/d%u%n", &d, &l) == 1) &&
-		    cl == l) {
-			rnm = Zalloc(14 + cl + 1);
-			(void) sprintf(rnm, "/dev/md/rdsk/d%u", d);
+		/* Fully qualified path - error */
+		if (unm[0] == '/') {
+			(void) mdsyserror(ep, EINVAL, unm);
+			return (NULL);
+		}
+
+		/* setname specified <setname>/<metadev> */
+		if (((sscanf(unm, "%[^/]/%" VAL2STR(BUFSIZ) "s%n",
+				snm, onmb, &len) == 2) && (cl == len))) {
+			/* Not <setname>/<metadev>  - error */
+			if (strchr(onmb, '/') != NULL) {
+				(void) mdsyserror(ep, EINVAL, unm);
+				return (NULL);
+			}
+
+			len = strlen("/dev/md//rdsk/") + strlen(snm) +
+				strlen(onmb) + 1;
+			rnm = Zalloc(len);
+			(void) snprintf(rnm, len, "/dev/md/%s/rdsk/%s",
+			    snm, onmb);
 			return (rnm);
 		}
 
-		/* with set */
-		if ((sscanf(unm,
-		    "%" VAL2STR(BUFSIZ) "[^/]/d%u%n", snm, &d, &l) == 2 ||
-		    sscanf(unm, "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/dsk/d%u%n",
-		    snm, &d, &l) == 2 ||
-		    sscanf(unm, "/dev/md/%" VAL2STR(BUFSIZ) "[^/]/rdsk/d%u%n",
-		    snm, &d, &l) == 2) && cl == l) {
-			len = 14 + cl + strlen(snm) + 1;
-			rnm = Zalloc(len);
-			(void) snprintf(rnm, len, "/dev/md/%s/rdsk/d%u",
-			    snm, d);
-			return (rnm);
-		}
+		/* Must be simple metaname/hsp pool name */
+		len = strlen("/dev/md/rdsk/") + strlen(unm) + 1;
+		rnm = Zalloc(len);
+		(void) snprintf(rnm, len, "/dev/md/rdsk/%s", unm);
+		return (rnm);
 	}
 
 	/* NOT Fully qualified path, done */
@@ -2161,9 +2383,10 @@
 
 static mdname_t *
 metainitfastname(
-	mdsetname_t	*sp,
-	char		*uname,
-	md_error_t	*ep
+	mdsetname_t		*sp,
+	char			*uname,
+	meta_device_type_t	uname_type,
+	md_error_t		*ep
 )
 {
 	uint_t			c = 0, t = 0, d = 0, s = 0;
@@ -2171,6 +2394,7 @@
 	mddrivename_t		*dnp;
 	mdname_t		*np;
 	mdnamelist_t		**fnlpp;
+	char			*cname;
 
 	for (fnlpp = &fastnmlp; (*fnlpp != NULL); fnlpp = &(*fnlpp)->next) {
 		np = (*fnlpp)->namep;
@@ -2187,27 +2411,10 @@
 
 
 	/* Metadevices */
-	if (is_metaname(uname)) {
-		char *p;
-		size_t len;
-
-		if ((p = strrchr(uname, '/')) != NULL)
-			++p;
-		else
-			p = uname;
-
-		if (metaislocalset(sp)) {
-			if (np->cname)
-				Free(np->cname);
-			np->cname = Strdup(p);
-		} else {
-			if (np->cname)
-				Free(np->cname);
-			len = strlen(sp->setname) + 1 + strlen(p) + 1;
-			np->cname = Zalloc(len);
-			(void) snprintf(np->cname, len, "%s/%s",
-			    sp->setname, p);
-		}
+	if (uname_type == META_DEVICE &&
+	    (cname = meta_canonicalize(sp, uname)) != NULL) {
+
+		np->cname = cname;
 		dnp->type = MDT_FAST_META;
 		goto done;
 	}
@@ -2252,7 +2459,7 @@
 	if ((dnp->cname = metadiskname(np->cname)) == NULL)
 		dnp->cname = Strdup(np->cname);
 
-	if ((np->rname = getrname_fast(uname, ep)) != NULL) {
+	if ((np->rname = getrname_fast(uname, uname_type, ep)) != NULL) {
 		if ((dnp->rname = metadiskname(np->rname)) == NULL)
 			dnp->rname = Strdup(np->rname);
 	} else {
@@ -2274,6 +2481,7 @@
 	mdsetname_t	**spp,
 	char		*uname,
 	int		fast,
+	meta_device_type_t	uname_type,
 	md_error_t	*ep
 )
 {
@@ -2289,17 +2497,20 @@
 	assert(uname != NULL);
 
 	/* check setname */
-	if ((cname = meta_name_getname(spp, uname, ep)) == NULL)
+	if ((cname = meta_name_getname(spp, uname, uname_type, ep)) == NULL)
 		return (NULL);
 
 	assert(*spp != NULL);
 	Free(cname);
 
 	/* get raw name (rname) of the slice and drive (dname) we have */
-	if ((rname = getrawnames(spp, uname, &dname, ep)) == NULL) {
+	if ((rname = getrawnames(spp, uname,
+				&dname, &uname_type, ep)) == NULL) {
 		return (NULL);
 	}
 
+	assert(uname_type != UNKNOWN);
+
 	/* look in cache first */
 	for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
 		dnp = (*tail)->drivenamep;
@@ -2311,7 +2522,7 @@
 			if (dname != NULL)
 				Free(dname);
 
-			if (uname2sliceno(uname, &partno, ep) < 0)
+			if (uname2sliceno(uname, uname_type, &partno, ep) < 0)
 				return (NULL);
 
 			return (metaslicename(dnp, partno, ep));
@@ -2326,7 +2537,7 @@
 		if (dname != NULL)
 			Free(dname);
 
-		return (metainitfastname(*spp, uname, ep));
+		return (metainitfastname(*spp, uname, uname_type, ep));
 	}
 
 	/* allocate new list element and drive */
@@ -2336,7 +2547,7 @@
 	metainitdrivename(dnp);
 
 	/* get parts info */
-	if (getparts(dnp, rname, dname, &nparts, &partno, ep) != 0)
+	if (getparts(dnp, rname, dname, uname_type, &nparts, &partno, ep) != 0)
 		goto out;
 
 	/*
@@ -2359,8 +2570,8 @@
 	}
 
 	/* setup name_t (or slice) wanted */
-	if ((np = setup_slice(*spp, dnp, uname, rname, dname, partno, ep))
-	    == NULL)
+	if ((np = setup_slice(*spp, uname_type, dnp, uname, rname,
+	    dname, partno, ep)) == NULL)
 		goto out;
 
 	/* canonical disk name */
@@ -2393,20 +2604,22 @@
 metaname(
 	mdsetname_t	**spp,
 	char		*uname,
+	meta_device_type_t	uname_type,
 	md_error_t	*ep
 )
 {
-	return (metaname_common(spp, uname, 0, ep));
+	return (metaname_common(spp, uname, 0, uname_type, ep));
 }
 
 mdname_t *
 metaname_fast(
 	mdsetname_t	**spp,
 	char		*uname,
+	meta_device_type_t	uname_type,
 	md_error_t	*ep
 )
 {
-	return (metaname_common(spp, uname, 1, ep));
+	return (metaname_common(spp, uname, 1, uname_type, ep));
 }
 
 /*
@@ -2414,15 +2627,14 @@
  */
 mddrivename_t *
 metadrivename(
-	mdsetname_t	**spp,
-	char		*uname,
-	md_error_t	*ep
+	mdsetname_t		**spp,
+	char			*uname,
+	md_error_t		*ep
 )
 {
 	char		*slicename;
 	mdname_t	*np;
 
-	char		*cname;
 	mddrivenamelist_t **tail;
 	mddrivename_t	*dnp;
 	char		*dname;
@@ -2430,21 +2642,13 @@
 	int		mplen;
 	size_t		len;
 
-	/* check setname, get comparison name */
 	assert(uname != NULL);
-	if ((cname = meta_name_getname(spp, uname, ep)) == NULL) {
+
+	if ((dname = metadiskname(uname)) == NULL) {
 		(void) mdsyserror(ep, ENOENT, uname);
 		return (NULL);
 	}
 
-	assert(*spp != NULL);
-
-	if ((dname = metadiskname(cname)) == NULL) {
-		(void) mdsyserror(ep, ENOENT, cname);
-		Free(cname);
-		return (NULL);
-	}
-
 	/* look in cache first */
 	for (tail = &drivelistp; (*tail != NULL); tail = &(*tail)->next) {
 		dnp = (*tail)->drivenamep;
@@ -2452,11 +2656,11 @@
 		    (strcmp(dnp->cname, dname) == 0)) ||
 		    (dnp->rname != NULL &&
 		    (strcmp(dnp->rname, dname) == 0))) {
-			Free(cname);
 			Free(dname);
 			return (dnp);
 		}
 	}
+	Free(dname);
 
 	/* Check each possible slice name based on MD_MAX_PARTS. */
 
@@ -2473,14 +2677,12 @@
 	/* Check for each slice in turn until we find one */
 	for (np = NULL, i = 0; ((np == NULL) && (i < MD_MAX_PARTS)); ++i) {
 		(void) snprintf(slicename, len, "%ss%d", uname, i);
-		np = metaname(spp, slicename, ep);
+		np = metaname(spp, slicename, LOGICAL_DEVICE, ep);
 	}
 	Free(slicename);
 
 	if (np == NULL) {
-		char	*dname;
-
-		if ((mdissyserror(ep, ENOENT)) &&
+		if ((mdiserror(ep, MDE_UNIT_NOT_FOUND)) &&
 		    ((dname = metadiskname(uname)) != NULL)) {
 			Free(dname);
 			(void) mderror(ep, MDE_NOT_DRIVENAME, uname);
@@ -2491,6 +2693,58 @@
 }
 
 /*
+ * FUNCTION:	metaslicename_type()
+ * INPUT:	dnp	- the drivename structure
+ *		sliceno	- the slice on the drive to return
+ *		type - LOGICAL_DEVICE or META_DEVICE
+ * OUTPUT:	ep	- return error pointer
+ * RETURNS:	mdname_t- pointer the the slice name structure
+ * PURPOSE:	interface to the parts struct in the drive name struct
+ *		Since there is no guarantee that the slice name
+ *		structures are populated users should call this
+ *		function rather than accessing the structure directly
+ *		since it will populate the structure values if they
+ *		haven't already been populated before returning.
+ */
+mdname_t *
+metaslicename_type(
+	mddrivename_t		*dnp,
+	uint_t			sliceno,
+	meta_device_type_t	uname_type,
+	md_error_t		*ep
+)
+{
+	mdsetname_t	*sp = NULL;
+	char		*namep = NULL;
+	mdname_t	*np;
+
+	assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META);
+
+	if (sliceno >= dnp->parts.parts_len) {
+		(void) mderror(ep, MDE_NOSLICE, dnp->cname);
+		return (NULL);
+	}
+
+	np = &dnp->parts.parts_val[sliceno];
+
+	/* check to see if the struct is already populated */
+	if (np->cname) {
+		return (np);
+	}
+
+	if ((namep = meta_name_getname(&sp, dnp->cname,
+					uname_type, ep)) == NULL)
+		return (NULL);
+
+	np = setup_slice(sp, uname_type, dnp, NULL, NULL, dnp->rname,
+	    sliceno, ep);
+
+	Free(namep);
+
+	return (np);
+}
+
+/*
  * FUNCTION:	metaslicename()
  * INPUT:	dnp	- the drivename structure
  *		sliceno	- the slice on the drive to return
@@ -2510,32 +2764,7 @@
 	md_error_t	*ep
 )
 {
-	mdsetname_t	*sp = NULL;
-	char		*namep = NULL;
-	mdname_t	*np;
-
-	assert(dnp->type != MDT_FAST_COMP && dnp->type != MDT_FAST_META);
-
-	if (sliceno >= dnp->parts.parts_len) {
-		(void) mderror(ep, MDE_NOSLICE, dnp->cname);
-		return (NULL);
-	}
-
-	np = &dnp->parts.parts_val[sliceno];
-
-	/* check to see if the struct is already populated */
-	if (np->cname) {
-		return (np);
-	}
-
-	if ((namep = meta_name_getname(&sp, dnp->cname, ep)) == NULL)
-		return (NULL);
-
-	np = setup_slice(sp, dnp, NULL, NULL, dnp->rname, sliceno, ep);
-
-	Free(namep);
-
-	return (np);
+	return (metaslicename_type(dnp, sliceno, LOGICAL_DEVICE, ep));
 }
 
 /*
@@ -2553,7 +2782,8 @@
 	mdsetname_t	*sp = NULL;
 	char		*uname;
 	mdname_t	*np;
-	size_t		len;
+	md_dev64_t	dev;
+	mdkey_t		key;
 
 	/* check set first */
 	if (spp == NULL)
@@ -2563,23 +2793,21 @@
 	assert(*spp != NULL);
 	sp = *spp;
 
-	/* build corresponding device name */
-	if (metaislocalset(sp)) {
-		uname = Malloc(20);
-		(void) sprintf(uname, "d%lu", MD_MIN2UNIT(mnum));
-	} else {
-		len = strlen(sp->setname) + 1 + 20;
-		uname = Malloc(len);
-		(void) snprintf(uname, len, "%s/d%lu", sp->setname,
-		    MD_MIN2UNIT(mnum));
-	}
+	/* get corresponding device name */
+	dev = metamakedev(mnum);
+	if ((uname = meta_getnmentbydev(sp->setno, MD_SIDEWILD, dev,
+	    NULL, NULL, &key, ep)) == NULL)
+		return (NULL);
 
 	/* setup name */
 	if (fast) {
-		np = metaname_fast(spp, uname, ep);
-		np->dev = metamakedev(mnum);
+		np = metaname_fast(spp, uname, META_DEVICE, ep);
+		if (np) {
+			np->dev = dev;
+			np->key = key;
+		}
 	} else
-		np = metaname(spp, uname, ep);
+		np = metaname(spp, uname, META_DEVICE, ep);
 
 	Free(uname);
 	return (np);
@@ -2590,15 +2818,19 @@
  */
 char *
 get_mdname(
+	mdsetname_t	*sp,
 	minor_t		mnum
 )
 {
 	mdname_t	*np;
 	md_error_t	status = mdnullerror;
+	mdsetname_t	**spp = NULL;
+
+	if (sp != NULL)
+		spp = &sp;
 
 	/* get name */
-	if ((np = metamnumname(NULL, mnum, 0, &status)) == NULL) {
-		mdclrerror(&status);
+	if ((np = metamnumname(spp, mnum, 0, &status)) == NULL) {
 		return (NULL);
 	}
 	assert(meta_getminor(np->dev) == mnum);
@@ -2694,6 +2926,7 @@
 	mdnamelist_t	**nlpp,
 	int		argc,
 	char		*argv[],
+	meta_device_type_t	type,
 	md_error_t	*ep
 )
 {
@@ -2703,7 +2936,8 @@
 	for (*nlpp = NULL; (argc > 0); ++count, --argc, ++argv) {
 		mdnamelist_t	*nlp = Zalloc(sizeof (*nlp));
 
-		if ((nlp->namep = metaname(spp, argv[0], ep)) == NULL) {
+		if ((nlp->namep = metaname(spp, argv[0],
+		    type, ep)) == NULL) {
 			metafreenamelist(*nlpp);
 			*nlpp = NULL;
 			return (-1);
@@ -2820,28 +3054,82 @@
 gethspname(
 	mdsetname_t	**spp,
 	char		*uname,
-	hsp_t		*hspp,
 	md_error_t	*ep
 )
 {
-	char		*sname = NULL;
+	char		*cname = NULL;
+
+	cname = meta_canonicalize(*spp, uname);
+	/* if it is not a meta/hsp name then flag an error */
+	if (cname == NULL) {
+		(void) mdsyserror(ep, ENOENT, uname);
+		return (NULL);
+	}
+	return (cname);
+}
+
+/*
+ * set up a hotspare pool name structure using both the name
+ * and the self id
+ */
+static mdhspname_t *
+metahspname_hsp(
+	mdsetname_t	**spp,
+	char		*uname,
+	hsp_t		hsp,
+	md_error_t	*ep
+)
+{
+	char		*cname;
+	mdhspnamelist_t	**tail;
+	mdhspname_t	*hspnp;
 
 	/* check setname */
 	assert(uname != NULL);
-	if (parse_hsp(uname, &sname, hspp) != 0) {
-		(void) mdsyserror(ep, ENOENT, uname);
+	if ((cname = gethspname(spp, uname, ep)) == NULL)
 		return (NULL);
+	assert(*spp != NULL);
+
+	/* look in cache first */
+	for (tail = &hsplistp; (*tail != NULL); tail = &(*tail)->next) {
+		hspnp = (*tail)->hspnamep;
+		if (strcmp(hspnp->hspname, cname) == 0) {
+			Free(cname);
+			/* if the hsp value has not been set then set it now */
+			if (hspnp->hsp == MD_HSP_NONE)
+				hspnp->hsp = hsp;
+			return (hspnp);
+		}
 	}
-	if (chksetname(spp, sname, ep) != 0) {
-		if (sname != NULL)
-			Free(sname);
-		return (NULL);
+
+	/* if the hsp number isn't specified then attempt to get it */
+	if (hsp == MD_HSP_NONE && (hsp = meta_gethspnmentbyname((*spp)->setno,
+	    MD_SIDEWILD, cname, ep)) == MD_HSP_NONE) {
+		if (! mdisok(ep)) {
+			/*
+			 * If the error is ENOENT, then we will continue on,
+			 * because the device does not yet exist.
+			 * For other types of errors, however, we'll bail out.
+			 */
+			if (! mdissyserror(ep, ENOENT)) {
+				Free(cname);
+				return (NULL);
+			}
+			mdclrerror(ep);
+		}
 	}
-	if (sname != NULL)
-		Free(sname);
-
-	/* return comparison name */
-	return (canon_hsp((*spp)->setname, *hspp));
+
+	/* allocate new list element and hspname */
+	*tail = Zalloc(sizeof (**tail));
+	hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp));
+	metainithspname(hspnp);
+
+	/* save hspname and number */
+	hspnp->hspname = cname;
+	hspnp->hsp = hsp;
+
+	/* success */
+	return (hspnp);
 }
 
 /*
@@ -2854,51 +3142,11 @@
 	md_error_t	*ep
 )
 {
-	char		*cname;
-	hsp_t		hsp;
-	mdhspnamelist_t	**tail;
-	mdhspname_t	*hspnp;
-
-	/* check setname */
-	assert(uname != NULL);
-	if ((cname = gethspname(spp, uname, &hsp, ep)) == NULL)
-		return (NULL);
-	assert(*spp != NULL);
-
-	/* look in cache first */
-	for (tail = &hsplistp; (*tail != NULL); tail = &(*tail)->next) {
-		hspnp = (*tail)->hspnamep;
-		if (strcmp(hspnp->hspname, cname) == 0) {
-			Free(cname);
-			return (hspnp);
-		}
-	}
-
-	/* allocate new list element and hspname */
-	*tail = Zalloc(sizeof (**tail));
-	hspnp = (*tail)->hspnamep = Zalloc(sizeof (*hspnp));
-	metainithspname(hspnp);
-
-	/* save hspname and number */
-	hspnp->hspname = cname;
-	hspnp->hsp = MAKE_HSP_ID((*spp)->setno, hsp);
-
-	/* success */
-	return (hspnp);
-
-	/* cleanup, return error */
-out:
-	metafreehspname(hspnp);
-	Free(hspnp);
-	Free(*tail);
-	*tail = NULL;
-	return (NULL);
-
-
+	return (metahspname_hsp(spp, uname, MD_HSP_NONE, ep));
 }
 
 /*
- * set up hotspare pool name from id
+ * set up hotspare pool name from key
  */
 mdhspname_t *
 metahsphspname(
@@ -2911,7 +3159,6 @@
 	mdsetname_t	*sp = NULL;
 	char		*uname;
 	mdhspname_t	*hspnp;
-	size_t		len;
 
 	/* check set first */
 	if (spp == NULL)
@@ -2921,19 +3168,13 @@
 	assert(*spp != NULL);
 	sp = *spp;
 
-	/* build corresponding hotspare pool name */
-	if (metaislocalset(sp)) {
-		uname = Malloc(20);
-		(void) sprintf(uname, "hsp%03u", HSP_ID(hsp));
-	} else {
-		len = strlen(sp->setname) + 1 + 20;
-		uname = Malloc(len);
-		(void) snprintf(uname, len, "%s/hsp%03lu", sp->setname,
-		    HSP_ID(hsp));
-	}
+	/* get corresponding hotspare pool name */
+	if ((uname = meta_gethspnmentbyid(sp->setno,
+			MD_SIDEWILD, hsp, ep)) == NULL)
+		return (NULL);
 
 	/* setup name */
-	hspnp = metahspname(spp, uname, ep);
+	hspnp = metahspname_hsp(spp, uname, hsp, ep);
 	Free(uname);
 	return (hspnp);
 }
@@ -2942,13 +3183,17 @@
  * return hotspare pool name
  */
 char *
-get_hspname(hsp_t hsp)
+get_hspname(mdsetname_t *sp, hsp_t hsp)
 {
 	mdhspname_t	*hspnp;
 	md_error_t	status = mdnullerror;
+	mdsetname_t	**spp = NULL;
+
+	if (sp != NULL)
+		spp = &sp;
 
 	/* get name */
-	if ((hspnp = metahsphspname(NULL, hsp, &status)) == NULL) {
+	if ((hspnp = metahsphspname(spp, hsp, &status)) == NULL) {
 		mdclrerror(&status);
 		return (NULL);
 	}
@@ -3050,7 +3295,7 @@
 	    dev, NULL, NULL, &key, ep)) == NULL) {
 		return (NULL);
 	}
-	namep = metaname_fast(spp, device_name, ep);
+	namep = metaname_fast(spp, device_name, LOGICAL_DEVICE, ep);
 	if (namep != NULL)
 		namep->key = key;
 
@@ -3136,9 +3381,9 @@
 		return (NULL);
 	}
 	if (fast)
-		namep = metaname_fast(spp, device_name, ep);
+		namep = metaname_fast(spp, device_name, UNKNOWN, ep);
 	else
-		namep = metaname(spp, device_name, ep);
+		namep = metaname(spp, device_name, UNKNOWN, ep);
 
 	assert(dev != NODEV64);
 	if (namep)
@@ -3148,6 +3393,18 @@
 }
 
 /*
+ * completely flush metadev/hsp caches
+ */
+void
+metaflushmetanames()
+{
+	metaflushhspnames();
+	metaflushdrivenames();
+	metaflushfastnames();
+	metaflushstatcache();
+}
+
+/*
  * completely flush the caches
  */
 void
--- a/usr/src/lib/lvm/libmeta/common/meta_namespace.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_namespace.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -84,6 +83,93 @@
 }
 
 /*
+ * Ask the driver for the hsp name, driver name, and minor number;
+ * which has been stored in the metadevice state database
+ * (on behalf of the utilities).
+ * (by key)
+ */
+char *
+meta_gethspnmentbyid(
+	set_t		setno,
+	side_t		sideno,
+	hsp_t		hspid,
+	md_error_t	*ep
+)
+{
+	struct mdhspnm_params	nm;
+	char			*device_name;
+
+	device_name = Malloc(MAXPATHLEN);
+	device_name[0] = '\0';
+
+	(void) memset(&nm, '\0', sizeof (nm));
+	nm.setno = setno;
+	nm.side = sideno;
+	nm.hspid = hspid;
+	nm.ret_hspid = MD_HSPID_WILD;
+	nm.hspname_len = MAXPATHLEN;
+	nm.hspname = (uint64_t)device_name;
+
+	if (metaioctl(MD_IOCGET_HSP_NM, &nm, &nm.mde, NULL) != 0) {
+		(void) mdstealerror(ep, &nm.mde);
+		Free(device_name);
+		return (NULL);
+	}
+
+	return (device_name);
+}
+
+/*
+ * Ask the driver for the hsp_self_id;
+ * which has been stored in the metadevice state database
+ * (on behalf of the utilities).
+ * (by hsp name)
+ */
+hsp_t
+meta_gethspnmentbyname(
+	set_t		setno,
+	side_t		sideno,
+	char		*hspname,
+	md_error_t	*ep
+)
+{
+	struct mdhspnm_params	nm;
+	char			*device_name;
+
+	/* must have a hsp name */
+	assert(hspname != NULL);
+
+	device_name = Malloc(MAXPATHLEN);
+	(void) strcpy(device_name, hspname);
+
+	(void) memset(&nm, '\0', sizeof (nm));
+	nm.setno = setno;
+	nm.side = sideno;
+	nm.hspid = MD_HSPID_WILD;
+	nm.ret_hspid = MD_HSPID_WILD;
+	nm.hspname_len = strlen(device_name) + 1;
+	nm.hspname = (uint64_t)device_name;
+
+	/*
+	 * The ioctl expects the a hsp name and return its hsp_self_id.
+	 */
+	if (metaioctl(MD_IOCGET_HSP_NM, &nm, &nm.mde, NULL) != 0) {
+		(void) mdstealerror(ep, &nm.mde);
+		Free(device_name);
+		return (MD_HSP_NONE);
+	}
+
+	if (nm.ret_hspid == MD_HSPID_WILD) {
+		Free(device_name);
+		return (MD_HSP_NONE);
+	}
+
+	Free(device_name);
+	return (nm.ret_hspid);
+}
+
+
+/*
  * Ask the driver for the minor name which has been stored in the
  * metadevice state database.
  * (by key)
@@ -277,6 +363,24 @@
 		return (NULL);
 	}
 
+	/*
+	 * With the friendly name work, each metadevice will have
+	 * an NM entry. However, to allow backward compatibility,
+	 * systems upgraded to a friendly name release won't have
+	 * NM entries for the pre-existing top level metadevices. This
+	 * implementation allows users to downgrade to a pre-friendly
+	 * name release since the configuration information (mddb) is
+	 * not modified.
+	 *
+	 * meta_getnmentbydev is called to get nm entry for all metadevices
+	 * and expects the minor and major number and returns a key and
+	 * name. For upgraded systems with pre-existing metadevices,
+	 * the only returning value will be the name since there's no nm
+	 * entry for pre-friendly name top level metadevices. So a return
+	 * key for the device will not be available and will be NULL.
+	 * Thus, the caller is responsible for making sure the returned key
+	 * is valid, not NULL.
+	 */
 	if (drvnm != NULL)
 		*drvnm = Strdup(nm.drvnm);
 	if (mnum != NULL)
@@ -599,3 +703,172 @@
 		mdclrerror(&status);
 	return (rval);
 }
+
+
+/*
+ * This routine when is called will store the metadevice name
+ * when it is first created
+ */
+mdkey_t
+add_self_name(
+	mdsetname_t	*sp,
+	char 		*uname,
+	md_mkdev_params_t	*params,
+	md_error_t	*ep
+)
+{
+	char		*p, *devname;
+	side_t		myside, side;
+	mdkey_t		key;
+	md_set_desc	*sd;
+	int		len;
+	char		*drvname = params->md_driver.md_drivername;
+	minor_t		minor = MD_MKMIN(sp->setno, params->un);
+	md_mnnode_desc	*mnside;
+
+	p = strrchr(uname, '/');
+	p = (p == NULL? uname : ++p);
+
+	/*
+	 * The valid qualified name
+	 */
+	if (metaislocalset(sp)) {
+	    len = strlen(p) + strlen("/dev/md/dsk/") + 1;
+	    devname = Malloc(len);
+	    (void) strcpy(devname, "/dev/md/dsk/");
+	    (void) strcat(devname, p);
+	} else {
+	    len = strlen(sp->setname) + strlen(p) +
+		strlen("/dev/md//dsk/") + 1;
+	    devname = Malloc(len);
+	    (void) snprintf(devname, len, "/dev/md/%s/dsk/%s",
+			sp->setname, p);
+	}
+
+	/*
+	 * Add self to the namespace
+	 */
+	if ((myside = getmyside(sp, ep)) == MD_SIDEWILD) {
+		Free(devname);
+		return (-1);
+	}
+
+	if (metaislocalset(sp)) {
+	    if ((key = add_name(sp, myside, MD_KEYWILD, drvname,
+		minor, devname, ep)) == MD_KEYBAD) {
+			Free(devname);
+			return (-1);
+	    }
+	} else {
+		/*
+		 * Add myside first and use the returned key to add other sides
+		 */
+		if ((key = add_name(sp, myside, MD_KEYWILD, drvname,
+		    minor, devname, ep)) == MD_KEYBAD) {
+			Free(devname);
+			return (-1);
+		}
+
+		/*
+		 * Add for all other sides
+		 */
+		if ((sd = metaget_setdesc(sp, ep)) == NULL) {
+			Free(devname);
+			return (-1);
+		}
+
+		if (MD_MNSET_DESC(sd)) {
+		    for (mnside = sd->sd_nodelist; mnside != NULL;
+			mnside = mnside->nd_next) {
+			if (mnside->nd_nodeid == myside)
+				continue;
+			if (add_name(sp, mnside->nd_nodeid, key, drvname,
+			    minor, devname, ep) == -1) {
+				Free(devname);
+				return (-1);
+			}
+		    }
+		} else {
+		    for (side = 0; side < MD_MAXSIDES; side++) {
+			if (sd->sd_nodes[side][0] == '\0')
+				continue;
+			if (side == myside)
+				continue;
+			if (add_name(sp, side, key, drvname, minor, devname,
+			    ep) == -1) {
+				Free(devname);
+				return (-1);
+			}
+		    }
+		}
+	}
+
+	Free(devname);
+	return (key);
+}
+
+
+/*
+ * This routine when is called will remove the metadevice name
+ * from the namespace and it is the last thing to do in the
+ * metaclear operation
+ */
+int
+del_self_name(
+	mdsetname_t	*sp,
+	mdkey_t		key,
+	md_error_t	*ep
+)
+{
+	side_t		myside;
+	int		rval = 0;
+	side_t		side;
+	md_set_desc	*sd;
+	md_mnnode_desc	*mnside;
+
+	assert(key != MD_KEYBAD);
+
+	if ((myside = getmyside(sp, ep)) == MD_SIDEWILD)
+		return (-1);
+
+	if (metaislocalset(sp)) {
+		rval = del_name(sp, myside, key, ep);
+	} else {
+		/*
+		 * Remove all other sides first
+		 */
+		if ((sd = metaget_setdesc(sp, ep)) == NULL) {
+			return (-1);
+		}
+
+		if (MD_MNSET_DESC(sd)) {
+		    for (mnside = sd->sd_nodelist; mnside != NULL;
+			mnside = mnside->nd_next) {
+			if (mnside->nd_nodeid == myside)
+				continue;
+			if ((rval = del_name(sp, mnside->nd_nodeid, key,
+			    ep)) == -1) {
+				goto out;
+			}
+		    }
+		} else {
+		    for (side = 0; side < MD_MAXSIDES; side++) {
+			if (sd->sd_nodes[side][0] == '\0')
+				continue;
+			if (side == myside)
+				continue;
+			if ((rval = del_name(sp, side, key, ep)) == -1) {
+				goto out;
+			}
+		    }
+		}
+
+		/*
+		 * del myside
+		 */
+		rval = del_name(sp, myside, key, ep);
+	}
+
+out:
+	return (rval);
+}
--- a/usr/src/lib/lvm/libmeta/common/meta_raid.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_raid.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -393,7 +392,14 @@
 
 
 	if (options & PRINT_LARGEDEVICES) {
-		if (raidp->common.revision != MD_64BIT_META_DEV) {
+		if ((raidp->common.revision & MD_64BIT_META_DEV) == 0) {
+			rval = 0;
+			goto out;
+		}
+	}
+
+	if (options & PRINT_FN) {
+		if ((raidp->common.revision & MD_FN_META_DEV) == 0) {
 			rval = 0;
 			goto out;
 		}
@@ -403,28 +409,14 @@
 	if (fprintf(fp, "%s -r", raidp->common.namep->cname) == EOF)
 		goto out;
 
-	/* print columns */
+	/*
+	 * Print columns. Always print the full path.
+	 */
 	for (col = 0; (col < raidp->cols.cols_len); ++col) {
 		md_raidcol_t	*mdrcp = &raidp->cols.cols_val[col];
 
-		/* print column */
-		/*
-		 * If the path is our standard /dev/rdsk or /dev/md/rdsk
-		 * then just print out the cxtxdxsx or the dx, metainit
-		 * will assume the default, otherwise we need the full
-		 * pathname to make sure this works as we intend.
-		 */
-		if ((strstr(mdrcp->colnamep->rname, "/dev/rdsk") == NULL) &&
-		    (strstr(mdrcp->colnamep->rname, "/dev/md/rdsk") == NULL) &&
-		    (strstr(mdrcp->colnamep->rname, "/dev/td/") == NULL)) {
-			/* not standard path, print full pathname */
-			if (fprintf(fp, " %s", mdrcp->colnamep->rname) == EOF)
-				goto out;
-		} else {
-			/* standard path so print ctd or d number */
-			if (fprintf(fp, " %s", mdrcp->colnamep->cname) == EOF)
-				goto out;
-		}
+		if (fprintf(fp, " %s", mdrcp->colnamep->rname) == EOF)
+			goto out;
 	}
 
 	if (fprintf(fp, " -k") == EOF)
@@ -806,7 +798,14 @@
 	uint_t		tstate = 0;
 
 	if (options & PRINT_LARGEDEVICES) {
-		if (raidp->common.revision != MD_64BIT_META_DEV) {
+		if ((raidp->common.revision & MD_64BIT_META_DEV) == 0) {
+			rval = 0;
+			goto out;
+		}
+	}
+
+	if (options & PRINT_FN) {
+		if ((raidp->common.revision & MD_FN_META_DEV) == 0) {
 			rval = 0;
 			goto out;
 		}
@@ -1390,10 +1389,10 @@
 
 	if (create_flag == MD_CRO_32BIT) {
 		mgp.options = MD_CRO_32BIT;
-		new_mr->c.un_revision = MD_32BIT_META_DEV;
+		new_mr->c.un_revision &= ~MD_64BIT_META_DEV;
 	} else {
 		mgp.options = MD_CRO_64BIT;
-		new_mr->c.un_revision = MD_64BIT_META_DEV;
+		new_mr->c.un_revision |= MD_64BIT_META_DEV;
 	}
 	if (metaioctl(MD_IOCGROW, &mgp, &mgp.mde, NULL) != 0) {
 		(void) mdstealerror(ep, &mgp.mde);
@@ -1583,7 +1582,6 @@
 	md_dev64_t		old_dev, new_dev;
 	diskaddr_t		new_start_blk, new_end_blk;
 	int			rebind;
-	mr_unit_t		*mr;
 	char			*new_devidp = NULL;
 	md_error_t		xep = mdnullerror;
 	int			ret;
@@ -1629,67 +1627,53 @@
 	params.old_dev = old_dev;
 	params.cmd = force ? FORCE_REPLACE_COMP : REPLACE_COMP;
 
-	if (options & MDCMD_CLUSTER_REPLACE) {
-		if ((mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL)
-			return (NULL);
-		Free(mr);
-		params.options = MDIOCTL_NO_RESYNC_RAID;
-		params.number_blks = metagetsize(newnp, ep);
-		if ((metagetlabel(newnp, ep) == MD_DISKADDR_ERROR) ||
-		    (metagetlabel(newnp, ep) == 0))
-			params.has_label = 0;
-		else
-			params.has_label = 1;
-		params.start_blk = metagetstart(sp, newnp, ep);
+	if ((strcmp(oldnp->rname, newnp->rname) == 0) &&
+	    (old_dev != new_dev)) {
+		rebind = 1;
 	} else {
-		if ((strcmp(oldnp->rname, newnp->rname) == 0) &&
-		    (old_dev != new_dev)) {
-			rebind = 1;
-		} else {
-			rebind = 0;
-		}
-		if (rebind) {
-			newnp->dev = new_dev;
-			newnp->start_blk = new_start_blk;
-			newnp->end_blk = new_end_blk;
-		}
+		rebind = 0;
+	}
+	if (rebind) {
+		newnp->dev = new_dev;
+		newnp->start_blk = new_start_blk;
+		newnp->end_blk = new_end_blk;
+	}
+
+	/*
+	 * Save a copy of the devid associated with the new disk, the
+	 * reason is that the checks for the column (meta_check_column)
+	 * via validate_new_raid(), could cause the disk's devid to be
+	 * changed to that of the devid that is currently stored in the
+	 * replica namespace for the disk in question. This devid could
+	 * be stale if we are replacing the disk. The actual function
+	 * that overwrites the devid is dr2drivedesc().
+	 */
 
-		/*
-		 * Save a copy of the devid associated with the new disk, the
-		 * reason is that the checks for the column (meta_check_column)
-		 * via validate_new_raid(), could cause the disk's devid to be
-		 * changed to that of the devid that is currently stored in the
-		 * replica namespace for the disk in question. This devid could
-		 * be stale if we are replacing the disk. The actual function
-		 * that overwrites the devid is dr2drivedesc().
-		 */
+	/* don't setup new_devid if no devid's or MN diskset */
+	if (newnp->drivenamep->devid != NULL)
+		new_devidp = Strdup(newnp->drivenamep->devid);
 
-		/* don't setup new_devid if no devid's or MN diskset */
-		if (newnp->drivenamep->devid != NULL)
-			new_devidp = Strdup(newnp->drivenamep->devid);
+	if (!metaislocalset(sp)) {
+		if ((sd = metaget_setdesc(sp, ep)) == NULL)
+			return (-1);
+		if (MD_MNSET_DESC(sd))
+			new_devidp = NULL;
+	}
 
-		if (!metaislocalset(sp)) {
-			if ((sd = metaget_setdesc(sp, ep)) == NULL)
-				return (-1);
-			if (MD_MNSET_DESC(sd))
-				new_devidp = NULL;
-		}
+	/* check out new (sets up start_blk, has_label, number_blks) */
+	if (validate_new_raid(sp, raidnp, newnp, &params, rebind,
+	    ep) != 0) {
+		Free(new_devidp);
+		return (-1);
+	}
 
-		/* check out new (sets up start_blk, has_label, number_blks) */
-		if (validate_new_raid(sp, raidnp, newnp, &params, rebind,
-		    ep) != 0) {
-			Free(new_devidp);
-			return (-1);
-		}
-
-		/*
-		 * Copy back the saved devid.
-		 */
-		Free(newnp->drivenamep->devid);
-		if (new_devidp) {
-			newnp->drivenamep->devid = Strdup(new_devidp);
-			Free(new_devidp);
-		}
+	/*
+	 * Copy back the saved devid.
+	 */
+	Free(newnp->drivenamep->devid);
+	if (new_devidp) {
+		newnp->drivenamep->devid = Strdup(new_devidp);
+		Free(new_devidp);
 	}
 
 	/* store name in namespace, allocate new key */
@@ -2106,7 +2090,7 @@
 		 * Otherwise it's of type raid_pwhdr32_od_t and has to
 		 * be converted.
 		 */
-		if (mr->c.un_revision == MD_64BIT_META_DEV) {
+		if (mr->c.un_revision & MD_64BIT_META_DEV) {
 			rpw = (raid_pwhdr_t *)buf;
 		} else {
 			RAID_CONVERT_RPW((raid_pwhdr32_od_t *)buf, rpw);
@@ -2386,10 +2370,10 @@
 	(void) memset(&set_params, 0, sizeof (set_params));
 	/* did the user tell us to generate a large device? */
 	if (create_flag == MD_CRO_64BIT) {
-		mr->c.un_revision = MD_64BIT_META_DEV;
+		mr->c.un_revision |= MD_64BIT_META_DEV;
 		set_params.options = MD_CRO_64BIT;
 	} else {
-		mr->c.un_revision = MD_32BIT_META_DEV;
+		mr->c.un_revision &= ~MD_64BIT_META_DEV;
 		set_params.options = MD_CRO_32BIT;
 	}
 	set_params.mnum = MD_SID(mr);
@@ -2444,7 +2428,7 @@
 	assert(argc > 0);
 	if (argc < 1)
 		goto syntax;
-	if ((raidnp = metaname(spp, uname, ep)) == NULL)
+	if ((raidnp = metaname(spp, uname, META_DEVICE, ep)) == NULL)
 		goto out;
 	assert(*spp != NULL);
 
@@ -2518,7 +2502,7 @@
 		mdname_t	*colnp;
 
 		/* parse column name */
-		if ((colnp = metaname(spp, argv[0], ep)) == NULL)
+		if ((colnp = metaname(spp, argv[0], UNKNOWN, ep)) == NULL)
 			goto out;
 		/* check for soft partitions */
 		if (meta_sp_issp(*spp, colnp, ep) != 0) {
--- a/usr/src/lib/lvm/libmeta/common/meta_rename.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_rename.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -101,6 +100,19 @@
 	md_rename_t	txn;
 	int		from_add_flag = 0;
 	int		to_add_flag = 0;
+	int		from_is_fn, to_is_fn;
+	bool_t		from_has_parent, to_has_parent;
+
+	/*
+	 * What types of devices we have here?
+	 * For MDRNOP_RENAME to_mdp is NULL
+	 */
+	from_is_fn = (from_mdp->revision & MD_FN_META_DEV);
+	from_has_parent = MD_HAS_PARENT(from_mdp->parent);
+	if (to_mdp) {
+		to_is_fn = (to_mdp->revision & MD_FN_META_DEV);
+		to_has_parent = MD_HAS_PARENT(to_mdp->parent);
+	}
 
 	/*
 	 * If the device exists a key may already exist so need to find it
@@ -119,13 +131,18 @@
 
 	if ((from_np->key == MD_KEYWILD) || (from_np->key == MD_KEYBAD)) {
 		/*
-		 * If from does not have key and it is a component device
-		 * then something really goes wrong
+		 * If we are top and revision indicates that we
+		 * should have key but we don't then something
+		 * really goes wrong
 		 */
-		assert(!MD_HAS_PARENT(from_mdp->parent));
+		assert(!from_has_parent && !from_is_fn);
+
+		if (from_has_parent || from_is_fn) {
+			return (-1);
+		}
 
 		/*
-		 * So only add the entry if from is a top device
+		 * So only add the entry if necessary
 		 */
 		if (add_key_name(sp, from_np, NULL, ep) != 0) {
 			assert(!mdisok(ep));
@@ -145,13 +162,18 @@
 
 	if ((to_np->key == MD_KEYWILD) || (to_np->key == MD_KEYBAD)) {
 		/*
-		 * If to does not have key and is not a top device
-		 * then something really goes wrong
+		 * If we are top and revision indicates that we
+		 * should have key but we don't then something
+		 * really goes wrong
 		 */
-		assert(!MD_HAS_PARENT(to_mdp->parent));
+		assert(!to_has_parent && !to_is_fn);
+
+		if (to_has_parent || to_is_fn) {
+			return (-1);
+		}
 
 		/*
-		 * Add entry
+		 * So only add the entry if necessary
 		 */
 		if (add_key_name(sp, to_np, NULL, ep) != 0) {
 			assert(!mdisok(ep));
@@ -180,19 +202,41 @@
 	if (metaioctl(MD_IOCRENAME, &txn, &txn.mde, from_np->cname) != 0) {
 		if (from_add_flag) {
 			(void) del_key_name(sp, from_np, ep);
+			/*
+			 * Attempt removal of device node
+			 */
+			(void) metaioctl(MD_IOCREM_DEV, &txn.from.mnum,
+				ep, NULL);
 		}
 
 		if (op == MDRNOP_RENAME || to_add_flag) {
 			(void) del_key_name(sp, to_np, ep);
+			/*
+			 * Attempt removal of device node
+			 */
+			(void) metaioctl(MD_IOCREM_DEV, &txn.to.mnum,
+				ep, NULL);
 		}
+
 		return (mdstealerror(ep, &txn.mde));
 	}
 
 	/*
-	 * If top device
+	 * Since now the metadevice can be ref'd in the namespace
+	 * by self and by the top device so upon the successful
+	 * rename/xchange, we need to check the type and make
+	 * necessary adjustment for the device's n_cnt in the namespace
+	 * by calling add_key_name/del_key_name to do the tricks
 	 */
-	if (op == MDRNOP_RENAME && !MD_HAS_PARENT(from_mdp->parent)) {
-		(void) del_key_name(sp, to_np, ep);
+	if (op == MDRNOP_RENAME && from_has_parent) {
+		(void) add_key_name(sp, to_np, NULL, ep);
+		if (from_is_fn)
+			(void) del_key_name(sp, from_np, ep);
+			(void) del_self_name(sp, from_np->key, ep);
+	}
+
+	if (op == MDRNOP_EXCHANGE && from_is_fn) {
+		(void) add_key_name(sp, from_np, NULL, ep);
 	}
 
 	/* force the name cache to re-read device state */
@@ -216,14 +260,11 @@
 {
 	int		 flags		= (options & MDCMD_FORCE)? FORCE: 0;
 	int		 rc		= 0;
-	mdcinfo_t	*cinfop;
 	char		*p;
-	md_set_desc	*sd;
-	mdkey_t		 side_key = MD_KEYWILD;
-	md_error_t	 dummy_ep = mdnullerror;
-	int		 i, j;
-	md_mnnode_desc	*nd, *nd_del;
 	md_common_t	*from_mdp;
+	minor_t		to_minor = meta_getminor(to_np->dev);
+	md_error_t	status = mdnullerror;
+	md_error_t	*t_ep = &status;
 
 	/* must have a set */
 	assert(sp != NULL);
@@ -263,130 +304,36 @@
 	}
 	mdclrerror(ep);
 
+	/*
+	 * The dest device name has been added early on
+	 * by meta_init_make_device call so get the entry from
+	 * the namespace
+	 */
+	if (meta_getnmentbydev(sp->setno, MD_SIDEWILD, to_np->dev,
+	    NULL, NULL, &to_np->key, ep) == NULL) {
+		return (-1);
+	}
+
 	/* If FORCE is not set, check if metadevice is open */
 	if (!(flags & FORCE)) {
-		if (check_open(sp, from_np, ep) != 0) {
-			return (-1);
-		}
+	    if (check_open(sp, from_np, ep) != 0) {
+		(void) del_key_name(sp, to_np, t_ep);
+		(void) metaioctl(MD_IOCREM_DEV, &to_minor, t_ep, NULL);
+		return (-1);
+	    }
 	}
 
 	/*
 	 * All checks are done, now we do the real work.
-	 * If we are in dryrun mode, we're done.
+	 * If we are in dryrun mode, clear the deivce node
+	 * and we are done.
 	 */
 	if (flags & DRYRUN) {
+		(void) del_key_name(sp, to_np, t_ep);
+		(void) metaioctl(MD_IOCREM_DEV, &to_minor, t_ep, NULL);
 		return (0); /* success */
 	}
 
-	/*
-	 * add key for new name to the namespace
-	 */
-	if ((cinfop = metagetcinfo(from_np, ep)) == NULL) {
-		assert(!mdisok(ep));
-		return (-1);
-	}
-
-	if (metaislocalset(sp)) {
-		to_np->key = add_name(sp, MD_SIDEWILD, MD_KEYWILD,
-		    cinfop->dname, meta_getminor(to_np->dev), to_np->bname, ep);
-	} else {
-		/*
-		 * As this is not the local set we have to create a namespace
-		 * record for each side (host) in the set. We cannot use
-		 * add_key_names() because the destination device (to_np)
-		 * should not exist and so the subsequent metagetcinfo()
-		 * call will fail when it tries to open the device, so we
-		 * have to use the information from the source device (from_np)
-		 */
-		if ((sd = metaget_setdesc(sp, ep)) == (md_set_desc *)NULL) {
-			return (-1);
-		}
-		to_np->key = MD_KEYWILD;
-
-		if (MD_MNSET_DESC(sd)) {
-			nd = sd->sd_nodelist;
-			while (nd) {
-				side_key = add_name(sp, (side_t)nd->nd_nodeid,
-				    to_np->key, cinfop->dname,
-				    meta_getminor(to_np->dev),
-				    to_np->bname, ep);
-				/*
-				 * Break out if failed to add the key,
-				 * but delete any name space records that
-				 * were added.
-				 */
-				if (side_key == MD_KEYBAD ||
-				    side_key == MD_KEYWILD) {
-					/*
-					 * If we have a valid to_np->key then
-					 * a record was added correctly but
-					 * we do not know for which side, so
-					 * we need to try to delete all of them.
-					 */
-
-					if (to_np->key != MD_KEYBAD &&
-					    to_np->key != MD_KEYWILD) {
-						nd_del = sd->sd_nodelist;
-						while ((nd_del != nd) &&
-						(nd_del != NULL)) {
-						    (void) del_name(sp,
-						    (side_t)nd_del->nd_nodeid,
-						    to_np->key, &dummy_ep);
-						    nd_del = nd_del->nd_next;
-						}
-						/* preserve error key state */
-						to_np->key = side_key;
-					}
-					break;
-				}
-				to_np->key = side_key;
-				nd = nd->nd_next;
-			}
-		} else {
-			for (i = 0; i < MD_MAXSIDES; i++) {
-				if (sd->sd_nodes[i][0] != '\0') {
-					side_key = add_name(sp, (side_t)i,
-					    to_np->key, cinfop->dname,
-					    meta_getminor(to_np->dev),
-					    to_np->bname, ep);
-					/*
-					 * Break out if failed to add the key,
-					 * but delete any name space records
-					 * that were added.
-					 */
-					if (side_key == MD_KEYBAD ||
-					    side_key == MD_KEYWILD) {
-						/*
-						 * If we have a valid
-						 * to_np->key then a record was
-						 * added correctly but we do
-						 * not know for which side, so
-						 * we need to try to delete
-						 * all of them.
-						 */
-						if (to_np->key != MD_KEYBAD &&
-						    to_np->key != MD_KEYWILD) {
-							for (j = 0; j < i;
-							    j++) {
-							    (void) del_name(sp,
-							    (side_t)j,
-							    to_np->key,
-							    &dummy_ep);
-							}
-							/*
-							 * preserve err
-							 * key state
-							 */
-							to_np->key = side_key;
-						}
-						break;
-					}
-					to_np->key = side_key;
-				}
-			}
-		}
-	}
-
 	if (to_np->key == MD_KEYBAD || to_np->key == MD_KEYWILD) {
 		assert(!mdisok(ep));
 		return (-1);
--- a/usr/src/lib/lvm/libmeta/common/meta_replace.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_replace.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -33,45 +32,6 @@
 #include <meta.h>
 #include <sys/lvm/md_stripe.h>
 
-int
-meta_replace(mdsetname_t *sp, mdname_t *metanp, mdname_t *oldnp,
-    mdname_t *newnp, char *uname, mdcmdopts_t options, md_error_t *ep)
-{
-	char			*miscname;
-
-	assert(sp != NULL);
-
-	if (is_hspname(uname)) {
-		mdhspname_t	*hspnp;
-
-		if ((hspnp = metahspname(&sp, uname, ep)) == NULL)
-			return (-1);
-		assert(sp != NULL);
-		(void) meta_hs_replace(sp, hspnp, oldnp, newnp, options, ep);
-		return (0);
-	}
-	assert(sp->setno == MD_MIN2SET(meta_getminor(metanp->dev)));
-	if (metachkmeta(metanp, ep) != 0)
-		return (-1);
-
-
-	if ((miscname = metagetmiscname(metanp, ep)) == NULL)
-		return (-1);
-
-	if (strcmp(miscname, MD_RAID) == 0) {
-		return (meta_raid_replace(sp, metanp, oldnp, newnp,
-		    options, ep));
-	} else if (strcmp(miscname, MD_TRANS) == 0) {
-		return (meta_trans_replace(sp, metanp, oldnp, newnp,
-		    options, ep));
-	} else if (strcmp(miscname, MD_STRIPE) == 0) {
-		return (meta_stripe_replace(sp, metanp, oldnp, newnp,
-		    options, ep));
-	}
-
-	return (mdmderror(ep, MDE_UNKNOWN_TYPE, meta_getminor(metanp->dev),
-	    metanp->cname));
-}
 /*
  * replace named device
  */
--- a/usr/src/lib/lvm/libmeta/common/meta_se_notify.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_se_notify.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -39,6 +38,7 @@
 obj2devname(uint32_t tag, set_t setno, md_dev64_t dev)
 {
 	char		*setname;
+	char		*uname;
 	char		name[MD_MAX_CTDLEN];
 	mdsetname_t	*sp;
 	md_error_t	status = mdnullerror;
@@ -60,22 +60,18 @@
 	case SVM_TAG_RAID5:
 	case SVM_TAG_STRIPE:
 	case SVM_TAG_TRANS:
-		if (setno == 0) {
-			rtn = snprintf(name, sizeof (name), "d%u",
-			    (unsigned)MD_MIN2UNIT(mnum));
-		} else if (setname != NULL) {
-			rtn = snprintf(name, sizeof (name), "%s/d%u", setname,
-			    (unsigned)MD_MIN2UNIT(mnum));
-		}
+		uname = get_mdname(sp, mnum);
+		if (uname == NULL)
+			return (NULL);
+
+		(void) strcpy(name, uname);
 		break;
 	case SVM_TAG_HSP:
-		if (setno == 0) {
-			rtn = snprintf(name, sizeof (name), "hsp%u",
-			    (unsigned)MD_MIN2UNIT(mnum));
-		} else if (setname != NULL) {
-			rtn = snprintf(name, sizeof (name), "%s/hsp%u",
-			    setname, (unsigned)MD_MIN2UNIT(mnum));
-		}
+		uname = get_hspname(sp, mnum);
+		if (uname == NULL)
+			return (NULL);
+
+		(void) strcpy(name, uname);
 		break;
 	case SVM_TAG_DRIVE:
 		(void) sprintf(name, "drive");
--- a/usr/src/lib/lvm/libmeta/common/meta_set.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_set.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -607,7 +606,7 @@
 		*ret_mnum = NODEV32;
 
 
-	if ((np = metaname(&sp, bname, ep)) == NULL)
+	if ((np = metaname(&sp, bname, LOGICAL_DEVICE, ep)) == NULL)
 		return (-1);
 
 /*
@@ -742,7 +741,7 @@
 	 * Need to pass the node the devid of the disk and get it to
 	 * send back the details of the disk from that side.
 	 */
-	if ((np = metaname(&sp, bname, ep)) == NULL)
+	if ((np = metaname(&sp, bname, UNKNOWN, ep)) == NULL)
 		return (-1);
 
 	dnp = np->drivenamep;
@@ -1783,12 +1782,12 @@
 
 	/* get device name */
 	if (flags & PRINT_FAST) {
-		if ((np = metaname_fast(&sp, nm, ep)) == NULL) {
+		if ((np = metaname_fast(&sp, nm, LOGICAL_DEVICE, ep)) == NULL) {
 			Free(nm);
 			return (NULL);
 		}
 	} else {
-		if ((np = metaname(&sp, nm, ep)) == NULL) {
+		if ((np = metaname(&sp, nm, LOGICAL_DEVICE, ep)) == NULL) {
 			Free(nm);
 			return (NULL);
 		}
--- a/usr/src/lib/lvm/libmeta/common/meta_set_prv.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_set_prv.c	Tue Mar 14 14:53:36 2006 -0800
@@ -149,7 +149,8 @@
 		 */
 		if (strcmp(np->rname, rname) != 0) {
 			/* different rname */
-			remote_np = metaname_fast(&sp, rname, ep);
+			remote_np = metaname_fast(&sp, rname,
+			    LOGICAL_DEVICE, ep);
 			if (remote_np != NULL) {
 				remote_dnp = remote_np->drivenamep;
 			}
--- a/usr/src/lib/lvm/libmeta/common/meta_sp.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_sp.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -777,8 +776,15 @@
 	/* check set pointer */
 	assert(sp != NULL);
 
+	/*
+	 * Get a list of the soft partitions that currently reside on
+	 * the component.  We should ALWAYS force reload the cache,
+	 * because if we're using the md.tab, we must rebuild
+	 * the list because it won't contain the previous (if any)
+	 * soft partition.
+	 */
 	/* find all soft partitions on the component */
-	count = meta_sp_get_by_component(sp, np, &spnlp, 0, ep);
+	count = meta_sp_get_by_component(sp, np, &spnlp, 1, ep);
 
 	if (count == -1) {
 		rval = -1;
@@ -1841,6 +1847,15 @@
 	mdname_t	*np = NULL;
 	mdsetname_t	*spsetp = NULL;
 	sp_ext_offset_t	cur_off;
+	md_set_desc	*sd;
+	int		init = 0;
+	mdkey_t		key;
+	minor_t		mnum;
+
+	if (!metaislocalset(sp)) {
+		if ((sd = metaget_setdesc(sp, ep)) == NULL)
+			return (-1);
+	}
 
 	if ((cur_off = meta_sp_get_start(sp, compnp, ep)) == MD_DISKADDR_ERROR)
 		return (-1);
@@ -1857,13 +1872,67 @@
 			}
 		}
 
+		/*
+		 * For the MN set, meta_init_make_device needs to
+		 * be run on all the nodes so the entries for the
+		 * softpart device name and its comp can be created
+		 * in the same order in the replica namespace.  If
+		 * we have it run on mdmn_do_iocset then the mddbs
+		 * will be out of sync between master node and slave
+		 * nodes.
+		 */
 		if (strcmp(wm.wm_mdname, MD_SP_FREEWMNAME) != 0) {
-			if (meta_init_make_device(&sp, wm.wm_mdname, ep) != 0)
+
+		    if (!metaislocalset(sp) && MD_MNSET_DESC(sd)) {
+			md_mn_msg_addmdname_t	*send_params;
+			int			result;
+			md_mn_result_t		*resp = NULL;
+			int			message_size;
+
+			message_size =  sizeof (*send_params) +
+			    strlen(wm.wm_mdname) + 1;
+			send_params = Zalloc(message_size);
+			send_params->addmdname_setno = sp->setno;
+			(void) strcpy(&send_params->addmdname_name[0],
+			    wm.wm_mdname);
+			result = mdmn_send_message(sp->setno,
+			    MD_MN_MSG_ADDMDNAME,
+			    MD_MSGF_PANIC_WHEN_INCONSISTENT,
+			    (char *)send_params, message_size, &resp,
+			    ep);
+			Free(send_params);
+			if (resp != NULL) {
+				if (resp->mmr_exitval != 0) {
+					free_result(resp);
+					return (-1);
+				}
+				free_result(resp);
+			}
+			if (result != 0)
 				return (-1);
-			np = metaname(&spsetp, wm.wm_mdname, ep);
-			if (np == NULL) {
-				return (-1);
+		    } else {
+
+			if (!is_existing_meta_hsp(sp, wm.wm_mdname)) {
+			    if ((key = meta_init_make_device(&sp,
+				wm.wm_mdname, ep)) <= 0) {
+					return (-1);
+				}
+				init = 1;
 			}
+		    }
+
+		    np = metaname(&spsetp, wm.wm_mdname, META_DEVICE, ep);
+		    if (np == NULL) {
+			if (init) {
+			    if (meta_getnmentbykey(sp->setno, MD_SIDEWILD,
+				key, NULL, &mnum, NULL, ep) != NULL) {
+				    (void) metaioctl(MD_IOCREM_DEV, &mnum,
+						ep, NULL);
+			    }
+			    (void) del_self_name(sp, key, ep);
+			}
+			return (-1);
+		    }
 		}
 
 		/* insert watermark into extent list */
@@ -1913,7 +1982,12 @@
 	int	extn;
 
 	if (options & PRINT_LARGEDEVICES) {
-		if (msp->common.revision != MD_64BIT_META_DEV)
+		if ((msp->common.revision & MD_64BIT_META_DEV) == 0)
+			return (0);
+	}
+
+	if (options & PRINT_FN) {
+		if ((msp->common.revision & MD_FN_META_DEV) == 0)
 			return (0);
 	}
 
@@ -1923,22 +1997,10 @@
 
 	/* print the component */
 	/*
-	 * If the path is our standard /dev/rdsk or /dev/md/rdsk
-	 * then just print out the cxtxdxsx or the dx, metainit
-	 * will assume the default, otherwise we need the full
-	 * pathname to make sure this works as we intend.
+	 * Always print the full path name
 	 */
-	if ((strstr(msp->compnamep->rname, "/dev/rdsk") == NULL) &&
-	    (strstr(msp->compnamep->rname, "/dev/md/rdsk") == NULL) &&
-	    (strstr(msp->compnamep->rname, "/dev/td/") == NULL)) {
-		/* not standard path so print full pathname */
-		if (fprintf(fp, " %s", msp->compnamep->rname) == EOF)
-			return (mdsyserror(ep, errno, fname));
-	} else {
-		/* standard path so print ctds or d number */
-		if (fprintf(fp, " %s", msp->compnamep->cname) == EOF)
-			return (mdsyserror(ep, errno, fname));
-	}
+	if (fprintf(fp, " %s", msp->compnamep->rname) == EOF)
+		return (mdsyserror(ep, errno, fname));
 
 	/* print out each extent */
 	for (extn = 0; (extn < msp->ext.ext_len); extn++) {
@@ -2041,7 +2103,16 @@
 	uint_t		tstate = 0;
 
 	if (options & PRINT_LARGEDEVICES) {
-		if (msp->common.revision != MD_64BIT_META_DEV) {
+		if ((msp->common.revision & MD_64BIT_META_DEV) == 0) {
+			return (0);
+		} else {
+			if (meta_getdevs(sp, msp->common.namep, nlpp, ep) != 0)
+				return (-1);
+		}
+	}
+
+	if (options & PRINT_FN) {
+		if ((msp->common.revision & MD_FN_META_DEV) == 0) {
 			return (0);
 		} else {
 			if (meta_getdevs(sp, msp->common.namep, nlpp, ep) != 0)
@@ -3704,7 +3775,7 @@
 
 	/* expect sp name, -p, optional -e, compname, and size parameters */
 	/* grab soft partition name */
-	if ((np = metaname(spp, devname, ep)) == NULL)
+	if ((np = metaname(spp, devname, META_DEVICE, ep)) == NULL)
 		goto out;
 
 	/* see if it exists already */
@@ -3750,7 +3821,7 @@
 		if ((spcompnp = metaslicename(dnp, 0, ep)) == NULL) {
 			goto out;
 		}
-	} else if ((spcompnp = metaname(spp, compname, ep)) == NULL) {
+	} else if ((spcompnp = metaname(spp, compname, UNKNOWN, ep)) == NULL) {
 		goto out;
 	}
 	assert(*spp != NULL);
@@ -4347,10 +4418,10 @@
 	(void) memset(&set_params, 0, sizeof (set_params));
 
 	if (create_flag == MD_CRO_64BIT) {
-		mp->c.un_revision = MD_64BIT_META_DEV;
+		mp->c.un_revision |= MD_64BIT_META_DEV;
 		set_params.options = MD_CRO_64BIT;
 	} else {
-		mp->c.un_revision = MD_32BIT_META_DEV;
+		mp->c.un_revision &= ~MD_64BIT_META_DEV;
 		set_params.options = MD_CRO_32BIT;
 	}
 
@@ -4730,7 +4801,7 @@
 	int		count;
 	md_sp_reset_t	reset_params;
 
-	if ((compnp = metaname(&sp, name, ep)) == NULL)
+	if ((compnp = metaname(&sp, name, UNKNOWN, ep)) == NULL)
 		return (-1);
 
 	/* If we're starting out with no soft partitions, it's an error */
@@ -4959,10 +5030,10 @@
 	(void) memset(&grow_params, 0, sizeof (grow_params));
 	if (new_un->c.un_total_blocks > MD_MAX_BLKS_FOR_SMALL_DEVS) {
 		grow_params.options = MD_CRO_64BIT;
-		new_un->c.un_revision = MD_64BIT_META_DEV;
+		new_un->c.un_revision |= MD_64BIT_META_DEV;
 	} else {
 		grow_params.options = MD_CRO_32BIT;
-		new_un->c.un_revision = MD_32BIT_META_DEV;
+		new_un->c.un_revision &= ~MD_64BIT_META_DEV;
 	}
 	grow_params.mnum = MD_SID(new_un);
 	grow_params.size = new_un->c.un_size;
@@ -5270,14 +5341,15 @@
 			newname[strlen(newname) - 1] = '\0';
 
 		if (!(is_metaname(newname)) ||
-		    (meta_init_make_device(&sp, newname, ep) != 0)) {
+		    (meta_init_make_device(&sp, newname, ep) <= 0)) {
 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
 			    "Invalid metadevice name\n"));
 			(void) fflush(stderr);
 			continue;
 		}
 
-		if ((*new_np = metaname(&sp, newname, ep)) == NULL) {
+		if ((*new_np = metaname(&sp, newname,
+		    META_DEVICE, ep)) == NULL) {
 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
 			    "Invalid metadevice name\n"));
 			(void) fflush(stderr);
@@ -6092,9 +6164,9 @@
 		set_params.options =
 				meta_check_devicesize(un_array[i]->un_length);
 		if (set_params.options == MD_CRO_64BIT) {
-			un_array[i]->c.un_revision = MD_64BIT_META_DEV;
+			un_array[i]->c.un_revision |= MD_64BIT_META_DEV;
 		} else {
-			un_array[i]->c.un_revision = MD_32BIT_META_DEV;
+			un_array[i]->c.un_revision &= ~MD_64BIT_META_DEV;
 		}
 		MD_SETDRIVERNAME(&set_params, MD_SP,
 		    MD_MIN2SET(set_params.mnum));
--- a/usr/src/lib/lvm/libmeta/common/meta_statconcise.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_statconcise.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1436,9 +1435,6 @@
 		case MDDB_F_HOTSPARE_POOL:
 			/*
 			 * Ondisk and incore records are always same size.
-			 * Also, hotspare pools will always be toplevel
-			 * metadevices, so we don't need to store a
-			 * hsp_self_id.
 			 */
 			hsp = (hot_spare_pool_ond_t *)((uintptr_t)rbp +
 			    (sizeof (mddb_rb_t) - sizeof (int)));
@@ -1448,7 +1444,14 @@
 			bcopy(hsp, mdrec->record, newreqsize);
 			hsp = (hot_spare_pool_ond_t *)mdrec->record;
 			mdrec->dfunc = &process_hotspare_pool;
-			mdrec->un_self_id = NULL;
+			/*
+			 * If the hsp has descriptive name we'll get
+			 * the un_self_id
+			 */
+			if (HSP_ID_IS_FN(hsp->hsp_self_id))
+				mdrec->un_self_id = hsp->hsp_self_id;
+			else
+				mdrec->un_self_id = NULL;
 			mdrec->has_parent = 0;
 			break;
 		/* All valid cases have been dealt with */
@@ -1467,16 +1470,31 @@
 		    nmname = (struct nm_name *)((char *)nmname +
 		    NAMSIZ(nmname))) {
 			/*
-			 * Matching the un_self_id for the record to the
-			 * n_minor name in the NM record, to extract the
-			 * metadevice name if it is in the namespace
+			 * Extract the metadevice/hsp name if it is
+			 * in the namespace.
+			 *
+			 * If it is a hot spare pool we will find our
+			 * match by comparing the NM record's n_key
+			 * with the extracted key from the hsp_self_id
+			 * Else, match the un_self_id for the record
+			 * to the n_minor name in the NM record.
 			 */
-			    if ((nmname->n_minor) == (uc.un_self_id)) {
-				(*mdrec).n_key = nmname->n_key;
-				uname = Strdup(nmname->n_name);
-				mdrec->n_name = uname;
-				break;
-			}
+			    if (mdrec->md_type == MDDB_F_HOTSPARE_POOL) {
+				if (nmname->n_key ==
+				    HSP_ID_TO_KEY(hsp->hsp_self_id)) {
+					mdrec->n_key = nmname->n_key;
+					uname = Strdup(nmname->n_name);
+					mdrec->n_name = uname;
+					break;
+				}
+			    } else {
+				if ((nmname->n_minor) == (uc.un_self_id)) {
+					(*mdrec).n_key = nmname->n_key;
+					uname = Strdup(nmname->n_name);
+					mdrec->n_name = uname;
+					break;
+				}
+			    }
 		}
 	}
 
@@ -1541,7 +1559,7 @@
 	mddb_rb32_t	*rbp_32;
 	mddb_rb_t	*rbp_64;
 	crc_skip_t	*skip = NULL;
-	int		is_32bit_record = 0;
+	int		is_32bit_record;
 
 	tmp_mdrec = Zalloc(sizeof (md_im_rec_t));
 	rbp = (void *)Zalloc(dbtob(dep->de_blkcount));
@@ -1596,9 +1614,16 @@
 	 * revision for the current 64bit or 32bit record block.  Also,
 	 * setting the flag for whether or not it is a 32bit record.
 	 */
-	if (revchk(MDDB_REV_RB, rbp_32->rb_revision) == 0) {
+	is_32bit_record = 0;
+	switch (rbp_32->rb_revision) {
+	case MDDB_REV_RB:
+	case MDDB_REV_RBFN:
 		is_32bit_record = 1;
-	} else if (revchk(MDDB_REV_RB64, rbp_32->rb_revision) != 0) {
+		break;
+	case MDDB_REV_RB64:
+	case MDDB_REV_RB64FN:
+		break;
+	default:
 		rval = -1;
 		(void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
 		goto out;
--- a/usr/src/lib/lvm/libmeta/common/meta_stripe.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_stripe.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -566,6 +565,13 @@
 		}
 	}
 
+	if (options & PRINT_FN) {
+		if (stripep->common.revision != MD_FN_META_DEV) {
+			rval = 0;
+			goto out;
+		}
+	}
+
 	/* print name and num rows */
 	if (fprintf(fp, "%s %u",
 	    stripep->common.namep->cname, stripep->rows.rows_len) == EOF)
@@ -580,32 +586,14 @@
 		if (fprintf(fp, " %u", rp->comps.comps_len) == EOF)
 			goto out;
 
-		/* print components */
+		/*
+		 * Print components. Always print the full path name.
+		 */
 		for (comp = 0; (comp < rp->comps.comps_len); ++comp) {
 			md_comp_t	*cp = &rp->comps.comps_val[comp];
 
-			/* print component */
-			/*
-			 * If the path is our standard /dev/rdsk or /dev/md/rdsk
-			 * then just print out the cxtxdxsx or the dx, metainit
-			 * will assume the default, otherwise we need the full
-			 * pathname to make sure this works as we intend.
-			 */
-			if ((strstr(cp->compnamep->rname, "/dev/rdsk") ==
-			    NULL) && (strstr(cp->compnamep->rname,
-			    "/dev/md/rdsk") == NULL) &&
-			    (strstr(cp->compnamep->rname, "/dev/td/") ==
-			    NULL)) {
-				/* not standard path, print full pathname */
-				if (fprintf(fp, " %s", cp->compnamep->rname)
-				    == EOF)
-					goto out;
-			} else {
-				/* standard path */
-				if (fprintf(fp, " %s", cp->compnamep->cname)
-				    == EOF)
-					goto out;
-			}
+			if (fprintf(fp, " %s", cp->compnamep->rname) == EOF)
+				goto out;
 		}
 
 		/* print interlace */
@@ -998,7 +986,24 @@
 	 * printing out the relocation information.
 	 */
 	if (options & PRINT_LARGEDEVICES) {
-		if (stripep->common.revision != MD_64BIT_META_DEV) {
+		if ((stripep->common.revision & MD_64BIT_META_DEV) == 0) {
+			rval = 0;
+			goto out;
+		} else {
+			if (meta_getdevs(sp, stripep->common.namep,
+			    nlpp, ep) != 0)
+				goto out;
+		}
+	}
+
+	/*
+	 * if the -D option has been specified check to see if the
+	 * metadevice has a descriptive name and print if so, also if a
+	 * descriptive device name we need to store the ctd involved
+	 * for use in printing out the relocation information.
+	 */
+	if (options & PRINT_FN) {
+		if ((stripep->common.revision & MD_FN_META_DEV) == 0) {
 			rval = 0;
 			goto out;
 		} else {
@@ -1493,10 +1498,10 @@
 	mgp.nrows = old_un->un_nrows;
 	if (create_flag == MD_CRO_32BIT) {
 		mgp.options = MD_CRO_32BIT;
-		new_un->c.un_revision = MD_32BIT_META_DEV;
+		new_un->c.un_revision &= ~MD_64BIT_META_DEV;
 	} else {
 		mgp.options = MD_CRO_64BIT;
-		new_un->c.un_revision = MD_64BIT_META_DEV;
+		new_un->c.un_revision |= MD_64BIT_META_DEV;
 	}
 
 	if ((MD_HAS_PARENT(old_un->c.un_parent)) &&
@@ -2096,10 +2101,10 @@
 
 	/* did the user tell us to generate a large device? */
 	if (create_flag == MD_CRO_64BIT) {
-		ms->c.un_revision = MD_64BIT_META_DEV;
+		ms->c.un_revision |= MD_64BIT_META_DEV;
 		set_params.options = MD_CRO_64BIT;
 	} else {
-		ms->c.un_revision = MD_32BIT_META_DEV;
+		ms->c.un_revision &= ~MD_64BIT_META_DEV;
 		set_params.options = MD_CRO_32BIT;
 	}
 
@@ -2156,7 +2161,7 @@
 	if (argc < 1)
 		goto syntax;
 
-	if ((stripenp = metaname(spp, uname, ep)) == NULL)
+	if ((stripenp = metaname(spp, uname, META_DEVICE, ep)) == NULL)
 		goto out;
 	assert(*spp != NULL);
 	uname = stripenp->cname;
@@ -2244,7 +2249,8 @@
 				    meta_getminor(stripenp->dev), uname);
 				goto out;
 			}
-			if ((compnp = metaname(spp, argv[0], ep)) == NULL) {
+			if ((compnp = metaname(spp, argv[0], UNKNOWN,
+			    ep)) == NULL) {
 				goto out;
 			}
 			/* check for soft partition */
--- a/usr/src/lib/lvm/libmeta/common/meta_tab.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_tab.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -137,7 +136,9 @@
  */
 static void
 parse_tab(
-	md_tab_t	*tabp
+	md_tab_t	*tabp,
+	char		*metatab_name,
+	md_error_t	*ep
 )
 {
 	uint_t		lineno = 1;
@@ -158,7 +159,7 @@
 	context = Malloc(len);
 
 	/* parse lines */
-	while (p < e) {
+	while (p < e && *p != '\0') {
 		md_tab_line_t	*linep;
 		char		*t;
 
@@ -230,8 +231,12 @@
 		    (! isspace(linep->argv[0][0])));
 		linep->context = Strdup(context);
 		linep->type = meta_get_init_type(linep->argc, linep->argv);
-		linep->cname = Strdup(meta_canonicalize(NULL, linep->argv[0]));
-		assert(linep->cname != NULL);
+		linep->cname = meta_canonicalize(NULL, linep->argv[0]);
+		/* if cname is NULL then the meta/hsp name is invalid */
+		if (linep->cname == NULL) {
+			(void) mderror(ep, MDE_SYNTAX, metatab_name);
+			break;
+		}
 	}
 
 	/* cleanup */
@@ -299,10 +304,11 @@
 	fd = -1;
 
 	/* parse it up */
-	parse_tab(tabp);
+	parse_tab(tabp, filename, ep);
 
-	/* return success */
-	return (tabp);
+	/* return success if file was correctly parsed */
+	if (mdisok(ep))
+		return (tabp);
 
 	/* cleanup, return error */
 out:
@@ -327,6 +333,10 @@
 	char		*cname = meta_canonicalize(sp, name);
 	size_t		line;
 
+	/* if name is not legal meta name then return NULL */
+	if (cname == NULL)
+		return (NULL);
+
 	for (line = 0; (line < tabp->nlines); ++line) {
 		md_tab_line_t	*linep = &tabp->lines[line];
 
--- a/usr/src/lib/lvm/libmeta/common/meta_trans.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/meta_trans.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1106,8 +1105,8 @@
 		return (0);
 	}
 
-	/* can't have a large trans */
-	if (!(options & PRINT_LARGEDEVICES)) {
+	/* can't have a large trans or descriptive name trans */
+	if (!(options & (PRINT_LARGEDEVICES | PRINT_FN))) {
 		/* print appropriate detail */
 		if (options & PRINT_SHORT) {
 			if (trans_print(transp, fname, fp, ep) != 0)
--- a/usr/src/lib/lvm/libmeta/common/metagetroot.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/common/metagetroot.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -81,7 +80,7 @@
 
 	if ((curroot = meta_get_current_root(ep)) == NULL)
 		return (NULL);
-	if ((rootnp = metaname(&sp, curroot, ep)) == NULL)
+	if ((rootnp = metaname(&sp, curroot, UNKNOWN, ep)) == NULL)
 		return (NULL);
 	if (metaismeta(rootnp)) {
 		if ((miscname = metagetmiscname(rootnp, ep)) == NULL)
--- a/usr/src/lib/lvm/libmeta/spec/meta.spec	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libmeta/spec/meta.spec	Tue Mar 14 14:53:36 2006 -0800
@@ -1,13 +1,12 @@
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -482,6 +481,10 @@
 version		SUNWprivate_1.1
 end
 
+function	meta_gethspnmentbyid
+version		SUNWprivate_1.1
+end
+
 function	meta_get_hsp_common
 version		SUNWprivate_1.1
 end
@@ -1158,6 +1161,14 @@
 version		SUNWprivate_1.1
 end
 
+function	meta_is_all
+version		SUNWprivate_1.1
+end
+
+function	meta_is_none
+version		SUNWprivate_1.1
+end
+
 function	is_hspname
 version		SUNWprivate_1.1
 end
@@ -1166,6 +1177,14 @@
 version		SUNWprivate_1.1
 end
 
+function	is_existing_metadevice
+version		SUNWprivate_1.1
+end
+
+function	is_existing_hsp
+version		SUNWprivate_1.1
+end
+
 function	is_metaname
 version		SUNWprivate_1.1
 end
@@ -1222,6 +1241,10 @@
 version		SUNWprivate_1.1
 end
 
+function	metaflushmetanames
+version		SUNWprivate_1.1
+end
+
 function	metaflushnames
 version		SUNWprivate_1.1
 end
@@ -1290,6 +1313,10 @@
 version		SUNWprivate_1.1
 end
 
+function	meta_name_getname
+version		SUNWprivate_1.1
+end
+
 function	metaname
 version		SUNWprivate_1.1
 end
@@ -1658,10 +1685,6 @@
 version		SUNWprivate_1.1
 end
 
-function	meta_replace
-version		SUNWprivate_1.1
-end
-
 function	meta_replace_byname
 version		SUNWprivate_1.1
 end
@@ -3713,3 +3736,11 @@
 function	read_master_block
 version		SUNWprivate_1.1
 end
+
+function	add_self_name
+version		SUNWprivate_1.1
+end
+
+function	del_self_name
+version		SUNWprivate_1.1
+end
--- a/usr/src/lib/lvm/libpreen/common/mdpreen.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libpreen/common/mdpreen.c	Tue Mar 14 14:53:36 2006 -0800
@@ -236,7 +236,7 @@
 	/*
 	 * get list of underlying physical devices.
 	 */
-	if ((namep = metaname(&sp, uname, ep)) == NULL) {
+	if ((namep = metaname(&sp, uname, UNKNOWN, ep)) == NULL) {
 		ep_valid = 1;
 		goto out;
 	}
--- a/usr/src/lib/lvm/libsvm/common/metainterfaces.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/lib/lvm/libsvm/common/metainterfaces.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -346,7 +345,7 @@
 
 	debug_printf("get_mdcomponents(): Enter unit name %s\n", uname);
 
-	if (((namep = metaname(&sp, uname, ep)) == NULL) ||
+	if (((namep = metaname(&sp, uname, META_DEVICE, ep)) == NULL) ||
 					(metachkmeta(namep, ep) != 0)) {
 		debug_printf("get_mdcomponents(): "
 				"metaname or metachkmeta failed\n");
--- a/usr/src/uts/common/io/lvm/hotspares/hotspares.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/hotspares/hotspares.c	Tue Mar 14 14:53:36 2006 -0800
@@ -88,21 +88,6 @@
 	return ((hot_spare_t *)NULL);
 }
 
-static hot_spare_pool_t *
-find_hot_spare_pool(set_t setno, int hsp_id)
-{
-	hot_spare_pool_t *hsp;
-
-	hsp = (hot_spare_pool_t *)md_set[setno].s_hsp;
-	while (hsp != NULL) {
-		if (hsp->hsp_self_id == hsp_id)
-			return (hsp);
-		hsp = hsp->hsp_next;
-	}
-
-	return ((hot_spare_pool_t *)0);
-}
-
 
 static int
 seths_create_hsp(set_hs_params_t *shs)
@@ -129,11 +114,13 @@
 		    shs->shs_hot_spare_pool));
 #else
 		recid = mddb_createrec(sizeof (hot_spare_pool_ond_t), typ1,
-			HSP_REC, MD_CRO_64BIT | MD_CRO_HOTSPARE_POOL, setno);
+		    HSP_REC, MD_CRO_64BIT | MD_CRO_HOTSPARE_POOL | MD_CRO_FN,
+		    setno);
 #endif
 	} else {
 		recid = mddb_createrec(sizeof (hot_spare_pool_ond_t), typ1,
-			HSP_REC, MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL, setno);
+		    HSP_REC, MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL | MD_CRO_FN,
+		    setno);
 	}
 
 	if (recid < 0) {
@@ -150,6 +137,7 @@
 	hsp->hsp_next = (hot_spare_pool_t *)md_set[setno].s_hsp;
 	hsp->hsp_refcount = 0;
 	hsp->hsp_nhotspares = 0;
+	hsp->hsp_revision |= MD_FN_META_DEV;
 
 	md_set[setno].s_hsp = (void *) hsp;
 
@@ -176,6 +164,7 @@
 	hot_spare_pool_t	*prev_hsp;
 	hot_spare_pool_t	*new_hsp;
 	hot_spare_pool_t	*old_hsp;
+	md_create_rec_option_t	options;
 	mddb_recid_t		recid;
 	mddb_recid_t		recids[5];
 	size_t			new_size;
@@ -310,7 +299,8 @@
 	if (hsp == NULL) {
 		/* create a hot spare pool record */
 		recid = mddb_createrec(sizeof (hot_spare_pool_ond_t),
-		    typ1, HSP_REC, MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL, setno);
+		    typ1, HSP_REC,
+		    MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL | MD_CRO_FN, setno);
 
 		if (recid < 0) {
 			return (mdhsperror(&shs->mde, MDE_HSP_CREATE_FAILURE,
@@ -326,6 +316,7 @@
 		hsp->hsp_next = (hot_spare_pool_t *)md_set[setno].s_hsp;
 		hsp->hsp_refcount = 0;
 		hsp->hsp_nhotspares = 0;
+		hsp->hsp_revision |= MD_FN_META_DEV;
 
 		/* force prev_hsp to NULL, this will cause hsp to be linked */
 		prev_hsp = (hot_spare_pool_t *)0;
@@ -356,8 +347,18 @@
 		 */
 		new_size = sizeof (hot_spare_pool_ond_t) +
 			(sizeof (mddb_recid_t) * hsp->hsp_nhotspares);
-		recid = mddb_createrec(new_size, typ1, HSP_REC,
-		    MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL, setno);
+
+		/*
+		 * The Friendly Name status of the new HSP should duplicate
+		 * the status of the existing one.
+		 */
+		if (hsp->hsp_revision & MD_FN_META_DEV) {
+			options =
+				MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL | MD_CRO_FN;
+		} else {
+			options = MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL;
+		}
+		recid = mddb_createrec(new_size, typ1, HSP_REC, options, setno);
 
 		if (recid < 0) {
 			return (mdhsperror(&shs->mde, MDE_HSP_CREATE_FAILURE,
@@ -395,9 +396,9 @@
 	}
 
 	if (shs->shs_size_option & MD_CRO_64BIT) {
-		hs->hs_revision = MD_64BIT_META_DEV;
+		hs->hs_revision |= MD_64BIT_META_DEV;
 	} else {
-		hs->hs_revision = MD_32BIT_META_DEV;
+		hs->hs_revision &= ~MD_64BIT_META_DEV;
 	}
 
 	/* lock the db records */
@@ -915,9 +916,9 @@
 	}
 
 	if (shs->shs_size_option & MD_CRO_64BIT) {
-		new_hs->hs_revision = MD_64BIT_META_DEV;
+		new_hs->hs_revision |= MD_64BIT_META_DEV;
 	} else {
-		new_hs->hs_revision = MD_32BIT_META_DEV;
+		new_hs->hs_revision &= ~MD_64BIT_META_DEV;
 	}
 
 	/* commit the db records */
@@ -1286,7 +1287,9 @@
 	dep = mddb_getrecdep(recid);
 	dep->de_flags = MDDB_F_HOTSPARE;
 	rbp = dep->de_rb;
-	if (rbp->rb_revision == MDDB_REV_RB) {
+	switch (rbp->rb_revision) {
+	case MDDB_REV_RB:
+	case MDDB_REV_RBFN:
 		/*
 		 * Needs to convert to internal 64 bit
 		 */
@@ -1298,14 +1301,17 @@
 		dep->de_rb_userdata = b_hs;
 		dep->de_reqsize = newreqsize;
 		hs = b_hs;
-	} else {
+		break;
+	case MDDB_REV_RB64:
+	case MDDB_REV_RB64FN:
 		hs = (hot_spare_t *)mddb_getrecaddr_resize
 			(recid, sizeof (*hs), 0);
+		break;
 	}
-
+	NOTE_FN(rbp->rb_revision, hs->hs_revision);
 
 #if defined(_ILP32)
-	if (hs->hs_revision == MD_64BIT_META_DEV) {
+	if (hs->hs_revision & MD_64BIT_META_DEV) {
 		char	devname[MD_MAX_CTDLEN];
 
 		set_hot_spare_state(hs, HSS_BROKEN);
@@ -1714,15 +1720,20 @@
 
 	dep = mddb_getrecdep(recid);
 	rbp = dep->de_rb;
-	if (rbp->rb_revision == MDDB_REV_RB) {
+	switch (rbp->rb_revision) {
+	case MDDB_REV_RB:
+	case MDDB_REV_RBFN:
 		/*
 		 * 32 bit hotspare
 		 */
 		hs32 = (hot_spare32_od_t *)mddb_getrecaddr(recid);
 		hs_recid = &(hs32->hs_record_id);
-	} else {
+		break;
+	case MDDB_REV_RB64:
+	case MDDB_REV_RB64FN:
 		hs64 = (hot_spare_t *)mddb_getrecaddr(recid);
 		hs_recid = &(hs64->hs_record_id);
+		break;
 	}
 
 	/*
--- a/usr/src/uts/common/io/lvm/md/md.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/md/md.c	Tue Mar 14 14:53:36 2006 -0800
@@ -996,6 +996,8 @@
 	int			size;
 	int			devid_flag;
 	int			retval;
+	uint_t			un;
+	int			un_next_set = 0;
 
 	md_haltsnarf_enter(setno);
 
@@ -1173,6 +1175,22 @@
 		}
 	} while (i);
 
+	/*
+	 * Set the first available slot and availability
+	 */
+	md_set[setno].s_un_avail = 0;
+	for (un = 0; un < MD_MAXUNITS; un++) {
+		if (md_set[setno].s_un[un] != NULL) {
+			continue;
+		} else {
+			if (!un_next_set) {
+				md_set[setno].s_un_next = un;
+				un_next_set = 1;
+			}
+			md_set[setno].s_un_avail++;
+		}
+	}
+
 	md_set_setstatus(setno, MD_SET_SNARFED);
 
 	recid = mddb_makerecid(setno, 0);
@@ -1884,3 +1902,54 @@
 
 	return (ENXIO);
 }
+
+/*
+ * Metadevice unit number dispatcher
+ * When this routine is called it will scan the
+ * incore unit array and return the avail slot
+ * hence the unit number to the caller
+ *
+ * Return -1 if there is nothing available
+ */
+unit_t
+md_get_nextunit(set_t setno)
+{
+	unit_t	un, start;
+
+	/*
+	 * If nothing available
+	 */
+	if (md_set[setno].s_un_avail == 0) {
+		return (MD_UNITBAD);
+	}
+
+	mutex_enter(&md_mx);
+	start = un = md_set[setno].s_un_next;
+
+	/* LINTED: E_CONSTANT_CONDITION */
+	while (1) {
+		if (md_set[setno].s_un[un] == NULL) {
+			/*
+			 * Advance the starting index for the next
+			 * md_get_nextunit call
+			 */
+			if (un == MD_MAXUNITS - 1) {
+				md_set[setno].s_un_next = 0;
+			} else {
+				md_set[setno].s_un_next = un + 1;
+			}
+			break;
+		}
+
+		un = ((un == MD_MAXUNITS - 1) ? 0 : un + 1);
+
+		if (un == start) {
+			un = MD_UNITBAD;
+			break;
+		}
+
+	}
+
+	mutex_exit(&md_mx);
+	return (un);
+}
--- a/usr/src/uts/common/io/lvm/md/md_ioctl.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/md/md_ioctl.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -55,6 +54,7 @@
 #include <sys/lvm/mdvar.h>
 #include <sys/lvm/md_rename.h>
 #include <sys/lvm/md_names.h>
+#include <sys/lvm/md_hotspares.h>
 
 extern md_ops_t		**md_ops;
 extern unit_t		md_nunits;
@@ -71,17 +71,22 @@
 extern kmutex_t		md_mx;
 extern kcondvar_t	md_cv;
 
+/* md_hotspares.c */
+extern	hot_spare_pool_t *find_hot_spare_pool(set_t setno, int hsp_id);
+
 /* md_med.c */
 extern int		med_addr_tab_nents;
 extern int		med_get_t_size_ioctl(mddb_med_t_parm_t *tpp, int mode);
 extern int		med_get_t_ioctl(mddb_med_t_parm_t *tpp, int mode);
 extern int		med_set_t_ioctl(mddb_med_t_parm_t *tpp, int mode);
+extern unit_t		md_get_nextunit(set_t setno);
 
 static int		md_mn_commd_present;
 
 /* md_mddb.c */
 extern mddb_set_t	*mddb_setenter(set_t setno, int flag, int *errorcodep);
 extern void		mddb_setexit(mddb_set_t *s);
+extern md_krwlock_t	nm_lock;
 
 /*
  * md_mn_is_commd_present:
@@ -185,8 +190,12 @@
 	}
 
 	nm->key = md_setdevname(nm->setno, side, nm->key, nm->drvnm,
-	    nm->mnum, name, 0);
-	if (((int)nm->key) < 0) {
+	    nm->mnum, name, 0, &nm->mde);
+	/*
+	 * If we got an error from md_setdevname & md_setdevname did not
+	 * set the error code, we'll default to MDE_DB_NOSPACE.
+	 */
+	if ((((int)nm->key) < 0) && mdisok(&nm->mde)) {
 		err = mdmddberror(&nm->mde, MDE_DB_NOSPACE, NODEV32, nm->setno);
 		goto out;
 	}
@@ -205,6 +214,9 @@
 	char		*name;
 	side_t		side;
 	md_dev64_t	dev = NODEV64;
+	mdc_unit_t	*un;
+	uint_t		id;
+	char		*setname;
 	int		err = 0;
 
 	mdclrerror(&nm->mde);
@@ -215,7 +227,6 @@
 	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
 		return (ENODEV);
 
-
 	name = kmem_alloc(MAXPATHLEN, KM_SLEEP);
 
 	if (nm->side == -1)
@@ -242,19 +253,61 @@
 			dev = md_makedevice(ddi_name_to_major(nm->drvnm),
 				nm->mnum);
 	}
-	err = md_getdevname(nm->setno, side, nm->key, dev, name, MAXPATHLEN);
-	if (err) {
-		if (err < 0)
-			err = EINVAL;
-		goto out;
-	}
-
-	err = md_getnment(nm->setno, side, nm->key, dev, nm->drvnm, 16,
-	    &nm->major, &nm->mnum, &nm->retkey);
-	if (err) {
-		if (err < 0)
-			err = EINVAL;
-		goto out;
+
+	/*
+	 * With the introduction of friendly names, all friendly named
+	 * metadevices will have an entry in the name space. However,
+	 * systems upgraded from pre-friendly name to a friendly name
+	 * release won't have name space entries for pre-friendly name
+	 * top level metadevices.
+	 *
+	 * So we search the name space for the our entry with either the
+	 * given dev_t or key. If we can't find the entry, we'll try the
+	 * un array to get information for our target metadevice. Note
+	 * we only use the un array when searching by dev_t since a
+	 * key implies an existing device which should have been
+	 * found in the name space with the call md_getdevname.
+	 */
+	if (md_getdevname(nm->setno, side, nm->key, dev, name,
+	    MAXPATHLEN) == 0) {
+		err = md_getnment(nm->setno, side, nm->key, dev, nm->drvnm,
+		    sizeof (nm->drvnm), &nm->major, &nm->mnum, &nm->retkey);
+		if (err) {
+			if (err < 0)
+				err = EINVAL;
+			goto out;
+		}
+	} else {
+		if ((nm->key != MD_KEYWILD) ||
+		    (MD_UNIT(nm->mnum) == NULL)) {
+			err = ENOENT;
+			goto out;
+		}
+
+		/*
+		 * We're here because the mnum is of a pre-friendly
+		 * name device. Make sure the major value is for
+		 * metadevices.
+		 */
+		if (nm->major != md_major) {
+			err = ENOENT;
+			goto out;
+		}
+
+		/*
+		 * get the unit number and setname to construct the
+		 * fully qualified name for the metadevice.
+		 */
+		un = MD_UNIT(nm->mnum);
+		id =  MD_MIN2UNIT(un->un_self_id);
+		if (nm->setno != MD_LOCAL_SET) {
+			setname = mddb_getsetname(nm->setno);
+			(void) snprintf(name, MAXPATHLEN,
+			    "/dev/md/%s/dsk/d%u", setname, id);
+		} else {
+			(void) snprintf(name, MAXPATHLEN,
+			    "/dev/md/dsk/d%u", id);
+		}
 	}
 
 	err = ddi_copyout(name, (caddr_t)(uintptr_t)nm->devname,
@@ -269,6 +322,193 @@
 	return (err);
 }
 
+static int
+gethspnm_ioctl(
+	mdhspnm_params_t	*nm,
+	int			mode
+)
+{
+	char			*name;
+	char			*tmpname;
+	char			*setname = NULL;
+	side_t			side;
+	hot_spare_pool_t	*hsp = NULL;
+	mdkey_t			key = MD_KEYWILD;
+	int			err = 0;
+
+	mdclrerror(&nm->mde);
+
+	if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0)
+		return (0);
+
+	if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0)
+		return (ENODEV);
+
+	name = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
+
+	if (nm->side == -1)
+		side = mddb_getsidenum(nm->setno);
+	else
+		side = nm->side;
+
+	/*
+	 * Get the key from input hspid, use different macros
+	 * since the hspid could be either a FN or pre-FN hspid.
+	 */
+	if (nm->hspid != MD_HSPID_WILD) {
+		if (HSP_ID_IS_FN(nm->hspid))
+			key = HSP_ID_TO_KEY(nm->hspid);
+		else
+			key = HSP_ID(nm->hspid);
+	}
+
+	/*
+	 * Get the input name if we're searching by hsp name. Check
+	 * that the input name length is less than MAXPATHLEN.
+	 */
+	if ((nm->hspid == MD_HSPID_WILD) &&
+	    (nm->hspname_len <= MAXPATHLEN)) {
+		err = ddi_copyin((caddr_t)(uintptr_t)nm->hspname,
+		    name, (sizeof (char)) * nm->hspname_len, mode);
+
+		/* Stop if ddi_copyin failed. */
+		if (err) {
+			err = EFAULT;
+			goto out;
+		}
+	}
+
+	/* Must have either a valid hspid or a name to continue */
+	if ((nm->hspid == MD_HSPID_WILD) && (name[0] == '\0')) {
+		err = EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Try to find the hsp namespace entry corresponds to either
+	 * the given hspid or name. If we can't find it, the hsp maybe
+	 * a pre-friendly name hsp so we'll try to find it in the
+	 * s_hsp array.
+	 */
+	if ((nm->hspid == MD_HSPID_WILD) || (HSP_ID_IS_FN(nm->hspid))) {
+
+		if (md_gethspinfo(nm->setno, side, key, nm->drvnm,
+		    &nm->ret_hspid, name) != 0) {
+			/*
+			 * If we were given a key for a FN hsp and
+			 * couldn't find its entry, simply errored
+			 * out.
+			 */
+			if (HSP_ID_IS_FN(nm->hspid)) {
+				err = ENOENT;
+				goto out;
+			}
+
+			/*
+			 * Since md_gethspinfo failed and the hspid is
+			 * not a FN hspid,  we must have a name for a
+			 * pre-FN hotspare pool
+			 */
+			if (name[0] == '\0') {
+				err = EINVAL;
+				goto out;
+			}
+
+			tmpname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
+			if (nm->setno != MD_LOCAL_SET)
+				setname = mddb_getsetname(nm->setno);
+
+			hsp = (hot_spare_pool_t *)md_set[nm->setno].s_hsp;
+			while (hsp != NULL) {
+				/* Only use the pre-friendly name hsp */
+				if (!(hsp->hsp_revision & MD_FN_META_DEV)) {
+
+					if (setname != NULL) {
+						(void) snprintf(tmpname,
+						    MAXPATHLEN,
+						    "%s/hsp%03u", setname,
+						    HSP_ID(hsp->hsp_self_id));
+					} else {
+						(void) snprintf(tmpname,
+						    MAXPATHLEN, "hsp%03u",
+						    HSP_ID(hsp->hsp_self_id));
+					}
+
+					if (strcmp(name, tmpname) == 0)
+						break;
+				}
+
+				hsp = hsp->hsp_next;
+			}
+			kmem_free(tmpname, MAXPATHLEN);
+
+			if (hsp == NULL) {
+				err = ENOENT;
+				goto out;
+			}
+
+			/* Return hsp_self_id */
+			nm->ret_hspid = hsp->hsp_self_id;
+		}
+
+	} else {
+		/*
+		 * We have a hspid for a pre-FN hotspare pool. Let's
+		 * try to find the matching hsp using the given
+		 * hspid.
+		 */
+		if (nm->hspid == MD_HSPID_WILD) {
+			err = ENOENT;
+			goto out;
+		}
+
+		hsp = (hot_spare_pool_t *)md_set[nm->setno].s_hsp;
+		while (hsp != NULL) {
+			if (hsp->hsp_self_id == nm->hspid)
+				break;
+			hsp = hsp->hsp_next;
+		}
+
+		if (hsp == NULL) {
+			err = ENOENT;
+			goto out;
+		}
+
+		/* Prepare a name to return */
+		if (nm->setno != MD_LOCAL_SET)
+			setname = mddb_getsetname(nm->setno);
+
+		if (setname != NULL) {
+			(void) snprintf(name, MAXPATHLEN, "%s/hsp%03u",
+			    setname, HSP_ID(hsp->hsp_self_id));
+		} else {
+			(void) snprintf(name, MAXPATHLEN, "hsp%03u",
+			    HSP_ID(hsp->hsp_self_id));
+		}
+
+		nm->ret_hspid = hsp->hsp_self_id;
+	}
+
+	if (nm->hspid != MD_HSPID_WILD) {
+		if ((strlen(name) + 1) > nm->hspname_len) {
+			err = EINVAL;
+			goto out;
+		}
+		err = ddi_copyout(name, (caddr_t)
+		    (uintptr_t)nm->hspname, strlen(name)+1, mode);
+	}
+
+	if (err) {
+		if (err < 0)
+			err = EINVAL;
+	}
+
+out:
+	kmem_free(name, MAXPATHLEN);
+	return (err);
+}
+
+
 /*ARGSUSED*/
 static int
 update_loc_namespace_ioctl(
@@ -1378,25 +1618,34 @@
 mkdev_ioctl(md_mkdev_params_t *p)
 {
 	set_t	setno = p->md_driver.md_setno;
+	unit_t	un;
 
 	mdclrerror(&p->mde);
 
+	/*
+	 * Get the next available unit number in this set
+	 */
+	un = md_get_nextunit(setno);
+	if (un == MD_UNITBAD) {
+		(void) mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, un);
+		return (ENODEV);
+	}
+
 	/* Validate arguments passed in to ioctl */
 	if (setno >= MD_MAXSETS) {
-		(void) mdmderror(&p->mde, MDE_INVAL_UNIT, p->mnum);
-		return (EINVAL);
-	}
-	if (p->mnum >= MD_MAXUNITS) {
-		(void) mdmderror(&p->mde, MDE_INVAL_UNIT, p->mnum);
+		(void) mderror(&p->mde, MDE_NO_SET);
 		return (EINVAL);
 	}
 
 	/* Create the device node */
-	if (md_create_minor_node(setno, p->mnum)) {
-		(void) mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, p->mnum);
+	if (md_create_minor_node(setno, un)) {
+		(void) mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, un);
 		return (ENODEV);
 	}
 
+	/* Return the minor number */
+	p->un = un;
+
 	return (0);
 }
 
@@ -1782,6 +2031,33 @@
 		break;
 	}
 
+	case MD_IOCGET_HSP_NM:
+	{
+		if (! (mode & FREAD))
+			return (EACCES);
+
+		sz = sizeof (mdhspnm_params_t);
+		d = kmem_alloc(sz, KM_SLEEP);
+
+		if (ddi_copyin(data, d, sz, mode) != 0) {
+			err = EFAULT;
+			break;
+		}
+
+		/* check data integrity */
+		if (((mdhspnm_params_t *)d)->setno >= md_nsets) {
+			err = EINVAL;
+			break;
+		}
+		if (((mdhspnm_params_t *)d)->hspname == NULL) {
+			err = EINVAL;
+			break;
+		}
+
+		err = gethspnm_ioctl((mdhspnm_params_t *)d, mode);
+		break;
+	}
+
 	case MD_IOCNXTKEY_NM:
 	{
 		if (! (mode & FREAD))
@@ -2960,6 +3236,42 @@
 		break;
 	}
 
+	case MD_IOCREM_DEV:
+	{
+		set_t	setno;
+
+		if (! (mode & FWRITE))
+			return (EACCES);
+
+		sz = sizeof (minor_t);
+
+		d = kmem_zalloc(sz, KM_SLEEP);
+
+		if (ddi_copyin(data, d, sz, mode) != 0) {
+			err = EFAULT;
+			break;
+		}
+
+		/*
+		 * This ioctl is called to cleanup the device name
+		 * space when metainit fails or -n is invoked
+		 * In this case, reclaim the dispatched un slot
+		 */
+		setno = MD_MIN2SET(*(minor_t *)d);
+		if (md_set[setno].s_un_next <= 0) {
+			err = EFAULT;
+			break;
+		} else {
+			md_set[setno].s_un_next--;
+		}
+
+		/*
+		 * Attempt to remove the assocated device node
+		 */
+		(void) md_remove_minor_node(*(minor_t *)d);
+		break;
+	}
+
 	/*
 	 * Update md_mn_commd_present global to reflect presence or absence of
 	 * /usr/sbin/rpc.mdcommd. This allows us to determine if an RPC failure
@@ -3030,6 +3342,7 @@
 		}
 		kmem_free(d, sz);
 	}
+
 	if (err)
 		return (err);
 	return (err_to_user);
@@ -3166,7 +3479,7 @@
 		return (EINVAL);
 
 	/* don't allow to create a vtoc for a big metadevice */
-	if (un->c.un_revision == MD_64BIT_META_DEV)
+	if (un->c.un_revision & MD_64BIT_META_DEV)
 		return (ENOTSUP);
 	/*
 	 * Validate the partition table
@@ -3589,3 +3902,25 @@
 
 	return (rval);
 }
+
+
+/*
+ * Remove device node
+ */
+void
+md_remove_minor_node(minor_t mnum)
+{
+	char			name[16];
+	extern dev_info_t	*md_devinfo;
+
+	/*
+	 * Attempt release of its minor node
+	 */
+	(void) snprintf(name, sizeof (name), "%d,%d,blk", MD_MIN2SET(mnum),
+		MD_MIN2UNIT(mnum));
+	ddi_remove_minor_node(md_devinfo, name);
+
+	(void) snprintf(name, sizeof (name), "%d,%d,raw", MD_MIN2SET(mnum),
+		MD_MIN2UNIT(mnum));
+	ddi_remove_minor_node(md_devinfo, name);
+}
--- a/usr/src/uts/common/io/lvm/md/md_mddb.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/md/md_mddb.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -250,7 +249,9 @@
 	ms_unit32_od_t		*small_un;
 	uint_t			rb_off = offsetof(mddb_rb32_t, rb_data[0]);
 
-	if (revision == MDDB_REV_RB) {
+	switch (revision) {
+	case MDDB_REV_RB:
+	case MDDB_REV_RBFN:
 		small_un = (ms_unit32_od_t *)un;
 		skip_prev = &skip_start;
 
@@ -279,7 +280,9 @@
 			skip_prev->skip_next = skip;
 			skip_prev = skip;
 		}
-	} else {
+		break;
+	case MDDB_REV_RB64:
+	case MDDB_REV_RB64FN:
 		big_un = (ms_unit_t *)un;
 		skip_prev = &skip_start;
 
@@ -308,6 +311,7 @@
 			skip_prev->skip_next = skip;
 			skip_prev = skip;
 		}
+		break;
 	}
 	/* Return the start of the list of fields to skip */
 	return (skip_start.skip_next);
@@ -332,12 +336,17 @@
 	skip_prev = &skip_start;
 
 	skip = (crc_skip_t *)kmem_zalloc(sizeof (crc_skip_t), KM_SLEEP);
-	if (revision == MDDB_REV_RB) {
+	switch (revision) {
+	case MDDB_REV_RB:
+	case MDDB_REV_RBFN:
 		skip->skip_offset = offsetof(mm_unit32_od_t,
 		    un_last_read) + rb_off;
-	} else {
+		break;
+	case MDDB_REV_RB64:
+	case MDDB_REV_RB64FN:
 		skip->skip_offset = offsetof(mm_unit_t,
 		    un_last_read) + rb_off;
+		break;
 	}
 	skip->skip_size = sizeof (int);
 	skip_prev->skip_next = skip;
@@ -345,12 +354,17 @@
 
 	for (i = 0; i < NMIRROR; i++) {
 		skip = (crc_skip_t *)kmem_zalloc(sizeof (crc_skip_t), KM_SLEEP);
-		if (revision == MDDB_REV_RB) {
+		switch (revision) {
+		case MDDB_REV_RB:
+		case MDDB_REV_RBFN:
 			skip->skip_offset = offsetof(mm_unit32_od_t,
 			    un_sm[i].sm_timestamp) + rb_off;
-		} else {
+			break;
+		case MDDB_REV_RB64:
+		case MDDB_REV_RB64FN:
 			skip->skip_offset = offsetof(mm_unit_t,
 			    un_sm[i].sm_timestamp) + rb_off;
+			break;
 		}
 		skip->skip_size = sizeof (md_timeval32_t);
 		skip_prev->skip_next = skip;
@@ -373,12 +387,17 @@
 	uint_t		rb_off = offsetof(mddb_rb32_t, rb_data[0]);
 
 	skip = (crc_skip_t *)kmem_zalloc(sizeof (crc_skip_t), KM_SLEEP);
-	if (revision == MDDB_REV_RB) {
+	switch (revision) {
+	case MDDB_REV_RB:
+	case MDDB_REV_RBFN:
 		skip->skip_offset = offsetof(hot_spare32_od_t, hs_timestamp) +
 		    rb_off;
-	} else {
+		break;
+	case MDDB_REV_RB64:
+	case MDDB_REV_RB64FN:
 		skip->skip_offset = offsetof(hot_spare_t, hs_timestamp) +
 		    rb_off;
+		break;
 	}
 	skip->skip_size = sizeof (md_timeval32_t);
 	return (skip);
@@ -1894,7 +1913,9 @@
 		return (MDDB_F_EFMT | MDDB_F_EDATA);
 	}
 	if ((revchk(MDDB_REV_RB, rbp->rb_revision) != 0) &&
-	    (revchk(MDDB_REV_RB64, rbp->rb_revision) != 0)) {
+	    (revchk(MDDB_REV_RB64, rbp->rb_revision) != 0) &&
+	    (revchk(MDDB_REV_RBFN, rbp->rb_revision) != 0) &&
+	    (revchk(MDDB_REV_RB64FN, rbp->rb_revision) != 0)) {
 		return (MDDB_F_EFMT | MDDB_F_EDATA);
 	}
 	/* Check crc for this record */
@@ -2312,7 +2333,8 @@
 	 */
 	if (!(md_get_setstatus(setno) & MD_SET_IMPORT) &&
 	    (type >= MDDB_FIRST_MODID) &&
-	    (rbp->rb_revision == MDDB_REV_RB)) {
+	    ((rbp->rb_revision == MDDB_REV_RB) ||
+		(rbp->rb_revision == MDDB_REV_RBFN))) {
 
 		switch (dep->de_flags) {
 
@@ -8859,9 +8881,15 @@
 
 	/* Do we have to create an old style (32 bit) record?  */
 	if (options & MD_CRO_32BIT) {
-		rbp->rb_revision = MDDB_REV_RB;
+		if (options & MD_CRO_FN)
+			rbp->rb_revision = MDDB_REV_RBFN;
+		else
+			rbp->rb_revision = MDDB_REV_RB;
 	} else {
-		rbp->rb_revision = MDDB_REV_RB64;
+		if (options & MD_CRO_FN)
+			rbp->rb_revision = MDDB_REV_RB64FN;
+		else
+			rbp->rb_revision = MDDB_REV_RB64;
 	}
 
 	/* set de_rb_userdata for non optimization records */
@@ -11971,6 +11999,14 @@
 	return (0);
 }
 
+/*
+ * md_update_minor
+ *
+ * This function updates the minor in the namespace entry for an
+ * underlying metadevice.  The function is called in mod_imp_set
+ * where mod is sp, stripe, mirror and raid.
+ *
+ */
 int
 md_update_minor(
 	set_t	setno,
@@ -12025,6 +12061,68 @@
 	return (retval);
 }
 
+/*
+ * md_update_top_device_minor
+ *
+ * This function updates the minor in the namespace entry for a top
+ * level metadevice.  The function is called in mod_imp_set where
+ * mod is sp, stripe, mirror and raid.
+ *
+ */
+int
+md_update_top_device_minor(
+	set_t	setno,
+	side_t	side,
+	md_dev64_t dev
+)
+{
+	struct nm_next_hdr	*nh;
+	struct nm_name		*n;
+	char			*shn;
+	int			retval = 1;
+
+	/*
+	 * Load the devid name space if it exists
+	 */
+	(void) md_load_namespace(setno, NULL, NM_DEVID);
+	if (! md_load_namespace(setno, NULL, 0L)) {
+		/*
+		 * Unload the devid namespace
+		 */
+		(void) md_unload_namespace(setno, NM_DEVID);
+		return (0);
+	}
+
+	rw_enter(&nm_lock.lock, RW_READER);
+
+	if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) {
+		retval = 0;
+		goto out;
+	}
+
+	/*
+	 * Look up the key
+	 */
+	if ((n = lookup_entry(nh, setno, side, MD_KEYWILD, dev, 0L)) != NULL) {
+		/*
+		 * Find the entry, update its n_minor if metadevice
+		 */
+		if ((shn = (char *)getshared_name(setno, n->n_drv_key, 0L))
+		    == NULL) {
+			retval = 0;
+			goto out;
+		}
+
+		if (strcmp(shn, "md") == 0) {
+			n->n_minor = MD_MKMIN(setno, MD_MIN2UNIT(n->n_minor));
+		}
+	}
+
+out:
+	rw_exit(&nm_lock.lock);
+	return (retval);
+}
+
 static void
 md_imp_nm(
 	mddb_set_t	*s
@@ -12326,6 +12424,7 @@
 	md_drive_record	*dr;
 	size_t		dr_size = sizeof (md_drive_record);
 	mdkey_t		dr_key;
+	md_error_t	error = MDNULLERROR;
 
 
 	if ((s = mddb_setenter(setno, MDDB_MUSTEXIST, &err)) == NULL)
@@ -12356,7 +12455,7 @@
 		 */
 		if ((dr_key = md_setdevname(MD_LOCAL_SET, 1, MD_KEYWILD,
 		    rip->ri_driver, md_getminor(rip->ri_dev),
-		    rip->ri_devname, setno)) == 0)
+		    rip->ri_devname, setno, &error)) == 0)
 			continue;
 
 		if (dr_key < 0) {
--- a/usr/src/uts/common/io/lvm/md/md_names.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/md/md_names.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -50,6 +49,27 @@
 void		md_devid_cleanup(set_t, uint_t);
 extern md_krwlock_t	nm_lock;
 
+typedef enum lookup_dev_result {
+	LOOKUP_DEV_FOUND,	/* Found a good record. */
+	LOOKUP_DEV_NOMATCH,	/* No matching record in DB. */
+	LOOKUP_DEV_CONFLICT	/* Name conflicts with existing record. */
+} lookup_dev_result_t;
+
+/* List of SVM module names. */
+static char *meta_names[] = {
+	"md",
+	MD_STRIPE,
+	MD_MIRROR,
+	MD_TRANS,
+	MD_HOTSPARES,
+	MD_RAID,
+	MD_VERIFY,
+	MD_SP,
+	MD_NOTIFY
+};
+
+#define	META_NAME_COUNT	(sizeof (meta_names) / sizeof (char *))
+
 /*
  * Used in translating from the md major name on miniroot to
  * md major name on target system.  This is only needed during
@@ -951,10 +971,18 @@
 	mdkey_t			shn_key;
 	ushort_t		shn_namlen;
 
-	if (nm != (char *)0)
+	if (nm == (char *)0) {
+		/* No name.  Search by key only. */
+		if (key == MD_KEYBAD) {
+			/* No key either.  Nothing to remove. */
+			return (0);
+		}
+	} else {
+		/* How long is the name? */
 		nm_len = ((devid_nm & NM_DEVID) ?
 			ddi_devid_sizeof((ddi_devid_t)nm) :
 			(strlen(nm) + 1));
+	}
 
 	this_rh = ((devid_nm & NM_DEVID) ?
 		&((struct devid_shr_rec *)record)->did_rec_hdr :
@@ -1132,7 +1160,7 @@
 
 			if ((key == MD_KEYWILD) && !devid_nm &&
 			    (dev == build_device_number(setno,
-					(struct nm_name *)n)))
+			    (struct nm_name *)n)))
 				return ((void *)n);
 		}
 
@@ -1162,7 +1190,29 @@
 	/*NOTREACHED*/
 }
 
-static struct nm_name *
+static int
+is_meta_drive(set_t setno, mdkey_t key)
+{
+	int				i;
+	struct nm_next_hdr		*nh;
+	struct nm_shared_name		*shn;
+
+	if ((nh = get_first_record(setno, 0, NM_SHARED)) == NULL)
+		return (FALSE);
+	if ((shn = (struct nm_shared_name *)lookup_shared_entry(nh,
+		key, NULL, NULL, NM_SHARED)) == NULL) {
+		return (FALSE);
+	}
+
+	/* See if the name is a metadevice. */
+	for (i = 0; i < META_NAME_COUNT; i++) {
+		if (strcmp(meta_names[i], shn->sn_name) == 0)
+			return (TRUE);
+	}
+	return (FALSE);
+}
+
+static lookup_dev_result_t
 lookup_deventry(
 	struct nm_next_hdr	*nh,	/* head record header */
 	set_t			setno,	/* set to lookup in */
@@ -1171,7 +1221,8 @@
 	char			*drvnm,	/* drvnm to be stored */
 	minor_t			mnum,	/* minor number to be stored */
 	char			*dirnm,	/* directory name to be stored */
-	char			*filenm	/* device filename to be stored */
+	char			*filenm, /* device filename to be stored */
+	struct nm_name		**ret_rec /* place return found rec. */
 )
 {
 	struct nm_next_hdr	*this_nh = nh->nmn_nextp;
@@ -1181,8 +1232,9 @@
 	size_t			offset;
 	mdkey_t			dirkey, drvkey;
 
+	*ret_rec = NULL;
 	if (this_nh == NULL)
-		return (0);
+		return (LOOKUP_DEV_NOMATCH);
 
 	record = (struct nm_rec *)this_nh->nmn_record;
 	this_rh = &record->r_rec_hdr;
@@ -1191,11 +1243,16 @@
 	offset = sizeof (struct nm_rec) - sizeof (struct nm_name);
 
 	if ((drvkey = getshared_key(setno, drvnm, 0L)) == MD_KEYBAD)
-		return (NULL);
-
-	if ((dirkey = getshared_key(setno, dirnm, 0L)) == MD_KEYBAD)
-		return (NULL);
-
+		return (LOOKUP_DEV_NOMATCH);
+
+	if (dirnm == NULL) {
+		/* No directory name to look up. */
+		dirkey = MD_KEYBAD;
+	} else {
+		/* Look up the directory name */
+		if ((dirkey = getshared_key(setno, dirnm, 0L)) == MD_KEYBAD)
+			return (LOOKUP_DEV_NOMATCH);
+	}
 	ASSERT(side != MD_SIDEWILD);
 
 	/* code to see if EMPTY record */
@@ -1203,7 +1260,7 @@
 		/* Go to next record */
 		this_nh = this_nh->nmn_nextp;
 		if (this_nh == NULL)
-			return (0);
+			return (LOOKUP_DEV_NOMATCH);
 		record = (struct nm_rec *)this_nh->nmn_record;
 		this_rh = &record->r_rec_hdr;
 		n = &record->r_name[0];
@@ -1216,15 +1273,83 @@
 		    (mnum == n->n_minor) &&
 		    (drvkey == n->n_drv_key) &&
 		    (dirkey == n->n_dir_key) &&
-		    (strcmp(filenm, n->n_name) == 0))
-			return (n);
-
+		    (strcmp(filenm, n->n_name) == 0)) {
+			*ret_rec = n;
+			return (LOOKUP_DEV_FOUND);
+		}
+
+		/*
+		 * Now check for a name conflict.  If the filenm of the
+		 * current record matches filename passed in we have a
+		 * potential conflict.  If all the other parameters match
+		 * except for the side number, then this is not a
+		 * conflict.  The reason is that there are cases where name
+		 * record is added to each side of a set.
+		 *
+		 * There is one additional complication.  It is only a
+		 * conflict if the drvkeys both represent metadevices.  It
+		 * is legal for a metadevice and a physical device to have
+		 * the same name.
+		 */
+		if (strcmp(filenm, n->n_name) == 0) {
+			int	both_meta;
+
+			/*
+			 * It is hsp and we are trying to add it twice
+			 */
+			if (strcmp(getshared_name(setno, n->n_drv_key, 0L),
+			    MD_HOTSPARES) == 0 && (side == n->n_side) &&
+			    find_hot_spare_pool(setno,
+				KEY_TO_HSP_ID(setno, n->n_key)) == NULL) {
+				/*
+				 * All entries removed
+				 */
+				rw_exit(&nm_lock.lock);
+				(void) md_rem_hspname(setno, n->n_key);
+				rw_enter(&nm_lock.lock, RW_WRITER);
+				return (LOOKUP_DEV_NOMATCH);
+			}
+
+			/*
+			 * It is metadevice and we are trying to add it twice
+			 */
+			if (md_set[setno].s_un[MD_MIN2UNIT(n->n_minor)]
+				== NULL && (side == n->n_side) &&
+			    ddi_name_to_major(getshared_name(setno,
+				n->n_drv_key, 0L)) == md_major) {
+				/*
+				 * Apparently it is invalid so
+				 * clean it up
+				 */
+				(void) md_remove_minor_node(n->n_minor);
+				rw_exit(&nm_lock.lock);
+				(void) md_rem_selfname(n->n_minor);
+				rw_enter(&nm_lock.lock, RW_WRITER);
+				return (LOOKUP_DEV_NOMATCH);
+			}
+
+			/* First see if the two drives are metadevices. */
+			if (is_meta_drive(setno, drvkey) &&
+				is_meta_drive(setno, n->n_drv_key)) {
+				both_meta = TRUE;
+			} else {
+				both_meta = FALSE;
+			}
+			/* Check rest of the parameters. */
+			if ((both_meta == TRUE) &&
+				((key != n->n_key) ||
+				(mnum != n->n_minor) ||
+				(drvkey != n->n_drv_key) ||
+				(dirkey != n->n_dir_key))) {
+				return (LOOKUP_DEV_CONFLICT);
+			}
+		}
 		n = (struct nm_name *)get_next_entry(this_nh, (caddr_t)n,
 		    NAMSIZ(n), &offset);
 
 		if (n == (struct nm_name *)0) {
 			if (offset)
-				return (n);
+				return (LOOKUP_DEV_NOMATCH);
 
 			/* Go to next record */
 			offset = sizeof (struct nm_rec) -
@@ -1368,6 +1493,129 @@
 	/*NOTREACHED*/
 }
 
+
+/*
+ * lookup_hspentry - Getting a hotspare pool entry from the namespace.
+ *		     Use either the NM key or the hotspare name to find
+ *		     a matching record in the namespace of the set.
+ */
+void *
+lookup_hspentry(
+	struct nm_next_hdr	*nh,	/* head record header */
+	set_t			setno,	/* set to lookup in */
+	side_t			side,	/* (key 1) side number */
+	mdkey_t			key,	/* (key 2) from md_setdevname */
+	char			*name	/* (alt. key 2), if key == MD_KEYWILD */
+)
+{
+	struct nm_next_hdr	*this_nh = nh->nmn_nextp;
+	struct nm_rec		*record;
+	struct nm_rec_hdr	*this_rh;
+	struct nm_name		*n;
+	size_t			offset, n_offset, n_size;
+	side_t			n_side;
+	mdkey_t			n_key;
+	char			*drv_name;
+	char			*tmpname;
+	char			*setname = NULL;
+
+	if ((key == MD_KEYWILD) && (name == '\0'))
+		return ((void *)0);
+
+	if (this_nh == NULL)
+		return ((void *)0);
+
+	record = (struct nm_rec *)this_nh->nmn_record;
+
+	this_rh = &record->r_rec_hdr;
+
+	if (setno != MD_LOCAL_SET) {
+		setname = mddb_getsetname(setno);
+		if (setname == NULL)
+			return ((void *)0);
+	}
+
+	/* code to see if EMPTY record */
+	while (this_nh && this_rh->r_used_size == sizeof (struct nm_rec_hdr)) {
+		/* Go to next record */
+		this_nh = this_nh->nmn_nextp;
+		if (this_nh == NULL)
+			return ((void *)0);
+		record = this_nh->nmn_record;
+		this_rh = &record->r_rec_hdr;
+	}
+
+	/*
+	 * n_offset will be used to reset offset
+	 */
+	n_offset = offset = (sizeof (struct nm_rec) - sizeof (struct nm_name));
+
+	n = ((struct nm_name *)&record->r_name[0]);
+
+	tmpname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
+
+	/*CONSTCOND*/
+	while (1) {
+		n_side = n->n_side;
+		n_size = NAMSIZ(n);
+		if ((drv_name = (char *)getshared_name(setno,
+		    n->n_drv_key, 0L)) != NULL) {
+
+			/* We're only interested in hsp NM records */
+			if ((strcmp(drv_name, "md_hotspares") == 0) &&
+			    ((side == n_side) || (side == MD_SIDEWILD))) {
+				n_key = n->n_key;
+
+				if ((key != MD_KEYWILD) && (key == n_key))
+					goto done;
+
+				/*
+				 * Searching by a hotspare pool name.
+				 * Since the input name is of the form
+				 * setname/hsp_name, we need to attach
+				 * the string 'setname/' in front of the
+				 * n->n_name.
+				 */
+				if (key == MD_KEYWILD) {
+					if (setname != NULL)
+					    (void) snprintf(tmpname, MAXPATHLEN,
+						"%s/%s", setname,
+						((struct nm_name *)n)->n_name);
+					else
+					    (void) snprintf(tmpname, MAXPATHLEN,
+						"%s",
+						((struct nm_name *)n)->n_name);
+
+					if ((strcmp(name, tmpname)) == 0)
+						goto done;
+				}
+			}
+		}
+
+		n = (struct nm_name *)get_next_entry(this_nh, (caddr_t)n,
+		    n_size, &offset);
+
+		if (n == NULL) {
+			/*
+			 * No next record, return
+			 */
+			if (offset)
+				goto done;
+
+			/* Go to next record */
+			offset = n_offset;
+			this_nh = this_nh->nmn_nextp;
+			record = (struct nm_rec *)this_nh->nmn_record;
+			this_rh = &record->r_rec_hdr;
+			n = ((struct nm_name *)&record->r_name[0]);
+		}
+	}
+
+done:
+	kmem_free(tmpname, MAXPATHLEN);
+	return ((void *)n);
+}
+
 static int
 md_make_devname(struct nm_name *n, set_t setno, char *string, size_t max_size)
 {
@@ -1484,7 +1732,8 @@
 	char	*drvnm,		/* store this driver name with devicename */
 	minor_t	mnum,		/* store this minor number as well */
 	char	*devname,	/* device name to be stored */
-	set_t	imp_setno	/* used exclusively by import */
+	set_t	imp_setno,	/* used exclusively by import */
+	md_error_t *ep		/* place to return error info */
 )
 {
 	struct nm_next_hdr	*nh, *did_nh = NULL;
@@ -1500,6 +1749,7 @@
 	dev_t			devt;
 	char			*mname = NULL;
 	side_t			thisside = MD_SIDEWILD;
+	lookup_dev_result_t	lookup_res;
 	mdkey_t			min_devid_key = MD_KEYWILD;
 	size_t			min_len;
 
@@ -1602,23 +1852,29 @@
 
 	/* find boundary between filename and directory */
 	cp = strrchr(devname, '/');
-	ASSERT(cp != NULL);
-
-	/* Isolate the directory name only; save character after '/' */
-	c = *(cp + 1);
-	*(cp + 1) = '\0';
-	dname = md_strdup(devname);
-
-	/* Restore character after '/' */
-	*(cp + 1) = c;
-	fname = cp+1;
+
+	if (cp == NULL) {
+		/* No directory part to the name. */
+		fname = devname;
+		dname = NULL;
+	} else {
+		/* Isolate the directory name only; save character after '/' */
+		c = *(cp + 1);
+		*(cp + 1) = '\0';
+		dname = md_strdup(devname);
+
+		/* Restore character after '/' */
+		*(cp + 1) = c;
+		fname = cp+1;
+	}
 
 	/*
 	 * If it already there in the name space
 	 */
-	if ((n = lookup_deventry(nh, setno, side, key,
-	    drvnm, mnum, dname, fname)) != NULL) {
-
+	lookup_res = lookup_deventry(nh, setno, side, key, drvnm, mnum, dname,
+		fname, &n);
+	switch (lookup_res) {
+	case LOOKUP_DEV_FOUND:
 		/* If we are importing the set */
 		if (md_get_setstatus(imp_setno) & MD_SET_IMPORT) {
 			retval = 0;
@@ -1654,73 +1910,96 @@
 			}
 		}
 		goto out;
-	}
-
-	/* Create a new name entry */
-	new = 1;
-	n = (struct nm_name *)alloc_entry(nh, md_set[setno].s_nmid,
-	    strlen(fname)+1, NM_NOTSHARED, &recids[0]);
-
-	if (n == NULL)
+
+	case LOOKUP_DEV_CONFLICT:
+		(void) mderror(ep, MDE_NAME_IN_USE);
+		retval = MD_KEYBAD;
 		goto out;
 
-	n->n_minor = mnum;
-	n->n_side = side;
-	n->n_key = ((key == MD_KEYWILD) ? create_key(nh) : key);
-	n->n_count = 1;
-
-	/* fill-in filename */
-	(void) strcpy(n->n_name, fname);
-	n->n_namlen = (ushort_t)(strlen(fname) + 1);
-
-	/*
-	 * If MDE_DB_NOSPACE occurs
-	 */
-	if (((n->n_drv_key =
-	    setshared_name(setno, drvnm, MD_KEYWILD, 0L)) == MD_KEYBAD) ||
-	    ((n->n_dir_key =
-	    setshared_name(setno, dname, MD_KEYWILD, 0L)) == MD_KEYBAD)) {
-		/*
-		 * Remove entry allocated by alloc_entry
-		 * and return MD_KEYBAD
-		 */
-		(void) remove_entry(nh, n->n_side, n->n_key, 0L);
-		goto out;
-	}
-
-	recids[1] = md_set[setno].s_nmid;
-	recids[2] = 0;
-	mddb_commitrecs_wrapper(recids);
-	retval = n->n_key;
-
-	/*
-	 * Now to find out if devid's were used for thisside and if
-	 * so what is the devid_key for the entry so that the correct
-	 * minor name entry (did_n) has the correct devid key.
-	 * Also get the minor name of the device, use the minor name
-	 * on this side because the assumption is that the slices are
-	 * going to be consistant across the nodes.
-	 */
-	if (key != MD_KEYWILD && (shared & NM_DEVID)) {
-		if ((did_n = (struct did_min_name *)
-		    lookup_entry(did_nh, setno, thisside, n->n_key,
-		    NODEV64, NM_DEVID)) == NULL) {
-			shared &= ~NM_DEVID;
-		} else {
-			min_devid_key = did_n->min_devid_key;
-			min_len = (size_t)did_n->min_namlen;
-		}
-	} else {
+	case LOOKUP_DEV_NOMATCH:
+		/* Create a new name entry */
+		new = 1;
+		n = (struct nm_name *)alloc_entry(nh, md_set[setno].s_nmid,
+		    strlen(fname)+1, NM_NOTSHARED, &recids[0]);
+
+		if (n == NULL)
+			goto out;
+
+		n->n_minor = mnum;
+		n->n_side = side;
+		n->n_key = ((key == MD_KEYWILD) ? create_key(nh) : key);
+		n->n_count = 1;
+
+		/* fill-in filename */
+		(void) strcpy(n->n_name, fname);
+		n->n_namlen = (ushort_t)(strlen(fname) + 1);
 
 		/*
-		 * It is possible for the minor name to be null, for
-		 * example a metadevice which means the minor name is
-		 * not initialised.
+		 * If MDE_DB_NOSPACE occurs
 		 */
-		if (mname == NULL)
+		if (((n->n_drv_key =
+			setshared_name(setno, drvnm, MD_KEYWILD, 0L)) ==
+			MD_KEYBAD)) {
+			/*
+			 * Remove entry allocated by alloc_entry
+			 * and return MD_KEYBAD
+			 */
+			(void) remove_entry(nh, n->n_side, n->n_key, 0L);
 			goto out;
-
-		min_len = strlen(mname) + 1;
+		}
+		if (dname == NULL) {
+			/* No directory name implies no key. */
+			n->n_dir_key = MD_KEYBAD;
+		} else {
+			/* We have a directory name to save. */
+			if ((n->n_dir_key =
+				setshared_name(setno, dname, MD_KEYWILD, 0L)) ==
+				MD_KEYBAD) {
+				/*
+				 * Remove entry allocated by alloc_entry
+				 * and return MD_KEYBAD
+				 */
+				(void) remove_entry(nh, n->n_side, n->n_key,
+					0L);
+				goto out;
+			}
+		}
+
+		recids[1] = md_set[setno].s_nmid;
+		recids[2] = 0;
+		mddb_commitrecs_wrapper(recids);
+		retval = n->n_key;
+
+		/*
+		 * Now to find out if devid's were used for thisside and if
+		 * so what is the devid_key for the entry so that the correct
+		 * minor name entry (did_n) has the correct devid key.
+		 * Also get the minor name of the device, use the minor name
+		 * on this side because the assumption is that the slices are
+		 * going to be consistant across the nodes.
+		 */
+		if (key != MD_KEYWILD && (shared & NM_DEVID)) {
+			if ((did_n = (struct did_min_name *)
+			    lookup_entry(did_nh, setno, thisside, n->n_key,
+			    NODEV64, NM_DEVID)) == NULL) {
+				shared &= ~NM_DEVID;
+			} else {
+				min_devid_key = did_n->min_devid_key;
+				min_len = (size_t)did_n->min_namlen;
+			}
+		} else {
+
+			/*
+			 * It is possible for the minor name to be null, for
+			 * example a metadevice which means the minor name is
+			 * not initialised.
+			 */
+			if (mname == NULL)
+				goto out;
+
+			min_len = strlen(mname) + 1;
+		}
+		break;
 	}
 
 	/*
@@ -2104,6 +2383,91 @@
 }
 
 /*
+ * md_gethspinfo -  Getting a hsp name or id from the database.
+ *		    A pointer to a character array is passed in for
+ *		    the hsp name to be built in. If a match is found,
+ *		    the corresponding hspid is stored in ret_hspid.
+ */
+int
+md_gethspinfo(
+	set_t	setno,		/* which set to get name from */
+	side_t	side,		/* (key 1) side number */
+	mdkey_t	key,		/* (key 2) key provided by md_setdevname() */
+	char	*drvnm,		/* return driver name here */
+	hsp_t	*ret_hspid,	/* returned key if key is MD_KEYWILD */
+	char	*hspname	/* alternate key or returned device name */
+)
+{
+	struct nm_next_hdr	*nh;
+	struct nm_name		*n;
+	char			*drv_name;
+	int			err = 0;
+	char			*setname = NULL;
+
+	/*
+	 * Load the devid name space if it exists
+	 */
+	(void) md_load_namespace(setno, NULL, NM_DEVID);
+	if (! md_load_namespace(setno, NULL, 0L)) {
+		/*
+		 * Unload the devid namespace
+		 */
+		(void) md_unload_namespace(setno, NM_DEVID);
+		return (ENOENT);
+	}
+
+	rw_enter(&nm_lock.lock, RW_READER);
+
+	if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) {
+		rw_exit(&nm_lock.lock);
+		return (ENOENT);
+	}
+
+	if ((n = (struct nm_name *)lookup_hspentry(nh, setno, side,
+	    key, hspname)) == NULL) {
+		rw_exit(&nm_lock.lock);
+		return (ENOENT);
+	}
+
+	/* Copy the driver name, device name and key for return */
+	drv_name = (char *)getshared_name(setno, n->n_drv_key, 0L);
+	if (!drv_name || (strlen(drv_name) > MD_MAXDRVNM)) {
+		rw_exit(&nm_lock.lock);
+		return (EFAULT);
+	}
+
+	/*
+	 * Pre-friendly hsp names are of the form hspxxx and we
+	 * should not have an entry in the namespace for them.
+	 * So make sure the NM entry we get is a hotspare pool.
+	 */
+	if ((strcmp(drv_name, "md_hotspares")) != 0) {
+		rw_exit(&nm_lock.lock);
+		return (ENOENT);
+	}
+	(void) strcpy(drvnm, drv_name);
+
+	/*
+	 * If the input key is not MD_KEYWILD, return the
+	 * hspname we found.
+	 */
+	if (key != MD_KEYWILD) {
+		setname = mddb_getsetname(setno);
+		if (setname != NULL)
+			(void) snprintf(hspname, MAXPATHLEN,
+			    "%s/%s", setname, n->n_name);
+		else
+			(void) snprintf(hspname, MAXPATHLEN,
+			    "%s", n->n_name);
+	}
+
+	*ret_hspid = KEY_TO_HSP_ID(setno, n->n_key);
+
+	rw_exit(&nm_lock.lock);
+	return (err);
+}
+
+/*
  * md_devid_found  - Check to see if this key has devid entry or not
  *		     Return 1 if there is one or 0 if none
  */
--- a/usr/src/uts/common/io/lvm/md/md_rename.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/md/md_rename.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1996-2002 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -738,6 +737,8 @@
 {
 	minor_t		from_min, to_min;
 	sv_dev_t	sv;
+	mddb_de_ic_t	*dep;
+	mddb_rb32_t	*rbp;
 
 	ASSERT(rtxnp);
 	ASSERT(rtxnp->op == MDRNOP_RENAME);
@@ -756,8 +757,21 @@
 	/*
 	 * self id changes in our own unit struct
 	 */
+	MD_SID(delta->unp) = to_min;
 
-	MD_SID(delta->unp) = to_min;
+	/*
+	 * make sure that dest always has correct un_revision
+	 * and rb_revision
+	 */
+	delta->unp->c.un_revision |= MD_FN_META_DEV;
+	dep = mddb_getrecdep(MD_RECID(delta->unp));
+	ASSERT(dep);
+	rbp = dep->de_rb;
+	if (rbp->rb_revision & MDDB_REV_RB) {
+		rbp->rb_revision = MDDB_REV_RBFN;
+	} else if (rbp->rb_revision & MDDB_REV_RB64) {
+		rbp->rb_revision = MDDB_REV_RB64FN;
+	}
 
 	/*
 	 * clear old array pointers to unit in-core and unit
@@ -798,6 +812,11 @@
 	md_rem_names(&sv, 1);
 
 	/*
+	 * Remove associated device node as well
+	 */
+	(void) md_remove_minor_node(from_min);
+
+	/*
 	 * and store the record id (from the unit struct) into recids
 	 * for later commitment by md_rename()
 	 */
@@ -1644,14 +1663,38 @@
 	IOLOCK		*iolockp)
 {
 	md_rendelta_t	*family		= NULL;
-	md_rentxn_t	 rtxn;
-	int		 err		= 0;
-	set_t		 setno;
+	md_rentxn_t	rtxn;
+	int		err		= 0;
+	set_t		setno;
+	mdc_unit_t	*mdc;
 
 	ASSERT(iolockp);
 	if (mrp == NULL)
 		return (EINVAL);
 
+	setno = MD_MIN2SET(mrp->from.mnum);
+	if (setno >= md_nsets) {
+		return (EINVAL);
+	}
+
+	/*
+	 * Early exit if top is eof trans
+	 */
+	mdc = (mdc_unit_t *)md_set[setno].s_un[MD_MIN2UNIT(mrp->from.mnum)];
+	while (mdc != NULL) {
+	    if (!MD_HAS_PARENT(mdc->un_parent)) {
+		break;
+	    } else {
+		mdc = (mdc_unit_t *)md_set[setno].s_un[MD_MIN2UNIT
+		    (mdc->un_parent)];
+	    }
+	}
+
+	if (mdc && mdc->un_type == MD_METATRANS) {
+		return (EINVAL);
+	}
+
+
 	mdclrerror(&mrp->mde);
 
 	bzero((void *) &rtxn, sizeof (md_rentxn_t));
@@ -1668,13 +1711,6 @@
 	rtxn.uflags	= mrp->flags;
 	rtxn.revision	= mrp->revision;
 
-
-	setno = MD_MIN2SET(rtxn.from.mnum);
-	if (setno >= md_nsets) {
-		err = EINVAL;
-		goto cleanup;
-	}
-
 	if (MD_MIN2UNIT(mrp->to.mnum) >= md_nunits) {
 		err = EINVAL;
 		goto cleanup;
--- a/usr/src/uts/common/io/lvm/md/md_subr.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/md/md_subr.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -54,6 +53,7 @@
 #include <sys/errno.h>
 #include <sys/door.h>
 #include <sys/lvm/mdmn_commd.h>
+#include <sys/lvm/md_hotspares.h>
 
 #include <sys/lvm/mdvar.h>
 #include <sys/lvm/md_names.h>
@@ -109,6 +109,9 @@
 
 extern mddb_set_t	*mddb_setenter(set_t setno, int flag, int *errorcodep);
 extern void		mddb_setexit(mddb_set_t *s);
+extern void		*lookup_entry(struct nm_next_hdr *, set_t,
+				side_t, mdkey_t, md_dev64_t, int);
+extern struct nm_next_hdr	*get_first_record(set_t, int, int);
 
 struct mdq_anchor	md_done_daemon; /* done request queue */
 struct mdq_anchor	md_mstr_daemon; /* mirror timeout requests */
@@ -2837,7 +2840,7 @@
 	}
 	/* setup the unavailable field */
 #if defined(_ILP32)
-	if (((md_unit_t *)MD_UNIT(mnum))->c.un_revision == MD_64BIT_META_DEV) {
+	if (((md_unit_t *)MD_UNIT(mnum))->c.un_revision & MD_64BIT_META_DEV) {
 		ui->ui_tstate |= MD_64MD_ON_32KERNEL;
 		cmn_err(CE_NOTE, "d%d is unavailable because 64 bit "
 		    "metadevices are not accessible on a 32 bit kernel",
@@ -2952,22 +2955,69 @@
 	minor_t		mnum
 )
 {
-	static char	buf[MD_MAX_SIDENAME_LEN];
+	static char	buf[MAXPATHLEN];
+	char		*devname;
+	char		*invalid = " (Invalid minor number %u) ";
+	char		*metaname;
+	mdc_unit_t	*un;
+	side_t		side;
 	set_t		setno = MD_MIN2SET(mnum);
 	unit_t		unit = MD_MIN2UNIT(mnum);
 
-	if ((setno >= md_nsets) || (unit >= md_nunits)) {
-		(void) snprintf(buf, 40, " (Invalid minor number %u) ", mnum);
+	if ((un = MD_UNIT(mnum)) == NULL) {
+		(void) snprintf(buf, sizeof (buf), invalid, mnum);
+		return (buf);
+	}
+
+	/*
+	 * If unit is not a friendly name unit, derive the name from the
+	 * minor number.
+	 */
+	if ((un->un_revision & MD_FN_META_DEV) == 0) {
+		/* This is a traditional metadevice */
+		if (setno == MD_LOCAL_SET) {
+			(void) snprintf(buf, sizeof (buf), "d%u",
+				(unsigned)unit);
+		} else {
+			(void) snprintf(buf, sizeof (buf), "%s/d%u",
+			    mddb_getsetname(setno), (unsigned)unit);
+		}
 		return (buf);
 	}
 
-	if (setno == 0) {
-		(void) sprintf(buf, "d%u", (unsigned)unit);
+	/*
+	 * It is a friendly name metadevice, so we need to get its name.
+	 */
+	side = mddb_getsidenum(setno);
+	devname = (char *)kmem_alloc(MAXPATHLEN, KM_SLEEP);
+	if (md_getdevname(setno, side, MD_KEYWILD,
+		md_makedevice(md_major, mnum), devname, MAXPATHLEN) == 0) {
+		/*
+		 * md_getdevname has given us either /dev/md/dsk/<metaname>
+		 * or /dev/md/<setname>/dsk/<metname> depending on whether
+		 * or not we are in the local set.  Thus, we'll pull the
+		 * metaname from this string.
+		 */
+		if ((metaname = strrchr(devname, '/')) == NULL) {
+			(void) snprintf(buf, sizeof (buf), invalid, mnum);
+			goto out;
+		}
+		metaname++;	/* move past slash */
+		if (setno == MD_LOCAL_SET) {
+			/* No set name. */
+			(void) snprintf(buf, sizeof (buf), "%s", metaname);
+		} else {
+			/* Include setname */
+			(void) snprintf(buf, sizeof (buf), "%s/%s",
+				mddb_getsetname(setno), metaname);
+		}
 	} else {
-		(void) sprintf(buf, "%s/d%u",
-		    mddb_getsetname(setno), (unsigned)unit);
+		/* We couldn't find the name. */
+		(void) snprintf(buf, sizeof (buf), invalid, mnum);
 	}
 
+out:
+	kmem_free(devname, MAXPATHLEN);
 	return (buf);
 }
 
@@ -4036,3 +4086,82 @@
 	mutex_exit(cp->cc_lockp);
 	return (ret != -1);
 }
+
+
+void
+md_rem_hspname(set_t setno, mdkey_t n_key)
+{
+	int	s;
+	int	max_sides;
+
+
+	/* All entries removed are in the same diskset */
+	if (md_get_setstatus(setno) & MD_SET_MNSET)
+		max_sides = MD_MNMAXSIDES;
+	else
+		max_sides = MD_MAXSIDES;
+
+	for (s = 0; s < max_sides; s++)
+		(void) md_remdevname(setno, s, n_key);
+}
+
+
+int
+md_rem_selfname(minor_t selfid)
+{
+	int	s;
+	set_t	setno = MD_MIN2SET(selfid);
+	int	max_sides;
+	md_dev64_t	dev;
+	struct nm_next_hdr	*nh;
+	struct nm_name	*n;
+	mdkey_t key;
+
+	/*
+	 * Get the key since remove routine expects it
+	 */
+	dev = md_makedevice(md_major, selfid);
+	if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) {
+		return (ENOENT);
+	}
+
+	if ((n = (struct nm_name *)lookup_entry(nh, setno, MD_SIDEWILD,
+		MD_KEYWILD, dev, 0L)) == NULL) {
+		return (ENOENT);
+	}
+
+	/* All entries removed are in the same diskset */
+	key = n->n_key;
+	if (md_get_setstatus(setno) & MD_SET_MNSET)
+		max_sides = MD_MNMAXSIDES;
+	else
+		max_sides = MD_MAXSIDES;
+
+	for (s = 0; s < max_sides; s++)
+		(void) md_remdevname(setno, s, key);
+
+	return (0);
+}
+
+void
+md_upd_set_unnext(set_t setno, unit_t un)
+{
+	if (un < md_set[setno].s_un_next) {
+		md_set[setno].s_un_next = un;
+	}
+}
+
+struct hot_spare_pool *
+find_hot_spare_pool(set_t setno, int hsp_id)
+{
+	hot_spare_pool_t *hsp;
+
+	hsp = (hot_spare_pool_t *)md_set[setno].s_hsp;
+	while (hsp != NULL) {
+		if (hsp->hsp_self_id == hsp_id)
+			return (hsp);
+		hsp = hsp->hsp_next;
+	}
+
+	return ((hot_spare_pool_t *)0);
+}
--- a/usr/src/uts/common/io/lvm/mirror/mirror.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/mirror/mirror.c	Tue Mar 14 14:53:36 2006 -0800
@@ -49,6 +49,7 @@
 #include <sys/debug.h>
 #include <sys/dklabel.h>
 #include <vm/hat.h>
+#include <sys/lvm/mdvar.h>
 #include <sys/lvm/md_mirror.h>
 #include <sys/lvm/md_convert.h>
 #include <sys/lvm/md_mddb.h>
@@ -1971,6 +1972,11 @@
 
 	MD_UNIT(mnum) = NULL;
 
+	/*
+	 * Attempt release of its minor node
+	 */
+	(void) md_remove_minor_node(mnum);
+
 	if (!removing)
 		return;
 
@@ -2007,6 +2013,14 @@
 	cv_destroy(&un->un_rs_progress_cv);
 	mutex_destroy(&un->un_dmr_mx);
 	cv_destroy(&un->un_dmr_cv);
+
+	/*
+	 * Remove self from the namespace
+	 */
+	if (un->c.un_revision & MD_FN_META_DEV) {
+		(void) md_rem_selfname(un->c.un_self_id);
+	}
+
 	mddb_deleterec_wrapper(un->c.un_record_id);
 	if (recid != 0)
 		mddb_deleterec_wrapper(recid);
@@ -4348,7 +4362,6 @@
 	mm_unit_t	*un;
 	mm_submirror_t	*sm;
 	char		*sm_nm;
-	size_t		namelen;
 	uint_t		next_side;
 	void		*kbuffer;
 
@@ -4468,8 +4481,7 @@
 	sm = &un->un_sm[un->un_dmr_last_read];
 	sm_nm = md_shortname(md_getminor(sm->sm_dev));
 
-	namelen = MIN(MD_MAX_SIDENAME_LEN, VOL_SIDENAME);
-	(void) strncpy(vdr->vdr_side_name, sm_nm, namelen);
+	(void) strncpy(vdr->vdr_side_name, sm_nm, sizeof (vdr->vdr_side_name));
 
 	/*
 	 * Determine if we've completed the read cycle. This is true iff the
@@ -4996,43 +5008,55 @@
 		dep->de_flags = MDDB_F_MIRROR;
 		rbp = dep->de_rb;
 
-		if ((rbp->rb_revision == MDDB_REV_RB) &&
-		    ((rbp->rb_private & MD_PRV_CONVD) == 0)) {
-			/*
-			 * This means, we have an old and small record
-			 * and this record hasn't already been converted.
-			 * Before we create an incore metadevice from this
-			 * we have to convert it to a big record.
-			 */
-			small_un = (mm_unit32_od_t *)mddb_getrecaddr(recid);
-			newreqsize = sizeof (mm_unit_t);
-			big_un = (mm_unit_t *)kmem_zalloc(newreqsize, KM_SLEEP);
-			mirror_convert((caddr_t)small_un, (caddr_t)big_un,
-			    SMALL_2_BIG);
-			kmem_free(small_un, dep->de_reqsize);
-
-			/*
-			 * Update userdata and incore userdata
-			 * incores are at the end of un
-			 */
-			dep->de_rb_userdata_ic = big_un;
-			dep->de_rb_userdata = big_un;
-			dep->de_icreqsize = newreqsize;
-			un = big_un;
-			rbp->rb_private |= MD_PRV_CONVD;
-		} else {
+		switch (rbp->rb_revision) {
+		case MDDB_REV_RB:
+		case MDDB_REV_RBFN:
+			if ((rbp->rb_private & MD_PRV_CONVD) == 0) {
+				/*
+				 * This means, we have an old and small
+				 * record and this record hasn't already
+				 * been converted.  Before we create an
+				 * incore metadevice from this we have to
+				 * convert it to a big record.
+				 */
+				small_un =
+				    (mm_unit32_od_t *)mddb_getrecaddr(recid);
+				newreqsize = sizeof (mm_unit_t);
+				big_un = (mm_unit_t *)kmem_zalloc(newreqsize,
+					KM_SLEEP);
+				mirror_convert((caddr_t)small_un,
+					(caddr_t)big_un, SMALL_2_BIG);
+				kmem_free(small_un, dep->de_reqsize);
+
+				/*
+				 * Update userdata and incore userdata
+				 * incores are at the end of un
+				 */
+				dep->de_rb_userdata_ic = big_un;
+				dep->de_rb_userdata = big_un;
+				dep->de_icreqsize = newreqsize;
+				un = big_un;
+				rbp->rb_private |= MD_PRV_CONVD;
+			} else {
+				/*
+				 * Unit already converted, just get the
+				 * record address.
+				 */
+				un = (mm_unit_t *)mddb_getrecaddr_resize(recid,
+					sizeof (*un), 0);
+			}
+			un->c.un_revision &= ~MD_64BIT_META_DEV;
+			break;
+		case MDDB_REV_RB64:
+		case MDDB_REV_RB64FN:
 			/* Big device */
 			un = (mm_unit_t *)mddb_getrecaddr_resize(recid,
 				sizeof (*un), 0);
+			un->c.un_revision |= MD_64BIT_META_DEV;
+			un->c.un_flag |= MD_EFILABEL;
+			break;
 		}
-
-		/* Set revision and flag accordingly */
-		if (rbp->rb_revision == MDDB_REV_RB) {
-			un->c.un_revision = MD_32BIT_META_DEV;
-		} else {
-			un->c.un_revision = MD_64BIT_META_DEV;
-			un->c.un_flag |= MD_EFILABEL;
-		}
+		NOTE_FN(rbp->rb_revision, un->c.un_revision);
 
 		/*
 		 * Create minor device node for snarfed entry.
@@ -5397,6 +5421,7 @@
 	mddb_rb32_t	*rbp;
 	mm_unit32_od_t	*un32;
 	mm_unit_t	*un64;
+	md_dev64_t	self_devt;
 	minor_t		*self_id;	/* minor needs to be updated */
 	md_parent_t	*parent_id;	/* parent needs to be updated */
 	mddb_recid_t	*record_id;	/* record id needs to be updated */
@@ -5417,7 +5442,9 @@
 		dep = mddb_getrecdep(recid);
 		rbp = dep->de_rb;
 
-		if (rbp->rb_revision == MDDB_REV_RB) {
+		switch (rbp->rb_revision) {
+		case MDDB_REV_RB:
+		case MDDB_REV_RBFN:
 			/*
 			 * Small device
 			 */
@@ -5437,7 +5464,9 @@
 				(setno), un32->un_sm[i].sm_key))
 				goto out;
 			}
-		} else {
+			break;
+		case MDDB_REV_RB64:
+		case MDDB_REV_RB64FN:
 			un64 = (mm_unit_t *)mddb_getrecaddr(recid);
 			self_id = &(un64->c.un_self_id);
 			parent_id = &(un64->c.un_parent);
@@ -5454,6 +5483,21 @@
 				(setno), un64->un_sm[i].sm_key))
 				goto out;
 			}
+			break;
+		}
+
+		/*
+		 * If this is a top level and a friendly name metadevice,
+		 * update its minor in the namespace.
+		 */
+		if ((*parent_id == MD_NO_PARENT) &&
+		    ((rbp->rb_revision == MDDB_REV_RBFN) ||
+		    (rbp->rb_revision == MDDB_REV_RB64FN))) {
+
+			self_devt = md_makedevice(md_major, *self_id);
+			if (!md_update_top_device_minor(setno,
+			    mddb_getsidenum(setno), self_devt))
+				goto out;
 		}
 
 		/*
--- a/usr/src/uts/common/io/lvm/mirror/mirror_ioctl.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/mirror/mirror_ioctl.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -74,6 +73,7 @@
 extern mdq_anchor_t	md_ff_daemonq;
 extern void		md_probe_one();
 extern void		mirror_openfail_console_info();
+
 #ifdef DEBUG
 extern int		mirror_debug_flag;
 #endif
@@ -194,7 +194,7 @@
 		return (mdmderror(&msp->mde, MDE_UNIT_TOO_LARGE, mnum));
 #else
 		recid = mddb_createrec((size_t)msp->size, typ1, MIRROR_REC,
-					MD_CRO_64BIT | MD_CRO_MIRROR, setno);
+			MD_CRO_64BIT | MD_CRO_MIRROR | MD_CRO_FN, setno);
 #endif
 	} else {
 		/*
@@ -202,7 +202,7 @@
 		 */
 		msp->size = sizeof (mm_unit32_od_t);
 		recid = mddb_createrec((size_t)msp->size, typ1, MIRROR_REC,
-					MD_CRO_32BIT | MD_CRO_MIRROR, setno);
+			MD_CRO_32BIT | MD_CRO_MIRROR | MD_CRO_FN, setno);
 	}
 	if (recid < 0)
 		return (mddbstatus2error(&msp->mde, (int)recid,
@@ -229,6 +229,7 @@
 		un->c.un_flag |= MD_EFILABEL;
 	}
 
+	un->c.un_revision |= MD_FN_META_DEV;
 	MD_RECID(un)	= recid;
 	MD_CAPAB(un)	= MD_CAN_PARENT | MD_CAN_META_CHILD | MD_CAN_SP;
 	MD_PARENT(un)	= MD_NO_PARENT;
@@ -261,6 +262,11 @@
 		return (err);
 	}
 
+	/*
+	 * Update unit availability
+	 */
+	md_set[setno].s_un_avail--;
+
 	mirror_commit(un, ALL_SUBMIRRORS, 0);
 	md_create_unit_incore(MD_SID(un), &mirror_md_ops, 0);
 	mirror_check_failfast(mnum);
@@ -354,6 +360,7 @@
 	minor_t		mnum = mirp->mnum;
 	mm_unit_t	*un;
 	mdi_unit_t	*ui;
+	set_t		setno = MD_MIN2SET(mnum);
 
 	mdclrerror(&mirp->mde);
 
@@ -393,6 +400,21 @@
 	}
 
 	reset_mirror(un, mnum, 1);
+
+	/*
+	 * Update unit availability
+	 */
+	md_set[setno].s_un_avail++;
+
+	/*
+	 * If MN set, reset s_un_next so all nodes can have
+	 * the same view of the next available slot when
+	 * nodes are -w and -j
+	 */
+	if (MD_MNSET_SETNO(setno)) {
+		(void) md_upd_set_unnext(setno, MD_MIN2UNIT(mnum));
+	}
+
 	rw_exit(&md_unit_array_rw.lock);
 	return (0);
 }
@@ -1300,7 +1322,7 @@
 	un->c.un_actual_tb = total_blocks;
 
 	/* Is the mirror growing from 32 bit device to 64 bit device? */
-	if ((un->c.un_revision == MD_32BIT_META_DEV) &&
+	if (((un->c.un_revision & MD_64BIT_META_DEV) == 0) &&
 	    (un->c.un_total_blocks > MD_MAX_BLKS_FOR_SMALL_DEVS)) {
 #if defined(_ILP32)
 		return (mdmderror(ep, MDE_UNIT_TOO_LARGE, mnum));
@@ -1311,15 +1333,21 @@
 		mddb_recid_t	old_recid = un->c.un_record_id;
 		mddb_recid_t	old_vtoc;
 		mddb_de_ic_t    *dep, *old_dep;
+		md_create_rec_option_t	options;
 
 		/* yup, new device size. So we need to replace the record */
 		typ1 = (mddb_type_t)md_getshared_key(MD_UN2SET(un),
 		    mirror_md_ops.md_driver.md_drivername);
 		setno = MD_MIN2SET(mnum);
+
+		/* Preserve the friendly name properties of growing unit */
+		options = MD_CRO_64BIT | MD_CRO_MIRROR;
+		if (un->c.un_revision & MD_FN_META_DEV)
+			options |= MD_CRO_FN;
 		recid = mddb_createrec(offsetof(mm_unit_t, un_smic), typ1,
-		    MIRROR_REC, MD_CRO_64BIT | MD_CRO_MIRROR, setno);
+		    MIRROR_REC, options, setno);
 		/* Resize to include incore fields */
-		un->c.un_revision = MD_64BIT_META_DEV;
+		un->c.un_revision |= MD_64BIT_META_DEV;
 		/* All 64 bit metadevices only support EFI labels. */
 		un->c.un_flag |= MD_EFILABEL;
 		/*
--- a/usr/src/uts/common/io/lvm/raid/raid.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/raid/raid.c	Tue Mar 14 14:53:36 2006 -0800
@@ -1075,6 +1075,11 @@
 
 	kmem_free(un->mr_ic, sizeof (*un->mr_ic));
 
+	/*
+	 * Attempt release of its minor node
+	 */
+	(void) md_remove_minor_node(mnum);
+
 	if (!removing)
 		return;
 
@@ -1120,6 +1125,12 @@
 
 	raid_commit(un, recids);
 
+	/*
+	 * Remove self from the namespace
+	 */
+	if (un->c.un_revision & MD_FN_META_DEV) {
+		(void) md_rem_selfname(un->c.un_self_id);
+	}
 
 	/* Remove the unit structure */
 	mddb_deleterec_wrapper(un->c.un_record_id);
@@ -3649,38 +3660,49 @@
 		dep = mddb_getrecdep(recid);
 		dep->de_flags = MDDB_F_RAID;
 		rbp = dep->de_rb;
-		if ((rbp->rb_revision == MDDB_REV_RB) &&
-		    ((rbp->rb_private & MD_PRV_CONVD) == 0)) {
-			/*
-			 * This means, we have an old and small record
-			 * and this record hasn't already been converted.
-			 * Before we create an incore metadevice from this
-			 * we have to convert it to a big record.
-			 */
-			small_un = (mr_unit32_od_t *)mddb_getrecaddr(recid);
-			ncol = small_un->un_totalcolumncnt;
-			newreqsize = sizeof (mr_unit_t) +
-				((ncol - 1) * sizeof (mr_column_t));
-			big_un = (mr_unit_t *)kmem_zalloc(newreqsize, KM_SLEEP);
-			raid_convert((caddr_t)small_un, (caddr_t)big_un,
-				SMALL_2_BIG);
-			kmem_free(small_un, dep->de_reqsize);
-			dep->de_rb_userdata = big_un;
-			dep->de_reqsize = newreqsize;
-			un = big_un;
-			rbp->rb_private |= MD_PRV_CONVD;
-		} else {
+		switch (rbp->rb_revision) {
+		case MDDB_REV_RB:
+		case MDDB_REV_RBFN:
+			if ((rbp->rb_private & MD_PRV_CONVD) == 0) {
+				/*
+				 * This means, we have an old and small record
+				 * and this record hasn't already been
+				 * converted.  Before we create an incore
+				 * metadevice from this we have to convert it to
+				 * a big record.
+				 */
+				small_un =
+				    (mr_unit32_od_t *)mddb_getrecaddr(recid);
+				ncol = small_un->un_totalcolumncnt;
+				newreqsize = sizeof (mr_unit_t) +
+					((ncol - 1) * sizeof (mr_column_t));
+				big_un = (mr_unit_t *)kmem_zalloc(newreqsize,
+					KM_SLEEP);
+				raid_convert((caddr_t)small_un, (caddr_t)big_un,
+					SMALL_2_BIG);
+				kmem_free(small_un, dep->de_reqsize);
+				dep->de_rb_userdata = big_un;
+				dep->de_reqsize = newreqsize;
+				un = big_un;
+				rbp->rb_private |= MD_PRV_CONVD;
+			} else {
+				/*
+				 * Record has already been converted.  Just
+				 * get its address.
+				 */
+				un = (mr_unit_t *)mddb_getrecaddr(recid);
+			}
+			un->c.un_revision &= ~MD_64BIT_META_DEV;
+			break;
+		case MDDB_REV_RB64:
+		case MDDB_REV_RB64FN:
 			/* Big device */
 			un = (mr_unit_t *)mddb_getrecaddr(recid);
+			un->c.un_revision |= MD_64BIT_META_DEV;
+			un->c.un_flag |= MD_EFILABEL;
+			break;
 		}
-
-		/* Set revision and flag accordingly */
-		if (rbp->rb_revision == MDDB_REV_RB) {
-			un->c.un_revision = MD_32BIT_META_DEV;
-		} else {
-			un->c.un_revision = MD_64BIT_META_DEV;
-			un->c.un_flag |= MD_EFILABEL;
-		}
+		NOTE_FN(rbp->rb_revision, un->c.un_revision);
 
 		/*
 		 * Create minor device node for snarfed entry.
@@ -4255,6 +4277,7 @@
 	mddb_rb32_t	*rbp;
 	mr_unit_t	*un64;
 	mr_unit32_od_t	*un32;
+	md_dev64_t	self_devt;
 	minor_t		*self_id;	/* minor needs to be updated */
 	md_parent_t	*parent_id;	/* parent needs to be updated */
 	mddb_recid_t	*record_id;	 /* record id needs to be updated */
@@ -4273,7 +4296,9 @@
 		dep = mddb_getrecdep(recid);
 		rbp = dep->de_rb;
 
-		if (rbp->rb_revision == MDDB_REV_RB) {
+		switch (rbp->rb_revision) {
+		case MDDB_REV_RB:
+		case MDDB_REV_RBFN:
 			/*
 			 * Small device
 			 */
@@ -4295,7 +4320,9 @@
 				device->un_hs_id = MAKERECID(
 				setno, device->un_hs_id);
 			}
-		} else {
+			break;
+		case MDDB_REV_RB64:
+		case MDDB_REV_RB64FN:
 			un64 = (mr_unit_t *)mddb_getrecaddr(recid);
 			self_id = &(un64->c.un_self_id);
 			parent_id = &(un64->c.un_parent);
@@ -4314,6 +4341,21 @@
 				device->un_hs_id = MAKERECID(
 				setno, device->un_hs_id);
 			}
+			break;
+		}
+
+		/*
+		 * If this is a top level and a friendly name metadevice,
+		 * update its minor in the namespace.
+		 */
+		if ((*parent_id == MD_NO_PARENT) &&
+		    ((rbp->rb_revision == MDDB_REV_RBFN) ||
+		    (rbp->rb_revision == MDDB_REV_RB64FN))) {
+
+			self_devt = md_makedevice(md_major, *self_id);
+			if (!md_update_top_device_minor(setno,
+			    mddb_getsidenum(setno), self_devt))
+				goto out;
 		}
 
 		/*
--- a/usr/src/uts/common/io/lvm/raid/raid_ioctl.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/raid/raid_ioctl.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -295,7 +294,7 @@
 		if (biowait(&bp))
 			err = 1;
 		if (i == 0) {
-			if (un->c.un_revision == MD_64BIT_META_DEV) {
+			if (un->c.un_revision & MD_64BIT_META_DEV) {
 				unit = ((raid_pwhdr_t *)buf)->rpw_unit;
 			} else {
 				unit = ((raid_pwhdr32_od_t *)buf)->rpw_unit;
@@ -305,7 +304,7 @@
 		 * depending upon being an 64bit or 32 bit raid, the
 		 * pre write headers have different layout
 		 */
-		if (un->c.un_revision == MD_64BIT_META_DEV) {
+		if (un->c.un_revision & MD_64BIT_META_DEV) {
 			if ((((raid_pwhdr_t *)buf)->rpw_column != i) ||
 			    (((raid_pwhdr_t *)buf)->rpw_unit != unit))
 				err = 1;
@@ -916,11 +915,11 @@
 		return (mdmderror(&msp->mde, MDE_UNIT_TOO_LARGE, mnum));
 #else
 		mr_recid = mddb_createrec(msp->size, typ1, 0,
-				MD_CRO_64BIT | MD_CRO_RAID, setno);
+			MD_CRO_64BIT | MD_CRO_RAID | MD_CRO_FN, setno);
 #endif
 	} else {
 		mr_recid = mddb_createrec(msp->size, typ1, 0,
-				MD_CRO_32BIT | MD_CRO_RAID, setno);
+			MD_CRO_32BIT | MD_CRO_RAID | MD_CRO_FN, setno);
 	}
 
 	if (mr_recid < 0)
@@ -964,6 +963,7 @@
 	MD_CAPAB(un) = MD_CAN_PARENT | MD_CAN_SP;
 	MD_PARENT(un) = MD_NO_PARENT;
 	un->un_resync_copysize = 0;
+	un->c.un_revision |= MD_FN_META_DEV;
 
 	if (UNIT_STATE(un) == RUS_INIT)
 		MD_STATUS(un) |= MD_UN_GROW_PENDING;
@@ -985,6 +985,11 @@
 		goto out;
 	}
 
+	/*
+	 * Update unit availability
+	 */
+	md_set[setno].s_un_avail--;
+
 	recids[rid] = 0;
 	if (un->un_hsp_id != -1) {
 		/* increment the reference count of the hot spare pool */
@@ -1674,6 +1679,7 @@
 	mddb_recid_t	mr_recid;
 	mddb_recid_t	old_vtoc = 0;
 	mddb_recid_t	*recids;
+	md_create_rec_option_t options;
 	int		err;
 	int		col, i;
 	int64_t		tb, atb;
@@ -1751,16 +1757,23 @@
 	typ1 = (mddb_type_t)md_getshared_key(setno,
 	    raid_md_ops.md_driver.md_drivername);
 
+	/*
+	 * Preserve the friendly name nature of the device that is
+	 * growing.
+	 */
+	options = MD_CRO_RAID;
+	if (un->c.un_revision & MD_FN_META_DEV)
+		options |= MD_CRO_FN;
 	if (mgph->options & MD_CRO_64BIT) {
 #if defined(_ILP32)
 		return (mdmderror(&mgph->mde, MDE_UNIT_TOO_LARGE, mnum));
 #else
 		mr_recid = mddb_createrec(mgph->size, typ1, 0,
-				MD_CRO_64BIT | MD_CRO_RAID, setno);
+				MD_CRO_64BIT | options, setno);
 #endif
 	} else {
 		mr_recid = mddb_createrec(mgph->size, typ1, 0,
-				MD_CRO_32BIT | MD_CRO_RAID, setno);
+				MD_CRO_32BIT | options, setno);
 	}
 	if (mr_recid < 0) {
 		rval = mddbstatus2error(&mgph->mde, (int)mr_recid,
@@ -1848,7 +1861,7 @@
 		 * and had a vtoc record attached to it, we remove the
 		 * vtoc record, because the layout has changed completely.
 		 */
-		if ((un->c.un_revision == MD_32BIT_META_DEV) &&
+		if (((un->c.un_revision & MD_64BIT_META_DEV) == 0) &&
 		    (un->c.un_vtoc_id != 0)) {
 			old_vtoc = un->c.un_vtoc_id;
 			new_un->c.un_vtoc_id =
@@ -1971,6 +1984,7 @@
 	minor_t		mnum = mirp->mnum;
 	mr_unit_t	*un;
 	mdi_unit_t	*ui;
+	set_t		setno = MD_MIN2SET(mnum);
 
 	mdclrerror(&mirp->mde);
 
@@ -2004,6 +2018,21 @@
 	}
 
 	reset_raid(un, mnum, 1);
+
+	/*
+	 * Update unit availability
+	 */
+	md_set[setno].s_un_avail++;
+
+	/*
+	 * If MN set, reset s_un_next so all nodes can have
+	 * the same view of the next available slot when
+	 * nodes are -w and -j
+	 */
+	if (MD_MNSET_SETNO(setno)) {
+		(void) md_upd_set_unnext(setno, MD_MIN2UNIT(mnum));
+	}
+
 	rw_exit(&md_unit_array_rw.lock);
 
 	return (0);
--- a/usr/src/uts/common/io/lvm/raid/raid_replay.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/raid/raid_replay.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,15 +18,14 @@
  *
  * CDDL HEADER END
  */
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
  * NAME:	raid_replay.c
  *
  * DESCRIPTION: RAID driver source file containing routines related to replay
@@ -745,13 +743,13 @@
 					else
 						goto replay_failed;
 				}
-				if (un->c.un_revision == MD_32BIT_META_DEV) {
+				if (un->c.un_revision & MD_64BIT_META_DEV) {
+					pwhdrp = (raid_pwhdr_t *)
+							rplybuf[j].rpl_data;
+				} else {
 					RAID_CONVERT_RPW((raid_pwhdr32_od_t *)
 							rplybuf[j].rpl_data,
 							pwhdrp);
-				} else {
-					pwhdrp = (raid_pwhdr_t *)
-							rplybuf[j].rpl_data;
 				}
 
 				/* first check pre-write magic number */
--- a/usr/src/uts/common/io/lvm/softpart/sp.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/softpart/sp.c	Tue Mar 14 14:53:36 2006 -0800
@@ -265,6 +265,11 @@
 
 	MD_UNIT(mnum) = NULL;
 
+	/*
+	 * Attempt release of minor node
+	 */
+	(void) md_remove_minor_node(mnum);
+
 	if (!removing)
 		return;
 
@@ -279,6 +284,13 @@
 	sv->key = un->un_key;
 	vtoc_id = un->c.un_vtoc_id;
 
+	/*
+	 * Remove self from the namespace
+	 */
+	if (un->c.un_revision & MD_FN_META_DEV) {
+		(void) md_rem_selfname(un->c.un_self_id);
+	}
+
 	/* Remove the unit structure */
 	mddb_deleterec_wrapper(un->c.un_record_id);
 
@@ -1277,38 +1289,46 @@
 		dep->de_flags = MDDB_F_SOFTPART;
 		rbp = dep->de_rb;
 
-		if ((rbp->rb_revision == MDDB_REV_RB) &&
-		    ((rbp->rb_private & MD_PRV_CONVD) == 0)) {
-			/*
-			 * This means, we have an old and small record.
-			 * And this record hasn't already been converted :-o
-			 * before we create an incore metadevice from this
-			 * we have to convert it to a big record.
-			 */
-			small_un = (mp_unit32_od_t *)mddb_getrecaddr(recid);
-			newreqsize = sizeof (mp_unit_t) +
-					((small_un->un_numexts - 1) *
-					sizeof (struct mp_ext));
-			big_un = (mp_unit_t *)kmem_zalloc(newreqsize, KM_SLEEP);
-			softpart_convert((caddr_t)small_un, (caddr_t)big_un,
-			    SMALL_2_BIG);
-			kmem_free(small_un, dep->de_reqsize);
-			dep->de_rb_userdata = big_un;
-			dep->de_reqsize = newreqsize;
-			rbp->rb_private |= MD_PRV_CONVD;
-			un = big_un;
-		} else {
+		switch (rbp->rb_revision) {
+		case MDDB_REV_RB:
+		case MDDB_REV_RBFN:
+			if ((rbp->rb_private & MD_PRV_CONVD) == 0) {
+				/*
+				 * This means, we have an old and small record.
+				 * And this record hasn't already been converted
+				 * :-o before we create an incore metadevice
+				 * from this we have to convert it to a big
+				 * record.
+				 */
+				small_un =
+				    (mp_unit32_od_t *)mddb_getrecaddr(recid);
+				newreqsize = sizeof (mp_unit_t) +
+						((small_un->un_numexts - 1) *
+						sizeof (struct mp_ext));
+				big_un = (mp_unit_t *)kmem_zalloc(newreqsize,
+					KM_SLEEP);
+				softpart_convert((caddr_t)small_un,
+					(caddr_t)big_un, SMALL_2_BIG);
+				kmem_free(small_un, dep->de_reqsize);
+				dep->de_rb_userdata = big_un;
+				dep->de_reqsize = newreqsize;
+				rbp->rb_private |= MD_PRV_CONVD;
+				un = big_un;
+			} else {
+				/* Record has already been converted */
+				un = (mp_unit_t *)mddb_getrecaddr(recid);
+			}
+			un->c.un_revision &= ~MD_64BIT_META_DEV;
+			break;
+		case MDDB_REV_RB64:
+		case MDDB_REV_RB64FN:
 			/* Large device */
 			un = (mp_unit_t *)mddb_getrecaddr(recid);
+			un->c.un_revision |= MD_64BIT_META_DEV;
+			un->c.un_flag |= MD_EFILABEL;
+			break;
 		}
-
-		/* Set revision and flag accordingly */
-		if (rbp->rb_revision == MDDB_REV_RB) {
-			un->c.un_revision = MD_32BIT_META_DEV;
-		} else {
-			un->c.un_revision = MD_64BIT_META_DEV;
-			un->c.un_flag |= MD_EFILABEL;
-		}
+		NOTE_FN(rbp->rb_revision, un->c.un_revision);
 
 		/*
 		 * Create minor node for snarfed entry.
@@ -1695,6 +1715,7 @@
 	mddb_rb32_t	*rbp;
 	mp_unit_t	*un64;
 	mp_unit32_od_t	*un32;
+	md_dev64_t	self_devt;
 	minor_t		*self_id;	/* minor needs to be updated */
 	md_parent_t	*parent_id;	/* parent needs to be updated */
 	mddb_recid_t	*record_id;	/* record id needs to be updated */
@@ -1712,7 +1733,9 @@
 		dep = mddb_getrecdep(recid);
 		rbp = dep->de_rb;
 
-		if (rbp->rb_revision == MDDB_REV_RB) {
+		switch (rbp->rb_revision) {
+		case MDDB_REV_RB:
+		case MDDB_REV_RBFN:
 			/*
 			 * Small device
 			 */
@@ -1724,7 +1747,10 @@
 			if (!md_update_minor(setno, mddb_getsidenum
 				(setno), un32->un_key))
 				goto out;
-		} else {
+			break;
+
+		case MDDB_REV_RB64:
+		case MDDB_REV_RB64FN:
 			un64 = (mp_unit_t *)mddb_getrecaddr(recid);
 			self_id = &(un64->c.un_self_id);
 			parent_id = &(un64->c.un_parent);
@@ -1733,6 +1759,21 @@
 			if (!md_update_minor(setno, mddb_getsidenum
 				(setno), un64->un_key))
 				goto out;
+			break;
+		}
+
+		/*
+		 * If this is a top level and a friendly name metadevice,
+		 * update its minor in the namespace.
+		 */
+		if ((*parent_id == MD_NO_PARENT) &&
+		    ((rbp->rb_revision == MDDB_REV_RBFN) ||
+		    (rbp->rb_revision == MDDB_REV_RB64FN))) {
+
+			self_devt = md_makedevice(md_major, *self_id);
+			if (!md_update_top_device_minor(setno,
+			    mddb_getsidenum(setno), self_devt))
+				goto out;
 		}
 
 		/*
--- a/usr/src/uts/common/io/lvm/softpart/sp_ioctl.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/softpart/sp_ioctl.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -73,6 +72,7 @@
 #include <sys/mkdev.h>
 #include <sys/stat.h>
 #include <sys/open.h>
+#include <sys/lvm/mdvar.h>
 #include <sys/lvm/md_sp.h>
 #include <sys/lvm/md_notify.h>
 #include <sys/modctl.h>
@@ -240,6 +240,12 @@
 	setno = MD_MIN2SET(mnum);
 	side = mddb_getsidenum(setno);
 	un = MD_UNIT(mnum);
+
+	if (un == NULL) {
+		err = EFAULT;
+		goto out;
+	}
+
 	mdep = &mup->mde;
 
 	mdclrerror(mdep);
@@ -481,12 +487,12 @@
 #if defined(_ILP32)
 		return (mdmderror(mdep, MDE_UNIT_TOO_LARGE, mnum));
 #else
-		recids[0] = mddb_createrec((size_t)msp->size, rec_type,
-				0, MD_CRO_64BIT | MD_CRO_SOFTPART, setno);
+		recids[0] = mddb_createrec((size_t)msp->size, rec_type, 0,
+			MD_CRO_64BIT | MD_CRO_SOFTPART | MD_CRO_FN, setno);
 #endif
 	} else {
-		recids[0] = mddb_createrec((size_t)msp->size, rec_type,
-				0, MD_CRO_32BIT | MD_CRO_SOFTPART, setno);
+		recids[0] = mddb_createrec((size_t)msp->size, rec_type, 0,
+			MD_CRO_32BIT | MD_CRO_SOFTPART | MD_CRO_FN, setno);
 	}
 	/* set initial value for possible child record */
 	recids[1] = 0;
@@ -521,6 +527,7 @@
 	MD_SID(un) = mnum;
 	MD_RECID(un) = recids[0];
 	MD_PARENT(un) = MD_NO_PARENT;
+	un->c.un_revision |= MD_FN_META_DEV;
 
 	/* if we are parenting a metadevice, set our child's parent field */
 	if (md_getmajor(un->un_dev) == md_major) {
@@ -548,6 +555,11 @@
 	}
 
 	/*
+	 * Update unit availability
+	 */
+	md_set[setno].s_un_avail--;
+
+	/*
 	 * commit the record.
 	 * if we had to update a child record, it will get commited
 	 * as well.
@@ -649,6 +661,7 @@
 	mdi_unit_t	*ui;
 	mp_unit_t	*un;
 	md_unit_t	*child_un;
+	set_t		setno = MD_MIN2SET(mnum);
 
 	mdclrerror(&softp->mde);
 
@@ -688,6 +701,20 @@
 	/* remove the soft partition */
 	reset_sp(un, mnum, 1);
 
+	/*
+	 * Update unit availability
+	 */
+	md_set[setno].s_un_avail++;
+
+	/*
+	 * If MN set, reset s_un_next so all nodes can have
+	 * the same view of the next available slot when
+	 * nodes are -w and -j
+	 */
+	if (MD_MNSET_SETNO(setno)) {
+		md_upd_set_unnext(setno, MD_MIN2UNIT(mnum));
+	}
+
 	/* release locks and return */
 out:
 	rw_exit(&md_unit_array_rw.lock);
@@ -723,6 +750,7 @@
 	mddb_recid_t	recid;
 	mddb_type_t	rec_type;
 	mddb_recid_t	old_vtoc = 0;
+	md_create_rec_option_t options;
 	int		err;
 	int		rval = 0;
 	set_t		setno;
@@ -776,17 +804,23 @@
 	rec_type = (mddb_type_t)md_getshared_key(setno,
 	    sp_md_ops.md_driver.md_drivername);
 
+	/*
+	 * Preserve the friendly name nature of the unit that is growing.
+	 */
+	options = MD_CRO_SOFTPART;
+	if (un->c.un_revision & MD_FN_META_DEV)
+		options |= MD_CRO_FN;
 	if (mgp->options & MD_CRO_64BIT) {
 #if defined(_ILP32)
 		rval = mdmderror(mdep, MDE_UNIT_TOO_LARGE, mnum);
 		goto out;
 #else
 		recid = mddb_createrec((size_t)mgp->size, rec_type, 0,
-				MD_CRO_64BIT | MD_CRO_SOFTPART, setno);
+				MD_CRO_64BIT | options, setno);
 #endif
 	} else {
 		recid = mddb_createrec((size_t)mgp->size, rec_type, 0,
-				MD_CRO_32BIT | MD_CRO_SOFTPART, setno);
+				MD_CRO_32BIT | options, setno);
 	}
 	if (recid < 0) {
 		rval = mddbstatus2error(mdep, (int)recid, mnum, setno);
@@ -804,6 +838,8 @@
 		rval = EFAULT;
 		goto out;
 	}
+	if (options & MD_CRO_FN)
+		new_un->c.un_revision |= MD_FN_META_DEV;
 
 	/* All 64 bit metadevices only support EFI labels. */
 	if (mgp->options & MD_CRO_64BIT) {
@@ -813,7 +849,7 @@
 		 * and had a vtoc record attached to it, we remove the
 		 * vtoc record, because the layout has changed completely.
 		 */
-		if ((un->c.un_revision == MD_32BIT_META_DEV) &&
+		if (((un->c.un_revision & MD_64BIT_META_DEV) == 0) &&
 		    (un->c.un_vtoc_id != 0)) {
 			old_vtoc = un->c.un_vtoc_id;
 			new_un->c.un_vtoc_id =
--- a/usr/src/uts/common/io/lvm/stripe/stripe.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/stripe/stripe.c	Tue Mar 14 14:53:36 2006 -0800
@@ -369,6 +369,11 @@
 
 	MD_UNIT(mnum) = NULL;
 
+	/*
+	 * Attempt release of its minor node
+	 */
+	(void) md_remove_minor_node(mnum);
+
 	if (!removing)
 		return;
 
@@ -467,6 +472,13 @@
 
 	vtoc_id = un->c.un_vtoc_id;
 
+	/*
+	 * Remove self from the namespace
+	 */
+	if (un->c.un_revision & MD_FN_META_DEV) {
+		(void) md_rem_selfname(un->c.un_self_id);
+	}
+
 	/* Remove the unit structure */
 	mddb_deleterec_wrapper(un->c.un_record_id);
 
@@ -835,37 +847,45 @@
 		dep->de_flags = MDDB_F_STRIPE;
 		rbp = dep->de_rb;
 
-		if ((rbp->rb_revision == MDDB_REV_RB) &&
-		    ((rbp->rb_private & MD_PRV_CONVD) == 0)) {
-			/*
-			 * This means, we have an old and small record
-			 * and this record hasn't already been converted.
-			 * Before we create an incore metadevice from this
-			 * we have to convert it to a big record.
-			 */
-			small_un = (ms_unit32_od_t *)mddb_getrecaddr(recid);
-			newreqsize = get_big_stripe_req_size(small_un,
-					COMPLETE_STRUCTURE);
-			big_un = (ms_unit_t *)kmem_zalloc(newreqsize, KM_SLEEP);
-			stripe_convert((caddr_t)small_un, (caddr_t)big_un,
-			    SMALL_2_BIG);
-			kmem_free(small_un, dep->de_reqsize);
-			dep->de_rb_userdata = big_un;
-			dep->de_reqsize = newreqsize;
-			un = big_un;
-			rbp->rb_private |= MD_PRV_CONVD;
-		} else {
+		switch (rbp->rb_revision) {
+		case MDDB_REV_RB:
+		case MDDB_REV_RBFN:
+			if ((rbp->rb_private & MD_PRV_CONVD) == 0) {
+				/*
+				 * This means, we have an old and small record
+				 * and this record hasn't already been
+				 * converted.  Before we create an incore
+				 * metadevice from this we have to convert it to
+				 * a big record.
+				 */
+				small_un =
+				    (ms_unit32_od_t *)mddb_getrecaddr(recid);
+				newreqsize = get_big_stripe_req_size(small_un,
+						COMPLETE_STRUCTURE);
+				big_un = (ms_unit_t *)kmem_zalloc(newreqsize,
+					KM_SLEEP);
+				stripe_convert((caddr_t)small_un,
+					(caddr_t)big_un, SMALL_2_BIG);
+				kmem_free(small_un, dep->de_reqsize);
+				dep->de_rb_userdata = big_un;
+				dep->de_reqsize = newreqsize;
+				un = big_un;
+				rbp->rb_private |= MD_PRV_CONVD;
+			} else {
+				/* Small device had already been converted */
+				un = (ms_unit_t *)mddb_getrecaddr(recid);
+			}
+			un->c.un_revision &= ~MD_64BIT_META_DEV;
+			break;
+		case MDDB_REV_RB64:
+		case MDDB_REV_RB64FN:
 			/* Big device */
 			un = (ms_unit_t *)mddb_getrecaddr(recid);
+			un->c.un_revision |= MD_64BIT_META_DEV;
+			un->c.un_flag |= MD_EFILABEL;
+			break;
 		}
-
-		/* Set revision and flag accordingly */
-		if (rbp->rb_revision == MDDB_REV_RB) {
-			un->c.un_revision = MD_32BIT_META_DEV;
-		} else {
-			un->c.un_revision = MD_64BIT_META_DEV;
-			un->c.un_flag |= MD_EFILABEL;
-		}
+		NOTE_FN(rbp->rb_revision, un->c.un_revision);
 
 		/* Create minor node for snarfed unit. */
 		(void) md_create_minor_node(MD_MIN2SET(MD_SID(un)), MD_SID(un));
@@ -1591,6 +1611,7 @@
 	mddb_rb32_t	*rbp;
 	ms_unit32_od_t	*un32;
 	ms_unit_t	*un64;
+	md_dev64_t	self_devt;
 	minor_t		*self_id;	/* minor needs to be updated */
 	md_parent_t	*parent_id;	/* parent needs to be updated */
 	mddb_recid_t	*record_id;	/* record id needs to be updated */
@@ -1612,7 +1633,9 @@
 		dep = mddb_getrecdep(recid);
 		rbp = dep->de_rb;
 
-		if (rbp->rb_revision == MDDB_REV_RB) {
+		switch (rbp->rb_revision) {
+		case MDDB_REV_RB:
+		case MDDB_REV_RBFN:
 			/*
 			 * Small device
 			 */
@@ -1640,7 +1663,9 @@
 				    setno, mdc->un_mirror.ms_hs_id);
 			    }
 			}
-		} else {
+			break;
+		case MDDB_REV_RB64:
+		case MDDB_REV_RB64FN:
 			un64 = (ms_unit_t *)mddb_getrecaddr(recid);
 			self_id = &(un64->c.un_self_id);
 			parent_id = &(un64->c.un_parent);
@@ -1665,6 +1690,21 @@
 				    setno, mdc->un_mirror.ms_hs_id);
 			    }
 			}
+			break;
+		}
+
+		/*
+		 * If this is a top level and a friendly name metadevice,
+		 * update its minor in the namespace.
+		 */
+		if ((*parent_id == MD_NO_PARENT) &&
+		    ((rbp->rb_revision == MDDB_REV_RBFN) ||
+		    (rbp->rb_revision == MDDB_REV_RB64FN))) {
+
+			self_devt = md_makedevice(md_major, *self_id);
+			if (!md_update_top_device_minor(setno,
+			    mddb_getsidenum(setno), self_devt))
+				goto out;
 		}
 
 		/*
--- a/usr/src/uts/common/io/lvm/stripe/stripe_ioctl.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/stripe/stripe_ioctl.c	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -43,6 +42,7 @@
 #include <sys/mkdev.h>
 #include <sys/stat.h>
 #include <sys/open.h>
+#include <sys/lvm/mdvar.h>
 #include <sys/lvm/md_stripe.h>
 #include <sys/lvm/md_notify.h>
 #include <sys/modctl.h>
@@ -176,11 +176,11 @@
 		return (mdmderror(mdep, MDE_UNIT_TOO_LARGE, mnum));
 #else
 		ms_recid = mddb_createrec((size_t)msp->size, typ1, 0,
-					MD_CRO_64BIT | MD_CRO_STRIPE, setno);
+			MD_CRO_64BIT | MD_CRO_STRIPE | MD_CRO_FN, setno);
 #endif
 	} else {
 		ms_recid = mddb_createrec((size_t)msp->size, typ1, 0,
-					MD_CRO_32BIT | MD_CRO_STRIPE, setno);
+			MD_CRO_32BIT | MD_CRO_STRIPE | MD_CRO_FN, setno);
 	}
 	if (ms_recid < 0)
 		return (mddbstatus2error(mdep, ms_recid, mnum, setno));
@@ -229,6 +229,7 @@
 	MD_RECID(un) = recids[0];
 	MD_CAPAB(un) = MD_CAN_PARENT | MD_CAN_SUB_MIRROR | MD_CAN_SP;
 	MD_PARENT(un) = MD_NO_PARENT;
+	un->c.un_revision |= MD_FN_META_DEV;
 
 	if (err = stripe_build_incore(p, 0)) {
 		MD_UNIT(mnum) = NULL;
@@ -237,6 +238,11 @@
 		return (err);
 	}
 
+	/*
+	 * Update unit availability
+	 */
+	md_set[setno].s_un_avail--;
+
 	recids[rid] = 0;
 	if (un->un_hsp_id != -1)
 		err = md_hot_spare_ifc(HSP_INCREF, un->un_hsp_id, 0, 0,
@@ -366,6 +372,21 @@
 
 	md_unit_openclose_exit(ui);
 	reset_stripe(un, mnum, 1);
+
+	/*
+	 * Update unit availability
+	 */
+	md_set[setno].s_un_avail++;
+
+	/*
+	 * If MN set, reset s_un_next so all nodes can have
+	 * the same view of the next available slot when
+	 * nodes are -w and -j
+	 */
+	if (MD_MNSET_SETNO(setno)) {
+		(void) md_upd_set_unnext(setno, MD_MIN2UNIT(mnum));
+	}
+
 	rw_exit(&md_unit_array_rw.lock);
 	return (0);
 }
@@ -383,6 +404,7 @@
 	mddb_recid_t	ms_recid;
 	mddb_recid_t	old_vtoc = 0;
 	mddb_recid_t	*recids;
+	md_create_rec_option_t options;
 	mddb_type_t	typ1;
 	int		err;
 	int64_t		tb, atb;
@@ -448,17 +470,23 @@
 	typ1 = (mddb_type_t)md_getshared_key(setno,
 	    stripe_md_ops.md_driver.md_drivername);
 
+	/*
+	 * Preserve the friendly name nature of growing device.
+	 */
+	options = MD_CRO_STRIPE;
+	if (un->c.un_revision & MD_FN_META_DEV)
+		options |= MD_CRO_FN;
 	if (mgp->options & MD_CRO_64BIT) {
 #if defined(_ILP32)
 		rval = mdmderror(mdep, MDE_UNIT_TOO_LARGE, mnum);
 		goto out;
 #else
 		ms_recid = mddb_createrec((size_t)mgp->size, typ1, 0,
-				MD_CRO_64BIT | MD_CRO_STRIPE, setno);
+				MD_CRO_64BIT | options, setno);
 #endif
 	} else {
 		ms_recid = mddb_createrec((size_t)mgp->size, typ1, 0,
-				MD_CRO_32BIT | MD_CRO_STRIPE, setno);
+				MD_CRO_32BIT | options, setno);
 	}
 
 
@@ -486,6 +514,8 @@
 		rval = EFAULT;
 		goto out;
 	}
+	if (options & MD_CRO_FN)
+		new_un->c.un_revision |= MD_FN_META_DEV;
 
 	/*
 	 * allocate the real recids array.  since we may have to
@@ -540,7 +570,7 @@
 		 * and had a vtoc record attached to it, we remove the
 		 * vtoc record, because the layout has changed completely.
 		 */
-		if ((un->c.un_revision == MD_32BIT_META_DEV) &&
+		if (((un->c.un_revision & MD_64BIT_META_DEV) == 0) &&
 		    (un->c.un_vtoc_id != 0)) {
 			old_vtoc = un->c.un_vtoc_id;
 			new_un->c.un_vtoc_id =
--- a/usr/src/uts/common/io/lvm/trans/mdtrans.c	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/io/lvm/trans/mdtrans.c	Tue Mar 14 14:53:36 2006 -0800
@@ -912,7 +912,7 @@
 			dep->de_icreqsize = newreqsize;
 			rbp->rb_private |= MD_PRV_CONVD;
 			un = big_un;
-			un->c.un_revision = MD_32BIT_META_DEV;
+			un->c.un_revision &= ~MD_64BIT_META_DEV;
 		} else {
 			/* already converted, just set the pointer */
 			un = dep->de_rb_userdata;
--- a/usr/src/uts/common/sys/lvm/md_mddb.h	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/sys/lvm/md_mddb.h	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -120,6 +119,21 @@
 
 /*
  * Set struct used by all parts of the driver, to store anchor pointers.
+ *
+ * Lock associated with field in this structure:
+ *
+ * Some of fields are accessible by both the single threaded ioctl thread
+ * and internal threads such as resync, hotsparing...etc.  In this case
+ * additional protection is needed.  For example, s_db is protected by
+ * s_dbmx additionally and s_un, s_ui are protected by md_unit_array_rw.lock
+ * s_nm, s_nmid, s_did_nm and s_did_nmid and s_dtp are protected by nm_lock
+ * Rest of other fileds are protected by md_mx.  Two fields s_un_next and
+ * s_un_avail are introduced by the friendly name project and are ONLY
+ * accessible via a single threaded ioctl thread which already is protected
+ * by the ioctl lock and there is no need to add extra protection to them.
+ * However, in the future if they become accessible by other internal threads
+ * then an additional protection such as md_mx lock is highly recommended.
+ *
  */
 typedef struct md_set {
 	uint_t		s_status;	/* set status */
@@ -137,6 +151,8 @@
 	int		s_am_i_master;	/* incore master flag for this node */
 	md_mn_nodeid_t	s_nodeid;	/* nodeid of this node - for MN sets */
 	uint_t		s_rcnt;		/* incore resync count for set */
+	unit_t		s_un_next;	/* s_un scan starts here */
+	unit_t		s_un_avail;	/* number of avail slots */
 } md_set_t;
 
 
@@ -181,6 +197,17 @@
  * with any nodeid (sideno) allowed.
  * The revision is set to MDDB_REV_MNLN which is a change of the
  * MDDB_REV_MAJOR portion of the revision.
+ *
+ * The record blocks have two binary properties.  A record block can
+ * represent either a 32 or 64 bit unit.  A record block can also represent
+ * a traditionally named unit or a friendly named unit.  Thus, there are
+ * minor revisions of record block.
+ *
+ *		Traditional		Friendly
+ *		Name			Name
+ *		-----------		--------
+ * 32 bit	MDDB_REV_RB		MDDB_REV_RBFN
+ * 64 bit	MDDB_REV_RB64		MDDB_REV_RB64FN
  */
 
 #define	MDDB_REV_MB	(uint_t)0x0201
@@ -192,9 +219,25 @@
 #define	MDDB_REV_MNLN	(uint_t)0x0300
 #define	MDDB_REV_RB	(uint_t)0x0200
 #define	MDDB_REV_RB64	(uint_t)0x0201
+#define	MDDB_REV_RBFN	(uint_t)0x0202
+#define	MDDB_REV_RB64FN	(uint_t)0x0203
 #define	MDDB_REV_DT	(uint_t)0x0100
 #define	MDDB_REV_DI	(uint_t)0x0100
 
+/*
+ * Transfer record block friendly name status to unit/hs structure.
+ */
+#define	NOTE_FN(rbv, unv)	switch (rbv) { \
+				case MDDB_REV_RB: \
+				case MDDB_REV_RB64: \
+					unv &= ~MD_FN_META_DEV; \
+					break; \
+				case MDDB_REV_RBFN: \
+				case MDDB_REV_RB64FN: \
+					unv |= MD_FN_META_DEV; \
+					break;	\
+				}
+
 #define	MDDB_BSIZE	(uint_t)DEV_BSIZE
 #define	MDDB_PREFIXCNT	10
 #define	MDDB_DRVNMCNT   10
@@ -838,6 +881,8 @@
 extern int			mddb_getinvlb_devid(set_t setno, int count,
 				    int size, char **ctdptr);
 extern int			md_update_minor(set_t, side_t, mdkey_t);
+extern int			md_update_top_device_minor(set_t, side_t,
+				    md_dev64_t);
 #ifdef DEBUG
 extern void			mddb_check(void);
 #endif /* DEBUG */
--- a/usr/src/uts/common/sys/lvm/md_raid.h	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/sys/lvm/md_raid.h	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -93,7 +92,7 @@
 #define	RAID_FILLIN_RPW(buf, un, sum, colnum, 				\
 			blkno, blkcnt, id,  				\
 			colcount, col, magic) { 			\
-	if ((un)->c.un_revision == MD_64BIT_META_DEV) { 		\
+	if ((un)->c.un_revision & MD_64BIT_META_DEV) { 		\
 		raid_pwhdr_t *rpw64	= (raid_pwhdr_t *)(void *)(buf);\
 		rpw64->rpw_magic	= magic;			\
 		rpw64->rpw_sum		= sum;				\
--- a/usr/src/uts/common/sys/lvm/mdio.h	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/sys/lvm/mdio.h	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -75,16 +74,55 @@
 #define	MAKE_HSP_ID(setno, id)  (((setno) << HSP_SET_SHIFT) | (id))
 
 /*
+ * The following macros were added to support friendly names for hot spare
+ * pools.  Before the addition of friendly names the hsp_self_id was merely
+ * the conbination of the set number and the hot spare pool number.  With
+ * friendly names a NM record is created to hold the hot spare pool name.
+ * The hsp_self_id now becomes the set number shifted left plus the NM
+ * record key plus 1000.  The number 1000 is used to collision between
+ * traditional hsp_self_ids and friendly name self ids.  In traditional hot
+ * spare pool the hot spare pool number could never be grater than 999.
+ *
+ * HSP_ID_IS_FN(hspid)	returns TRUE if the hot spare pool ID is the ID of
+ * 			a friendly named hsp.  Will return FALSE otherwise.
+ * 			hspid may contain the set bits, since HSP_ID_IS_FN
+ * 			will call HSP_ID as part of doing its work.
+ *
+ * KEY_TO_HSP_ID(setno, reckey)	constructs a hot spare pool ID (hsp_t) from
+ * 			a set number and a NM record key.  The result is
+ * 			suitable for storing in the hsp_self_id member of a
+ * 			hot_spare_pool struct.
+ *
+ * HSP_ID_TO_KEY(hspid)	returns the NM key that is encoded in the hot spare
+ * 			pool ID.  MD_KEYBAD will be returned if hspid does
+ * 			not represent a friendly named hsp.  hspid may
+ * 			contain the set bits, since HSP_ID_TO_KEY will call
+ * 			HSP_ID as part of doing its work.
+ *
+ * HSP_KEY_OK(reckey)	Insures that the NM record key is not so large as
+ * 			to interfere with the set number bits in a hot
+ * 			spare pool self id.  This macro will probably only
+ * 			be used in meta_hs_add.
+ */
+#define	HSP_FN_BASE	(1000)
+#define	HSP_ID_IS_FN(hspid) (HSP_ID(hspid) > HSP_FN_BASE)
+#define	KEY_TO_HSP_ID(setno, key) ((setno << HSP_SET_SHIFT) | \
+					(key + HSP_FN_BASE))
+#define	HSP_ID_TO_KEY(hspid) ((HSP_ID_IS_FN(hspid)) ? \
+				(HSP_ID(hspid) - HSP_FN_BASE) : MD_KEYBAD)
+#define	HSP_KEY_OK(key)	(((key + HSP_FN_BASE) & HSP_SET_MASK) == 0)
+
+/*
  * for did stat ioctl
  */
 #define	MD_FIND_INVDID	0x01
 #define	MD_GET_INVDID	0x02
 
 /*
- * for setting the un_revision
+ * for setting the un_revision, hsp_revision and hs_revision
  */
-#define	MD_32BIT_META_DEV	0
-#define	MD_64BIT_META_DEV	1
+#define	MD_64BIT_META_DEV	0x01
+#define	MD_FN_META_DEV		0x02	/* Friendly named metadevice */
 
 /*
  * for trans EOF error messages
@@ -268,6 +306,18 @@
 	uint_t		ref_count;	/* returned n_count */
 } mdnm_params_t;
 
+typedef struct mdhspnm_params {
+	md_error_t	mde;		/* Error return */
+	char		drvnm[MD_MAXDRVNM];  /* drvnm for get/set/rem nm */
+	uint_t		hspname_len;	/* Length of device name, for set nm */
+	uint64_t	hspname;	/* Address of device name for set/get */
+	set_t		setno;		/* Which namespace set to use */
+	side_t		side;		/* -1 == current side, >0 specified */
+	hsp_t		hspid;		/* 0 == alloc one, else use this key */
+	hsp_t		ret_hspid;	/* return key here! */
+	uint_t		ref_count;	/* returned n_count */
+} mdhspnm_params_t;
+
 typedef struct md_getdevs_params {
 	MD_DRIVER
 	md_error_t	mde;
@@ -374,7 +424,7 @@
 typedef struct md_mkdev_params {
 	MD_DRIVER
 	md_error_t	mde;		/* Error return */
-	minor_t		mnum;
+	unit_t		un;
 } md_mkdev_params_t;
 
 /*
@@ -697,6 +747,8 @@
 #define	MD_MN_SETSYNC		(MDIOC|102) /* multi-threaded MD_IOCSETSYNC */
 #define	MD_MN_POKE_HOTSPARES	(MDIOC|103) /* poke hotspares */
 #define	MD_DB_LBINITTIME	(MDIOC|104) /* get the lb_inittime */
+#define	MD_IOCGET_HSP_NM	(MDIOC|105) /* get hsp entry from namespace */
+#define	MD_IOCREM_DEV		(MDIOC|106) /* remove device node for unit */
 
 #define	MDIOC_MISC	(MDIOC|128)	/* misc module base */
 /* Used in DEBUG_TEST code */
--- a/usr/src/uts/common/sys/lvm/mdiox.x	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/sys/lvm/mdiox.x	Tue Mar 14 14:53:36 2006 -0800
@@ -1,13 +1,9 @@
 %/*
-% * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
-% * Use is subject to license terms.
-% *
 % * CDDL HEADER START
 % *
 % * The contents of this file are subject to the terms of the
-% * Common Development and Distribution License, Version 1.0 only
-% * (the "License").  You may not use this file except in compliance
-% * with the License.
+% * Common Development and Distribution License (the "License").
+% * You may not use this file except in compliance with the License.
 % *
 % * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 % * or http://www.opensolaris.org/os/licensing.
@@ -23,6 +19,11 @@
 % * CDDL HEADER END
 % */
 %
+%/*
+% * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+% * Use is subject to license terms.
+% */
+%
 %#pragma ident	"%Z%%M%	%I%	%E% SMI"
 %
 %/*
@@ -159,7 +160,8 @@
 	MD_CRO_TRANS_LOG	= 0x100,
 	MD_CRO_HOTSPARE		= 0x200,
 	MD_CRO_HOTSPARE_POOL	= 0x400,
-	MD_CRO_CHANGELOG	= 0x800
+	MD_CRO_CHANGELOG	= 0x800,
+	MD_CRO_FN		= 0x1000
 };
 
 %
@@ -532,9 +534,32 @@
 	MD_METASP
 };
 
+%/* SVM general device types
+% *
+% * META_DEVICE refers to any SVM metadevice
+% * LOGICAL_DEVICE refers to any underlying physical device
+% * HSP_DEVICE refers to a hotspare pool
+% *
+% * In the past, the device type can be determined via
+% * the device name (such as d10, c1t1d1s1).  With
+% * the friendly name implementation, it is not possible
+% * to determine from the device name.  In the code,
+% * whereever the device type is obvious that type will be
+% * used explicitly otherwise 'UNKNOWN' will be used and
+% * specific SVM lookup routines will be called to determine
+% * the device type associated with the name.
+% */
+enum meta_device_type_t {
+	UNKNOWN = 0,
+	META_DEVICE,
+	HSP_DEVICE,
+	LOGICAL_DEVICE
+}; 
+
 #ifdef RPC_HDR
 %
 %/* misc module names */
+%/* When modifying this list also update meta_names in md_names.c */
 %#define	MD_STRIPE	"md_stripe"
 %#define	MD_MIRROR	"md_mirror"
 %#define	MD_TRANS	"md_trans"
@@ -1369,7 +1394,12 @@
 	MDE_STRIPE_TRUNC_MULTIPLE,	/* multiple component stripe trun */
 	MDE_SMF_FAIL,		/* service management facility error */
 	MDE_SMF_NO_SERVICE,	/* service not enabled in SMF */
-	MDE_ZONE_ADMIN		/* in a zone & no admin device */
+	MDE_AMBIGUOUS_DEV,	/* Ambiguous device specified */
+	MDE_NAME_IN_USE,	/* Friendly name already in use.  For */
+				/* instance name desired for hot spare pool */
+				/* is being used for a metadevice. */
+	MDE_ZONE_ADMIN,		/* in a zone & no admin device */
+	MDE_NAME_ILLEGAL	/* illegal syntax for metadevice or hsp name */
 };
 
 struct md_void_error_t {
--- a/usr/src/uts/common/sys/lvm/mdmn_commd.x	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/sys/lvm/mdmn_commd.x	Tue Mar 14 14:53:36 2006 -0800
@@ -1,27 +1,26 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
+%/*
+% * CDDL HEADER START
+% *
+% * The contents of this file are subject to the terms of the
+% * Common Development and Distribution License (the "License").
+% * You may not use this file except in compliance with the License.
+% *
+% * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+% * or http://www.opensolaris.org/os/licensing.
+% * See the License for the specific language governing permissions
+% * and limitations under the License.
+% *
+% * When distributing Covered Code, include this CDDL HEADER in each
+% * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+% * If applicable, add the following below this CDDL HEADER, with the
+% * fields enclosed by brackets "[]" replaced with your own identifying
+% * information: Portions Copyright [yyyy] [name of copyright owner]
+% *
+% * CDDL HEADER END
+% */
 %
 %/*
-% * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+% * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 % * Use is subject to license terms.
 % */
 %
@@ -103,6 +102,7 @@
 	MD_MN_MSG_SP_SETSTAT2,		/* Update softpart status on error */
 	MD_MN_MSG_SETSYNC,		/* Set resync status */
 	MD_MN_MSG_POKE_HOTSPARES,	/* Call poke_hotspares */
+	MD_MN_MSG_ADDMDNAME,		/* Add metadevice name */
 	MD_MN_NMESSAGES /* insert elements before */
 };
 
@@ -314,6 +314,14 @@
 	char		addkeyname_name[1];	/* must be last element */
 };
 
+/*
+ * Add metadevice name into replica
+ */
+struct md_mn_msg_addmdname_t {
+	set_t		addmdname_setno;
+	char		addmdname_name[1];
+};
+
 /* Message format for DELKEYNAME message */
 
 struct md_mn_msg_delkeyname_t {
--- a/usr/src/uts/common/sys/lvm/mdvar.h	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/sys/lvm/mdvar.h	Tue Mar 14 14:53:36 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -707,6 +706,7 @@
 extern md_parent_t md_get_parent(md_dev64_t);
 extern void	md_set_parent(md_dev64_t, md_parent_t);
 extern void	md_reset_parent(md_dev64_t);
+extern struct hot_spare_pool *find_hot_spare_pool(set_t, int);
 extern int	md_hot_spare_ifc(hs_cmds_t, mddb_recid_t, u_longlong_t, int,
 		    mddb_recid_t *, mdkey_t *, md_dev64_t *, diskaddr_t *);
 extern int	md_notify_interface(md_event_cmds_t cmd, md_tags_t type,
@@ -748,6 +748,9 @@
 extern int	md_init_probereq(struct md_probedev_impl *p,
 		    daemon_queue_t **hdrpp);
 extern boolean_t callb_md_mrs_cpr(void *, int);
+extern void	md_upd_set_unnext(set_t, unit_t);
+extern int	md_rem_selfname(minor_t);
+extern void	md_rem_hspname(set_t, mdkey_t);
 
 /* Externals from md_ioctl.c */
 extern int	md_mn_is_commd_present(void);
@@ -762,13 +765,16 @@
 extern int	md_dkiocgetefi(minor_t, void *, int);
 extern int	md_dkiocsetefi(minor_t, void *, int);
 extern int	md_dkiocpartition(minor_t, void *, int);
+extern void	md_remove_minor_node(minor_t);
 
 
 /* Externals from md_names.c */
 extern mdkey_t	md_setdevname(set_t, side_t, mdkey_t, char *, minor_t, char *,
-			set_t);
+			set_t, md_error_t *);
 extern int	md_getdevname(set_t, side_t, mdkey_t, md_dev64_t, char *,
 		    size_t);
+extern int	md_gethspinfo(set_t, side_t, mdkey_t, char *, hsp_t *,
+		    char *);
 extern int	md_getkeyfromdev(set_t, side_t, md_dev64_t, mdkey_t *, int *);
 extern int	md_devid_found(set_t, side_t, mdkey_t);
 extern int	md_getnment(set_t, side_t, mdkey_t, md_dev64_t,
--- a/usr/src/uts/common/sys/lvm/meta_basic.x	Tue Mar 14 14:33:40 2006 -0800
+++ b/usr/src/uts/common/sys/lvm/meta_basic.x	Tue Mar 14 14:53:36 2006 -0800
@@ -1,13 +1,9 @@
 %/*
-% * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
-% * Use is subject to license terms.
-% *
 % * CDDL HEADER START
 % *
 % * The contents of this file are subject to the terms of the
-% * Common Development and Distribution License, Version 1.0 only
-% * (the "License").  You may not use this file except in compliance
-% * with the License.
+% * Common Development and Distribution License (the "License").
+% * You may not use this file except in compliance with the License.
 % *
 % * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 % * or http://www.opensolaris.org/os/licensing.
@@ -23,6 +19,11 @@
 % * CDDL HEADER END
 % */
 %
+%/*
+% * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+% * Use is subject to license terms.
+% */
+%
 %#pragma ident	"%Z%%M%	%I%	%E% SMI"
 %
 
@@ -254,6 +255,8 @@
 %
 %#define	MD_KEYWILD	((mdkey_t)0)
 %#define	MD_KEYBAD	((mdkey_t)~0UL)
+%#define	MD_UNITBAD	((unit_t)~0UL)
+%#define	MD_HSPID_WILD	((hsp_t)~0UL)
 
 %/* Maximum length of a metadevice name */
 %#define	MD_MAX_SIDENAME_LEN	(MD_MAXDRVNM + MD_MAX_SETNAME + 2)