changeset 10344:67004039f55e

6763580 md_update_namespace() doesn't follow nmn_nextp correctly resulting in kmem corruption/panics
author Andrew Balfour <Andrew.Balfour@Sun.COM>
date Wed, 19 Aug 2009 12:13:19 -0700
parents 8e7e92586904
children 160b63eaeb0a
files usr/src/uts/common/io/lvm/md/md_names.c
diffstat 1 files changed, 453 insertions(+), 343 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/lvm/md/md_names.c	Wed Aug 19 10:25:34 2009 -0700
+++ b/usr/src/uts/common/io/lvm/md/md_names.c	Wed Aug 19 12:13:19 2009 -0700
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/errno.h>
 #include <sys/debug.h>
 #include <sys/sysmacros.h>
@@ -41,8 +39,19 @@
 extern int	*md_nm_snarfed;
 void		*lookup_entry(struct nm_next_hdr *, set_t,
 			side_t, mdkey_t, md_dev64_t, int);
+void		*lookup_entry_common(struct nm_next_hdr *, set_t,
+			side_t, mdkey_t, md_dev64_t, int, void **, size_t *);
+void		*lookup_entry_record_offset(struct nm_next_hdr *, set_t,
+			side_t, mdkey_t, md_dev64_t, int, void *, size_t *);
+
 void		*lookup_shared_entry(struct nm_next_hdr *,
 			mdkey_t, char *, mddb_recid_t *, int);
+void		*lookup_shared_entry_common(struct nm_next_hdr *,
+			mdkey_t, char *, mddb_recid_t *, int, void **,
+			size_t *);
+void		*lookup_shared_entry_record_offset(struct nm_next_hdr *,
+			mdkey_t, char *, mddb_recid_t *, int, void *, size_t *);
+
 static void	add_to_devid_list(ddi_devid_t did);
 static int	devid_is_unique(ddi_devid_t did);
 static size_t	free_devid_list(int *count);
@@ -128,7 +137,7 @@
 		return (0);
 
 	if ((shared & NM_SHARED) && (lookup_shared_entry(nh, key, (char *)0,
-		NULL, nmspace) != NULL))
+	    NULL, nmspace) != NULL))
 		return (0);
 
 	/*
@@ -136,7 +145,7 @@
 	 * we dont keep track of the nonshared in the devid nmspace
 	 */
 	if (!(shared & NM_NOTSHARED) &&
-		(lookup_entry(nh, 0, -1, key, NODEV64, 0L) != NULL))
+	    (lookup_entry(nh, 0, -1, key, NODEV64, 0L) != NULL))
 		return (0);
 
 	return (1);
@@ -193,8 +202,8 @@
 		 * Deal with the device id name space
 		 */
 		nmid = md_set[setno].s_did_nmid =
-			mddb_createrec(sizeof (struct nm_header),
-				MDDB_DID_NM_HDR, 1, MD_CRO_32BIT, setno);
+		    mddb_createrec(sizeof (struct nm_header),
+		    MDDB_DID_NM_HDR, 1, MD_CRO_32BIT, setno);
 		/*
 		 * Out of space
 		 */
@@ -202,8 +211,8 @@
 			return (nmid);
 	} else {
 		nmid = md_set[setno].s_nmid =
-			mddb_createrec(sizeof (struct nm_header),
-				MDDB_NM_HDR, 1, MD_CRO_32BIT, setno);
+		    mddb_createrec(sizeof (struct nm_header),
+		    MDDB_NM_HDR, 1, MD_CRO_32BIT, setno);
 		/*
 		 * Out of space
 		 */
@@ -262,28 +271,28 @@
 		 * Device id name space
 		 */
 		rec_type = ((shared & NM_SHARED) ?
-			MDDB_DID_SHR_NM : MDDB_DID_NM);
+		    MDDB_DID_SHR_NM : MDDB_DID_NM);
 		used_size = ((shared & NM_SHARED) ?
-			(sizeof (struct devid_shr_rec) -
-				sizeof (struct did_shr_name)) :
-			(sizeof (struct devid_min_rec) -
-				sizeof (struct did_min_name)));
+		    (sizeof (struct devid_shr_rec) -
+		    sizeof (struct did_shr_name)) :
+		    (sizeof (struct devid_min_rec) -
+		    sizeof (struct did_min_name)));
 		alloc_size = ((shared & NM_SHARED) ?
-			NM_DID_ALLOC_SIZE : NM_ALLOC_SIZE);
+		    NM_DID_ALLOC_SIZE : NM_ALLOC_SIZE);
 	} else {
 		rec_type = ((shared & NM_SHARED) ?
-			MDDB_SHR_NM : MDDB_NM);
+		    MDDB_SHR_NM : MDDB_NM);
 		used_size = ((shared & NM_SHARED) ?
-			(sizeof (struct nm_shr_rec) -
-				sizeof (struct nm_shared_name)) :
-			(sizeof (struct nm_rec) - sizeof (struct nm_name)));
+		    (sizeof (struct nm_shr_rec) -
+		    sizeof (struct nm_shared_name)) :
+		    (sizeof (struct nm_rec) - sizeof (struct nm_name)));
 		alloc_size = NM_ALLOC_SIZE;
 	}
 
 	used_size += needed_space;
 
 	new_id = mddb_createrec((size_t)alloc_size, rec_type, 1,
-		MD_CRO_32BIT, setno);
+	    MD_CRO_32BIT, setno);
 	if (new_id < 0)
 		return (new_id);
 
@@ -297,7 +306,7 @@
 
 	((struct nm_rec_hdr *)new_nh->nmn_record)->r_alloc_size = alloc_size;
 	((struct nm_rec_hdr *)new_nh->nmn_record)->r_used_size =
-		(uint_t)used_size;
+	    (uint_t)used_size;
 
 	mddb_commitrecs_wrapper(recids);
 	return (0);
@@ -312,7 +321,7 @@
 {
 	struct nm_rec_hdr	*rh = (struct nm_rec_hdr *)nh->nmn_record;
 	struct nm_rec_hdr	*parent_rh = (struct nm_rec_hdr *)
-						parent_nh->nmn_record;
+	    parent_nh->nmn_record;
 	struct nm_rec_hdr	*new_rh;
 	void			*new_rec;
 	mddb_recid_t		new_id;
@@ -329,16 +338,16 @@
 		 * Device id name space
 		 */
 		rec_type = ((shared & NM_SHARED) ?
-			MDDB_DID_SHR_NM : MDDB_DID_NM);
+		    MDDB_DID_SHR_NM : MDDB_DID_NM);
 		alloc_size = ((shared & NM_SHARED) ?
-			NM_DID_ALLOC_SIZE : NM_ALLOC_SIZE);
+		    NM_DID_ALLOC_SIZE : NM_ALLOC_SIZE);
 	} else {
 		rec_type = ((shared & NM_SHARED) ? MDDB_SHR_NM : MDDB_NM);
 		alloc_size = NM_ALLOC_SIZE;
 	}
 
 	new_id = mddb_createrec((size_t)rh->r_alloc_size + alloc_size, rec_type,
-			1, MD_CRO_32BIT, setno);
+	    1, MD_CRO_32BIT, setno);
 	/*
 	 * No space
 	 */
@@ -465,12 +474,12 @@
 		 * Device id name space
 		 */
 		needed_space = ((shared & NM_SHARED) ?
-			sizeof (struct did_shr_name) :
-			sizeof (struct did_min_name)) + len - 1;
+		    sizeof (struct did_shr_name) :
+		    sizeof (struct did_min_name)) + len - 1;
 	else
 		needed_space = ((shared & NM_SHARED) ?
-			sizeof (struct nm_shared_name) :
-			sizeof (struct nm_name)) + len - 1;
+		    sizeof (struct nm_shared_name) :
+		    sizeof (struct nm_name)) + len - 1;
 
 	needed_space = roundup(needed_space, sizeof (uint_t));
 
@@ -484,13 +493,16 @@
 			this_rec = this_nh->nmn_record;
 
 			if (shared & NM_DEVID)
-			    this_rh = ((shared & NM_SHARED) ?
-			    &((struct devid_shr_rec *)this_rec)->did_rec_hdr :
-			    &((struct devid_min_rec *)this_rec)->min_rec_hdr);
+				this_rh = ((shared & NM_SHARED) ?
+				    &((struct devid_shr_rec *)
+				    this_rec)->did_rec_hdr :
+				    &((struct devid_min_rec *)
+				    this_rec)->min_rec_hdr);
 			else
-			    this_rh = ((shared & NM_SHARED) ?
-			    &((struct nm_shr_rec *)this_rec)->sr_rec_hdr :
-			    &((struct nm_rec *)this_rec)->r_rec_hdr);
+				this_rh = ((shared & NM_SHARED) ?
+				    &((struct nm_shr_rec *)
+				    this_rec)->sr_rec_hdr :
+				    &((struct nm_rec *)this_rec)->r_rec_hdr);
 
 			/* check for space in this record */
 			if ((this_rh->r_alloc_size - this_rh->r_used_size) >=
@@ -530,7 +542,7 @@
 {
 
 	if (((struct nm_rec_hdr *)nh->nmn_record)->r_used_size <=
-			(*off + ent_size)) {
+	    (*off + ent_size)) {
 		if (nh->nmn_nextp == NULL)
 			return ((caddr_t)0);
 
@@ -555,8 +567,8 @@
 	struct nm_next_hdr	*first_nh;
 	mddb_recid_t		recids[3];
 	size_t			c = ((struct nm_rec_hdr *)
-				    nh->nmn_record)->r_used_size - offset -
-				    ent_size;
+	    nh->nmn_record)->r_used_size - offset -
+	    ent_size;
 	set_t			setno;
 	mdkey_t			ent_key;
 
@@ -567,11 +579,11 @@
 
 	recids[0] = id;
 	recids[1] = ((devid_nm & NM_DEVID) ? md_set[setno].s_did_nmid :
-		md_set[setno].s_nmid);
+	    md_set[setno].s_nmid);
 	recids[2] = 0;
 	ent_key = ((devid_nm & NM_DEVID) ?
-		((struct did_min_name *)ent)->min_key :
-		((struct nm_name *)ent)->n_key);
+	    ((struct did_min_name *)ent)->min_key :
+	    ((struct nm_name *)ent)->n_key);
 
 	if (c == 0)
 		(void) bzero(ent, ent_size);	/* last entry */
@@ -604,8 +616,8 @@
 	struct nm_next_hdr	*first_nh;
 	mddb_recid_t		recids[3];
 	size_t			c = ((struct nm_rec_hdr *)
-				    nh->nmn_record)->r_used_size - offset -
-				    ent_size;
+	    nh->nmn_record)->r_used_size - offset -
+	    ent_size;
 	set_t			setno;
 	uint_t			count;
 
@@ -615,7 +627,7 @@
 
 	recids[0] = id;
 	recids[1] = ((devid_nm & NM_DEVID) ? md_set[setno].s_did_nmid :
-		md_set[setno].s_nmid);
+	    md_set[setno].s_nmid);
 	recids[2] = 0;
 
 	if (devid_nm & NM_DEVID) {
@@ -628,8 +640,8 @@
 		mdkey_t	ent_key;
 
 		ent_key = ((devid_nm & NM_DEVID) ?
-			((struct did_shr_name *)ent)->did_key :
-			((struct nm_shared_name *)ent)->sn_key);
+		    ((struct did_shr_name *)ent)->did_key :
+		    ((struct nm_shared_name *)ent)->sn_key);
 
 		if (c == 0)
 			(void) bzero(ent, ent_size);	/* last entry */
@@ -639,7 +651,7 @@
 		}
 
 		((struct nm_rec_hdr *)nh->nmn_record)->r_used_size -=
-			(uint_t)ent_size;
+		    (uint_t)ent_size;
 		destroy_key(first_nh, devid_nm | NM_SHARED, ent_key);
 	}
 
@@ -704,8 +716,8 @@
 
 		/* allocate an entry and fill it in */
 		if ((did_shn = (struct did_shr_name *)alloc_entry(nh,
-			md_set[setno].s_did_nmid, len, shared | NM_DEVID,
-			&recid)) == NULL)
+		    md_set[setno].s_did_nmid, len, shared | NM_DEVID,
+		    &recid)) == NULL)
 			return (MD_KEYBAD);
 		did_shn->did_key = create_key(nh);
 		did_shn->did_count = 1;
@@ -718,7 +730,7 @@
 		key = did_shn->did_key;
 	} else {
 		if ((shn = (struct nm_shared_name *)lookup_shared_entry(nh,
-			0, shrname, &recid, 0L)) != NULL) {
+		    0, shrname, &recid, 0L)) != NULL) {
 			/* Increment reference count */
 			shn->sn_count++;
 			if (!(devid_nm & NM_NOCOMMIT))
@@ -739,7 +751,7 @@
 
 	recids[0] = recid;
 	recids[1] = ((devid_nm & NM_DEVID) ? md_set[setno].s_did_nmid :
-			md_set[setno].s_nmid);
+	    md_set[setno].s_nmid);
 	recids[2] = 0;
 
 	if (!(devid_nm & NM_NOCOMMIT))
@@ -758,15 +770,15 @@
 		return ((void *)0);
 
 	shn = (char *)((devid_nm & NM_DEVID) ?
-		lookup_shared_entry(nh, shrkey, (char *)0, &recid, devid_nm) :
-		lookup_shared_entry(nh, shrkey, (char *)0, &recid, 0L));
+	    lookup_shared_entry(nh, shrkey, (char *)0, &recid, devid_nm) :
+	    lookup_shared_entry(nh, shrkey, (char *)0, &recid, 0L));
 
 	if (shn == NULL)
 		return ((void *)0);
 
 	return ((void *)((devid_nm & NM_DEVID) ?
-		((struct did_shr_name *)shn)->did_devid :
-		((struct nm_shared_name *)shn)->sn_name));
+	    ((struct did_shr_name *)shn)->did_devid :
+	    ((struct nm_shared_name *)shn)->sn_name));
 }
 
 static mdkey_t
@@ -785,8 +797,8 @@
 		return (MD_KEYBAD);
 
 	return (((devid_nm & NM_DEVID) ?
-		((struct did_shr_name *)shn)->did_key :
-		((struct nm_shared_name *)shn)->sn_key));
+	    ((struct did_shr_name *)shn)->did_key :
+	    ((struct nm_shared_name *)shn)->sn_key));
 }
 
 static int
@@ -800,7 +812,7 @@
 		return (ENOENT);
 
 	shn = (struct nm_shared_name *)lookup_shared_entry(nh, shrkey,
-		(char *)0, &recid, 0L);
+	    (char *)0, &recid, 0L);
 	if (shn == NULL)
 		return (ENOENT);
 	shn->sn_data = (uint32_t)(uintptr_t)data;
@@ -825,17 +837,17 @@
 	side_t			n_side;
 
 	n_offset = offset = ((devid_nm & NM_DEVID) ?
-		(sizeof (struct devid_min_rec) - sizeof (struct did_min_name))
-				:
-		(sizeof (struct nm_rec) - sizeof (struct nm_name)));
+	    (sizeof (struct devid_min_rec) - sizeof (struct did_min_name))
+	    :
+	    (sizeof (struct nm_rec) - sizeof (struct nm_name)));
 
 	this_rh = ((devid_nm & NM_DEVID) ?
-		&((struct devid_min_rec *)record)->min_rec_hdr :
-		&((struct nm_rec *)record)->r_rec_hdr);
+	    &((struct devid_min_rec *)record)->min_rec_hdr :
+	    &((struct nm_rec *)record)->r_rec_hdr);
 
 	n = ((devid_nm & NM_DEVID) ?
-		((caddr_t)&((struct devid_min_rec *)record)->minor_name[0]) :
-		((caddr_t)&((struct nm_rec *)record)->r_name[0]));
+	    ((caddr_t)&((struct devid_min_rec *)record)->minor_name[0]) :
+	    ((caddr_t)&((struct nm_rec *)record)->r_name[0]));
 
 	/*CONSTCOND*/
 	while (1) {
@@ -872,10 +884,10 @@
 			    :
 			    &((struct nm_rec *)record)->r_rec_hdr);
 			n = ((devid_nm & NM_DEVID) ?
-				((caddr_t)&((struct devid_min_rec *)
-					record)->minor_name[0]) :
-				((caddr_t)&((struct nm_rec *)
-					record)->r_name[0]));
+			    ((caddr_t)&((struct devid_min_rec *)
+			    record)->minor_name[0]) :
+			    ((caddr_t)&((struct nm_rec *)
+			    record)->r_name[0]));
 		}
 	}
 	/*NOTREACHED*/
@@ -899,17 +911,17 @@
 	side_t			n_side;
 
 	n_offset = offset = ((devid_nm & NM_DEVID) ?
-		(sizeof (struct devid_min_rec) - sizeof (struct did_min_name))
-				:
-		(sizeof (struct nm_rec) - sizeof (struct nm_name)));
+	    (sizeof (struct devid_min_rec) - sizeof (struct did_min_name))
+	    :
+	    (sizeof (struct nm_rec) - sizeof (struct nm_name)));
 
 	this_rh = ((devid_nm & NM_DEVID) ?
-		&((struct devid_min_rec *)record)->min_rec_hdr :
-		&((struct nm_rec *)record)->r_rec_hdr);
+	    &((struct devid_min_rec *)record)->min_rec_hdr :
+	    &((struct nm_rec *)record)->r_rec_hdr);
 
 	n = ((devid_nm & NM_DEVID) ?
-		((caddr_t)&((struct devid_min_rec *)record)->minor_name[0]) :
-		((caddr_t)&((struct nm_rec *)record)->r_name[0]));
+	    ((caddr_t)&((struct devid_min_rec *)record)->minor_name[0]) :
+	    ((caddr_t)&((struct nm_rec *)record)->r_name[0]));
 
 	/*CONSTCOND*/
 	while (1) {
@@ -926,7 +938,7 @@
 
 		if ((side == n_side) && (key == n_key))
 			return (rem_entry(this_nh, recid, (char *)n, n_size,
-				offset, devid_nm));
+			    offset, devid_nm));
 
 		n = (caddr_t)get_next_entry(this_nh, n, n_size, &offset);
 
@@ -940,14 +952,14 @@
 			record = this_nh->nmn_record;
 			recid = this_rh->r_next_recid;
 			this_rh = ((devid_nm & NM_DEVID) ?
-				&((struct devid_min_rec *)record)->min_rec_hdr
-					:
-				&((struct nm_rec *)record)->r_rec_hdr);
+			    &((struct devid_min_rec *)record)->min_rec_hdr
+			    :
+			    &((struct nm_rec *)record)->r_rec_hdr);
 			n = ((devid_nm & NM_DEVID) ?
-				((caddr_t)&((struct devid_min_rec *)
-					record)->minor_name[0]) :
-				((caddr_t)&((struct nm_rec *)
-					record)->r_name[0]));
+			    ((caddr_t)&((struct devid_min_rec *)
+			    record)->minor_name[0]) :
+			    ((caddr_t)&((struct nm_rec *)
+			    record)->r_name[0]));
 		}
 	}
 	/*NOTREACHED*/
@@ -980,22 +992,22 @@
 	} else {
 		/* How long is the name? */
 		nm_len = ((devid_nm & NM_DEVID) ?
-			ddi_devid_sizeof((ddi_devid_t)nm) :
-			(strlen(nm) + 1));
+		    ddi_devid_sizeof((ddi_devid_t)nm) :
+		    (strlen(nm) + 1));
 	}
 
 	this_rh = ((devid_nm & NM_DEVID) ?
-		&((struct devid_shr_rec *)record)->did_rec_hdr :
-		&((struct nm_shr_rec *)record)->sr_rec_hdr);
+	    &((struct devid_shr_rec *)record)->did_rec_hdr :
+	    &((struct nm_shr_rec *)record)->sr_rec_hdr);
 
 	shn_offset = offset = ((devid_nm & NM_DEVID) ?
-		(sizeof (struct devid_shr_rec) - sizeof (struct did_shr_name))
-			:
-		(sizeof (struct nm_shr_rec) - sizeof (struct nm_shared_name)));
+	    (sizeof (struct devid_shr_rec) - sizeof (struct did_shr_name))
+	    :
+	    (sizeof (struct nm_shr_rec) - sizeof (struct nm_shared_name)));
 
 	shn = ((devid_nm & NM_DEVID) ?
-		((caddr_t)&((struct devid_shr_rec *)record)->device_id[0]) :
-		((caddr_t)&((struct nm_shr_rec *)record)->sr_name[0]));
+	    ((caddr_t)&((struct devid_shr_rec *)record)->device_id[0]) :
+	    ((caddr_t)&((struct nm_shr_rec *)record)->sr_name[0]));
 
 	/*CONSTCOND*/
 	while (1) {
@@ -1012,15 +1024,15 @@
 
 		if ((key != 0) && (key == shn_key))
 			return (rem_shr_entry(this_nh, recid, (char *)shn,
-				shn_size, offset, devid_nm));
+			    shn_size, offset, devid_nm));
 
 		if (nm_len == shn_namlen) {
 			if (!devid_nm) {
-			    if (strcmp(nm, ((struct nm_shared_name *)
-					shn)->sn_name) == 0)
+				if (strcmp(nm, ((struct nm_shared_name *)
+				    shn)->sn_name) == 0)
 				return (rem_shr_entry(this_nh, recid,
-					(char *)shn, shn_size, offset,
-					devid_nm));
+				    (char *)shn, shn_size, offset,
+				    devid_nm));
 			} else {
 
 				if (nm == NULL ||
@@ -1028,17 +1040,17 @@
 				    == NULL) {
 					return (0);
 				}
-			    if (ddi_devid_compare((ddi_devid_t)nm,
-				(ddi_devid_t)(((struct did_shr_name *)shn)->
-					did_devid)) == 0)
+				if (ddi_devid_compare((ddi_devid_t)nm,
+				    (ddi_devid_t)(((struct did_shr_name *)shn)->
+				    did_devid)) == 0)
 				return (rem_shr_entry(this_nh, recid,
-					(char *)shn, shn_size, offset,
-					devid_nm));
+				    (char *)shn, shn_size, offset,
+				    devid_nm));
 			}
 		}
 
 		shn = (caddr_t)get_next_entry(this_nh,
-			(caddr_t)shn, shn_size, &offset);
+		    (caddr_t)shn, shn_size, &offset);
 
 		if (shn == (caddr_t)0) {
 			if (offset)
@@ -1050,13 +1062,13 @@
 			record = this_nh->nmn_record;
 			recid = this_rh->r_next_recid;
 			this_rh = ((devid_nm & NM_DEVID) ?
-				&((struct devid_shr_rec *)record)->did_rec_hdr :
-				&((struct nm_shr_rec *)record)->sr_rec_hdr);
+			    &((struct devid_shr_rec *)record)->did_rec_hdr :
+			    &((struct nm_shr_rec *)record)->sr_rec_hdr);
 			shn = ((devid_nm & NM_DEVID) ?
-				((caddr_t)&((struct devid_shr_rec *)
-					record)->device_id[0]) :
-				((caddr_t)&((struct nm_shr_rec *)
-					record)->sr_name[0]));
+			    ((caddr_t)&((struct devid_shr_rec *)
+			    record)->device_id[0]) :
+			    ((caddr_t)&((struct nm_shr_rec *)
+			    record)->sr_name[0]));
 		}
 	}
 	/*NOTREACHED*/
@@ -1088,6 +1100,22 @@
 }
 
 void *
+lookup_entry_record_offset(
+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 */
+	md_dev64_t	dev, /* (alt. key 2) use if key == KEYWILD */
+	int		devid_nm, /* Which name space? */
+	void		*recp, /* pointer to the record containing the result */
+	size_t		*offsetp /* offset in the above record of result */
+)
+{
+	return (lookup_entry_common(nh, setno, side, key, dev, devid_nm,
+	    &recp, offsetp));
+}
+
+void *
 lookup_entry(
 	struct nm_next_hdr	*nh,	/* head record header */
 	set_t			setno,	/* set to lookup in */
@@ -1097,6 +1125,22 @@
 	int			devid_nm /* Which name space? */
 )
 {
+	return (lookup_entry_common(nh, setno, side, key, dev, devid_nm,
+	    NULL, NULL));
+}
+
+void *
+lookup_entry_common(
+	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 */
+	md_dev64_t		dev,	/* (alt. key 2) use if key == KEYWILD */
+	int			devid_nm,	/* Which name space? */
+	void			**recp, /* record containing the result */
+	size_t			*offsetp /* offset in the record of result */
+)
+{
 	struct nm_next_hdr	*this_nh = nh->nmn_nextp;
 	void			*record;
 	struct nm_rec_hdr	*this_rh;
@@ -1114,8 +1158,8 @@
 	record = this_nh->nmn_record;
 
 	this_rh = ((devid_nm & NM_DEVID) ?
-		&((struct devid_min_rec *)record)->min_rec_hdr :
-		&((struct nm_rec *)record)->r_rec_hdr);
+	    &((struct devid_min_rec *)record)->min_rec_hdr :
+	    &((struct nm_rec *)record)->r_rec_hdr);
 
 	/* code to see if EMPTY record */
 	while (this_nh && this_rh->r_used_size == sizeof (struct nm_rec_hdr)) {
@@ -1125,20 +1169,20 @@
 			return ((void *)0);
 		record = this_nh->nmn_record;
 		this_rh = ((devid_nm & NM_DEVID) ?
-			&((struct devid_min_rec *)record)->min_rec_hdr :
-			&((struct nm_rec *)record)->r_rec_hdr);
+		    &((struct devid_min_rec *)record)->min_rec_hdr :
+		    &((struct nm_rec *)record)->r_rec_hdr);
 	}
 
 	/*
 	 * n_offset will be used to reset offset
 	 */
 	n_offset = offset = ((devid_nm & NM_DEVID) ?
-		(sizeof (struct devid_min_rec) - sizeof (struct did_min_name)) :
-		(sizeof (struct nm_rec) - sizeof (struct nm_name)));
+	    (sizeof (struct devid_min_rec) - sizeof (struct did_min_name)) :
+	    (sizeof (struct nm_rec) - sizeof (struct nm_name)));
 
 	n = ((devid_nm & NM_DEVID) ?
-		((caddr_t)&((struct devid_min_rec *)record)->minor_name[0]) :
-		((caddr_t)&((struct nm_rec *)record)->r_name[0]));
+	    ((caddr_t)&((struct devid_min_rec *)record)->minor_name[0]) :
+	    ((caddr_t)&((struct nm_rec *)record)->r_name[0]));
 
 	/*CONSTCOND*/
 	while (1) {
@@ -1155,23 +1199,34 @@
 
 		if ((side == n_side) || (side == MD_SIDEWILD)) {
 
-			if ((key != MD_KEYWILD) && (key == n_key))
+			if ((key != MD_KEYWILD) && (key == n_key)) {
+				if (recp)
+					*recp = record;
+				if (offsetp)
+					*offsetp = offset;
 				return ((void *)n);
+			}
 
 			if ((key == MD_KEYWILD) && !devid_nm &&
 			    (dev == build_device_number(setno,
-			    (struct nm_name *)n)))
+			    (struct nm_name *)n))) {
+				if (recp)
+					*recp = record;
+				if (offsetp)
+					*offsetp = offset;
 				return ((void *)n);
+			}
+
 		}
 
 		n = (caddr_t)get_next_entry(this_nh, n, n_size, &offset);
 
 		if (n == NULL) {
 			/*
-			 * No next record, return
+			 * No next record, return NULL
 			 */
-			if (offset)
-				return ((void *)n);
+			if (this_nh->nmn_nextp == NULL)
+				return (NULL);
 
 			/* Go to next record */
 			offset = n_offset;
@@ -1181,10 +1236,10 @@
 			    &((struct devid_min_rec *)record)->min_rec_hdr :
 			    &((struct nm_rec *)record)->r_rec_hdr);
 			n = ((devid_nm & NM_DEVID) ?
-				((caddr_t)&((struct devid_min_rec *)
-					record)->minor_name[0]) :
-				((caddr_t)&((struct nm_rec *)
-					record)->r_name[0]));
+			    ((caddr_t)&((struct devid_min_rec *)
+			    record)->minor_name[0]) :
+			    ((caddr_t)&((struct nm_rec *)
+			    record)->r_name[0]));
 		}
 	}
 	/*NOTREACHED*/
@@ -1200,7 +1255,7 @@
 	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) {
+	    key, NULL, NULL, NM_SHARED)) == NULL) {
 		return (FALSE);
 	}
 
@@ -1300,7 +1355,7 @@
 			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) {
+			    KEY_TO_HSP_ID(setno, n->n_key)) == NULL) {
 				/*
 				 * All entries removed
 				 */
@@ -1314,9 +1369,9 @@
 			 * 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) &&
+			    == NULL && (side == n->n_side) &&
 			    ddi_name_to_major(getshared_name(setno,
-				n->n_drv_key, 0L)) == md_major) {
+			    n->n_drv_key, 0L)) == md_major) {
 				/*
 				 * Apparently it is invalid so
 				 * clean it up
@@ -1330,17 +1385,17 @@
 
 			/* First see if the two drives are metadevices. */
 			if (is_meta_drive(setno, drvkey) &&
-				is_meta_drive(setno, n->n_drv_key)) {
+			    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))) {
+			    ((key != n->n_key) ||
+			    (mnum != n->n_minor) ||
+			    (drvkey != n->n_drv_key) ||
+			    (dirkey != n->n_dir_key))) {
 				return (LOOKUP_DEV_CONFLICT);
 			}
 		}
@@ -1364,6 +1419,21 @@
 }
 
 void *
+lookup_shared_entry_record_offset(
+	struct nm_next_hdr *nh,	/* First record header to start lookup */
+	mdkey_t		key,	/* Shared key, used as key if nm is NULL */
+	char *nm,		/* Shared name, used as key if non-NULL */
+	mddb_recid_t *id,	/* mddb record id of record entry is found in */
+	int devid_nm,		/* which name space? */
+	void *recp,		/* pointer to record containing the result */
+	size_t *offset_p	/* offest in the above record of the result */
+)
+{
+	return (lookup_shared_entry_common(nh, key, nm, id, devid_nm, &recp,
+	    offset_p));
+}
+
+void *
 lookup_shared_entry(
 	struct nm_next_hdr *nh,	/* First record header to start lookup */
 	mdkey_t key,		/* Shared key, used as key if nm is NULL */
@@ -1371,6 +1441,22 @@
 	mddb_recid_t *id,	/* mddb record id of record entry is found in */
 	int	devid_nm)	/* which name space? */
 {
+	return (lookup_shared_entry_common(nh, key, nm, id, devid_nm, NULL,
+	    NULL));
+}
+
+void *
+lookup_shared_entry_common(
+	struct nm_next_hdr *nh, /* First record header to start lookup */
+	mdkey_t key,		/* Shared key, used as key if nm is NULL */
+	char *nm,		/* Shared name, used as key if non-NULL */
+	mddb_recid_t *id,	/* mddb record id of record entry is found in */
+	int	devid_nm,	/* which name space? */
+	void	**recp,		/* pointer to record containing the result */
+	size_t	*offsetp	/* offest in the above record of the result */
+)
+{
+
 	struct nm_rec_hdr	*rh = (struct nm_rec_hdr *)nh->nmn_record;
 	struct nm_next_hdr	*this_nh = nh->nmn_nextp;
 	void			*record;
@@ -1382,21 +1468,21 @@
 	ushort_t		shn_namlen;
 
 	if (this_nh == NULL)
-		return ((void *)0);
+		return ((void *) 0);
 
 	record = this_nh->nmn_record;
 
 	if (nm != (char *)0)
 		nm_len = ((devid_nm & NM_DEVID) ?
-			ddi_devid_sizeof((ddi_devid_t)nm) :
-			(strlen(nm) + 1));
+		    ddi_devid_sizeof((ddi_devid_t)nm) :
+		    (strlen(nm) + 1));
 
 	if (id != NULL)
 		*id = rh->r_next_recid;
 
 	this_rh = ((devid_nm & NM_DEVID) ?
-		&((struct devid_shr_rec *)record)->did_rec_hdr :
-		&((struct nm_shr_rec *)record)->sr_rec_hdr);
+	    &((struct devid_shr_rec *)record)->did_rec_hdr :
+	    &((struct nm_shr_rec *)record)->sr_rec_hdr);
 
 	/* code to see if EMPTY record */
 	while (this_nh && this_rh->r_used_size == sizeof (struct nm_rec_hdr)) {
@@ -1409,20 +1495,20 @@
 			*id = this_rh->r_next_recid;
 
 		this_rh = ((devid_nm & NM_DEVID) ?
-			&((struct devid_shr_rec *)record)->did_rec_hdr :
-			&((struct nm_shr_rec *)record)->sr_rec_hdr);
+		    &((struct devid_shr_rec *)record)->did_rec_hdr :
+		    &((struct nm_shr_rec *)record)->sr_rec_hdr);
 	}
 
 	/*
 	 * shn_offset will be used to reset offset
 	 */
 	shn_offset = offset = ((devid_nm & NM_DEVID) ?
-		(sizeof (struct devid_shr_rec) - sizeof (struct did_shr_name)) :
-		(sizeof (struct nm_shr_rec) - sizeof (struct nm_shared_name)));
+	    (sizeof (struct devid_shr_rec) - sizeof (struct did_shr_name)) :
+	    (sizeof (struct nm_shr_rec) - sizeof (struct nm_shared_name)));
 
 	shn = ((devid_nm & NM_DEVID) ?
-		((caddr_t)&((struct devid_shr_rec *)record)->device_id[0]) :
-		((caddr_t)&((struct nm_shr_rec *)record)->sr_name[0]));
+	    ((caddr_t)&((struct devid_shr_rec *)record)->device_id[0]) :
+	    ((caddr_t)&((struct nm_shr_rec *)record)->sr_name[0]));
 
 	/*CONSTCOND*/
 	while (1) {
@@ -1437,31 +1523,51 @@
 			shn_size = SHR_NAMSIZ((struct nm_shared_name *)shn);
 		}
 
-		if ((key != 0) && (key == shn_key))
+		if ((key != 0) && (key == shn_key)) {
+			if (recp)
+				*recp = record;
+			if (offsetp)
+				*offsetp = offset;
 			return ((void *)shn);
+		}
 
 		/* Lookup by name */
 		if (nm != NULL) {
-		    if (devid_nm & NM_IMP_SHARED) {
+			if (devid_nm & NM_IMP_SHARED) {
 			/*
 			 * the nm passed in is "/dev/md" in the import case
 			 * and we want to do a partial match on that.
 			 */
 			if (strncmp(nm, ((struct nm_shared_name *)shn)->sn_name,
-			    strlen(nm)) == 0)
-			    return ((void *)shn);
-		    } else if (nm_len == shn_namlen) {
-			if (devid_nm & NM_DEVID) {
-			    if (ddi_devid_compare((ddi_devid_t)nm,
-				(ddi_devid_t)(((struct did_shr_name *)shn)->
-					did_devid)) == 0)
-				return ((void *)shn);
-			} else {
-			    if (strcmp(nm, ((struct nm_shared_name *)
-					shn)->sn_name) == 0)
+			    strlen(nm)) == 0) {
+				if (recp)
+					*recp = record;
+				if (offsetp)
+					*offsetp = offset;
 				return ((void *)shn);
 			}
-		    }
+			} else if (nm_len == shn_namlen) {
+			if (devid_nm & NM_DEVID) {
+				if (ddi_devid_compare((ddi_devid_t)nm,
+				    (ddi_devid_t)(((struct did_shr_name *)shn)->
+				    did_devid)) == 0) {
+					if (recp)
+						*recp = record;
+					if (offsetp)
+						*offsetp = offset;
+					return ((void *)shn);
+				}
+			} else {
+				if (strcmp(nm, ((struct nm_shared_name *)
+				    shn)->sn_name) == 0) {
+					if (recp)
+						*recp = record;
+					if (offsetp)
+						*offsetp = offset;
+					return ((void *)shn);
+				}
+			}
+			}
 		}
 
 		shn = (caddr_t)get_next_entry(this_nh,
@@ -1471,8 +1577,8 @@
 			/*
 			 * No next record, return
 			 */
-			if (offset)
-				return ((void *)shn);
+			if (this_nh->nmn_nextp == NULL)
+				return (NULL);
 
 			/* Go to next record */
 			offset = shn_offset;
@@ -1481,13 +1587,13 @@
 			if (id != NULL)
 				*id = this_rh->r_next_recid;
 			this_rh = ((devid_nm & NM_DEVID) ?
-				&((struct devid_shr_rec *)record)->did_rec_hdr :
-				&((struct nm_shr_rec *)record)->sr_rec_hdr);
+			    &((struct devid_shr_rec *)record)->did_rec_hdr :
+			    &((struct nm_shr_rec *)record)->sr_rec_hdr);
 			shn = ((devid_nm & NM_DEVID) ?
-				((caddr_t)&((struct devid_shr_rec *)
-					record)->device_id[0]) :
-				((caddr_t)&((struct nm_shr_rec *)
-					record)->sr_name[0]));
+			    ((caddr_t)&((struct devid_shr_rec *)
+			    record)->device_id[0]) :
+			    ((caddr_t)&((struct nm_shr_rec *)
+			    record)->sr_name[0]));
 		}
 	}
 	/*NOTREACHED*/
@@ -1578,13 +1684,16 @@
 				 */
 				if (key == MD_KEYWILD) {
 					if (setname != NULL)
-					    (void) snprintf(tmpname, MAXPATHLEN,
-						"%s/%s", setname,
-						((struct nm_name *)n)->n_name);
+						(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);
+						(void) snprintf(tmpname,
+						    MAXPATHLEN, "%s",
+						    ((struct nm_name *)
+						    n)->n_name);
 
 					if ((strcmp(name, tmpname)) == 0)
 						goto done;
@@ -1657,13 +1766,16 @@
 
 	if (shared & NM_DEVID)
 		overhead_size = ((shared & NM_SHARED) ?
-		(sizeof (struct devid_shr_rec) - sizeof (struct did_shr_name))
-				:
-		(sizeof (struct devid_min_rec) - sizeof (struct did_min_name)));
+		    (sizeof (struct devid_shr_rec) -
+		    sizeof (struct did_shr_name))
+		    :
+		    (sizeof (struct devid_min_rec) -
+		    sizeof (struct did_min_name)));
 	else
 		overhead_size = ((shared & NM_SHARED) ?
-		(sizeof (struct nm_shr_rec) - sizeof (struct nm_shared_name)) :
-		(sizeof (struct nm_rec) - sizeof (struct nm_name)));
+		    (sizeof (struct nm_shr_rec) -
+		    sizeof (struct nm_shared_name)) :
+		    (sizeof (struct nm_rec) - sizeof (struct nm_name)));
 
 	while (rh->r_next_recid > 0) {
 		this_nh = kmem_zalloc(sizeof (*this_nh), KM_SLEEP);
@@ -1673,15 +1785,18 @@
 		ASSERT(this_nh->nmn_record != NULL);
 
 		if (shared & NM_DEVID)
-		    this_rh = ((shared & NM_SHARED) ?
-		    &((struct devid_shr_rec *)this_nh->nmn_record)->did_rec_hdr
-			:
-		    &((struct devid_min_rec *)
-		    this_nh->nmn_record)->min_rec_hdr);
+			this_rh = ((shared & NM_SHARED) ?
+			    &((struct devid_shr_rec *)
+			    this_nh->nmn_record)->did_rec_hdr
+			    :
+			    &((struct devid_min_rec *)
+			    this_nh->nmn_record)->min_rec_hdr);
 		else
-		    this_rh = ((shared & NM_SHARED) ?
-		    &((struct nm_shr_rec *)this_nh->nmn_record)->sr_rec_hdr :
-		    &((struct nm_rec *)this_nh->nmn_record)->r_rec_hdr);
+			this_rh = ((shared & NM_SHARED) ?
+			    &((struct nm_shr_rec *)
+			    this_nh->nmn_record)->sr_rec_hdr
+			    :
+			    &((struct nm_rec *)this_nh->nmn_record)->r_rec_hdr);
 
 		/*
 		 * Check for empty records and clean them up.
@@ -1691,7 +1806,7 @@
 		    (multi_node && md_set[setno].s_am_i_master)) {
 			if (this_rh->r_used_size == overhead_size) {
 				mddb_setrecprivate(rh->r_next_recid,
-					MD_PRV_PENDDEL);
+				    MD_PRV_PENDDEL);
 				rh->r_next_recid = this_rh->r_next_recid;
 				kmem_free(this_nh, sizeof (*this_nh));
 				nh->nmn_nextp = NULL;
@@ -1934,7 +2049,7 @@
 	 * If it already there in the name space
 	 */
 	lookup_res = lookup_deventry(nh, setno, side, key, drvnm, mnum, dname,
-		fname, &n);
+	    fname, &n);
 
 	/* If we are importing the set */
 	if (imp_flag && (lookup_res == LOOKUP_DEV_FOUND)) {
@@ -1991,11 +2106,11 @@
 			 */
 			if ((did_n = (struct did_min_name *)
 			    lookup_entry(did_nh, setno, side, n->n_key,
-				NODEV64, NM_DEVID)) != NULL) {
+			    NODEV64, NM_DEVID)) != NULL) {
 
 				did_n->min_count++;
 				(void) update_entry(did_nh, did_n->min_side,
-						did_n->min_key, NM_DEVID);
+				    did_n->min_key, NM_DEVID);
 			} else {
 				/*
 				 * If a disk device does not support
@@ -2035,8 +2150,8 @@
 		 * If MDE_DB_NOSPACE occurs
 		 */
 		if (((n->n_drv_key =
-			setshared_name(setno, drvnm, MD_KEYWILD, 0L)) ==
-			MD_KEYBAD)) {
+		    setshared_name(setno, drvnm, MD_KEYWILD, 0L)) ==
+		    MD_KEYBAD)) {
 			/*
 			 * Remove entry allocated by alloc_entry
 			 * and return MD_KEYBAD
@@ -2050,14 +2165,14 @@
 		} else {
 			/* We have a directory name to save. */
 			if ((n->n_dir_key =
-				setshared_name(setno, dname, MD_KEYWILD, 0L)) ==
-				MD_KEYBAD) {
+			    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);
+				    0L);
 				goto out;
 			}
 		}
@@ -2120,18 +2235,18 @@
 
 	if (shared & NM_DEVID) {
 		new_did_n = (struct did_min_name *)alloc_entry(did_nh,
-			md_set[setno].s_did_nmid, min_len,
-			shared, &recids[0]);
+		    md_set[setno].s_did_nmid, min_len,
+		    shared, &recids[0]);
 
 		/*
 		 * No space
 		 */
 		if (new_did_n == NULL) {
-		    if (new) {
+			if (new) {
 			(void) remove_entry(nh, n->n_side, n->n_key, 0L);
 			retval = MD_KEYBAD;
-		    }
-		    goto out;
+			}
+			goto out;
 		}
 
 		new_did_n->min_side = side;
@@ -2176,10 +2291,11 @@
 			 * Remove entry allocated by alloc_entry
 			 */
 			(void) remove_entry(did_nh, new_did_n->min_side,
-				new_did_n->min_key, NM_DEVID);
+			    new_did_n->min_key, NM_DEVID);
 			if (new) {
-			    (void) remove_entry(nh, n->n_side, n->n_key, 0L);
-			    retval = MD_KEYBAD;
+				(void) remove_entry(nh, n->n_side, n->n_key,
+				    0L);
+				retval = MD_KEYBAD;
 			}
 		} else {
 			recids[1] = md_set[setno].s_did_nmid;
@@ -2266,19 +2382,19 @@
 		int		compare_rc = 1;
 
 		did_n = (struct did_min_name *)lookup_entry(
-				did_nh, setno, side, key, NODEV64, NM_DEVID);
+		    did_nh, setno, side, key, NODEV64, NM_DEVID);
 		if (did_n == NULL) {
 			continue;
 		}
 		did_shr_n = (struct did_shr_name *)lookup_shared_entry(
-				did_shr_nh, did_n->min_devid_key, (char *)0,
-				NULL, NM_DEVID);
+		    did_shr_nh, did_n->min_devid_key, (char *)0,
+		    NULL, NM_DEVID);
 		if ((did_shr_n->did_data & NM_DEVID_VALID) != NULL) {
 			continue;
 		}
 		/* found invalid device id. Add to list */
 		devt = md_dev64_to_dev(
-				md_getdevnum(setno, side, key, MD_TRUST_DEVT));
+		    md_getdevnum(setno, side, key, MD_TRUST_DEVT));
 		get_rc = ddi_lyr_get_devid(devt, &rtn_devid);
 		if (get_rc == DDI_SUCCESS) {
 			compare_rc = ddi_devid_compare(rtn_devid,
@@ -2294,7 +2410,7 @@
 				return (-1);
 			}
 			n = (struct nm_name *)lookup_entry(
-					nh, setno, side, key, NODEV64, 0L);
+			    nh, setno, side, key, NODEV64, 0L);
 			if (n == NULL) {
 				rw_exit(&nm_lock.lock);
 				return ((int)NODEV64);
@@ -2307,7 +2423,7 @@
 				return (-1);
 			}
 			if ((tmpname = strrchr(diskname, 's')) != NULL)
-			    *tmpname = '\0';
+				*tmpname = '\0';
 			dont_add_it = 0;
 			for (i = 0; i < (cnt - 1); i++) {
 				if (strcmp(diskname, tmpctd) == 0) {
@@ -2397,19 +2513,19 @@
 		int		compare_rc = 1;
 
 		did_n = (struct did_min_name *)lookup_entry(
-				did_nh, setno, side, key, NODEV64, NM_DEVID);
+		    did_nh, setno, side, key, NODEV64, NM_DEVID);
 		if (did_n == NULL) {
 			continue;
 		}
 		did_shr_n = (struct did_shr_name *)lookup_shared_entry(
-				did_shr_nh, did_n->min_devid_key, (char *)0,
-				NULL, NM_DEVID);
+		    did_shr_nh, did_n->min_devid_key, (char *)0,
+		    NULL, NM_DEVID);
 		if ((did_shr_n->did_data & NM_DEVID_VALID) != 0) {
 			continue;
 		}
 
 		devt = md_dev64_to_dev(
-				md_getdevnum(setno, side, key, MD_TRUST_DEVT));
+		    md_getdevnum(setno, side, key, MD_TRUST_DEVT));
 		get_rc = ddi_lyr_get_devid(devt, &rtn_devid);
 		if (get_rc == DDI_SUCCESS) {
 			compare_rc = ddi_devid_compare(rtn_devid,
@@ -2423,7 +2539,7 @@
 			/* device id is invalid */
 			cnt++;
 			n = (struct nm_name *)lookup_entry(
-					nh, setno, side, key, NODEV64, 0L);
+			    nh, setno, side, key, NODEV64, 0L);
 			if (n == NULL) {
 				rw_exit(&nm_lock.lock);
 				return ((int)NODEV64);
@@ -2509,7 +2625,7 @@
 
 	if ((n = (struct nm_name *)lookup_entry(nh, setno, side, key,
 	    dev, 0L))
-		== NULL) {
+	    == NULL) {
 		rw_exit(&nm_lock.lock);
 		return (ENOENT);
 	}
@@ -2759,7 +2875,7 @@
 
 	if ((n = (struct nm_name *)lookup_entry(nh, setno, side, key,
 	    dev, 0L))
-		== NULL) {
+	    == NULL) {
 		rw_exit(&nm_lock.lock);
 		return (ENOENT);
 	}
@@ -2817,22 +2933,23 @@
 	 * so that this check is only done once.
 	 */
 	if (!(md_get_setstatus(setno) & MD_SET_DIDCLUP)) {
-	    if ((MD_MNSET_SETNO(setno) && (md_set[setno].s_am_i_master)) ||
-		(!(MD_MNSET_SETNO(setno)))) {
-		    if (!(((mddb_set_t *)md_set[setno].s_db)->s_lbp->lb_flags
-			& MDDB_DEVID_STYLE) || md_devid_destroy) {
-			    (void) md_load_namespace(setno, NULL, NM_DEVID);
-			    (void) md_devid_cleanup(setno, 1);
-		    }
-	    }
-	    md_set_setstatus(setno, MD_SET_DIDCLUP);
+		if ((MD_MNSET_SETNO(setno) && (md_set[setno].s_am_i_master)) ||
+		    (!(MD_MNSET_SETNO(setno)))) {
+			if (!(((mddb_set_t *)
+			    md_set[setno].s_db)->s_lbp->lb_flags
+			    & MDDB_DEVID_STYLE) || md_devid_destroy) {
+				(void) md_load_namespace(setno, NULL, NM_DEVID);
+				(void) md_devid_cleanup(setno, 1);
+			}
+		}
+		md_set_setstatus(setno, MD_SET_DIDCLUP);
 	}
 
 	/*
 	 * Test the MDDB_DEVID_STYLE bit
 	 */
 	if (((mddb_set_t *)md_set[setno].s_db)->s_lbp->lb_flags
-		& MDDB_DEVID_STYLE) {
+	    & MDDB_DEVID_STYLE) {
 		(void) md_load_namespace(setno, NULL, NM_DEVID);
 		devid_nm = 1;
 	}
@@ -2855,8 +2972,8 @@
 	 * If not even in the primary name space, bail out
 	 */
 	if (((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) ||
-		((n = (struct nm_name *)lookup_entry(nh, setno, side, key,
-			NODEV64, 0L)) == NULL)) {
+	    ((n = (struct nm_name *)lookup_entry(nh, setno, side, key,
+	    NODEV64, 0L)) == NULL)) {
 		rw_exit(&nm_lock.lock);
 		return (NODEV64);
 	}
@@ -2875,11 +2992,12 @@
 	 * Reference the device id namespace
 	 */
 	if (devid_nm) {
-	    if (((did_nh = get_first_record(setno, 1, NM_DEVID | NM_NOTSHARED))
-		== NULL) || ((did_shr_nh = get_first_record(setno, 1,
-			NM_DEVID | NM_SHARED)) == NULL)) {
-		devid_nm = 0;
-	    }
+		if (((did_nh = get_first_record(setno, 1, NM_DEVID |
+		    NM_NOTSHARED)) == NULL) || ((did_shr_nh =
+		    get_first_record(setno, 1, NM_DEVID | NM_SHARED))
+		    == NULL)) {
+			devid_nm = 0;
+		}
 	}
 
 	/*
@@ -2887,16 +3005,16 @@
 	 * this device has disk tracking info stored
 	 */
 	if (devid_nm && ((did_n = (struct did_min_name *)lookup_entry(did_nh,
-		setno, side, key, NODEV64, NM_DEVID)) != NULL)) {
+	    setno, side, key, NODEV64, NM_DEVID)) != NULL)) {
 		/*
 		 * Get the minor name and the device id
 		 */
 		devid = (ddi_devid_t)getshared_name(setno,
-						did_n->min_devid_key, NM_DEVID);
+		    did_n->min_devid_key, NM_DEVID);
 
 		did_shr_n = (struct did_shr_name *)lookup_shared_entry(
-					did_shr_nh, did_n->min_devid_key,
-					(char *)0, NULL, NM_DEVID);
+		    did_shr_nh, did_n->min_devid_key,
+		    (char *)0, NULL, NM_DEVID);
 
 		if ((devid == NULL) || (did_shr_n == NULL)) {
 			rw_exit(&nm_lock.lock);
@@ -2905,7 +3023,7 @@
 
 
 		if (ddi_lyr_devid_to_devlist(devid, did_n->min_name, &ndevs,
-			&devs) == DDI_SUCCESS) {
+		    &devs) == DDI_SUCCESS) {
 
 			md_dev64_t tdev;
 			int cnt;
@@ -2943,10 +3061,10 @@
 			 */
 			if (MD_UPGRADE)
 				drvnm = md_targ_major_to_name(md_getmajor
-					(md_xlate_mini_2_targ(retval)));
+				    (md_xlate_mini_2_targ(retval)));
 			else
 				drvnm = ddi_major_to_name(
-						md_getmajor(retval));
+				    md_getmajor(retval));
 
 			/*
 			 * It is a valid device id
@@ -3064,17 +3182,17 @@
 			 * If retval has a device id, add them
 			 */
 			if ((ddi_lyr_get_devid(md_dev64_to_dev(retval), &devid)
-							== DDI_SUCCESS) &&
+			    == DDI_SUCCESS) &&
 			    (ddi_lyr_get_minor_name(md_dev64_to_dev(retval),
-							S_IFBLK, &mname)
-							== DDI_SUCCESS)) {
+			    S_IFBLK, &mname)
+			    == DDI_SUCCESS)) {
 				/*
 				 * Add them into the devid name space
 				 */
 				did_n = (struct did_min_name *)alloc_entry(
-					did_nh, md_set[setno].s_did_nmid,
-					strlen(mname)+1, NM_DEVID|NM_NOTSHARED,
-					&recids[0]);
+				    did_nh, md_set[setno].s_did_nmid,
+				    strlen(mname)+1, NM_DEVID|NM_NOTSHARED,
+				    &recids[0]);
 
 				if (did_n) {
 					did_n->min_side = side;
@@ -3085,16 +3203,16 @@
 					    (ushort_t)(strlen(mname)+1);
 					did_n->min_devid_key =
 					    setshared_name(setno,
-						(char *)devid, MD_KEYWILD,
-						NM_DEVID);
+					    (char *)devid, MD_KEYWILD,
+					    NM_DEVID);
 					/*
 					 * Commit the change to the record
 					 */
 					if (did_n->min_devid_key == MD_KEYBAD) {
 						(void) remove_entry(did_nh,
-							did_n->min_side,
-							did_n->min_key,
-							NM_DEVID);
+						    did_n->min_side,
+						    did_n->min_key,
+						    NM_DEVID);
 					} else {
 						recids[1] =
 						    md_set[setno].s_did_nmid;
@@ -3112,7 +3230,7 @@
 				kmem_free(mname, strlen(mname) + 1);
 		} else {
 			retval = md_makedevice(md_major,
-						md_getminor(retval_targ));
+			    md_getminor(retval_targ));
 		}
 	}
 
@@ -3155,15 +3273,15 @@
 	}
 
 	for (key++; key < ((struct nm_rec_hdr *)nh->nmn_record)->r_next_key;
-			key++) {
+	    key++) {
 		if ((n = (struct nm_name *)lookup_entry(nh, setno, side, key,
-			NODEV64, 0L)) != NULL)
+		    NODEV64, 0L)) != NULL)
 			break;
 	}
 
 	if (n != NULL) {
 		if (cnt != NULL)
-		    *cnt = n->n_count;
+			*cnt = n->n_count;
 
 		retval = n->n_key;
 	}
@@ -3190,8 +3308,7 @@
 	mdkey_t			ent_did_key;
 	uint32_t		ent_did_count;
 	uint32_t		ent_did_data;
-	struct nm_next_hdr	*this_did_shr_nh;
-	void			*record;
+	void			*record, *n_record;
 	size_t			offset;
 	struct did_shr_name	*shn;
 	mddb_recid_t		recids[3];
@@ -3199,7 +3316,7 @@
 	struct nm_next_hdr	*this_did_nh;
 	struct did_min_name	*n;
 	struct did_shr_name	*shr_n;
-	mdkey_t			o_key, devid_key;
+	mdkey_t			devid_key;
 	size_t			ent_size, size;
 
 	(void) md_load_namespace(setno, NULL, NM_DEVID);
@@ -3211,7 +3328,7 @@
 
 	offset = (sizeof (struct devid_shr_rec) - sizeof (struct did_shr_name));
 	if ((nh = get_first_record(setno, 0, NM_DEVID | NM_NOTSHARED)) ==
-									NULL) {
+	    NULL) {
 		rw_exit(&nm_lock.lock);
 		return (ENOENT);
 	}
@@ -3226,16 +3343,18 @@
 		rw_exit(&nm_lock.lock);
 		return (ENOENT);
 	}
+
 	if ((n = (struct did_min_name *)lookup_entry(nh, setno, side, key,
 	    NODEV64, NM_DEVID)) == NULL) {
 		rw_exit(&nm_lock.lock);
 		return (ENOENT);
 	}
 	devid_key = n->min_devid_key;
-
 	rw_exit(&nm_lock.lock);
+
 	devt = md_dev64_to_dev(
-			md_getdevnum(setno, side, key, MD_TRUST_DEVT));
+	    md_getdevnum(setno, side, key, MD_TRUST_DEVT));
+
 	rw_enter(&nm_lock.lock, RW_WRITER);
 	if (ddi_lyr_get_devid(devt, &rtn_devid) == DDI_SUCCESS) {
 		did_shr_nh = get_first_record(setno, 0, NM_DEVID | NM_SHARED);
@@ -3244,31 +3363,19 @@
 			rw_exit(&nm_lock.lock);
 			return ((int)NODEV64);
 		}
-		this_did_shr_nh = did_shr_nh->nmn_nextp;
-		record = this_did_shr_nh->nmn_record;
-		shn = &((struct devid_shr_rec *)record)->device_id[0];
-		shr_n = (struct did_shr_name *)lookup_shared_entry(
-				did_shr_nh, n->min_devid_key, (char *)0,
-				&recids[0], NM_DEVID);
+
+		n_record = did_shr_nh->nmn_nextp->nmn_record;
+
+		shr_n = (struct did_shr_name *)
+		    lookup_shared_entry_record_offset(did_shr_nh, devid_key,
+		    (char *)0, &recids[0], NM_DEVID, n_record, &offset);
+
 		if (shr_n == NULL) {
 			ddi_devid_free(rtn_devid);
 			rw_exit(&nm_lock.lock);
 			return (ENOENT);
 		}
-		o_key = shn->did_key;
-		while (devid_key != o_key) {
-			shn = (struct did_shr_name *)get_next_entry(
-					this_did_shr_nh, (caddr_t)shn,
-					DID_SHR_NAMSIZ(shn), &offset);
-			if (shn == NULL) {
-				if (offset) {
-					ddi_devid_free(rtn_devid);
-					rw_exit(&nm_lock.lock);
-					return (ENOENT);
-				}
-			}
-			o_key = shn->did_key;
-		}
+
 		devid = (ddi_devid_t)shr_n->did_devid;
 		if (ddi_devid_compare(rtn_devid, devid) != 0) {
 			/* remove old devid info */
@@ -3276,8 +3383,19 @@
 			ent_did_count = shr_n->did_count;
 			ent_did_data = shr_n->did_data;
 			ent_size = DID_SHR_NAMSIZ(shr_n);
-			size = ((struct nm_rec_hdr *)this_did_shr_nh->
-			    nmn_record)->r_used_size - offset - ent_size;
+
+			/*
+			 * So we're going to overwrite this record; if it's the
+			 * last entry, just bzero() it. If it's not, then copy
+			 * the remaining entries back to the start of our entry
+			 */
+
+			size = ((struct nm_rec_hdr *)n_record)->r_used_size
+			    - offset - ent_size;
+
+			ASSERT(size + offset <= ((struct nm_rec_hdr *)
+			    n_record)->r_used_size);
+
 			if (size == 0) {
 				(void) bzero(shr_n, ent_size);
 			} else {
@@ -3285,8 +3403,8 @@
 				    size);
 				(void) bzero((caddr_t)shr_n + size, ent_size);
 			}
-			((struct nm_rec_hdr *)this_did_shr_nh->nmn_record)->
-			    r_used_size -= ent_size;
+			((struct nm_rec_hdr *)n_record)->r_used_size -=
+			    ent_size;
 			/* add in new devid info */
 			if ((shn = (struct did_shr_name *)alloc_entry(
 			    did_shr_nh, md_set[setno].s_did_nmid,
@@ -3336,18 +3454,15 @@
 {
 	struct nm_next_hdr	*nh;
 	struct nm_name		*n;
-	struct nm_name		*o_n;
-	struct nm_next_hdr	*this_nh;
 	struct nm_next_hdr	*snh;
 	struct nm_shared_name	*shn;
-	void			*record;
+	void			*n_record;
 	mddb_recid_t		recids[3];
 	size_t			size;
 	mdkey_t			ent_key, ent_drv_key, ent_dir_key, new_dir_key;
 	uint32_t		ent_count;
 	side_t			ent_side;
 	size_t			offset;
-	mdkey_t			o_key = NULL;
 	char			*old_pathname;
 	int			ent_size;
 
@@ -3363,27 +3478,14 @@
 		return (ENOENT);
 	}
 
-	this_nh = nh->nmn_nextp;
-	record = this_nh->nmn_record;
-	o_n = &((struct nm_rec *)record)->r_name[0];
-	if ((n = (struct nm_name *)lookup_entry(nh, setno, side, key, NODEV64,
-	    0L)) == NULL) {
+	n_record = nh->nmn_nextp->nmn_record;
+
+	if ((n = (struct nm_name *)lookup_entry_record_offset(nh, setno, side,
+	    key, NODEV64, 0L, n_record, &offset)) == NULL) {
 		rw_exit(&nm_lock.lock);
 		return (ENOENT);
 	}
 
-	o_key = o_n->n_key;
-	while (key != o_key) {
-		o_n = (struct nm_name *)get_next_entry(this_nh, (caddr_t)o_n,
-		    NAMSIZ(o_n), &offset);
-		if (o_n == NULL) {
-			if (offset) {
-				rw_exit(&nm_lock.lock);
-				return (ENOENT);
-			}
-		}
-		o_key = o_n->n_key;
-	}
 	/* save the values from the old record */
 	ent_side = n->n_side;
 	ent_key = n->n_key;
@@ -3391,8 +3493,16 @@
 	ent_drv_key = n->n_drv_key;
 	ent_dir_key = n->n_dir_key;
 	ent_size = NAMSIZ(n);
-	size = ((struct nm_rec_hdr *)this_nh->nmn_record)->r_used_size - offset
-	    - ent_size;
+
+	/*
+	 * So we're going to overwrite this record; if it's the last
+	 * entry, just bzero() it. If it's not, then copy the
+	 * remaining entries back to the start of our entry
+	 */
+
+	size = ((struct nm_rec_hdr *)n_record)->r_used_size - offset - ent_size;
+
+	ASSERT(offset + size <= ((struct nm_rec_hdr *)n_record)->r_alloc_size);
 
 	if (size == 0) {
 		(void) bzero(n, ent_size);    /* last entry */
@@ -3400,7 +3510,7 @@
 		(void) ovbcopy((caddr_t)n + ent_size, n, size);
 		(void) bzero((caddr_t)n + size, ent_size);
 	}
-	((struct nm_rec_hdr *)this_nh->nmn_record)->r_used_size -= ent_size;
+	((struct nm_rec_hdr *)n_record)->r_used_size -= ent_size;
 
 	rw_exit(&nm_lock.lock);
 	/* check to see if we have a new pathname */
@@ -3635,7 +3745,7 @@
 	 * If it is not in the primary name space, nothing to remove
 	 */
 	if ((n = (struct nm_name *)lookup_entry(nh, setno, side, key, NODEV64,
-		0L)) == NULL) {
+	    0L)) == NULL) {
 		rw_exit(&nm_lock.lock);
 		return (ENOENT);
 	}
@@ -3646,11 +3756,11 @@
 	 */
 	if (md_set[setno].s_did_nm &&
 	    ((did_nh = get_first_record(setno, 0, NM_DEVID | NM_NOTSHARED))
-		!= NULL) &&
+	    != NULL) &&
 	    ((did_shr_nh = get_first_record(setno, 0, NM_DEVID | NM_SHARED))
-		!= NULL)) {
+	    != NULL)) {
 		did_n = (struct did_min_name *)lookup_entry(did_nh, setno,
-			side, key, NODEV64, NM_DEVID);
+		    side, key, NODEV64, NM_DEVID);
 	}
 
 	n->n_count--;
@@ -3680,7 +3790,7 @@
 	}
 
 	if (remove_shared_entry(shared_nh, drv_key, (char *)0, 0L) ||
-		remove_shared_entry(shared_nh, dir_key, (char *)0, 0L)) {
+	    remove_shared_entry(shared_nh, dir_key, (char *)0, 0L)) {
 		rw_exit(&nm_lock.lock);
 		return (EINVAL);
 	}
@@ -3695,7 +3805,7 @@
 		}
 
 		if (remove_shared_entry(did_shr_nh, did_key, (char *)0,
-			NM_DEVID)) {
+		    NM_DEVID)) {
 			rw_exit(&nm_lock.lock);
 			return (EINVAL);
 		}
@@ -3858,7 +3968,7 @@
 	if (hdr_recid < 0) {
 		if (ep != NULL)
 			return (mddbstatus2error(ep, hdr_recid, NODEV32,
-							setno));
+			    setno));
 		return (0);
 	}
 
@@ -3902,9 +4012,9 @@
 		mddb_setrecprivate(hdr_recid, MD_PRV_GOTIT);
 
 		build_rec_hdr_list(&hdr->hh_names, hdr_recid,
-				devid_nm | NM_NOTSHARED);
+		    devid_nm | NM_NOTSHARED);
 		build_rec_hdr_list(&hdr->hh_shared, hdr_recid,
-				devid_nm | NM_SHARED);
+		    devid_nm | NM_SHARED);
 
 		/*
 		 * Only cleanup a MN diskset if this node is master.
@@ -3943,8 +4053,8 @@
 	rw_enter(&nm_lock.lock, RW_WRITER);
 
 	hhdr = ((devid_nm & NM_DEVID) ?
-		(struct nm_header_hdr *)md_set[setno].s_did_nm :
-		(struct nm_header_hdr *)md_set[setno].s_nm);
+	    (struct nm_header_hdr *)md_set[setno].s_did_nm :
+	    (struct nm_header_hdr *)md_set[setno].s_nm);
 
 	if (devid_nm) {
 		md_set[setno].s_did_nmid = 0;
@@ -4024,14 +4134,14 @@
 	 */
 	while ((key = md_getnextkey(setno, side, key, NULL)) != MD_KEYWILD) {
 		if ((n = (struct nm_name *)lookup_entry(nh, setno, side, key,
-			NODEV64, 0L)) == NULL) {
+		    NODEV64, 0L)) == NULL) {
 			break;
 		} else {
 			md_dev64_t dev64 = build_device_number(setno, n);
 			dev_t dev = md_dev64_to_dev(dev64);
 
 			if (ddi_lyr_get_minor_name(dev, S_IFBLK, &mname)
-						!= DDI_SUCCESS) {
+			    != DDI_SUCCESS) {
 				continue;
 			} else {
 				if (mname) {
@@ -4203,10 +4313,10 @@
 	 * If it is an empty name space
 	 */
 	if (((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) ||
-		((did_nh = get_first_record(setno, 1, NM_DEVID | NM_NOTSHARED))
-			== NULL) ||
-		((did_shr_nh = get_first_record(setno, 1, NM_DEVID |
-			NM_SHARED)) == NULL)) {
+	    ((did_nh = get_first_record(setno, 1, NM_DEVID | NM_NOTSHARED))
+	    == NULL) ||
+	    ((did_shr_nh = get_first_record(setno, 1, NM_DEVID |
+	    NM_SHARED)) == NULL)) {
 		return;
 	}
 
@@ -4225,7 +4335,7 @@
 	 * Not empty
 	 */
 	n_offset = offset = (sizeof (struct devid_min_rec) -
-		sizeof (struct did_min_name));
+	    sizeof (struct did_min_name));
 	did_n = &(record->minor_name[0]);
 
 	/*CONSTCOND*/
@@ -4237,13 +4347,13 @@
 		 * It is not in the primary, remove it from the devid nmspace
 		 */
 		doit = (all ? 1 :
-			(lookup_entry(nh, setno, MD_SIDEWILD, did_n->min_key,
-				NODEV64, 0L) == NULL));
+		    (lookup_entry(nh, setno, MD_SIDEWILD, did_n->min_key,
+		    NODEV64, 0L) == NULL));
 		if (doit) {
 			(void) remove_entry(did_nh, did_n->min_side,
-					did_n->min_key, NM_DEVID);
+			    did_n->min_key, NM_DEVID);
 			(void) remove_shared_entry(did_shr_nh, did_key,
-					(char *)0, NM_DEVID);
+			    (char *)0, NM_DEVID);
 			/*
 			 * We delete something so reset scan
 			 */
@@ -4257,7 +4367,7 @@
 		}
 
 		did_n = (struct did_min_name *)get_next_entry(this_nh,
-			(caddr_t)did_n, n_size, &offset);
+		    (caddr_t)did_n, n_size, &offset);
 
 		/*
 		 * Next record?
@@ -4295,7 +4405,7 @@
 	ddi_devid_t		devid;
 	dev_t			*devs; /* ddi returns dev_t not md_dev64_t */
 	int			ndevs,
-				cnt;
+	    cnt;
 	set_t			setno;
 	int			update = 0;
 	md_dev64_t		targ_dev;
@@ -4309,8 +4419,8 @@
 	setno = MD_MIN2SET(mnum);
 
 	if (((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) ||
-		((n = (struct nm_name *)lookup_entry(nh, setno, MD_SIDEWILD,
-			key, NODEV64, 0L)) == NULL)) {
+	    ((n = (struct nm_name *)lookup_entry(nh, setno, MD_SIDEWILD,
+	    key, NODEV64, 0L)) == NULL)) {
 		return (NODEV64);
 	}
 
@@ -4320,17 +4430,17 @@
 	 * then return whatever passed in
 	 */
 	if (((did_nh = get_first_record(setno, 0, NM_DEVID | NM_NOTSHARED))
-		!= NULL) && ((did_n = (struct did_min_name *)lookup_entry
-		(did_nh, setno, MD_SIDEWILD, key, NODEV64, NM_DEVID))
-		!= NULL)) {
+	    != NULL) && ((did_n = (struct did_min_name *)lookup_entry
+	    (did_nh, setno, MD_SIDEWILD, key, NODEV64, NM_DEVID))
+	    != NULL)) {
 		/*
 		 * Get the current devt and update mddb devt if necessary
 		 */
 		devid =	(ddi_devid_t)getshared_name(setno,
-			did_n->min_devid_key, NM_DEVID);
+		    did_n->min_devid_key, NM_DEVID);
 
 		if (devid && (ddi_lyr_devid_to_devlist(devid, did_n->min_name,
-			&ndevs, &devs) == DDI_SUCCESS)) {
+		    &ndevs, &devs) == DDI_SUCCESS)) {
 
 			/*
 			 * This device has been powered off
@@ -4357,7 +4467,7 @@
 				return (NODEV64);
 
 			if (update &&
-				!(md_get_setstatus(setno) & MD_SET_STALE)) {
+			    !(md_get_setstatus(setno) & MD_SET_STALE)) {
 				n->n_minor = md_getminor(targ_dev);
 				/*
 				 * If we have the key for the driver get