Home | History | Annotate | Download | only in md
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <sys/errno.h>
     27 #include <sys/debug.h>
     28 #include <sys/sysmacros.h>
     29 #include <sys/t_lock.h>
     30 #include <sys/stat.h>
     31 
     32 #define	MDDB
     33 #include <sys/lvm/mdvar.h>
     34 #include <sys/lvm/md_names.h>
     35 #include <sys/ddi.h>
     36 #include <sys/sunddi.h>
     37 
     38 extern md_set_t	md_set[];
     39 extern int	*md_nm_snarfed;
     40 void		*lookup_entry(struct nm_next_hdr *, set_t,
     41 			side_t, mdkey_t, md_dev64_t, int);
     42 void		*lookup_entry_common(struct nm_next_hdr *, set_t,
     43 			side_t, mdkey_t, md_dev64_t, int, void **, size_t *);
     44 void		*lookup_entry_record_offset(struct nm_next_hdr *, set_t,
     45 			side_t, mdkey_t, md_dev64_t, int, void *, size_t *);
     46 
     47 void		*lookup_shared_entry(struct nm_next_hdr *,
     48 			mdkey_t, char *, mddb_recid_t *, int);
     49 void		*lookup_shared_entry_common(struct nm_next_hdr *,
     50 			mdkey_t, char *, mddb_recid_t *, int, void **,
     51 			size_t *);
     52 void		*lookup_shared_entry_record_offset(struct nm_next_hdr *,
     53 			mdkey_t, char *, mddb_recid_t *, int, void *, size_t *);
     54 
     55 static void	add_to_devid_list(ddi_devid_t did);
     56 static int	devid_is_unique(ddi_devid_t did);
     57 static size_t	free_devid_list(int *count);
     58 void		md_devid_cleanup(set_t, uint_t);
     59 extern md_krwlock_t	nm_lock;
     60 
     61 typedef enum lookup_dev_result {
     62 	LOOKUP_DEV_FOUND,	/* Found a good record. */
     63 	LOOKUP_DEV_NOMATCH,	/* No matching record in DB. */
     64 	LOOKUP_DEV_CONFLICT	/* Name conflicts with existing record. */
     65 } lookup_dev_result_t;
     66 
     67 /* List of SVM module names. */
     68 static char *meta_names[] = {
     69 	"md",
     70 	MD_STRIPE,
     71 	MD_MIRROR,
     72 	MD_TRANS,
     73 	MD_HOTSPARES,
     74 	MD_RAID,
     75 	MD_VERIFY,
     76 	MD_SP,
     77 	MD_NOTIFY
     78 };
     79 
     80 #define	META_NAME_COUNT	(sizeof (meta_names) / sizeof (char *))
     81 
     82 /*
     83  * Used in translating from the md major name on miniroot to
     84  * md major name on target system.  This is only needed during
     85  * upgrade.
     86  */
     87 
     88 extern major_t md_major, md_major_targ;
     89 
     90 /*
     91  * During upgrade, SVM basically runs with the devt from the target
     92  * being upgraded.  Translations are made from the miniroot devt to/from the
     93  * target devt when the devt is to be stored in the SVM metadriver's
     94  * unit structures.
     95  *
     96  * The following routines return a translated (aka miniroot) devt:
     97  *	- md_getdevnum
     98  *	- the metadriver's get_devs routines (stripe_getdevs, etc.)
     99  *
    100  * By the same token, the major number and major name conversion operations
    101  * need to use the name_to_major file from the target system instead
    102  * of the name_to_major file on the miniroot.  So, calls to
    103  * ddi_name_to_major must be replaced with calls to md_targ_name_to_major
    104  * when running on an upgrade.  Same is true with calls to
    105  * ddi_major_to_name.
    106  */
    107 
    108 static mdkey_t
    109 create_key(struct nm_next_hdr *nh)
    110 {
    111 	mdkey_t	retval;
    112 	struct nm_rec_hdr	*rh = (struct nm_rec_hdr *)nh->nmn_record;
    113 
    114 	retval = rh->r_next_key;
    115 	/* increment the next_key, keeps them unique */
    116 	rh->r_next_key++;
    117 
    118 	return (retval);
    119 }
    120 
    121 static int
    122 unused_key(struct nm_next_hdr *nh, int shared, mdkey_t key)
    123 {
    124 	mdkey_t	min_value;
    125 	int	nmspace;
    126 
    127 	if (shared & NM_DEVID) {
    128 		min_value = 1;
    129 		nmspace = NM_DEVID;
    130 	} else {
    131 		min_value = ((shared & NM_SHARED) ? MDDB_FIRST_MODID : 1);
    132 		nmspace = 0;
    133 	}
    134 
    135 	/* Just say no if the key passed in is less than the initial */
    136 	if (key < min_value)
    137 		return (0);
    138 
    139 	if ((shared & NM_SHARED) && (lookup_shared_entry(nh, key, (char *)0,
    140 	    NULL, nmspace) != NULL))
    141 		return (0);
    142 
    143 	/*
    144 	 * The set num in lookup_entry is not used in this case
    145 	 * we dont keep track of the nonshared in the devid nmspace
    146 	 */
    147 	if (!(shared & NM_NOTSHARED) &&
    148 	    (lookup_entry(nh, 0, -1, key, NODEV64, 0L) != NULL))
    149 		return (0);
    150 
    151 	return (1);
    152 }
    153 
    154 static void
    155 destroy_key(struct nm_next_hdr *nh, int shared, mdkey_t key)
    156 {
    157 	struct nm_rec_hdr *rh = (struct nm_rec_hdr *)nh->nmn_record;
    158 
    159 	if ((key + 1) != rh->r_next_key)
    160 		return;
    161 
    162 	while (unused_key(nh, shared, key))
    163 		key--;
    164 	rh->r_next_key = key + 1;
    165 }
    166 
    167 static void
    168 cleanup_unused_rec(set_t setno, int devid_nm)
    169 {
    170 	mddb_recid_t	recid;
    171 	mddb_type_t	hdr, shr, notshr;
    172 
    173 	hdr = ((devid_nm & NM_DEVID) ? MDDB_DID_NM_HDR : MDDB_NM_HDR);
    174 	notshr = ((devid_nm & NM_DEVID) ? MDDB_DID_NM : MDDB_NM);
    175 	shr = ((devid_nm & NM_DEVID) ? MDDB_DID_SHR_NM : MDDB_SHR_NM);
    176 
    177 	recid = mddb_makerecid(setno, 0);
    178 	while ((recid = mddb_getnextrec(recid, hdr, 0)) > 0)
    179 		if (! (mddb_getrecprivate(recid) & MD_PRV_GOTIT))
    180 			mddb_setrecprivate(recid, MD_PRV_PENDDEL);
    181 
    182 	recid = mddb_makerecid(setno, 0);
    183 	while ((recid = mddb_getnextrec(recid, notshr, 0)) > 0)
    184 		if (! (mddb_getrecprivate(recid) & MD_PRV_GOTIT))
    185 			mddb_setrecprivate(recid, MD_PRV_PENDDEL);
    186 
    187 	recid = mddb_makerecid(setno, 0);
    188 	while ((recid = mddb_getnextrec(recid, shr, 0)) > 0)
    189 		if (! (mddb_getrecprivate(recid) & MD_PRV_GOTIT))
    190 			mddb_setrecprivate(recid, MD_PRV_PENDDEL);
    191 }
    192 
    193 static int
    194 create_hdr(set_t setno, int shared)
    195 {
    196 	struct nm_header_hdr	*hhdr;
    197 	mddb_recid_t		nmid;
    198 
    199 
    200 	if (shared & NM_DEVID) {
    201 		/*
    202 		 * Deal with the device id name space
    203 		 */
    204 		nmid = md_set[setno].s_did_nmid =
    205 		    mddb_createrec(sizeof (struct nm_header),
    206 		    MDDB_DID_NM_HDR, 1, MD_CRO_32BIT, setno);
    207 		/*
    208 		 * Out of space
    209 		 */
    210 		if (nmid < 0)
    211 			return (nmid);
    212 	} else {
    213 		nmid = md_set[setno].s_nmid =
    214 		    mddb_createrec(sizeof (struct nm_header),
    215 		    MDDB_NM_HDR, 1, MD_CRO_32BIT, setno);
    216 		/*
    217 		 * Out of space
    218 		 */
    219 		if (nmid < 0)
    220 			return (nmid);
    221 	}
    222 
    223 	hhdr = kmem_zalloc(sizeof (*hhdr), KM_SLEEP);
    224 
    225 	if (shared & NM_DEVID) {
    226 		md_set[setno].s_did_nm = hhdr;
    227 	} else {
    228 		md_set[setno].s_nm = hhdr;
    229 	}
    230 
    231 	hhdr->hh_header = (struct nm_header *)mddb_getrecaddr(nmid);
    232 	hhdr->hh_names.nmn_record = &(hhdr->hh_header->h_names);
    233 	hhdr->hh_shared.nmn_record = &(hhdr->hh_header->h_shared);
    234 
    235 	/*
    236 	 * h_names.r_next_key is set to zero in devid nmspace
    237 	 * since we dont keep track of it
    238 	 */
    239 	if (shared & NM_DEVID) {
    240 		hhdr->hh_header->h_names.r_next_key = 0;
    241 		hhdr->hh_header->h_shared.r_next_key = 1;
    242 	} else {
    243 		hhdr->hh_header->h_names.r_next_key = 1;
    244 		hhdr->hh_header->h_shared.r_next_key = MDDB_FIRST_MODID;
    245 	}
    246 
    247 	mddb_commitrec_wrapper(nmid);
    248 	return (0);
    249 }
    250 
    251 static int
    252 create_record(
    253 	mddb_recid_t		p_recid,	/* parent recid */
    254 	struct nm_next_hdr	*nh,		/* parent record header */
    255 	int			shared,
    256 	size_t			needed_space)
    257 {
    258 	struct nm_rec_hdr	*rh = (struct nm_rec_hdr *)nh->nmn_record;
    259 	struct nm_next_hdr	*new_nh;
    260 	mddb_type_t		rec_type;
    261 	size_t			used_size;
    262 	size_t			alloc_size;
    263 	mddb_recid_t		recids[3];
    264 	set_t			setno;
    265 	mddb_recid_t		new_id;
    266 
    267 	setno = mddb_getsetnum(p_recid);
    268 
    269 	if (shared & NM_DEVID) {
    270 		/*
    271 		 * Device id name space
    272 		 */
    273 		rec_type = ((shared & NM_SHARED) ?
    274 		    MDDB_DID_SHR_NM : MDDB_DID_NM);
    275 		used_size = ((shared & NM_SHARED) ?
    276 		    (sizeof (struct devid_shr_rec) -
    277 		    sizeof (struct did_shr_name)) :
    278 		    (sizeof (struct devid_min_rec) -
    279 		    sizeof (struct did_min_name)));
    280 		alloc_size = ((shared & NM_SHARED) ?
    281 		    NM_DID_ALLOC_SIZE : NM_ALLOC_SIZE);
    282 	} else {
    283 		rec_type = ((shared & NM_SHARED) ?
    284 		    MDDB_SHR_NM : MDDB_NM);
    285 		used_size = ((shared & NM_SHARED) ?
    286 		    (sizeof (struct nm_shr_rec) -
    287 		    sizeof (struct nm_shared_name)) :
    288 		    (sizeof (struct nm_rec) - sizeof (struct nm_name)));
    289 		alloc_size = NM_ALLOC_SIZE;
    290 	}
    291 
    292 	used_size += needed_space;
    293 
    294 	new_id = mddb_createrec((size_t)alloc_size, rec_type, 1,
    295 	    MD_CRO_32BIT, setno);
    296 	if (new_id < 0)
    297 		return (new_id);
    298 
    299 	recids[0] = rh->r_next_recid = new_id;
    300 	recids[1] = p_recid;
    301 	recids[2] = 0;
    302 
    303 	new_nh = (struct nm_next_hdr *)kmem_zalloc(sizeof (*new_nh), KM_SLEEP);
    304 	nh->nmn_nextp = new_nh;
    305 	new_nh->nmn_record = mddb_getrecaddr(rh->r_next_recid);
    306 
    307 	((struct nm_rec_hdr *)new_nh->nmn_record)->r_alloc_size = alloc_size;
    308 	((struct nm_rec_hdr *)new_nh->nmn_record)->r_used_size =
    309 	    (uint_t)used_size;
    310 
    311 	mddb_commitrecs_wrapper(recids);
    312 	return (0);
    313 }
    314 
    315 static int
    316 expand_record(
    317 	struct nm_next_hdr	*parent_nh,	/* parent record header */
    318 	mddb_recid_t		parent_recid,	/* parent record id */
    319 	struct nm_next_hdr	*nh,		/* record hdr to be expanded */
    320 	int			shared)		/* boolean - shared or not */
    321 {
    322 	struct nm_rec_hdr	*rh = (struct nm_rec_hdr *)nh->nmn_record;
    323 	struct nm_rec_hdr	*parent_rh = (struct nm_rec_hdr *)
    324 	    parent_nh->nmn_record;
    325 	struct nm_rec_hdr	*new_rh;
    326 	void			*new_rec;
    327 	mddb_recid_t		new_id;
    328 	mddb_recid_t		old_id;
    329 	mddb_recid_t		recids[3];
    330 	set_t			setno;
    331 	mddb_type_t		rec_type;
    332 	size_t			alloc_size;
    333 
    334 	setno = mddb_getsetnum(parent_recid);
    335 
    336 	if (shared & NM_DEVID) {
    337 		/*
    338 		 * Device id name space
    339 		 */
    340 		rec_type = ((shared & NM_SHARED) ?
    341 		    MDDB_DID_SHR_NM : MDDB_DID_NM);
    342 		alloc_size = ((shared & NM_SHARED) ?
    343 		    NM_DID_ALLOC_SIZE : NM_ALLOC_SIZE);
    344 	} else {
    345 		rec_type = ((shared & NM_SHARED) ? MDDB_SHR_NM : MDDB_NM);
    346 		alloc_size = NM_ALLOC_SIZE;
    347 	}
    348 
    349 	new_id = mddb_createrec((size_t)rh->r_alloc_size + alloc_size, rec_type,
    350 	    1, MD_CRO_32BIT, setno);
    351 	/*
    352 	 * No space
    353 	 */
    354 	if (new_id < 0)
    355 		return (new_id);
    356 
    357 	new_rec = mddb_getrecaddr(new_id);
    358 	(void) bcopy(rh, new_rec, rh->r_alloc_size);
    359 
    360 	recids[0] = parent_recid;
    361 	recids[1] = new_id;
    362 	recids[2] = 0;
    363 
    364 	/* Fix up rec hdr to point at this new record */
    365 	nh->nmn_record = new_rec;
    366 	old_id = parent_rh->r_next_recid;
    367 	parent_rh->r_next_recid = new_id;
    368 
    369 	if (shared & NM_DEVID)
    370 		/*
    371 		 * Device id name space
    372 		 */
    373 		new_rh = ((shared & NM_SHARED) ?
    374 		    &((struct devid_shr_rec *)new_rec)->did_rec_hdr :
    375 		    &((struct devid_min_rec *)new_rec)->min_rec_hdr);
    376 	else
    377 		new_rh = ((shared & NM_SHARED) ?
    378 		    &((struct nm_shr_rec *)new_rec)->sr_rec_hdr :
    379 		    &((struct nm_rec *)new_rec)->r_rec_hdr);
    380 
    381 	new_rh->r_alloc_size += alloc_size;
    382 	if (!(shared & NM_NOCOMMIT))
    383 		mddb_commitrecs_wrapper(recids);
    384 
    385 	/* delete the old record */
    386 	mddb_deleterec_wrapper(old_id);
    387 
    388 	return (0);
    389 }
    390 
    391 struct nm_next_hdr *
    392 get_first_record(set_t setno, int alloc, int shared)
    393 {
    394 	struct nm_next_hdr	*nh;
    395 	mddb_recid_t		nmid;
    396 
    397 	ASSERT(md_get_setstatus(setno) & MD_SET_NM_LOADED);
    398 
    399 	if (shared & NM_DEVID) {
    400 		/*
    401 		 * We are dealing with the device id name space.
    402 		 * If set is a MN diskset, just return 0 since
    403 		 * devids aren't yet supported in MN disksets.
    404 		 */
    405 		if (MD_MNSET_SETNO(setno))
    406 			return ((struct nm_next_hdr *)0);
    407 		if (md_set[setno].s_did_nm == NULL)
    408 			if (create_hdr(setno, shared) < 0)
    409 				return ((struct nm_next_hdr *)0);
    410 
    411 		nh = ((shared & NM_SHARED) ?
    412 		    &((struct nm_header_hdr *)md_set[setno].s_did_nm)->hh_shared
    413 		    :
    414 		    &((struct nm_header_hdr *)
    415 		    md_set[setno].s_did_nm)->hh_names);
    416 
    417 		nmid = md_set[setno].s_did_nmid;
    418 	} else {
    419 		/*
    420 		 * We are dealing with the regular one (non-devid)
    421 		 */
    422 		if (md_set[setno].s_nm == NULL)
    423 			if (create_hdr(setno, shared) < 0)
    424 				return ((struct nm_next_hdr *)0);
    425 
    426 		nh = ((shared & NM_SHARED) ?
    427 		    &((struct nm_header_hdr *)md_set[setno].s_nm)->hh_shared
    428 		    :
    429 		    &((struct nm_header_hdr *)md_set[setno].s_nm)->hh_names);
    430 
    431 		nmid = md_set[setno].s_nmid;
    432 	}
    433 
    434 	/*
    435 	 * Name space exists
    436 	 */
    437 	if (nh->nmn_nextp != NULL)
    438 		return (nh);
    439 
    440 	/*
    441 	 * If name space is expected and is empty
    442 	 */
    443 	if (! alloc)
    444 		return ((struct nm_next_hdr *)0);
    445 
    446 	/*
    447 	 * Empty is okay alloc it
    448 	 */
    449 	if (create_record(nmid, nh, shared, 0L) < 0)
    450 		return ((struct nm_next_hdr *)0);
    451 
    452 	return (nh);
    453 }
    454 
    455 
    456 void *
    457 alloc_entry(
    458 	struct nm_next_hdr *nh,		/* parent name header */
    459 	mddb_recid_t recid,		/* parent record id */
    460 	size_t len,			/* length of entry */
    461 	int shared,			/* shared boolean */
    462 	mddb_recid_t *id)		/* return of new record id */
    463 {
    464 	struct nm_rec_hdr	*rh;		/* parent */
    465 	mddb_recid_t		this_recid;
    466 	struct nm_next_hdr	*this_nh;
    467 	struct nm_rec_hdr	*this_rh;
    468 	void			*this_rec;
    469 	size_t			needed_space;
    470 	char			*name;
    471 
    472 	if (shared & NM_DEVID)
    473 		/*
    474 		 * Device id name space
    475 		 */
    476 		needed_space = ((shared & NM_SHARED) ?
    477 		    sizeof (struct did_shr_name) :
    478 		    sizeof (struct did_min_name)) + len - 1;
    479 	else
    480 		needed_space = ((shared & NM_SHARED) ?
    481 		    sizeof (struct nm_shared_name) :
    482 		    sizeof (struct nm_name)) + len - 1;
    483 
    484 	needed_space = roundup(needed_space, sizeof (uint_t));
    485 
    486 	/* check the next record to see if it has space */
    487 	/*CONSTCOND*/
    488 	while (1) {
    489 		while ((this_nh = nh->nmn_nextp) != NULL) {
    490 
    491 			rh = (struct nm_rec_hdr *)nh->nmn_record;
    492 			this_recid = rh->r_next_recid;
    493 			this_rec = this_nh->nmn_record;
    494 
    495 			if (shared & NM_DEVID)
    496 				this_rh = ((shared & NM_SHARED) ?
    497 				    &((struct devid_shr_rec *)
    498 				    this_rec)->did_rec_hdr :
    499 				    &((struct devid_min_rec *)
    500 				    this_rec)->min_rec_hdr);
    501 			else
    502 				this_rh = ((shared & NM_SHARED) ?
    503 				    &((struct nm_shr_rec *)
    504 				    this_rec)->sr_rec_hdr :
    505 				    &((struct nm_rec *)this_rec)->r_rec_hdr);
    506 
    507 			/* check for space in this record */
    508 			if ((this_rh->r_alloc_size - this_rh->r_used_size) >=
    509 			    needed_space) {
    510 				/* allocate space in this record */
    511 				name = (char *)this_rec + this_rh->r_used_size;
    512 				this_rh->r_used_size += (uint_t)needed_space;
    513 				if (!(shared & NM_NOCOMMIT))
    514 					mddb_commitrec_wrapper(this_recid);
    515 				*id = this_recid;
    516 				return ((caddr_t)name);
    517 			}
    518 
    519 			/* if we can expand the record we look again */
    520 			if (expand_record(nh, recid, this_nh, shared) == 0)
    521 				continue;
    522 
    523 			/* advance parent to this record, and go try next */
    524 			recid = this_recid;
    525 			nh = this_nh;
    526 		}
    527 
    528 		/* no space, try creating a new record after parent */
    529 		if (create_record(recid, nh, shared, 0L) < 0)
    530 			return ((caddr_t)0);
    531 	} /* go check the new record */
    532 	/* can't get here, but lint seems to think so */
    533 	/* NOTREACHED */
    534 }
    535 
    536 static void *
    537 get_next_entry(
    538 	struct nm_next_hdr *nh,
    539 	caddr_t ent,
    540 	size_t ent_size,
    541 	size_t *off)
    542 {
    543 
    544 	if (((struct nm_rec_hdr *)nh->nmn_record)->r_used_size <=
    545 	    (*off + ent_size)) {
    546 		if (nh->nmn_nextp == NULL)
    547 			return ((caddr_t)0);
    548 
    549 		/* offset == 0, means go to next record */
    550 		*off = 0;
    551 		return ((caddr_t)0);
    552 	}
    553 
    554 	*off += ent_size;
    555 	return ((caddr_t)((char *)ent + ent_size));
    556 }
    557 
    558 static int
    559 rem_entry(
    560 	struct nm_next_hdr *nh,	/* record header for entry being removed */
    561 	mddb_recid_t id,	/* record id for entry being removed */
    562 	void *ent,		/* address of entry to be removed */
    563 	size_t ent_size,	/* size of entry to be removed */
    564 	size_t offset,		/* offset of entry within record */
    565 	int devid_nm)		/* which name space? 0 - primary */
    566 {
    567 	struct nm_next_hdr	*first_nh;
    568 	mddb_recid_t		recids[3];
    569 	size_t			c = ((struct nm_rec_hdr *)
    570 	    nh->nmn_record)->r_used_size - offset -
    571 	    ent_size;
    572 	set_t			setno;
    573 	mdkey_t			ent_key;
    574 
    575 
    576 	setno = mddb_getsetnum(id);
    577 	first_nh = get_first_record(setno, 0, devid_nm | NM_NOTSHARED);
    578 	ASSERT(first_nh != NULL);
    579 
    580 	recids[0] = id;
    581 	recids[1] = ((devid_nm & NM_DEVID) ? md_set[setno].s_did_nmid :
    582 	    md_set[setno].s_nmid);
    583 	recids[2] = 0;
    584 	ent_key = ((devid_nm & NM_DEVID) ?
    585 	    ((struct did_min_name *)ent)->min_key :
    586 	    ((struct nm_name *)ent)->n_key);
    587 
    588 	if (c == 0)
    589 		(void) bzero(ent, ent_size);	/* last entry */
    590 	else {
    591 		(void) ovbcopy((caddr_t)ent+ent_size, ent, c);
    592 		(void) bzero((caddr_t)ent+c, ent_size);
    593 	}
    594 
    595 	((struct nm_rec_hdr *)nh->nmn_record)->r_used_size -= (uint_t)ent_size;
    596 
    597 	/*
    598 	 * We don't keep track of keys in the device id nonshared namespace
    599 	 */
    600 	if (!devid_nm)
    601 		destroy_key(first_nh, NM_NOTSHARED, ent_key);
    602 
    603 	mddb_commitrecs_wrapper(recids);
    604 	return (0);
    605 }
    606 
    607 static int
    608 rem_shr_entry(
    609 	struct nm_next_hdr *nh,	/* record header for entry being removed */
    610 	mddb_recid_t id,	/* record id for entry being removed */
    611 	void *ent,		/* address of entry to be removed */
    612 	size_t ent_size,	/* size of entry to be removed */
    613 	size_t offset,		/* offset of entry within record */
    614 	int devid_nm)		/* which name space? 0 - primary */
    615 {
    616 	struct nm_next_hdr	*first_nh;
    617 	mddb_recid_t		recids[3];
    618 	size_t			c = ((struct nm_rec_hdr *)
    619 	    nh->nmn_record)->r_used_size - offset -
    620 	    ent_size;
    621 	set_t			setno;
    622 	uint_t			count;
    623 
    624 	setno = mddb_getsetnum(id);
    625 	first_nh = get_first_record(setno, 0, devid_nm | NM_SHARED);
    626 	ASSERT(first_nh != NULL);
    627 
    628 	recids[0] = id;
    629 	recids[1] = ((devid_nm & NM_DEVID) ? md_set[setno].s_did_nmid :
    630 	    md_set[setno].s_nmid);
    631 	recids[2] = 0;
    632 
    633 	if (devid_nm & NM_DEVID) {
    634 		count = --((struct did_shr_name *)ent)->did_count;
    635 	} else {
    636 		count = --((struct nm_shared_name *)ent)->sn_count;
    637 	}
    638 
    639 	if (count == 0 || devid_nm & NM_IMP_SHARED) {
    640 		mdkey_t	ent_key;
    641 
    642 		ent_key = ((devid_nm & NM_DEVID) ?
    643 		    ((struct did_shr_name *)ent)->did_key :
    644 		    ((struct nm_shared_name *)ent)->sn_key);
    645 
    646 		if (c == 0)
    647 			(void) bzero(ent, ent_size);	/* last entry */
    648 		else {
    649 			(void) ovbcopy((caddr_t)ent+ent_size, ent, c);
    650 			(void) bzero((caddr_t)ent+c, ent_size);
    651 		}
    652 
    653 		((struct nm_rec_hdr *)nh->nmn_record)->r_used_size -=
    654 		    (uint_t)ent_size;
    655 		destroy_key(first_nh, devid_nm | NM_SHARED, ent_key);
    656 	}
    657 
    658 	if (!(devid_nm & NM_NOCOMMIT))
    659 		mddb_commitrecs_wrapper(recids);
    660 	return (0);
    661 }
    662 
    663 static mdkey_t
    664 setshared_name(set_t setno, char *shrname, mdkey_t shrkey, int devid_nm)
    665 {
    666 	struct nm_next_hdr	*nh;
    667 	struct nm_shared_name	*shn;
    668 	struct did_shr_name	*did_shn = (struct did_shr_name *)NULL;
    669 	mddb_recid_t		recid;
    670 	mddb_recid_t		recids[3];
    671 	size_t			len;
    672 	mdkey_t			key;
    673 	int			shared = NM_SHARED;
    674 
    675 
    676 	if (shrkey == MD_KEYWILD) {
    677 		len = ((devid_nm & NM_DEVID) ?
    678 		    ddi_devid_sizeof((ddi_devid_t)shrname) :
    679 		    (strlen(shrname) + 1));
    680 	}
    681 	/*
    682 	 * If devid_nm is not NULL, nh will point to the did name space
    683 	 */
    684 	if (devid_nm & NM_NOCOMMIT) {
    685 		if ((nh = get_first_record(setno, 0, devid_nm | NM_SHARED))
    686 		    == NULL)
    687 			return (MD_KEYBAD);
    688 	} else {
    689 		if ((nh = get_first_record(setno, 1, devid_nm | NM_SHARED))
    690 		    == NULL)
    691 			return (MD_KEYBAD);
    692 	}
    693 	if (devid_nm & NM_NOCOMMIT)
    694 		shared = NM_NOCOMMIT  | shared;
    695 	if (devid_nm & NM_DEVID) {
    696 		/*
    697 		 * A key has been supplied so find the corresponding entry
    698 		 * which must exist.
    699 		 */
    700 		if (shrkey != MD_KEYWILD) {
    701 			did_shn = (struct did_shr_name *)lookup_shared_entry(nh,
    702 			    shrkey, NULL, &recid, devid_nm);
    703 			if (did_shn == (struct did_shr_name *)NULL)
    704 				return (MD_KEYBAD);
    705 		} else {
    706 			did_shn = (struct did_shr_name *)lookup_shared_entry(nh,
    707 			    0, shrname, &recid, devid_nm);
    708 		}
    709 		if (did_shn != (struct did_shr_name *)NULL) {
    710 			did_shn->did_count++;
    711 			if (!(devid_nm & NM_NOCOMMIT))
    712 				mddb_commitrec_wrapper(recid);
    713 			return (did_shn->did_key);
    714 		}
    715 
    716 
    717 		/* allocate an entry and fill it in */
    718 		if ((did_shn = (struct did_shr_name *)alloc_entry(nh,
    719 		    md_set[setno].s_did_nmid, len, shared | NM_DEVID,
    720 		    &recid)) == NULL)
    721 			return (MD_KEYBAD);
    722 		did_shn->did_key = create_key(nh);
    723 		did_shn->did_count = 1;
    724 		did_shn->did_size = (ushort_t)len;
    725 		/*
    726 		 * Let the whole world know it is valid devid
    727 		 */
    728 		did_shn->did_data = NM_DEVID_VALID;
    729 		bcopy((void *)shrname, (void *)did_shn->did_devid, len);
    730 		key = did_shn->did_key;
    731 	} else {
    732 		if ((shn = (struct nm_shared_name *)lookup_shared_entry(nh,
    733 		    0, shrname, &recid, 0L)) != NULL) {
    734 			/* Increment reference count */
    735 			shn->sn_count++;
    736 			if (!(devid_nm & NM_NOCOMMIT))
    737 				mddb_commitrec_wrapper(recid);
    738 			return (shn->sn_key);
    739 		}
    740 
    741 		/* allocate an entry and fill it in */
    742 		if ((shn = (struct nm_shared_name *)alloc_entry(nh,
    743 		    md_set[setno].s_nmid, len, shared, &recid)) == NULL)
    744 			return (MD_KEYBAD);
    745 		shn->sn_key = create_key(nh);
    746 		shn->sn_count = 1;
    747 		shn->sn_namlen = (ushort_t)len;
    748 		(void) strcpy(shn->sn_name, shrname);
    749 		key = shn->sn_key;
    750 	}
    751 
    752 	recids[0] = recid;
    753 	recids[1] = ((devid_nm & NM_DEVID) ? md_set[setno].s_did_nmid :
    754 	    md_set[setno].s_nmid);
    755 	recids[2] = 0;
    756 
    757 	if (!(devid_nm & NM_NOCOMMIT))
    758 		mddb_commitrecs_wrapper(recids);
    759 	return (key);
    760 }
    761 
    762 void *
    763 getshared_name(set_t setno, mdkey_t shrkey, int devid_nm)
    764 {
    765 	char			*shn;
    766 	struct nm_next_hdr	*nh;
    767 	mddb_recid_t		recid;
    768 
    769 	if ((nh = get_first_record(setno, 0, devid_nm | NM_SHARED)) == NULL)
    770 		return ((void *)0);
    771 
    772 	shn = (char *)((devid_nm & NM_DEVID) ?
    773 	    lookup_shared_entry(nh, shrkey, (char *)0, &recid, devid_nm) :
    774 	    lookup_shared_entry(nh, shrkey, (char *)0, &recid, 0L));
    775 
    776 	if (shn == NULL)
    777 		return ((void *)0);
    778 
    779 	return ((void *)((devid_nm & NM_DEVID) ?
    780 	    ((struct did_shr_name *)shn)->did_devid :
    781 	    ((struct nm_shared_name *)shn)->sn_name));
    782 }
    783 
    784 static mdkey_t
    785 getshared_key(set_t setno, char *shrname, int devid_nm)
    786 {
    787 	struct nm_next_hdr	*nh;
    788 	char			*shn;
    789 	mddb_recid_t		recid;
    790 
    791 	if ((nh = get_first_record(setno, 1, devid_nm |  NM_SHARED)) == NULL)
    792 		return (MD_KEYBAD);
    793 
    794 	shn = (char *)lookup_shared_entry(nh, 0, shrname, &recid, devid_nm);
    795 
    796 	if (shn == NULL)
    797 		return (MD_KEYBAD);
    798 
    799 	return (((devid_nm & NM_DEVID) ?
    800 	    ((struct did_shr_name *)shn)->did_key :
    801 	    ((struct nm_shared_name *)shn)->sn_key));
    802 }
    803 
    804 static int
    805 setshared_data(set_t setno, mdkey_t shrkey, caddr_t data)
    806 {
    807 	struct nm_shared_name	*shn;
    808 	struct nm_next_hdr	*nh;
    809 	mddb_recid_t		recid;
    810 
    811 	if ((nh = get_first_record(setno, 0, NM_SHARED)) == NULL)
    812 		return (ENOENT);
    813 
    814 	shn = (struct nm_shared_name *)lookup_shared_entry(nh, shrkey,
    815 	    (char *)0, &recid, 0L);
    816 	if (shn == NULL)
    817 		return (ENOENT);
    818 	shn->sn_data = (uint32_t)(uintptr_t)data;
    819 	return (0);
    820 }
    821 
    822 int
    823 update_entry(
    824 	struct nm_next_hdr	*nh,		/* head record header */
    825 	side_t			side,		/* (key 1) side number */
    826 	mdkey_t			key,		/* (key 2) via md_setdevname */
    827 	int			devid_nm)	/* Which name space? */
    828 {
    829 	struct nm_rec_hdr	*rh = (struct nm_rec_hdr *)nh->nmn_record;
    830 	struct nm_next_hdr	*this_nh = nh->nmn_nextp;
    831 	void			*record = this_nh->nmn_record;
    832 	mddb_recid_t		recid = rh->r_next_recid;
    833 	struct nm_rec_hdr	*this_rh;
    834 	caddr_t			n;
    835 	size_t			offset, n_offset, n_size;
    836 	mdkey_t			n_key;
    837 	side_t			n_side;
    838 
    839 	n_offset = offset = ((devid_nm & NM_DEVID) ?
    840 	    (sizeof (struct devid_min_rec) - sizeof (struct did_min_name))
    841 	    :
    842 	    (sizeof (struct nm_rec) - sizeof (struct nm_name)));
    843 
    844 	this_rh = ((devid_nm & NM_DEVID) ?
    845 	    &((struct devid_min_rec *)record)->min_rec_hdr :
    846 	    &((struct nm_rec *)record)->r_rec_hdr);
    847 
    848 	n = ((devid_nm & NM_DEVID) ?
    849 	    ((caddr_t)&((struct devid_min_rec *)record)->minor_name[0]) :
    850 	    ((caddr_t)&((struct nm_rec *)record)->r_name[0]));
    851 
    852 	/*CONSTCOND*/
    853 	while (1) {
    854 
    855 		if (devid_nm & NM_DEVID) {
    856 			n_side = ((struct did_min_name *)n)->min_side;
    857 			n_key = ((struct did_min_name *)n)->min_key;
    858 			n_size = DID_NAMSIZ((struct did_min_name *)n);
    859 
    860 		} else {
    861 			n_side = ((struct nm_name *)n)->n_side;
    862 			n_key = ((struct nm_name *)n)->n_key;
    863 			n_size = NAMSIZ((struct nm_name *)n);
    864 		}
    865 
    866 		if ((side == n_side) && (key == n_key)) {
    867 			mddb_commitrec_wrapper(recid);
    868 			return (0);
    869 		}
    870 
    871 		n = (caddr_t)get_next_entry(this_nh, n, n_size, &offset);
    872 
    873 		if (n == NULL) {
    874 			if (offset)
    875 				return (ENOENT);
    876 
    877 			/* Go to next record */
    878 			offset = n_offset;
    879 			this_nh = this_nh->nmn_nextp;
    880 			record = this_nh->nmn_record;
    881 			recid = this_rh->r_next_recid;
    882 			this_rh = ((devid_nm & NM_DEVID) ?
    883 			    &((struct devid_min_rec *)record)->min_rec_hdr
    884 			    :
    885 			    &((struct nm_rec *)record)->r_rec_hdr);
    886 			n = ((devid_nm & NM_DEVID) ?
    887 			    ((caddr_t)&((struct devid_min_rec *)
    888 			    record)->minor_name[0]) :
    889 			    ((caddr_t)&((struct nm_rec *)
    890 			    record)->r_name[0]));
    891 		}
    892 	}
    893 	/*NOTREACHED*/
    894 }
    895 
    896 int
    897 remove_entry(
    898 	struct nm_next_hdr	*nh,		/* head record header */
    899 	side_t			side,		/* (key 1) side number */
    900 	mdkey_t			key,		/* (key 2) via md_setdevname */
    901 	int			devid_nm)	/* which name space? */
    902 {
    903 	struct nm_rec_hdr	*rh = (struct nm_rec_hdr *)nh->nmn_record;
    904 	struct nm_next_hdr	*this_nh = nh->nmn_nextp;
    905 	void			*record = this_nh->nmn_record;
    906 	mddb_recid_t		recid = rh->r_next_recid;
    907 	struct nm_rec_hdr	*this_rh;
    908 	caddr_t			n;
    909 	size_t			offset, n_offset, n_size;
    910 	mdkey_t			n_key;
    911 	side_t			n_side;
    912 
    913 	n_offset = offset = ((devid_nm & NM_DEVID) ?
    914 	    (sizeof (struct devid_min_rec) - sizeof (struct did_min_name))
    915 	    :
    916 	    (sizeof (struct nm_rec) - sizeof (struct nm_name)));
    917 
    918 	this_rh = ((devid_nm & NM_DEVID) ?
    919 	    &((struct devid_min_rec *)record)->min_rec_hdr :
    920 	    &((struct nm_rec *)record)->r_rec_hdr);
    921 
    922 	n = ((devid_nm & NM_DEVID) ?
    923 	    ((caddr_t)&((struct devid_min_rec *)record)->minor_name[0]) :
    924 	    ((caddr_t)&((struct nm_rec *)record)->r_name[0]));
    925 
    926 	/*CONSTCOND*/
    927 	while (1) {
    928 
    929 		if (devid_nm & NM_DEVID) {
    930 			n_side = ((struct did_min_name *)n)->min_side;
    931 			n_key = ((struct did_min_name *)n)->min_key;
    932 			n_size = DID_NAMSIZ((struct did_min_name *)n);
    933 		} else {
    934 			n_side = ((struct nm_name *)n)->n_side;
    935 			n_key = ((struct nm_name *)n)->n_key;
    936 			n_size = NAMSIZ((struct nm_name *)n);
    937 		}
    938 
    939 		if ((side == n_side) && (key == n_key))
    940 			return (rem_entry(this_nh, recid, (char *)n, n_size,
    941 			    offset, devid_nm));
    942 
    943 		n = (caddr_t)get_next_entry(this_nh, n, n_size, &offset);
    944 
    945 		if (n == NULL) {
    946 			if (offset)
    947 				return (ENOENT);
    948 
    949 			/* Go to next record */
    950 			offset = n_offset;
    951 			this_nh = this_nh->nmn_nextp;
    952 			record = this_nh->nmn_record;
    953 			recid = this_rh->r_next_recid;
    954 			this_rh = ((devid_nm & NM_DEVID) ?
    955 			    &((struct devid_min_rec *)record)->min_rec_hdr
    956 			    :
    957 			    &((struct nm_rec *)record)->r_rec_hdr);
    958 			n = ((devid_nm & NM_DEVID) ?
    959 			    ((caddr_t)&((struct devid_min_rec *)
    960 			    record)->minor_name[0]) :
    961 			    ((caddr_t)&((struct nm_rec *)
    962 			    record)->r_name[0]));
    963 		}
    964 	}
    965 	/*NOTREACHED*/
    966 }
    967 
    968 int
    969 remove_shared_entry(
    970 	struct nm_next_hdr *nh,	/* First record header to start lookup */
    971 	mdkey_t key,		/* Shared key, used as key if nm is NULL */
    972 	char *nm,		/* Shared name, used as key if non-NULL */
    973 	int devid_nm)		/* which name space? */
    974 {
    975 	struct nm_rec_hdr	*rh = (struct nm_rec_hdr *)nh->nmn_record;
    976 	struct nm_next_hdr	*this_nh = nh->nmn_nextp;
    977 	void			*record = this_nh->nmn_record;
    978 	struct nm_rec_hdr	*this_rh;
    979 	caddr_t			shn;
    980 	mddb_recid_t		recid = rh->r_next_recid;
    981 	size_t			offset, shn_offset;
    982 	size_t			nm_len = 0, shn_size;
    983 	mdkey_t			shn_key;
    984 	ushort_t		shn_namlen;
    985 
    986 	if (nm == (char *)0) {
    987 		/* No name.  Search by key only. */
    988 		if (key == MD_KEYBAD) {
    989 			/* No key either.  Nothing to remove. */
    990 			return (0);
    991 		}
    992 	} else {
    993 		/* How long is the name? */
    994 		nm_len = ((devid_nm & NM_DEVID) ?
    995 		    ddi_devid_sizeof((ddi_devid_t)nm) :
    996 		    (strlen(nm) + 1));
    997 	}
    998 
    999 	this_rh = ((devid_nm & NM_DEVID) ?
   1000 	    &((struct devid_shr_rec *)record)->did_rec_hdr :
   1001 	    &((struct nm_shr_rec *)record)->sr_rec_hdr);
   1002 
   1003 	shn_offset = offset = ((devid_nm & NM_DEVID) ?
   1004 	    (sizeof (struct devid_shr_rec) - sizeof (struct did_shr_name))
   1005 	    :
   1006 	    (sizeof (struct nm_shr_rec) - sizeof (struct nm_shared_name)));
   1007 
   1008 	shn = ((devid_nm & NM_DEVID) ?
   1009 	    ((caddr_t)&((struct devid_shr_rec *)record)->device_id[0]) :
   1010 	    ((caddr_t)&((struct nm_shr_rec *)record)->sr_name[0]));
   1011 
   1012 	/*CONSTCOND*/
   1013 	while (1) {
   1014 
   1015 		if (devid_nm & NM_DEVID) {
   1016 			shn_key = ((struct did_shr_name *)shn)->did_key;
   1017 			shn_namlen = ((struct did_shr_name *)shn)->did_size;
   1018 			shn_size = DID_SHR_NAMSIZ((struct did_shr_name *)shn);
   1019 		} else {
   1020 			shn_key = ((struct nm_shared_name *)shn)->sn_key;
   1021 			shn_namlen = ((struct nm_shared_name *)shn)->sn_namlen;
   1022 			shn_size = SHR_NAMSIZ((struct nm_shared_name *)shn);
   1023 		}
   1024 
   1025 		if ((key != 0) && (key == shn_key))
   1026 			return (rem_shr_entry(this_nh, recid, (char *)shn,
   1027 			    shn_size, offset, devid_nm));
   1028 
   1029 		if (nm_len == shn_namlen) {
   1030 			if (!devid_nm) {
   1031 				if (strcmp(nm, ((struct nm_shared_name *)
   1032 				    shn)->sn_name) == 0)
   1033 				return (rem_shr_entry(this_nh, recid,
   1034 				    (char *)shn, shn_size, offset,
   1035 				    devid_nm));
   1036 			} else {
   1037 
   1038 				if (nm == NULL ||
   1039 				    ((struct did_shr_name *)shn)->did_devid
   1040 				    == NULL) {
   1041 					return (0);
   1042 				}
   1043 				if (ddi_devid_compare((ddi_devid_t)nm,
   1044 				    (ddi_devid_t)(((struct did_shr_name *)shn)->
   1045 				    did_devid)) == 0)
   1046 				return (rem_shr_entry(this_nh, recid,
   1047 				    (char *)shn, shn_size, offset,
   1048 				    devid_nm));
   1049 			}
   1050 		}
   1051 
   1052 		shn = (caddr_t)get_next_entry(this_nh,
   1053 		    (caddr_t)shn, shn_size, &offset);
   1054 
   1055 		if (shn == (caddr_t)0) {
   1056 			if (offset)
   1057 				return (ENOENT);
   1058 
   1059 			/* Go to next record */
   1060 			offset = shn_offset;
   1061 			this_nh = this_nh->nmn_nextp;
   1062 			record = this_nh->nmn_record;
   1063 			recid = this_rh->r_next_recid;
   1064 			this_rh = ((devid_nm & NM_DEVID) ?
   1065 			    &((struct devid_shr_rec *)record)->did_rec_hdr :
   1066 			    &((struct nm_shr_rec *)record)->sr_rec_hdr);
   1067 			shn = ((devid_nm & NM_DEVID) ?
   1068 			    ((caddr_t)&((struct devid_shr_rec *)
   1069 			    record)->device_id[0]) :
   1070 			    ((caddr_t)&((struct nm_shr_rec *)
   1071 			    record)->sr_name[0]));
   1072 		}
   1073 	}
   1074 	/*NOTREACHED*/
   1075 }
   1076 
   1077 static md_dev64_t
   1078 build_device_number(set_t setno, struct nm_name *n)
   1079 {
   1080 	major_t	maj;
   1081 	char	*shn;
   1082 	md_dev64_t dev;
   1083 
   1084 	/*
   1085 	 * Can't determine the driver name
   1086 	 */
   1087 	if ((shn = (char *)getshared_name(setno, n->n_drv_key, 0L)) == NULL)
   1088 		return (NODEV64);
   1089 
   1090 	if (MD_UPGRADE)
   1091 		maj = md_targ_name_to_major(shn);
   1092 	else
   1093 		maj = ddi_name_to_major(shn);
   1094 
   1095 	if (maj == (major_t)-1)
   1096 		return (NODEV64);
   1097 	dev = md_makedevice(maj, n->n_minor);
   1098 
   1099 	return (dev);
   1100 }
   1101 
   1102 void *
   1103 lookup_entry_record_offset(
   1104 struct	nm_next_hdr	*nh, /* head record header */
   1105 	set_t		setno, /* set to lookup in */
   1106 	side_t		side, /* (key 1) side number */
   1107 	mdkey_t		key, /* (key 2) from md_setdevname */
   1108 	md_dev64_t	dev, /* (alt. key 2) use if key == KEYWILD */
   1109 	int		devid_nm, /* Which name space? */
   1110 	void		*recp, /* pointer to the record containing the result */
   1111 	size_t		*offsetp /* offset in the above record of result */
   1112 )
   1113 {
   1114 	return (lookup_entry_common(nh, setno, side, key, dev, devid_nm,
   1115 	    &recp, offsetp));
   1116 }
   1117 
   1118 void *
   1119 lookup_entry(
   1120 	struct nm_next_hdr	*nh,	/* head record header */
   1121 	set_t			setno,	/* set to lookup in */
   1122 	side_t			side,	/* (key 1) side number */
   1123 	mdkey_t			key,	/* (key 2) from md_setdevname */
   1124 	md_dev64_t		dev,	/* (alt. key 2) use if key == KEYWILD */
   1125 	int			devid_nm /* Which name space? */
   1126 )
   1127 {
   1128 	return (lookup_entry_common(nh, setno, side, key, dev, devid_nm,
   1129 	    NULL, NULL));
   1130 }
   1131 
   1132 void *
   1133 lookup_entry_common(
   1134 	struct nm_next_hdr	*nh,	/* head record header */
   1135 	set_t			setno,	/* set to lookup in */
   1136 	side_t			side,	/* (key 1) side number */
   1137 	mdkey_t			key,	/* (key 2) from md_setdevname */
   1138 	md_dev64_t		dev,	/* (alt. key 2) use if key == KEYWILD */
   1139 	int			devid_nm,	/* Which name space? */
   1140 	void			**recp, /* record containing the result */
   1141 	size_t			*offsetp /* offset in the record of result */
   1142 )
   1143 {
   1144 	struct nm_next_hdr	*this_nh = nh->nmn_nextp;
   1145 	void			*record;
   1146 	struct nm_rec_hdr	*this_rh;
   1147 	caddr_t			n;
   1148 	size_t			offset, n_offset, n_size;
   1149 	side_t			n_side;
   1150 	mdkey_t			n_key;
   1151 
   1152 	if ((key == MD_KEYWILD) && (dev == NODEV64))
   1153 		return ((void *)0);
   1154 
   1155 	if (this_nh == NULL)
   1156 		return ((void *)0);
   1157 
   1158 	record = this_nh->nmn_record;
   1159 
   1160 	this_rh = ((devid_nm & NM_DEVID) ?
   1161 	    &((struct devid_min_rec *)record)->min_rec_hdr :
   1162 	    &((struct nm_rec *)record)->r_rec_hdr);
   1163 
   1164 	/* code to see if EMPTY record */
   1165 	while (this_nh && this_rh->r_used_size == sizeof (struct nm_rec_hdr)) {
   1166 		/* Go to next record */
   1167 		this_nh = this_nh->nmn_nextp;
   1168 		if (this_nh == NULL)
   1169 			return ((void *)0);
   1170 		record = this_nh->nmn_record;
   1171 		this_rh = ((devid_nm & NM_DEVID) ?
   1172 		    &((struct devid_min_rec *)record)->min_rec_hdr :
   1173 		    &((struct nm_rec *)record)->r_rec_hdr);
   1174 	}
   1175 
   1176 	/*
   1177 	 * n_offset will be used to reset offset
   1178 	 */
   1179 	n_offset = offset = ((devid_nm & NM_DEVID) ?
   1180 	    (sizeof (struct devid_min_rec) - sizeof (struct did_min_name)) :
   1181 	    (sizeof (struct nm_rec) - sizeof (struct nm_name)));
   1182 
   1183 	n = ((devid_nm & NM_DEVID) ?
   1184 	    ((caddr_t)&((struct devid_min_rec *)record)->minor_name[0]) :
   1185 	    ((caddr_t)&((struct nm_rec *)record)->r_name[0]));
   1186 
   1187 	/*CONSTCOND*/
   1188 	while (1) {
   1189 
   1190 		if (devid_nm & NM_DEVID) {
   1191 			n_side = ((struct did_min_name *)n)->min_side;
   1192 			n_key = ((struct did_min_name *)n)->min_key;
   1193 			n_size = DID_NAMSIZ((struct did_min_name *)n);
   1194 		} else {
   1195 			n_side = ((struct nm_name *)n)->n_side;
   1196 			n_key = ((struct nm_name *)n)->n_key;
   1197 			n_size = NAMSIZ((struct nm_name *)n);
   1198 		}
   1199 
   1200 		if ((side == n_side) || (side == MD_SIDEWILD)) {
   1201 
   1202 			if ((key != MD_KEYWILD) && (key == n_key)) {
   1203 				if (recp)
   1204 					*recp = record;
   1205 				if (offsetp)
   1206 					*offsetp = offset;
   1207 				return ((void *)n);
   1208 			}
   1209 
   1210 			if ((key == MD_KEYWILD) && !devid_nm &&
   1211 			    (dev == build_device_number(setno,
   1212 			    (struct nm_name *)n))) {
   1213 				if (recp)
   1214 					*recp = record;
   1215 				if (offsetp)
   1216 					*offsetp = offset;
   1217 				return ((void *)n);
   1218 			}
   1219 
   1220 		}
   1221 
   1222 		n = (caddr_t)get_next_entry(this_nh, n, n_size, &offset);
   1223 
   1224 		if (n == NULL) {
   1225 			/*
   1226 			 * No next record, return NULL
   1227 			 */
   1228 			if (this_nh->nmn_nextp == NULL)
   1229 				return (NULL);
   1230 
   1231 			/* Go to next record */
   1232 			offset = n_offset;
   1233 			this_nh = this_nh->nmn_nextp;
   1234 			record = this_nh->nmn_record;
   1235 			this_rh = ((devid_nm & NM_DEVID) ?
   1236 			    &((struct devid_min_rec *)record)->min_rec_hdr :
   1237 			    &((struct nm_rec *)record)->r_rec_hdr);
   1238 			n = ((devid_nm & NM_DEVID) ?
   1239 			    ((caddr_t)&((struct devid_min_rec *)
   1240 			    record)->minor_name[0]) :
   1241 			    ((caddr_t)&((struct nm_rec *)
   1242 			    record)->r_name[0]));
   1243 		}
   1244 	}
   1245 	/*NOTREACHED*/
   1246 }
   1247 
   1248 static int
   1249 is_meta_drive(set_t setno, mdkey_t key)
   1250 {
   1251 	int				i;
   1252 	struct nm_next_hdr		*nh;
   1253 	struct nm_shared_name		*shn;
   1254 
   1255 	if ((nh = get_first_record(setno, 0, NM_SHARED)) == NULL)
   1256 		return (FALSE);
   1257 	if ((shn = (struct nm_shared_name *)lookup_shared_entry(nh,
   1258 	    key, NULL, NULL, NM_SHARED)) == NULL) {
   1259 		return (FALSE);
   1260 	}
   1261 
   1262 	/* See if the name is a metadevice. */
   1263 	for (i = 0; i < META_NAME_COUNT; i++) {
   1264 		if (strcmp(meta_names[i], shn->sn_name) == 0)
   1265 			return (TRUE);
   1266 	}
   1267 	return (FALSE);
   1268 }
   1269 
   1270 static lookup_dev_result_t
   1271 lookup_deventry(
   1272 	struct nm_next_hdr	*nh,	/* head record header */
   1273 	set_t			setno,	/* set to lookup in */
   1274 	side_t			side,	/* (key 1) side number */
   1275 	mdkey_t			key,	/* (key 2) from md_setdevname */
   1276 	char			*drvnm,	/* drvnm to be stored */
   1277 	minor_t			mnum,	/* minor number to be stored */
   1278 	char			*dirnm,	/* directory name to be stored */
   1279 	char			*filenm, /* device filename to be stored */
   1280 	struct nm_name		**ret_rec /* place return found rec. */
   1281 )
   1282 {
   1283 	struct nm_next_hdr	*this_nh = nh->nmn_nextp;
   1284 	struct nm_rec		*record;
   1285 	struct nm_rec_hdr	*this_rh;
   1286 	struct nm_name		*n;
   1287 	size_t			offset;
   1288 	mdkey_t			dirkey, drvkey;
   1289 
   1290 	*ret_rec = NULL;
   1291 	if (this_nh == NULL)
   1292 		return (LOOKUP_DEV_NOMATCH);
   1293 
   1294 	record = (struct nm_rec *)this_nh->nmn_record;
   1295 	this_rh = &record->r_rec_hdr;
   1296 	n = &record->r_name[0];
   1297 
   1298 	offset = sizeof (struct nm_rec) - sizeof (struct nm_name);
   1299 
   1300 	if ((drvkey = getshared_key(setno, drvnm, 0L)) == MD_KEYBAD)
   1301 		return (LOOKUP_DEV_NOMATCH);
   1302 
   1303 	if (dirnm == NULL) {
   1304 		/* No directory name to look up. */
   1305 		dirkey = MD_KEYBAD;
   1306 	} else {
   1307 		/* Look up the directory name */
   1308 		if ((dirkey = getshared_key(setno, dirnm, 0L)) == MD_KEYBAD)
   1309 			return (LOOKUP_DEV_NOMATCH);
   1310 	}
   1311 	ASSERT(side != MD_SIDEWILD);
   1312 
   1313 	/* code to see if EMPTY record */
   1314 	while (this_nh && this_rh->r_used_size == sizeof (struct nm_rec_hdr)) {
   1315 		/* Go to next record */
   1316 		this_nh = this_nh->nmn_nextp;
   1317 		if (this_nh == NULL)
   1318 			return (LOOKUP_DEV_NOMATCH);
   1319 		record = (struct nm_rec *)this_nh->nmn_record;
   1320 		this_rh = &record->r_rec_hdr;
   1321 		n = &record->r_name[0];
   1322 	}
   1323 
   1324 	/*CONSTCOND*/
   1325 	while (1) {
   1326 		if ((side == n->n_side) &&
   1327 		    ((key == MD_KEYWILD) || (key == n->n_key)) &&
   1328 		    (mnum == n->n_minor) &&
   1329 		    (drvkey == n->n_drv_key) &&
   1330 		    (dirkey == n->n_dir_key) &&
   1331 		    (strcmp(filenm, n->n_name) == 0)) {
   1332 			*ret_rec = n;
   1333 			return (LOOKUP_DEV_FOUND);
   1334 		}
   1335 
   1336 		/*
   1337 		 * Now check for a name conflict.  If the filenm of the
   1338 		 * current record matches filename passed in we have a
   1339 		 * potential conflict.  If all the other parameters match
   1340 		 * except for the side number, then this is not a
   1341 		 * conflict.  The reason is that there are cases where name
   1342 		 * record is added to each side of a set.
   1343 		 *
   1344 		 * There is one additional complication.  It is only a
   1345 		 * conflict if the drvkeys both represent metadevices.  It
   1346 		 * is legal for a metadevice and a physical device to have
   1347 		 * the same name.
   1348 		 */
   1349 		if (strcmp(filenm, n->n_name) == 0) {
   1350 			int	both_meta;
   1351 
   1352 			/*
   1353 			 * It is hsp and we are trying to add it twice
   1354 			 */
   1355 			if (strcmp(getshared_name(setno, n->n_drv_key, 0L),
   1356 			    MD_HOTSPARES) == 0 && (side == n->n_side) &&
   1357 			    find_hot_spare_pool(setno,
   1358 			    KEY_TO_HSP_ID(setno, n->n_key)) == NULL) {
   1359 				/*
   1360 				 * All entries removed
   1361 				 */
   1362 				rw_exit(&nm_lock.lock);
   1363 				(void) md_rem_hspname(setno, n->n_key);
   1364 				rw_enter(&nm_lock.lock, RW_WRITER);
   1365 				return (LOOKUP_DEV_NOMATCH);
   1366 			}
   1367 
   1368 			/*
   1369 			 * It is metadevice and we are trying to add it twice
   1370 			 */
   1371 			if (md_set[setno].s_un[MD_MIN2UNIT(n->n_minor)]
   1372 			    == NULL && (side == n->n_side) &&
   1373 			    ddi_name_to_major(getshared_name(setno,
   1374 			    n->n_drv_key, 0L)) == md_major) {
   1375 				/*
   1376 				 * Apparently it is invalid so
   1377 				 * clean it up
   1378 				 */
   1379 				md_remove_minor_node(n->n_minor);
   1380 				rw_exit(&nm_lock.lock);
   1381 				(void) md_rem_selfname(n->n_minor);
   1382 				rw_enter(&nm_lock.lock, RW_WRITER);
   1383 				return (LOOKUP_DEV_NOMATCH);
   1384 			}
   1385 
   1386 			/* First see if the two drives are metadevices. */
   1387 			if (is_meta_drive(setno, drvkey) &&
   1388 			    is_meta_drive(setno, n->n_drv_key)) {
   1389 				both_meta = TRUE;
   1390 			} else {
   1391 				both_meta = FALSE;
   1392 			}
   1393 			/* Check rest of the parameters. */
   1394 			if ((both_meta == TRUE) &&
   1395 			    ((key != n->n_key) ||
   1396 			    (mnum != n->n_minor) ||
   1397 			    (drvkey != n->n_drv_key) ||
   1398 			    (dirkey != n->n_dir_key))) {
   1399 				return (LOOKUP_DEV_CONFLICT);
   1400 			}
   1401 		}
   1402 		n = (struct nm_name *)get_next_entry(this_nh, (caddr_t)n,
   1403 		    NAMSIZ(n), &offset);
   1404 
   1405 		if (n == (struct nm_name *)0) {
   1406 			if (offset)
   1407 				return (LOOKUP_DEV_NOMATCH);
   1408 
   1409 			/* Go to next record */
   1410 			offset = sizeof (struct nm_rec) -
   1411 			    sizeof (struct nm_name);
   1412 			this_nh = this_nh->nmn_nextp;
   1413 			record = (struct nm_rec *)this_nh->nmn_record;
   1414 			this_rh = &record->r_rec_hdr;
   1415 			n = &record->r_name[0];
   1416 		}
   1417 	}
   1418 	/*NOTREACHED*/
   1419 }
   1420 
   1421 void *
   1422 lookup_shared_entry_record_offset(
   1423 	struct nm_next_hdr *nh,	/* First record header to start lookup */
   1424 	mdkey_t		key,	/* Shared key, used as key if nm is NULL */
   1425 	char *nm,		/* Shared name, used as key if non-NULL */
   1426 	mddb_recid_t *id,	/* mddb record id of record entry is found in */
   1427 	int devid_nm,		/* which name space? */
   1428 	void *recp,		/* pointer to record containing the result */
   1429 	size_t *offset_p	/* offest in the above record of the result */
   1430 )
   1431 {
   1432 	return (lookup_shared_entry_common(nh, key, nm, id, devid_nm, &recp,
   1433 	    offset_p));
   1434 }
   1435 
   1436 void *
   1437 lookup_shared_entry(
   1438 	struct nm_next_hdr *nh,	/* First record header to start lookup */
   1439 	mdkey_t key,		/* Shared key, used as key if nm is NULL */
   1440 	char *nm,		/* Shared name, used as key if non-NULL */
   1441 	mddb_recid_t *id,	/* mddb record id of record entry is found in */
   1442 	int	devid_nm)	/* which name space? */
   1443 {
   1444 	return (lookup_shared_entry_common(nh, key, nm, id, devid_nm, NULL,
   1445 	    NULL));
   1446 }
   1447 
   1448 void *
   1449 lookup_shared_entry_common(
   1450 	struct nm_next_hdr *nh, /* First record header to start lookup */
   1451 	mdkey_t key,		/* Shared key, used as key if nm is NULL */
   1452 	char *nm,		/* Shared name, used as key if non-NULL */
   1453 	mddb_recid_t *id,	/* mddb record id of record entry is found in */
   1454 	int	devid_nm,	/* which name space? */
   1455 	void	**recp,		/* pointer to record containing the result */
   1456 	size_t	*offsetp	/* offest in the above record of the result */
   1457 )
   1458 {
   1459 
   1460 	struct nm_rec_hdr	*rh = (struct nm_rec_hdr *)nh->nmn_record;
   1461 	struct nm_next_hdr	*this_nh = nh->nmn_nextp;
   1462 	void			*record;
   1463 	struct nm_rec_hdr	*this_rh;
   1464 	caddr_t			shn;
   1465 	size_t			offset, shn_offset;
   1466 	size_t			nm_len = 0, shn_size;
   1467 	mdkey_t			shn_key;
   1468 	ushort_t		shn_namlen;
   1469 
   1470 	if (this_nh == NULL)
   1471 		return ((void *) 0);
   1472 
   1473 	record = this_nh->nmn_record;
   1474 
   1475 	if (nm != (char *)0)
   1476 		nm_len = ((devid_nm & NM_DEVID) ?
   1477 		    ddi_devid_sizeof((ddi_devid_t)nm) :
   1478 		    (strlen(nm) + 1));
   1479 
   1480 	if (id != NULL)
   1481 		*id = rh->r_next_recid;
   1482 
   1483 	this_rh = ((devid_nm & NM_DEVID) ?
   1484 	    &((struct devid_shr_rec *)record)->did_rec_hdr :
   1485 	    &((struct nm_shr_rec *)record)->sr_rec_hdr);
   1486 
   1487 	/* code to see if EMPTY record */
   1488 	while (this_nh && this_rh->r_used_size == sizeof (struct nm_rec_hdr)) {
   1489 		/* Go to next record */
   1490 		this_nh = this_nh->nmn_nextp;
   1491 		if (this_nh == NULL)
   1492 			return ((void *)0);
   1493 		record = this_nh->nmn_record;
   1494 		if (id != NULL)
   1495 			*id = this_rh->r_next_recid;
   1496 
   1497 		this_rh = ((devid_nm & NM_DEVID) ?
   1498 		    &((struct devid_shr_rec *)record)->did_rec_hdr :
   1499 		    &((struct nm_shr_rec *)record)->sr_rec_hdr);
   1500 	}
   1501 
   1502 	/*
   1503 	 * shn_offset will be used to reset offset
   1504 	 */
   1505 	shn_offset = offset = ((devid_nm & NM_DEVID) ?
   1506 	    (sizeof (struct devid_shr_rec) - sizeof (struct did_shr_name)) :
   1507 	    (sizeof (struct nm_shr_rec) - sizeof (struct nm_shared_name)));
   1508 
   1509 	shn = ((devid_nm & NM_DEVID) ?
   1510 	    ((caddr_t)&((struct devid_shr_rec *)record)->device_id[0]) :
   1511 	    ((caddr_t)&((struct nm_shr_rec *)record)->sr_name[0]));
   1512 
   1513 	/*CONSTCOND*/
   1514 	while (1) {
   1515 
   1516 		if (devid_nm & NM_DEVID) {
   1517 			shn_key = ((struct did_shr_name *)shn)->did_key;
   1518 			shn_namlen = ((struct did_shr_name *)shn)->did_size;
   1519 			shn_size = DID_SHR_NAMSIZ((struct did_shr_name *)shn);
   1520 		} else {
   1521 			shn_key = ((struct nm_shared_name *)shn)->sn_key;
   1522 			shn_namlen = ((struct nm_shared_name *)shn)->sn_namlen;
   1523 			shn_size = SHR_NAMSIZ((struct nm_shared_name *)shn);
   1524 		}
   1525 
   1526 		if ((key != 0) && (key == shn_key)) {
   1527 			if (recp)
   1528 				*recp = record;
   1529 			if (offsetp)
   1530 				*offsetp = offset;
   1531 			return ((void *)shn);
   1532 		}
   1533 
   1534 		/* Lookup by name */
   1535 		if (nm != NULL) {
   1536 			if (devid_nm & NM_IMP_SHARED) {
   1537 			/*
   1538 			 * the nm passed in is "/dev/md" in the import case
   1539 			 * and we want to do a partial match on that.
   1540 			 */
   1541 			if (strncmp(nm, ((struct nm_shared_name *)shn)->sn_name,
   1542 			    strlen(nm)) == 0) {
   1543 				if (recp)
   1544 					*recp = record;
   1545 				if (offsetp)
   1546 					*offsetp = offset;
   1547 				return ((void *)shn);
   1548 			}
   1549 			} else if (nm_len == shn_namlen) {
   1550 			if (devid_nm & NM_DEVID) {
   1551 				if (ddi_devid_compare((ddi_devid_t)nm,
   1552 				    (ddi_devid_t)(((struct did_shr_name *)shn)->
   1553 				    did_devid)) == 0) {
   1554 					if (recp)
   1555 						*recp = record;
   1556 					if (offsetp)
   1557 						*offsetp = offset;
   1558 					return ((void *)shn);
   1559 				}
   1560 			} else {
   1561 				if (strcmp(nm, ((struct nm_shared_name *)
   1562 				    shn)->sn_name) == 0) {
   1563 					if (recp)
   1564 						*recp = record;
   1565 					if (offsetp)
   1566 						*offsetp = offset;
   1567 					return ((void *)shn);
   1568 				}
   1569 			}
   1570 			}
   1571 		}
   1572 
   1573 		shn = (caddr_t)get_next_entry(this_nh,
   1574 		    (caddr_t)shn, shn_size, &offset);
   1575 
   1576 		if (shn == (caddr_t)0) {
   1577 			/*
   1578 			 * No next record, return
   1579 			 */
   1580 			if (this_nh->nmn_nextp == NULL)
   1581 				return (NULL);
   1582 
   1583 			/* Go to next record */
   1584 			offset = shn_offset;
   1585 			this_nh = this_nh->nmn_nextp;
   1586 			record = this_nh->nmn_record;
   1587 			if (id != NULL)
   1588 				*id = this_rh->r_next_recid;
   1589 			this_rh = ((devid_nm & NM_DEVID) ?
   1590 			    &((struct devid_shr_rec *)record)->did_rec_hdr :
   1591 			    &((struct nm_shr_rec *)record)->sr_rec_hdr);
   1592 			shn = ((devid_nm & NM_DEVID) ?
   1593 			    ((caddr_t)&((struct devid_shr_rec *)
   1594 			    record)->device_id[0]) :
   1595 			    ((caddr_t)&((struct nm_shr_rec *)
   1596 			    record)->sr_name[0]));
   1597 		}
   1598 	}
   1599 	/*NOTREACHED*/
   1600 }
   1601 
   1602 
   1603 /*
   1604  * lookup_hspentry - Getting a hotspare pool entry from the namespace.
   1605  *		     Use either the NM key or the hotspare name to find
   1606  *		     a matching record in the namespace of the set.
   1607  */
   1608 void *
   1609 lookup_hspentry(
   1610 	struct nm_next_hdr	*nh,	/* head record header */
   1611 	set_t			setno,	/* set to lookup in */
   1612 	side_t			side,	/* (key 1) side number */
   1613 	mdkey_t			key,	/* (key 2) from md_setdevname */
   1614 	char			*name	/* (alt. key 2), if key == MD_KEYWILD */
   1615 )
   1616 {
   1617 	struct nm_next_hdr	*this_nh = nh->nmn_nextp;
   1618 	struct nm_rec		*record;
   1619 	struct nm_rec_hdr	*this_rh;
   1620 	struct nm_name		*n;
   1621 	size_t			offset, n_offset, n_size;
   1622 	side_t			n_side;
   1623 	mdkey_t			n_key;
   1624 	char			*drv_name;
   1625 	char			*tmpname;
   1626 	char			*setname = NULL;
   1627 
   1628 	if ((key == MD_KEYWILD) && (name == '\0'))
   1629 		return ((void *)0);
   1630 
   1631 	if (this_nh == NULL)
   1632 		return ((void *)0);
   1633 
   1634 	record = (struct nm_rec *)this_nh->nmn_record;
   1635 
   1636 	this_rh = &record->r_rec_hdr;
   1637 
   1638 	if (setno != MD_LOCAL_SET) {
   1639 		setname = mddb_getsetname(setno);
   1640 		if (setname == NULL)
   1641 			return ((void *)0);
   1642 	}
   1643 
   1644 	/* code to see if EMPTY record */
   1645 	while (this_nh && this_rh->r_used_size == sizeof (struct nm_rec_hdr)) {
   1646 		/* Go to next record */
   1647 		this_nh = this_nh->nmn_nextp;
   1648 		if (this_nh == NULL)
   1649 			return ((void *)0);
   1650 		record = this_nh->nmn_record;
   1651 		this_rh = &record->r_rec_hdr;
   1652 	}
   1653 
   1654 	/*
   1655 	 * n_offset will be used to reset offset
   1656 	 */
   1657 	n_offset = offset = (sizeof (struct nm_rec) - sizeof (struct nm_name));
   1658 
   1659 	n = ((struct nm_name *)&record->r_name[0]);
   1660 
   1661 	tmpname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
   1662 
   1663 	/*CONSTCOND*/
   1664 	while (1) {
   1665 		n_side = n->n_side;
   1666 		n_size = NAMSIZ(n);
   1667 		if ((drv_name = (char *)getshared_name(setno,
   1668 		    n->n_drv_key, 0L)) != NULL) {
   1669 
   1670 			/* We're only interested in hsp NM records */
   1671 			if ((strcmp(drv_name, "md_hotspares") == 0) &&
   1672 			    ((side == n_side) || (side == MD_SIDEWILD))) {
   1673 				n_key = n->n_key;
   1674 
   1675 				if ((key != MD_KEYWILD) && (key == n_key))
   1676 					goto done;
   1677 
   1678 				/*
   1679 				 * Searching by a hotspare pool name.
   1680 				 * Since the input name is of the form
   1681 				 * setname/hsp_name, we need to attach
   1682 				 * the string 'setname/' in front of the
   1683 				 * n->n_name.
   1684 				 */
   1685 				if (key == MD_KEYWILD) {
   1686 					if (setname != NULL)
   1687 						(void) snprintf(tmpname,
   1688 						    MAXPATHLEN, "%s/%s",
   1689 						    setname,
   1690 						    ((struct nm_name *)
   1691 						    n)->n_name);
   1692 					else
   1693 						(void) snprintf(tmpname,
   1694 						    MAXPATHLEN, "%s",
   1695 						    ((struct nm_name *)
   1696 						    n)->n_name);
   1697 
   1698 					if ((strcmp(name, tmpname)) == 0)
   1699 						goto done;
   1700 				}
   1701 			}
   1702 		}
   1703 
   1704 		n = (struct nm_name *)get_next_entry(this_nh, (caddr_t)n,
   1705 		    n_size, &offset);
   1706 
   1707 		if (n == NULL) {
   1708 			/*
   1709 			 * No next record, return
   1710 			 */
   1711 			if (offset)
   1712 				goto done;
   1713 
   1714 			/* Go to next record */
   1715 			offset = n_offset;
   1716 			this_nh = this_nh->nmn_nextp;
   1717 			record = (struct nm_rec *)this_nh->nmn_record;
   1718 			this_rh = &record->r_rec_hdr;
   1719 			n = ((struct nm_name *)&record->r_name[0]);
   1720 		}
   1721 	}
   1722 
   1723 done:
   1724 	kmem_free(tmpname, MAXPATHLEN);
   1725 	return ((void *)n);
   1726 }
   1727 
   1728 static int
   1729 md_make_devname(struct nm_name *n, set_t setno, char *string, size_t max_size)
   1730 {
   1731 
   1732 	char	*dir_name;
   1733 	size_t	dir_len;
   1734 
   1735 	/*
   1736 	 * Can't determine the path
   1737 	 */
   1738 	if ((dir_name =
   1739 	    (char *)getshared_name(setno, n->n_dir_key, 0L)) == NULL)
   1740 		return ((int)NODEV64);
   1741 
   1742 	dir_len = strlen(dir_name);
   1743 	if ((dir_len + n->n_namlen) > max_size)
   1744 		return (EFAULT);
   1745 
   1746 	/* Tack the directory and device strings together */
   1747 	(void) strcpy(strcpy(string, dir_name) + dir_len, n->n_name);
   1748 	return (0);
   1749 }
   1750 
   1751 static void
   1752 build_rec_hdr_list(struct nm_next_hdr *nh, mddb_recid_t recid, int shared)
   1753 {
   1754 	size_t			overhead_size;
   1755 	struct nm_rec_hdr	*this_rh;
   1756 	uint_t			private;
   1757 	struct nm_rec_hdr	*rh = (struct nm_rec_hdr *)nh->nmn_record;
   1758 	struct nm_next_hdr	*this_nh;
   1759 	set_t			setno;
   1760 	int			multi_node = 0;
   1761 
   1762 	/* If given record is for a multi_node set, set flag */
   1763 	setno = DBSET(recid);
   1764 	if (MD_MNSET_SETNO(setno))
   1765 		multi_node = 1;
   1766 
   1767 	if (shared & NM_DEVID)
   1768 		overhead_size = ((shared & NM_SHARED) ?
   1769 		    (sizeof (struct devid_shr_rec) -
   1770 		    sizeof (struct did_shr_name))
   1771 		    :
   1772 		    (sizeof (struct devid_min_rec) -
   1773 		    sizeof (struct did_min_name)));
   1774 	else
   1775 		overhead_size = ((shared & NM_SHARED) ?
   1776 		    (sizeof (struct nm_shr_rec) -
   1777 		    sizeof (struct nm_shared_name)) :
   1778 		    (sizeof (struct nm_rec) - sizeof (struct nm_name)));
   1779 
   1780 	while (rh->r_next_recid > 0) {
   1781 		this_nh = kmem_zalloc(sizeof (*this_nh), KM_SLEEP);
   1782 		nh->nmn_nextp = this_nh;
   1783 		this_nh->nmn_record = mddb_getrecaddr(rh->r_next_recid);
   1784 
   1785 		ASSERT(this_nh->nmn_record != NULL);
   1786 
   1787 		if (shared & NM_DEVID)
   1788 			this_rh = ((shared & NM_SHARED) ?
   1789 			    &((struct devid_shr_rec *)
   1790 			    this_nh->nmn_record)->did_rec_hdr
   1791 			    :
   1792 			    &((struct devid_min_rec *)
   1793 			    this_nh->nmn_record)->min_rec_hdr);
   1794 		else
   1795 			this_rh = ((shared & NM_SHARED) ?
   1796 			    &((struct nm_shr_rec *)
   1797 			    this_nh->nmn_record)->sr_rec_hdr
   1798 			    :
   1799 			    &((struct nm_rec *)this_nh->nmn_record)->r_rec_hdr);
   1800 
   1801 		/*
   1802 		 * Check for empty records and clean them up.
   1803 		 * For a MN diskset, only do this if master.
   1804 		 */
   1805 		if ((!multi_node) ||
   1806 		    (multi_node && md_set[setno].s_am_i_master)) {
   1807 			if (this_rh->r_used_size == overhead_size) {
   1808 				mddb_setrecprivate(rh->r_next_recid,
   1809 				    MD_PRV_PENDDEL);
   1810 				rh->r_next_recid = this_rh->r_next_recid;
   1811 				kmem_free(this_nh, sizeof (*this_nh));
   1812 				nh->nmn_nextp = NULL;
   1813 				mddb_setrecprivate(recid, MD_PRV_PENDCOM);
   1814 				continue;
   1815 			}
   1816 		}
   1817 
   1818 		private = mddb_getrecprivate(rh->r_next_recid);
   1819 		mddb_setrecprivate(rh->r_next_recid, (private | MD_PRV_GOTIT));
   1820 		recid = rh->r_next_recid;
   1821 		rh = this_rh;
   1822 		nh = this_nh;
   1823 	}
   1824 }
   1825 
   1826 static void
   1827 zero_data_ptrs(struct nm_next_hdr *nh, set_t setno)
   1828 {
   1829 	mdkey_t	i;
   1830 	struct nm_rec_hdr	*rh = (struct nm_rec_hdr *)nh->nmn_record;
   1831 
   1832 	if (rh->r_next_recid == 0)
   1833 		return;
   1834 
   1835 	for (i = MDDB_FIRST_MODID; i < rh->r_next_key; i++)
   1836 		(void) setshared_data(setno, i, (caddr_t)-1);
   1837 }
   1838 
   1839 /*
   1840  * md_setdevname - Allows putting a device name into the database
   1841  */
   1842 mdkey_t
   1843 md_setdevname(
   1844 	set_t		setno,	/* specify which namespace to put in */
   1845 	side_t		side,	/* (key 1) side # */
   1846 	mdkey_t		key,	/* (key 2) KEYWILD - alloc key, else use key */
   1847 	char		*drvnm,	/* store this driver name with devicename */
   1848 	minor_t		mnum,	/* store this minor number as well */
   1849 	char		*devname,	/* device name to be stored */
   1850 	int		imp_flag,	/* used exclusively by import */
   1851 	ddi_devid_t	imp_devid,	/* used exclusively by import */
   1852 	char		*imp_mname,	/* used exclusively by import */
   1853 	set_t		imp_setno,	/* used exclusively by import */
   1854 	md_error_t	*ep		/* place to return error info */
   1855 )
   1856 {
   1857 	struct nm_next_hdr	*nh, *did_nh = NULL;
   1858 	struct nm_name		*n;
   1859 	struct did_min_name	*did_n;
   1860 	struct did_min_name	*new_did_n;
   1861 	mddb_recid_t		recids[3];
   1862 	char			*cp, *dname = NULL, *fname;
   1863 	char			c;
   1864 	mdkey_t			retval = MD_KEYBAD;
   1865 	int			shared = -1, new = 0;
   1866 	ddi_devid_t		devid = NULL;
   1867 	dev_t			devt;
   1868 	char			*mname = NULL;
   1869 	side_t			thisside = MD_SIDEWILD;
   1870 	lookup_dev_result_t	lookup_res;
   1871 	mdkey_t			min_devid_key = MD_KEYWILD;
   1872 	size_t			min_len;
   1873 	int			use_devid = 0;
   1874 	side_t			temp_side;
   1875 
   1876 	/*
   1877 	 * Don't allow addition of new names to namespace during upgrade.
   1878 	 */
   1879 	if (MD_UPGRADE)  {
   1880 		return (MD_KEYBAD);
   1881 	}
   1882 
   1883 	/*
   1884 	 * Make sure devname is not empty
   1885 	 */
   1886 	if (devname == (char *)NULL || strncmp(devname, "", 1) == 0) {
   1887 		cmn_err(CE_WARN, "Unknown device with minor number of %d",
   1888 		    mnum);
   1889 		return (MD_KEYBAD);
   1890 	}
   1891 
   1892 	/*
   1893 	 * Load the devid name space if it exists
   1894 	 */
   1895 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   1896 	if (! md_load_namespace(setno, NULL, 0L)) {
   1897 		/*
   1898 		 * Unload the devid namespace
   1899 		 */
   1900 		(void) md_unload_namespace(setno, NM_DEVID);
   1901 		return (MD_KEYBAD);
   1902 	}
   1903 
   1904 	/*
   1905 	 * Go looking for an existing devid namespace record for this
   1906 	 * key. We need to do this here as md_devid_found() also
   1907 	 * requires the nm_lock.lock.
   1908 	 */
   1909 	if ((!imp_flag) && (setno == MD_LOCAL_SET) && (side > 0) &&
   1910 	    (key != MD_KEYWILD)) {
   1911 		/*
   1912 		 * We must be adding a namespace record for a disk in a
   1913 		 * shared metaset of some description. As we already have a
   1914 		 * key, walk all the valid sides for the set and see if we
   1915 		 * have a devid record present. This will be used to help
   1916 		 * determine which namespace we add this new record into.
   1917 		 */
   1918 		for (temp_side = 1; temp_side < MD_MAXSIDES; temp_side++) {
   1919 			if (md_devid_found(setno, temp_side, key) == 0) {
   1920 				/*
   1921 				 * We have a devid record for this key.
   1922 				 * Assume it's safe to use devid's for the
   1923 				 * other side records as well.
   1924 				 */
   1925 				use_devid = 1;
   1926 				break;
   1927 			}
   1928 		}
   1929 	}
   1930 
   1931 	rw_enter(&nm_lock.lock, RW_WRITER);
   1932 
   1933 	/*
   1934 	 * Find out what namespace/set/side combination that is
   1935 	 * being dealt with. If this is not done then we stand a
   1936 	 * chance of adding in incorrect devid details to match
   1937 	 * the remote side's disk information. For example:
   1938 	 * disk c2t0d0s0 may have devt of 32,256 on this side
   1939 	 * but 32,567 on the remote side and if this is the case
   1940 	 * we do not want to add the devid for disk 32,567 on
   1941 	 * this side into the namespace.
   1942 	 */
   1943 	if (setno == MD_LOCAL_SET && side == 0)
   1944 		/* local set/local side */
   1945 		thisside = side;
   1946 	else if (setno == MD_LOCAL_SET && side > 0) {
   1947 		/*
   1948 		 * local set/non-local side information ie a set record
   1949 		 *
   1950 		 * if the key is not set then this is the first time
   1951 		 * through this code which means this is the first record
   1952 		 * which then means the record to be added is for this node
   1953 		 */
   1954 		if (key == MD_KEYWILD) {
   1955 			thisside = side;
   1956 		} else {
   1957 			/*
   1958 			 * This is not the first time through this code,
   1959 			 * so we have already got a record in the namespace.
   1960 			 * Check if the earlier search for this record found
   1961 			 * a devid record or not, and set the namespace
   1962 			 * accordingly.
   1963 			 */
   1964 			if (use_devid == 1) {
   1965 				/* A devid record exists */
   1966 				shared = NM_DEVID | NM_NOTSHARED;
   1967 			} else {
   1968 				/* No devid record exists for this key */
   1969 				shared = NM_NOTSHARED;
   1970 			}
   1971 		}
   1972 	} else if (setno != MD_LOCAL_SET) {
   1973 		/* set record */
   1974 		thisside = mddb_getsidenum(setno);
   1975 	}
   1976 
   1977 	/*
   1978 	 * Check to see if it has a device id associated with
   1979 	 * and if the MDDB_DEVID_STYLE flag is set. If the device
   1980 	 * is a metadevice the get_minor_name will fail. No account
   1981 	 * of the side information is taken here because it is dealt
   1982 	 * with later on.
   1983 	 */
   1984 	if (!imp_flag) {
   1985 		/*
   1986 		 * Only do this if we have not already set the namespace type,
   1987 		 * otherwise we run the risk of adding a record for an invalid
   1988 		 * minor number from a remote node.
   1989 		 */
   1990 		if (shared == -1) {
   1991 			devt = makedevice(ddi_name_to_major(drvnm), mnum);
   1992 			if ((ddi_lyr_get_devid(devt, &devid) == DDI_SUCCESS) &&
   1993 			    (ddi_lyr_get_minor_name(devt, S_IFBLK, &mname) ==
   1994 			    DDI_SUCCESS) &&
   1995 			    (((mddb_set_t *)md_set[setno].s_db)->s_lbp->lb_flags
   1996 			    & MDDB_DEVID_STYLE))
   1997 				/*
   1998 				 * Reference the device id namespace
   1999 				 */
   2000 				shared = NM_DEVID | NM_NOTSHARED;
   2001 			else
   2002 				shared = NM_NOTSHARED;
   2003 		}
   2004 	} else {
   2005 		/* Importing diskset has devids so store in namespace */
   2006 		devid = kmem_alloc(ddi_devid_sizeof(imp_devid), KM_SLEEP);
   2007 		bcopy(imp_devid, devid, ddi_devid_sizeof(imp_devid));
   2008 		mname = md_strdup(imp_mname);
   2009 		shared = NM_DEVID | NM_NOTSHARED;
   2010 	}
   2011 
   2012 	/*
   2013 	 * Always lookup the primary name space
   2014 	 */
   2015 	if ((nh = get_first_record(setno, 1, NM_NOTSHARED)) == NULL) {
   2016 		retval = MD_KEYBAD;
   2017 		goto out;
   2018 	}
   2019 
   2020 	/*
   2021 	 * If it has a device id then get the header for the devid namespace
   2022 	 */
   2023 	if (shared & NM_DEVID) {
   2024 		if ((did_nh = get_first_record(setno, 1, shared)) == NULL) {
   2025 			retval = MD_KEYBAD;
   2026 			goto out;
   2027 		}
   2028 	}
   2029 
   2030 	/* find boundary between filename and directory */
   2031 	cp = strrchr(devname, '/');
   2032 
   2033 	if (cp == NULL) {
   2034 		/* No directory part to the name. */
   2035 		fname = devname;
   2036 		dname = NULL;
   2037 	} else {
   2038 		/* Isolate the directory name only; save character after '/' */
   2039 		c = *(cp + 1);
   2040 		*(cp + 1) = '\0';
   2041 		dname = md_strdup(devname);
   2042 
   2043 		/* Restore character after '/' */
   2044 		*(cp + 1) = c;
   2045 		fname = cp+1;
   2046 	}
   2047 
   2048 	/*
   2049 	 * If it already there in the name space
   2050 	 */
   2051 	lookup_res = lookup_deventry(nh, setno, side, key, drvnm, mnum, dname,
   2052 	    fname, &n);
   2053 
   2054 	/* If we are importing the set */
   2055 	if (imp_flag && (lookup_res == LOOKUP_DEV_FOUND)) {
   2056 		ushort_t	did_sz;
   2057 		ddi_devid_t	did;
   2058 
   2059 		/*
   2060 		 * We need to check for the case where there is a disk
   2061 		 * already in the namespace with a different ID from
   2062 		 * the one we want to add, but the same name. This is
   2063 		 * possible in the case of an unavailable disk.
   2064 		 */
   2065 		rw_exit(&nm_lock.lock);
   2066 		if (md_getdevid(setno, side, n->n_key, NULL, &did_sz) != 0)
   2067 			did_sz = 0;
   2068 		rw_enter(&nm_lock.lock, RW_WRITER);
   2069 		if (did_sz > 0) {
   2070 			did = kmem_zalloc(did_sz, KM_SLEEP);
   2071 			rw_exit(&nm_lock.lock);
   2072 			(void) md_getdevid(setno, side, n->n_key, did, &did_sz);
   2073 			rw_enter(&nm_lock.lock, RW_WRITER);
   2074 			if (ddi_devid_compare(did, devid) == 0) {
   2075 				kmem_free(did, did_sz);
   2076 				retval = 0;
   2077 				goto out;
   2078 			}
   2079 			kmem_free(did, did_sz);
   2080 		}
   2081 		/*
   2082 		 * This is not the same disk so we haven't really found it.
   2083 		 * Thus, we need to say it's "NOMATCH" and create a new
   2084 		 * entry.
   2085 		 */
   2086 		lookup_res = LOOKUP_DEV_NOMATCH;
   2087 	}
   2088 	switch (lookup_res) {
   2089 	case LOOKUP_DEV_FOUND:
   2090 		/* If we are importing the set */
   2091 		if (md_get_setstatus(imp_setno) & MD_SET_IMPORT) {
   2092 			retval = 0;
   2093 			goto out;
   2094 		}
   2095 
   2096 		/* Increment reference count */
   2097 		retval = n->n_key;
   2098 		n->n_count++;
   2099 		(void) update_entry(nh, n->n_side, n->n_key, 0L);
   2100 
   2101 		/* Also in the device id name space if there is one */
   2102 		if (did_nh) {
   2103 			/*
   2104 			 * Use thisside for the sideno as this is the
   2105 			 * side this is running on.
   2106 			 */
   2107 			if ((did_n = (struct did_min_name *)
   2108 			    lookup_entry(did_nh, setno, side, n->n_key,
   2109 			    NODEV64, NM_DEVID)) != NULL) {
   2110 
   2111 				did_n->min_count++;
   2112 				(void) update_entry(did_nh, did_n->min_side,
   2113 				    did_n->min_key, NM_DEVID);
   2114 			} else {
   2115 				/*
   2116 				 * If a disk device does not support
   2117 				 * devid then we would fail to find the
   2118 				 * device and then try and add it, bit
   2119 				 * silly.
   2120 				 */
   2121 				goto add_devid;
   2122 			}
   2123 		}
   2124 		goto out;
   2125 
   2126 	case LOOKUP_DEV_CONFLICT:
   2127 		(void) mderror(ep, MDE_NAME_IN_USE);
   2128 		retval = MD_KEYBAD;
   2129 		goto out;
   2130 
   2131 	case LOOKUP_DEV_NOMATCH:
   2132 		/* Create a new name entry */
   2133 		new = 1;
   2134 		n = (struct nm_name *)alloc_entry(nh, md_set[setno].s_nmid,
   2135 		    strlen(fname)+1, NM_NOTSHARED, &recids[0]);
   2136 
   2137 		if (n == NULL)
   2138 			goto out;
   2139 
   2140 		n->n_minor = mnum;
   2141 		n->n_side = side;
   2142 		n->n_key = ((key == MD_KEYWILD) ? create_key(nh) : key);
   2143 		n->n_count = 1;
   2144 
   2145 		/* fill-in filename */
   2146 		(void) strcpy(n->n_name, fname);
   2147 		n->n_namlen = (ushort_t)(strlen(fname) + 1);
   2148 
   2149 		/*
   2150 		 * If MDE_DB_NOSPACE occurs
   2151 		 */
   2152 		if (((n->n_drv_key =
   2153 		    setshared_name(setno, drvnm, MD_KEYWILD, 0L)) ==
   2154 		    MD_KEYBAD)) {
   2155 			/*
   2156 			 * Remove entry allocated by alloc_entry
   2157 			 * and return MD_KEYBAD
   2158 			 */
   2159 			(void) remove_entry(nh, n->n_side, n->n_key, 0L);
   2160 			goto out;
   2161 		}
   2162 		if (dname == NULL) {
   2163 			/* No directory name implies no key. */
   2164 			n->n_dir_key = MD_KEYBAD;
   2165 		} else {
   2166 			/* We have a directory name to save. */
   2167 			if ((n->n_dir_key =
   2168 			    setshared_name(setno, dname, MD_KEYWILD, 0L)) ==
   2169 			    MD_KEYBAD) {
   2170 				/*
   2171 				 * Remove entry allocated by alloc_entry
   2172 				 * and return MD_KEYBAD
   2173 				 */
   2174 				(void) remove_entry(nh, n->n_side, n->n_key,
   2175 				    0L);
   2176 				goto out;
   2177 			}
   2178 		}
   2179 
   2180 		recids[1] = md_set[setno].s_nmid;
   2181 		recids[2] = 0;
   2182 		mddb_commitrecs_wrapper(recids);
   2183 		retval = n->n_key;
   2184 
   2185 		/*
   2186 		 * Now to find out if devid's were used for thisside and if
   2187 		 * so what is the devid_key for the entry so that the correct
   2188 		 * minor name entry (did_n) has the correct devid key.
   2189 		 * Also get the minor name of the device, use the minor name
   2190 		 * on this side because the assumption is that the slices are
   2191 		 * going to be consistant across the nodes.
   2192 		 */
   2193 		if (key != MD_KEYWILD && (shared & NM_DEVID)) {
   2194 			if ((did_n = (struct did_min_name *)
   2195 			    lookup_entry(did_nh, setno, thisside, n->n_key,
   2196 			    NODEV64, NM_DEVID)) == NULL) {
   2197 				shared &= ~NM_DEVID;
   2198 			} else {
   2199 				min_devid_key = did_n->min_devid_key;
   2200 				min_len = (size_t)did_n->min_namlen;
   2201 				/*
   2202 				 * Need to save the min_name as well because
   2203 				 * if the alloc_entry() needs to expand the
   2204 				 * record then it will free the existing
   2205 				 * record (which will free any references
   2206 				 * to information within it ie did_n->min_name)
   2207 				 */
   2208 				if (mname != NULL) {
   2209 					kmem_free(mname, strlen(mname) + 1);
   2210 				}
   2211 				mname = kmem_alloc(min_len, KM_SLEEP);
   2212 				(void) strcpy(mname, did_n->min_name);
   2213 			}
   2214 		} else {
   2215 
   2216 			/*
   2217 			 * It is possible for the minor name to be null, for
   2218 			 * example a metadevice which means the minor name is
   2219 			 * not initialised.
   2220 			 */
   2221 			if (mname == NULL)
   2222 				goto out;
   2223 
   2224 			min_len = strlen(mname) + 1;
   2225 		}
   2226 		break;
   2227 	}
   2228 
   2229 	/*
   2230 	 * We have the key and if the NM_DEVID bit is on
   2231 	 * use the key to add the device id into the device id name space
   2232 	 */
   2233 
   2234 add_devid:
   2235 
   2236 	if (shared & NM_DEVID) {
   2237 		new_did_n = (struct did_min_name *)alloc_entry(did_nh,
   2238 		    md_set[setno].s_did_nmid, min_len,
   2239 		    shared, &recids[0]);
   2240 
   2241 		/*
   2242 		 * No space
   2243 		 */
   2244 		if (new_did_n == NULL) {
   2245 			if (new) {
   2246 			(void) remove_entry(nh, n->n_side, n->n_key, 0L);
   2247 			retval = MD_KEYBAD;
   2248 			}
   2249 			goto out;
   2250 		}
   2251 
   2252 		new_did_n->min_side = side;
   2253 		new_did_n->min_key = n->n_key;
   2254 		new_did_n->min_count = n->n_count;
   2255 
   2256 		/*
   2257 		 * If the key is set then we know that there should
   2258 		 * be a corresponding devid entry because when the record
   2259 		 * associated with the key was created it would have created
   2260 		 * a corresponding devid entry, all we need to do is find
   2261 		 * that record and increment the count.
   2262 		 */
   2263 		if (key != MD_KEYWILD) {
   2264 
   2265 			/*
   2266 			 * Need to copy the information from the original
   2267 			 * side (thisside).
   2268 			 */
   2269 			new_did_n->min_devid_key = min_devid_key;
   2270 			min_devid_key = setshared_name(setno,
   2271 			    (char *)NULL, min_devid_key, NM_DEVID);
   2272 			if (new_did_n->min_devid_key != min_devid_key) {
   2273 				cmn_err(CE_NOTE,
   2274 				    "addname: failed to add to record");
   2275 			}
   2276 			(void) strcpy(new_did_n->min_name, mname);
   2277 			new_did_n->min_namlen = (ushort_t)min_len;
   2278 		} else {
   2279 
   2280 			/* use the did_n allocated above! */
   2281 			(void) strcpy(new_did_n->min_name, mname);
   2282 			new_did_n->min_namlen = (ushort_t)(strlen(mname) + 1);
   2283 			new_did_n->min_devid_key = setshared_name(setno,
   2284 			    (char *)devid, MD_KEYWILD, NM_DEVID);
   2285 		}
   2286 		/*
   2287 		 * If MDE_DB_NOSPACE occurs
   2288 		 */
   2289 		if (new_did_n->min_devid_key == MD_KEYBAD) {
   2290 			/*
   2291 			 * Remove entry allocated by alloc_entry
   2292 			 */
   2293 			(void) remove_entry(did_nh, new_did_n->min_side,
   2294 			    new_did_n->min_key, NM_DEVID);
   2295 			if (new) {
   2296 				(void) remove_entry(nh, n->n_side, n->n_key,
   2297 				    0L);
   2298 				retval = MD_KEYBAD;
   2299 			}
   2300 		} else {
   2301 			recids[1] = md_set[setno].s_did_nmid;
   2302 			recids[2] = 0;
   2303 			mddb_commitrecs_wrapper(recids);
   2304 		}
   2305 	}
   2306 out:
   2307 	if (devid) {
   2308 		ddi_devid_free(devid);
   2309 	}
   2310 	if (dname)
   2311 		freestr(dname);
   2312 	if (mname)
   2313 		kmem_free(mname, strlen(mname) + 1);
   2314 	rw_exit(&nm_lock.lock);
   2315 	return (retval);
   2316 }
   2317 
   2318 /*
   2319  * md_get_invdid - return the invalid device id's
   2320  */
   2321 int
   2322 md_get_invdid(
   2323 	set_t	setno,
   2324 	side_t	side,
   2325 	int	count,
   2326 	int	size,
   2327 	void	*ctdptr
   2328 )
   2329 {
   2330 	struct nm_next_hdr	*did_shr_nh, *did_nh = NULL, *nh = NULL;
   2331 	struct did_shr_name	*did_shr_n;
   2332 	struct did_min_name	*did_n;
   2333 	struct nm_name		*n;
   2334 	int			key = MD_KEYWILD;
   2335 	int			cnt = 0;
   2336 	char			*cptr = (char *)ctdptr;
   2337 	int			i, dont_add_it;
   2338 	char			*tmpctd;
   2339 	char			*diskname;
   2340 	char			*tmpname;
   2341 
   2342 	/* first get the invalid devid's from the loc block */
   2343 	if ((cnt = mddb_getinvlb_devid(setno, count, size, &cptr)) == -1) {
   2344 		return (-1);
   2345 	}
   2346 
   2347 	/*
   2348 	 * Load the devid name space if it exists
   2349 	 */
   2350 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   2351 	if (! md_load_namespace(setno, NULL, 0L)) {
   2352 		/*
   2353 		 * Unload the devid namespace
   2354 		 */
   2355 		(void) md_unload_namespace(setno, NM_DEVID);
   2356 		return (ENOENT);
   2357 	}
   2358 
   2359 	rw_enter(&nm_lock.lock, RW_READER);
   2360 
   2361 	did_nh = get_first_record(setno, 0, NM_DEVID | NM_NOTSHARED);
   2362 	if (did_nh == NULL) {
   2363 		rw_exit(&nm_lock.lock);
   2364 		return (0);
   2365 	}
   2366 
   2367 	did_shr_nh = get_first_record(setno, 1, NM_DEVID | NM_SHARED);
   2368 	if (did_shr_nh == NULL) {
   2369 		rw_exit(&nm_lock.lock);
   2370 		return (0);
   2371 	}
   2372 
   2373 	nh = get_first_record(setno, 0, NM_NOTSHARED);
   2374 	if (nh == NULL) {
   2375 		rw_exit(&nm_lock.lock);
   2376 		return (0);
   2377 	}
   2378 	while ((key = md_getnextkey(setno, side, key, NULL)) != MD_KEYWILD) {
   2379 		dev_t		devt;
   2380 		ddi_devid_t	rtn_devid = NULL;
   2381 		int		get_rc;
   2382 		int		compare_rc = 1;
   2383 
   2384 		did_n = (struct did_min_name *)lookup_entry(
   2385 		    did_nh, setno, side, key, NODEV64, NM_DEVID);
   2386 		if (did_n == NULL) {
   2387 			continue;
   2388 		}
   2389 		did_shr_n = (struct did_shr_name *)lookup_shared_entry(
   2390 		    did_shr_nh, did_n->min_devid_key, (char *)0,
   2391 		    NULL, NM_DEVID);
   2392 		if ((did_shr_n->did_data & NM_DEVID_VALID) != NULL) {
   2393 			continue;
   2394 		}
   2395 		/* found invalid device id. Add to list */
   2396 		devt = md_dev64_to_dev(
   2397 		    md_getdevnum(setno, side, key, MD_TRUST_DEVT));
   2398 		get_rc = ddi_lyr_get_devid(devt, &rtn_devid);
   2399 		if (get_rc == DDI_SUCCESS) {
   2400 			compare_rc = ddi_devid_compare(rtn_devid,
   2401 			    (ddi_devid_t)did_shr_n-> did_devid);
   2402 			ddi_devid_free(rtn_devid);
   2403 		}
   2404 
   2405 		if ((get_rc == DDI_SUCCESS) && (compare_rc == 0)) {
   2406 			did_shr_n->did_data |= NM_DEVID_VALID;
   2407 		} else {
   2408 			if (cnt++ > count) {
   2409 				rw_exit(&nm_lock.lock);
   2410 				return (-1);
   2411 			}
   2412 			n = (struct nm_name *)lookup_entry(
   2413 			    nh, setno, side, key, NODEV64, 0L);
   2414 			if (n == NULL) {
   2415 				rw_exit(&nm_lock.lock);
   2416 				return ((int)NODEV64);
   2417 			}
   2418 			tmpctd = ctdptr;
   2419 			diskname = md_strdup(n->n_name);
   2420 			if (strlen(diskname) > size) {
   2421 				kmem_free(diskname, strlen(diskname) + 1);
   2422 				rw_exit(&nm_lock.lock);
   2423 				return (-1);
   2424 			}
   2425 			if ((tmpname = strrchr(diskname, 's')) != NULL)
   2426 				*tmpname = '\0';
   2427 			dont_add_it = 0;
   2428 			for (i = 0; i < (cnt - 1); i++) {
   2429 				if (strcmp(diskname, tmpctd) == 0) {
   2430 					dont_add_it = 1;
   2431 					break;
   2432 				}
   2433 				tmpctd += size;
   2434 			}
   2435 			if (dont_add_it == 0) {
   2436 				(void) strcpy(cptr, diskname);
   2437 				cptr += size;
   2438 			}
   2439 			kmem_free(diskname, strlen(n->n_name) + 1);
   2440 		}
   2441 	}
   2442 	*cptr = '\0';
   2443 	rw_exit(&nm_lock.lock);
   2444 	return (0);
   2445 }
   2446 /*
   2447  * md_validate_devid - Checks the device id's to see if they're valid.
   2448  *			Returns a count of the number of invalid device id's
   2449  */
   2450 int
   2451 md_validate_devid(
   2452 	set_t	setno,
   2453 	side_t	side,
   2454 	int	*rmaxsz
   2455 )
   2456 {
   2457 	struct nm_next_hdr	*did_shr_nh, *did_nh = NULL;
   2458 	struct did_shr_name	*did_shr_n;
   2459 	struct did_min_name	*did_n;
   2460 	struct nm_name		*n;
   2461 	struct nm_next_hdr	*nh = NULL;
   2462 	int			cnt = 0;
   2463 	int			key = MD_KEYWILD;
   2464 	int			maxsz = 0;
   2465 	int			len;
   2466 
   2467 	/*
   2468 	 * do the locator blocks first...
   2469 	 */
   2470 
   2471 	if ((cnt = mddb_validate_lb(setno, &maxsz)) == -1) {
   2472 		return (-1);
   2473 	}
   2474 
   2475 	/*
   2476 	 * Load the devid name space if it exists
   2477 	 */
   2478 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   2479 	if (! md_load_namespace(setno, NULL, 0L)) {
   2480 		/*
   2481 		 * Unload the devid namespace
   2482 		 */
   2483 		(void) md_unload_namespace(setno, NM_DEVID);
   2484 		return (-1);
   2485 	}
   2486 
   2487 	rw_enter(&nm_lock.lock, RW_READER);
   2488 
   2489 	did_nh = get_first_record(setno, 0, NM_DEVID | NM_NOTSHARED);
   2490 	if (did_nh == NULL) {
   2491 		rw_exit(&nm_lock.lock);
   2492 		*rmaxsz = maxsz;
   2493 		return (cnt);
   2494 	}
   2495 
   2496 	did_shr_nh = get_first_record(setno, 0, NM_DEVID | NM_SHARED);
   2497 	if (did_shr_nh == NULL) {
   2498 		rw_exit(&nm_lock.lock);
   2499 		*rmaxsz = maxsz;
   2500 		return (cnt);
   2501 	}
   2502 
   2503 	nh = get_first_record(setno, 0, NM_NOTSHARED);
   2504 	if (nh == NULL) {
   2505 		rw_exit(&nm_lock.lock);
   2506 		*rmaxsz = maxsz;
   2507 		return (cnt);
   2508 	}
   2509 	while ((key = md_getnextkey(setno, side, key, NULL)) != MD_KEYWILD) {
   2510 		dev_t		devt;
   2511 		ddi_devid_t	rtn_devid = NULL;
   2512 		int		get_rc;
   2513 		int		compare_rc = 1;
   2514 
   2515 		did_n = (struct did_min_name *)lookup_entry(
   2516 		    did_nh, setno, side, key, NODEV64, NM_DEVID);
   2517 		if (did_n == NULL) {
   2518 			continue;
   2519 		}
   2520 		did_shr_n = (struct did_shr_name *)lookup_shared_entry(
   2521 		    did_shr_nh, did_n->min_devid_key, (char *)0,
   2522 		    NULL, NM_DEVID);
   2523 		if ((did_shr_n->did_data & NM_DEVID_VALID) != 0) {
   2524 			continue;
   2525 		}
   2526 
   2527 		devt = md_dev64_to_dev(
   2528 		    md_getdevnum(setno, side, key, MD_TRUST_DEVT));
   2529 		get_rc = ddi_lyr_get_devid(devt, &rtn_devid);
   2530 		if (get_rc == DDI_SUCCESS) {
   2531 			compare_rc = ddi_devid_compare(rtn_devid,
   2532 			    (ddi_devid_t)did_shr_n->did_devid);
   2533 			ddi_devid_free(rtn_devid);
   2534 		}
   2535 
   2536 		if ((get_rc == DDI_SUCCESS) && (compare_rc == 0)) {
   2537 			did_shr_n->did_data |= NM_DEVID_VALID;
   2538 		} else {
   2539 			/* device id is invalid */
   2540 			cnt++;
   2541 			n = (struct nm_name *)lookup_entry(
   2542 			    nh, setno, side, key, NODEV64, 0L);
   2543 			if (n == NULL) {
   2544 				rw_exit(&nm_lock.lock);
   2545 				return ((int)NODEV64);
   2546 			}
   2547 			/* update max size if necessary */
   2548 			len = (int)strlen(n->n_name);
   2549 			if (maxsz < len)
   2550 				maxsz = len;
   2551 		}
   2552 	}
   2553 	rw_exit(&nm_lock.lock);
   2554 	*rmaxsz = maxsz;
   2555 	return (cnt);
   2556 }
   2557 
   2558 /*
   2559  * md_getdevname
   2560  *
   2561  * Wrapper for md_getdevname_common()
   2562  */
   2563 int
   2564 md_getdevname(
   2565 	set_t	setno,		/* which set to get name from */
   2566 	side_t	side,		/* (key 1) side number */
   2567 	mdkey_t	key,		/* (key 2) key provided by md_setdevname() */
   2568 	md_dev64_t	dev,	/* (alt. key 2) use this if key == KEYWILD */
   2569 	char	*devname,	/* char array to put device name in */
   2570 	size_t	max_size	/* size of char array */
   2571 )
   2572 {
   2573 	return (md_getdevname_common(setno, side, key, dev, devname,
   2574 	    max_size, MD_WAIT_LOCK));
   2575 }
   2576 
   2577 /*
   2578  * md_getdevname_common
   2579  *		   Allows getting a device name from the database.
   2580  *		   A pointer to a character array is passed in for
   2581  *		   the device name to be built in. Also the max_size
   2582  *		   is the maximum number of characters which can be put
   2583  *		   in the devname[].
   2584  */
   2585 int
   2586 md_getdevname_common(
   2587 	set_t	setno,		/* which set to get name from */
   2588 	side_t	side,		/* (key 1) side number */
   2589 	mdkey_t	key,		/* (key 2) key provided by md_setdevname() */
   2590 	md_dev64_t	dev,	/* (alt. key 2) use this if key == KEYWILD */
   2591 	char	*devname,	/* char array to put device name in */
   2592 	size_t	max_size,	/* size of char array */
   2593 	int	try_lock	/* whether to spin on the namespace lock */
   2594 )
   2595 {
   2596 	struct nm_next_hdr	*nh;
   2597 	struct nm_name		*n;
   2598 	int			err;
   2599 
   2600 	/*
   2601 	 * Load the devid name space if it exists
   2602 	 */
   2603 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   2604 	if (! md_load_namespace(setno, NULL, 0L)) {
   2605 		/*
   2606 		 * Unload the devid namespace
   2607 		 */
   2608 		(void) md_unload_namespace(setno, NM_DEVID);
   2609 		return (ENOENT);
   2610 	}
   2611 
   2612 	if (try_lock) {
   2613 		if (rw_tryenter(&nm_lock.lock, RW_READER) == 0) {
   2614 			/* Cannot obtain the lock without blocking */
   2615 			return (EAGAIN);
   2616 		}
   2617 	} else {
   2618 		rw_enter(&nm_lock.lock, RW_READER);
   2619 	}
   2620 
   2621 	if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) {
   2622 		rw_exit(&nm_lock.lock);
   2623 		return (ENOENT);
   2624 	}
   2625 
   2626 	if ((n = (struct nm_name *)lookup_entry(nh, setno, side, key,
   2627 	    dev, 0L))
   2628 	    == NULL) {
   2629 		rw_exit(&nm_lock.lock);
   2630 		return (ENOENT);
   2631 	}
   2632 
   2633 	err = md_make_devname(n, setno, devname, max_size);
   2634 
   2635 	rw_exit(&nm_lock.lock);
   2636 	return (err);
   2637 }
   2638 
   2639 /*
   2640  * md_gethspinfo -  Getting a hsp name or id from the database.
   2641  *		    A pointer to a character array is passed in for
   2642  *		    the hsp name to be built in. If a match is found,
   2643  *		    the corresponding hspid is stored in ret_hspid.
   2644  */
   2645 int
   2646 md_gethspinfo(
   2647 	set_t	setno,		/* which set to get name from */
   2648 	side_t	side,		/* (key 1) side number */
   2649 	mdkey_t	key,		/* (key 2) key provided by md_setdevname() */
   2650 	char	*drvnm,		/* return driver name here */
   2651 	hsp_t	*ret_hspid,	/* returned key if key is MD_KEYWILD */
   2652 	char	*hspname	/* alternate key or returned device name */
   2653 )
   2654 {
   2655 	struct nm_next_hdr	*nh;
   2656 	struct nm_name		*n;
   2657 	char			*drv_name;
   2658 	int			err = 0;
   2659 	char			*setname = NULL;
   2660 
   2661 	/*
   2662 	 * Load the devid name space if it exists
   2663 	 */
   2664 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   2665 	if (! md_load_namespace(setno, NULL, 0L)) {
   2666 		/*
   2667 		 * Unload the devid namespace
   2668 		 */
   2669 		(void) md_unload_namespace(setno, NM_DEVID);
   2670 		return (ENOENT);
   2671 	}
   2672 
   2673 	rw_enter(&nm_lock.lock, RW_READER);
   2674 
   2675 	if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) {
   2676 		rw_exit(&nm_lock.lock);
   2677 		return (ENOENT);
   2678 	}
   2679 
   2680 	if ((n = (struct nm_name *)lookup_hspentry(nh, setno, side,
   2681 	    key, hspname)) == NULL) {
   2682 		rw_exit(&nm_lock.lock);
   2683 		return (ENOENT);
   2684 	}
   2685 
   2686 	/* Copy the driver name, device name and key for return */
   2687 	drv_name = (char *)getshared_name(setno, n->n_drv_key, 0L);
   2688 	if (!drv_name || (strlen(drv_name) > MD_MAXDRVNM)) {
   2689 		rw_exit(&nm_lock.lock);
   2690 		return (EFAULT);
   2691 	}
   2692 
   2693 	/*
   2694 	 * Pre-friendly hsp names are of the form hspxxx and we
   2695 	 * should not have an entry in the namespace for them.
   2696 	 * So make sure the NM entry we get is a hotspare pool.
   2697 	 */
   2698 	if ((strcmp(drv_name, "md_hotspares")) != 0) {
   2699 		rw_exit(&nm_lock.lock);
   2700 		return (ENOENT);
   2701 	}
   2702 	(void) strcpy(drvnm, drv_name);
   2703 
   2704 	/*
   2705 	 * If the input key is not MD_KEYWILD, return the
   2706 	 * hspname we found.
   2707 	 */
   2708 	if (key != MD_KEYWILD) {
   2709 		setname = mddb_getsetname(setno);
   2710 		if (setname != NULL)
   2711 			(void) snprintf(hspname, MAXPATHLEN,
   2712 			    "%s/%s", setname, n->n_name);
   2713 		else
   2714 			(void) snprintf(hspname, MAXPATHLEN,
   2715 			    "%s", n->n_name);
   2716 	}
   2717 
   2718 	*ret_hspid = KEY_TO_HSP_ID(setno, n->n_key);
   2719 
   2720 	rw_exit(&nm_lock.lock);
   2721 	return (err);
   2722 }
   2723 
   2724 /*
   2725  * md_devid_found  - Check to see if this key has devid entry or not
   2726  *		     Return 1 if there is one or 0 if none
   2727  */
   2728 int
   2729 md_devid_found(
   2730 	set_t	setno,		/* which set to get name from */
   2731 	side_t	side,		/* (key 1) side number */
   2732 	mdkey_t	key		/* key used to find entry in namespace */
   2733 )
   2734 {
   2735 	struct nm_next_hdr	*nh;
   2736 
   2737 	/*
   2738 	 * Load the devid name space if it exists
   2739 	 */
   2740 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   2741 	if (! md_load_namespace(setno, NULL, 0L)) {
   2742 		/*
   2743 		 * Unload the devid namespace
   2744 		 */
   2745 		(void) md_unload_namespace(setno, NM_DEVID);
   2746 		return (0);
   2747 	}
   2748 
   2749 	rw_enter(&nm_lock.lock, RW_READER);
   2750 
   2751 	if ((nh = get_first_record(setno, 0, NM_DEVID| NM_NOTSHARED)) == NULL) {
   2752 		rw_exit(&nm_lock.lock);
   2753 		return (0);
   2754 	}
   2755 
   2756 	/*
   2757 	 * Look up the key
   2758 	 */
   2759 	if (lookup_entry(nh, setno, side, key, NODEV64, NM_DEVID) == NULL) {
   2760 			/* This key not in database */
   2761 			rw_exit(&nm_lock.lock);
   2762 			return (0);
   2763 	}
   2764 
   2765 	rw_exit(&nm_lock.lock);
   2766 	/* found a key */
   2767 	return (1);
   2768 }
   2769 
   2770 
   2771 /*
   2772  * md_getkeyfromdev  - Allows getting a key from the database by using the dev.
   2773  *                     Returns the first key found and the number of keys
   2774  *                     found that match dev.
   2775  */
   2776 int
   2777 md_getkeyfromdev(
   2778 	set_t	setno,		/* which set to get name from */
   2779 	side_t	side,		/* (key 1) side number */
   2780 	md_dev64_t	dev,	/* dev to match against */
   2781 	mdkey_t	*firstkey,	/* ptr for first key found */
   2782 	int	*numkeysmatch	/* ptr to number of keys matching dev */
   2783 )
   2784 {
   2785 	struct nm_next_hdr	*nh;
   2786 	struct nm_name		*n;
   2787 	int			keynum;
   2788 
   2789 	/*
   2790 	 * Load the devid name space if it exists
   2791 	 */
   2792 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   2793 	if (! md_load_namespace(setno, NULL, 0L)) {
   2794 		/*
   2795 		 * Unload the devid namespace
   2796 		 */
   2797 		(void) md_unload_namespace(setno, NM_DEVID);
   2798 		return (ENOENT);
   2799 	}
   2800 
   2801 	rw_enter(&nm_lock.lock, RW_READER);
   2802 
   2803 	if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) {
   2804 		rw_exit(&nm_lock.lock);
   2805 		return (ENOENT);
   2806 	}
   2807 
   2808 	/*
   2809 	 * Walk through all keys in the namespace looking for a match
   2810 	 * against the given dev.  Count the number of matches and
   2811 	 * set firstkey to be first matched key.
   2812 	 */
   2813 	*numkeysmatch = 0;
   2814 	for (keynum = 1; keynum <
   2815 	    ((struct nm_rec_hdr *)nh->nmn_record)->r_next_key; keynum++) {
   2816 		if ((n = (struct nm_name *)lookup_entry(nh, setno, side,
   2817 		    keynum, dev, 0L)) == NULL) {
   2818 			/* This key not in database */
   2819 			continue;
   2820 		} else {
   2821 			/* found a key, look for the dev match */
   2822 			if (dev == build_device_number(setno,
   2823 			    (struct nm_name *)n)) {
   2824 				/* found a dev match */
   2825 				(*numkeysmatch)++;
   2826 				if (*numkeysmatch == 1) {
   2827 					*firstkey = n->n_key;
   2828 				}
   2829 			}
   2830 		}
   2831 	}
   2832 
   2833 	rw_exit(&nm_lock.lock);
   2834 	return (0);
   2835 }
   2836 
   2837 /*
   2838  * md_getnment  - Allows getting a driver name and minor # from the database.
   2839  */
   2840 int
   2841 md_getnment(
   2842 	set_t	setno,		/* which set to get name from */
   2843 	side_t	side,		/* (key 1) side number */
   2844 	mdkey_t	key,		/* (key 2) key provided by md_setdevname() */
   2845 	md_dev64_t dev,
   2846 	char	*drvnm,		/* char array to put driver name in */
   2847 	uint_t	max_size,	/* size of char array */
   2848 	major_t	*major,		/* address for major number */
   2849 	minor_t	*mnum,		/* address for minor number */
   2850 	mdkey_t	*retkey		/* address for returning key */
   2851 )
   2852 {
   2853 	struct nm_next_hdr	*nh;
   2854 	struct nm_name		*n;
   2855 	char			*drv_name;
   2856 
   2857 	/*
   2858 	 * Load the devid name space if it exists
   2859 	 */
   2860 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   2861 	if (! md_load_namespace(setno, NULL, 0L)) {
   2862 		/*
   2863 		 * Unload the devid namespace
   2864 		 */
   2865 		(void) md_unload_namespace(setno, NM_DEVID);
   2866 		return (ENOENT);
   2867 	}
   2868 
   2869 	rw_enter(&nm_lock.lock, RW_READER);
   2870 
   2871 	if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) {
   2872 		rw_exit(&nm_lock.lock);
   2873 		return (ENOENT);
   2874 	}
   2875 
   2876 	if ((n = (struct nm_name *)lookup_entry(nh, setno, side, key,
   2877 	    dev, 0L))
   2878 	    == NULL) {
   2879 		rw_exit(&nm_lock.lock);
   2880 		return (ENOENT);
   2881 	}
   2882 
   2883 	drv_name = (char *)getshared_name(setno, n->n_drv_key, 0L);
   2884 	if (!drv_name || (strlen(drv_name) > max_size)) {
   2885 		rw_exit(&nm_lock.lock);
   2886 		return (EFAULT);
   2887 	}
   2888 
   2889 	/* Copy the driver name, and fill in the minor number */
   2890 	(void) strcpy(drvnm, drv_name);
   2891 	if (MD_UPGRADE)
   2892 		*major = md_targ_name_to_major(drvnm);
   2893 	else
   2894 		*major = ddi_name_to_major(drvnm);
   2895 	*mnum = n->n_minor;
   2896 	*retkey = n->n_key;
   2897 
   2898 	rw_exit(&nm_lock.lock);
   2899 
   2900 	return (0);
   2901 }
   2902 
   2903 /*
   2904  * md_getdevnum  - Allows getting a device number from the database.
   2905  * This routine returns a translated (aka miniroot) md_dev64_t.
   2906  */
   2907 md_dev64_t
   2908 md_getdevnum(
   2909 	set_t	setno,		/* which set to get name from */
   2910 	side_t	side,		/* (key 1) side number */
   2911 	mdkey_t	key,		/* (key 2) key provided by md_setdevname() */
   2912 	int	flag)		/* If set then return devt from namespace */
   2913 {
   2914 	struct nm_next_hdr	*nh, *did_shr_nh, *did_nh = NULL;
   2915 	struct nm_name		*n;
   2916 	struct did_min_name	*did_n;
   2917 	struct did_shr_name	*did_shr_n;
   2918 	md_dev64_t		retval, retval_targ;
   2919 	int			did_found = 0;
   2920 	ddi_devid_t		devid = NULL;
   2921 	int			ndevs;
   2922 	dev_t			*devs;
   2923 	char			*drv, *drvnm, *mname = NULL;
   2924 	mddb_recid_t		recids[3];
   2925 	int			devid_nm = 0;
   2926 
   2927 	/*
   2928 	 * If a MN diskset and this node is the master OR
   2929 	 * if a traditional diskset, then check to see if the
   2930 	 * did namespace should be cleaned up.
   2931 	 *
   2932 	 * Always set MD_SET_DIDCLUP bit in set's status field
   2933 	 * so that this check is only done once.
   2934 	 */
   2935 	if (!(md_get_setstatus(setno) & MD_SET_DIDCLUP)) {
   2936 		if ((MD_MNSET_SETNO(setno) && (md_set[setno].s_am_i_master)) ||
   2937 		    (!(MD_MNSET_SETNO(setno)))) {
   2938 			if (!(((mddb_set_t *)
   2939 			    md_set[setno].s_db)->s_lbp->lb_flags
   2940 			    & MDDB_DEVID_STYLE) || md_devid_destroy) {
   2941 				(void) md_load_namespace(setno, NULL, NM_DEVID);
   2942 				(void) md_devid_cleanup(setno, 1);
   2943 			}
   2944 		}
   2945 		md_set_setstatus(setno, MD_SET_DIDCLUP);
   2946 	}
   2947 
   2948 	/*
   2949 	 * Test the MDDB_DEVID_STYLE bit
   2950 	 */
   2951 	if (((mddb_set_t *)md_set[setno].s_db)->s_lbp->lb_flags
   2952 	    & MDDB_DEVID_STYLE) {
   2953 		(void) md_load_namespace(setno, NULL, NM_DEVID);
   2954 		devid_nm = 1;
   2955 	}
   2956 
   2957 	/*
   2958 	 * Load the primary name space
   2959 	 */
   2960 	if (! md_load_namespace(setno, NULL, 0L)) {
   2961 		/*
   2962 		 * Unload the devid namespace
   2963 		 */
   2964 		(void) md_unload_namespace(setno, NM_DEVID);
   2965 		return (NODEV64);
   2966 	}
   2967 
   2968 	rw_enter(&nm_lock.lock, RW_READER);
   2969 
   2970 
   2971 	/*
   2972 	 * If not even in the primary name space, bail out
   2973 	 */
   2974 	if (((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) ||
   2975 	    ((n = (struct nm_name *)lookup_entry(nh, setno, side, key,
   2976 	    NODEV64, 0L)) == NULL)) {
   2977 		rw_exit(&nm_lock.lock);
   2978 		return (NODEV64);
   2979 	}
   2980 
   2981 	/*
   2982 	 * Entry corresponds to this key is referenced and snarfed so
   2983 	 * we set the value to 1.  During the name space cleanup we will check
   2984 	 * this value and if it is set then we know it is part of the
   2985 	 * current configuration.  For any 'key' whose value is not set
   2986 	 * then we know it is an 'orphan' entry and will be removed.
   2987 	 */
   2988 	if (md_nm_snarfed)
   2989 		md_nm_snarfed[key] = 1;
   2990 
   2991 	/*
   2992 	 * Reference the device id namespace
   2993 	 */
   2994 	if (devid_nm) {
   2995 		if (((did_nh = get_first_record(setno, 1, NM_DEVID |
   2996 		    NM_NOTSHARED)) == NULL) || ((did_shr_nh =
   2997 		    get_first_record(setno, 1, NM_DEVID | NM_SHARED))
   2998 		    == NULL)) {
   2999 			devid_nm = 0;
   3000 		}
   3001 	}
   3002 
   3003 	/*
   3004 	 * If the key is in the device id name space then
   3005 	 * this device has disk tracking info stored
   3006 	 */
   3007 	if (devid_nm && ((did_n = (struct did_min_name *)lookup_entry(did_nh,
   3008 	    setno, side, key, NODEV64, NM_DEVID)) != NULL)) {
   3009 		/*
   3010 		 * Get the minor name and the device id
   3011 		 */
   3012 		devid = (ddi_devid_t)getshared_name(setno,
   3013 		    did_n->min_devid_key, NM_DEVID);
   3014 
   3015 		did_shr_n = (struct did_shr_name *)lookup_shared_entry(
   3016 		    did_shr_nh, did_n->min_devid_key,
   3017 		    (char *)0, NULL, NM_DEVID);
   3018 
   3019 		if ((devid == NULL) || (did_shr_n == NULL)) {
   3020 			rw_exit(&nm_lock.lock);
   3021 			return (NODEV64);
   3022 		}
   3023 
   3024 
   3025 		if (ddi_lyr_devid_to_devlist(devid, did_n->min_name, &ndevs,
   3026 		    &devs) == DDI_SUCCESS) {
   3027 
   3028 			md_dev64_t tdev;
   3029 			int cnt;
   3030 
   3031 			did_found = 1;
   3032 
   3033 			/*
   3034 			 * Save the first available devt
   3035 			 * During upgrade, this is a miniroot devt.
   3036 			 */
   3037 
   3038 			retval = md_expldev(devs[0]);
   3039 
   3040 			/*
   3041 			 * For a multipath device more than 1 md_dev64_t will
   3042 			 * occur. In this case retval will be set to
   3043 			 * the md_dev64_t that was previously set.
   3044 			 */
   3045 
   3046 			if (ndevs > 1) {
   3047 
   3048 				/* get the stored md_dev64_t */
   3049 				tdev = build_device_number(setno, n);
   3050 				for (cnt = 0; cnt < ndevs; cnt++) {
   3051 					if (tdev == md_expldev(devs[cnt])) {
   3052 						retval = tdev;
   3053 						break;
   3054 					}
   3055 				}
   3056 			}
   3057 
   3058 			/*
   3059 			 * If during upgrade, switch drvnm to be target
   3060 			 * device's name, not miniroot's name.
   3061 			 */
   3062 			if (MD_UPGRADE)
   3063 				drvnm = md_targ_major_to_name(md_getmajor
   3064 				    (md_xlate_mini_2_targ(retval)));
   3065 			else
   3066 				drvnm = ddi_major_to_name(
   3067 				    md_getmajor(retval));
   3068 
   3069 			/*
   3070 			 * It is a valid device id
   3071 			 */
   3072 			did_shr_n->did_data = NM_DEVID_VALID;
   3073 
   3074 			/*
   3075 			 * Free the memory
   3076 			 */
   3077 			(void) ddi_lyr_free_devlist(devs, ndevs);
   3078 		} else {
   3079 			/*
   3080 			 * Invalid device id, say so
   3081 			 * and check flag to see if we can return
   3082 			 * devt stored in the namespace
   3083 			 */
   3084 			did_shr_n->did_data = NM_DEVID_INVALID;
   3085 			rw_exit(&nm_lock.lock);
   3086 
   3087 			/*
   3088 			 * If flag does not have MD_TRUST_DEVT bit on
   3089 			 * then with the invalid device id we simply cant
   3090 			 * trust the devt in the namespace at all
   3091 			 *
   3092 			 * Bit MD_TRUST_DEVT is set by metadevadm or
   3093 			 * when a diskset is taken and it does not have
   3094 			 * any associated devid records for the drive
   3095 			 * records in the set.
   3096 			 *
   3097 			 * When this bit is set that means devt can be
   3098 			 * trusted and we just go ahead do whatever user
   3099 			 * ask for
   3100 			 */
   3101 			if (!(flag & MD_TRUST_DEVT))
   3102 				return (NODEV64);
   3103 
   3104 			/* build_device_number returns a target devt */
   3105 			retval_targ = build_device_number(setno, n);
   3106 			/* translate devt to miniroot devt */
   3107 			if ((retval = md_xlate_targ_2_mini(retval_targ))
   3108 			    == NODEV64) {
   3109 				return (NODEV64);
   3110 			}
   3111 			return (retval);
   3112 		}
   3113 	}
   3114 
   3115 
   3116 	/*
   3117 	 * If no entry is found in the device id name space
   3118 	 * It can be one of:
   3119 	 *	underlying meta device
   3120 	 *	No device id associated
   3121 	 *	Has a device id but mddb is in the old fromat
   3122 	 */
   3123 	if (did_found) {
   3124 		/*
   3125 		 * Update the name entry if necessary
   3126 		 */
   3127 		if ((retval_targ = md_xlate_mini_2_targ(retval)) == NODEV64) {
   3128 			rw_exit(&nm_lock.lock);
   3129 			return (NODEV64);
   3130 		}
   3131 
   3132 		if (n->n_minor != md_getminor(retval_targ))
   3133 			n->n_minor = md_getminor(retval_targ);
   3134 
   3135 		if ((drv =
   3136 		    (char *)getshared_name(setno, n->n_drv_key, 0L)) == NULL) {
   3137 			rw_exit(&nm_lock.lock);
   3138 			return (NODEV64);
   3139 		}
   3140 
   3141 		if (strcmp(drv, drvnm) != 0)
   3142 			n->n_drv_key = setshared_name(setno, drvnm,
   3143 			    MD_KEYWILD, 0L);
   3144 
   3145 		if (!(md_get_setstatus(setno) & MD_SET_STALE))
   3146 			(void) update_entry(nh, side, key, 0L);
   3147 	} else {
   3148 		/*
   3149 		 * Has a device id associated with it?
   3150 		 * If yes, then we will try to add them into the device id nm
   3151 		 * build_device_number returns a target devt.
   3152 		 */
   3153 		if ((retval_targ = build_device_number(setno, n)) == NODEV64) {
   3154 			rw_exit(&nm_lock.lock);
   3155 			return (NODEV64);
   3156 		}
   3157 
   3158 		/*
   3159 		 * We don't translate the devt of the meta device
   3160 		 * and currently no device id associated with metadevice
   3161 		 */
   3162 		if (md_getmajor(retval_targ) != md_major_targ) {
   3163 
   3164 			if ((retval = md_xlate_targ_2_mini(retval_targ))
   3165 			    == NODEV64) {
   3166 				rw_exit(&nm_lock.lock);
   3167 				return (NODEV64);
   3168 			}
   3169 
   3170 			/*
   3171 			 * Add the device id info only if
   3172 			 * MDDB_DEVID_STYLE bit is set
   3173 			 *
   3174 			 */
   3175 			if (!devid_nm) {
   3176 				rw_exit(&nm_lock.lock);
   3177 				return (retval);
   3178 			}
   3179 
   3180 			/*
   3181 			 * We can continue if we are here
   3182 			 * If retval has a device id, add them
   3183 			 */
   3184 			if ((ddi_lyr_get_devid(md_dev64_to_dev(retval), &devid)
   3185 			    == DDI_SUCCESS) &&
   3186 			    (ddi_lyr_get_minor_name(md_dev64_to_dev(retval),
   3187 			    S_IFBLK, &mname)
   3188 			    == DDI_SUCCESS)) {
   3189 				/*
   3190 				 * Add them into the devid name space
   3191 				 */
   3192 				did_n = (struct did_min_name *)alloc_entry(
   3193 				    did_nh, md_set[setno].s_did_nmid,
   3194 				    strlen(mname)+1, NM_DEVID|NM_NOTSHARED,
   3195 				    &recids[0]);
   3196 
   3197 				if (did_n) {
   3198 					did_n->min_side = side;
   3199 					did_n->min_key = key;
   3200 					did_n->min_count = 1;
   3201 					(void) strcpy(did_n->min_name, mname);
   3202 					did_n->min_namlen =
   3203 					    (ushort_t)(strlen(mname)+1);
   3204 					did_n->min_devid_key =
   3205 					    setshared_name(setno,
   3206 					    (char *)devid, MD_KEYWILD,
   3207 					    NM_DEVID);
   3208 					/*
   3209 					 * Commit the change to the record
   3210 					 */
   3211 					if (did_n->min_devid_key == MD_KEYBAD) {
   3212 						(void) remove_entry(did_nh,
   3213 						    did_n->min_side,
   3214 						    did_n->min_key,
   3215 						    NM_DEVID);
   3216 					} else {
   3217 						recids[1] =
   3218 						    md_set[setno].s_did_nmid;
   3219 						recids[2] = 0;
   3220 						mddb_commitrecs_wrapper(recids);
   3221 					}
   3222 				}
   3223 			}
   3224 			/*
   3225 			 * Free all the memory
   3226 			 */
   3227 			if (devid)
   3228 				ddi_devid_free(devid);
   3229 			if (mname)
   3230 				kmem_free(mname, strlen(mname) + 1);
   3231 		} else {
   3232 			retval = md_makedevice(md_major,
   3233 			    md_getminor(retval_targ));
   3234 		}
   3235 	}
   3236 
   3237 	rw_exit(&nm_lock.lock);
   3238 	return (retval);
   3239 }
   3240 
   3241 /*
   3242  * md_getnextkey  - Allows running thru the list of defined device names.
   3243  */
   3244 mdkey_t
   3245 md_getnextkey(
   3246 	set_t	setno,		/* which set to get name from */
   3247 	side_t	side,		/* (key 1) side number */
   3248 	mdkey_t	key,		/* (key 2) wildcarded or from md_getnextkey() */
   3249 	uint_t	*cnt)		/* n_count returns here */
   3250 {
   3251 	struct nm_next_hdr	*nh;
   3252 	struct nm_name		*n = NULL;
   3253 	mdkey_t			retval = MD_KEYWILD;
   3254 
   3255 
   3256 	/*
   3257 	 * Load the devid name space if it exists
   3258 	 */
   3259 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   3260 	if (! md_load_namespace(setno, NULL, 0L)) {
   3261 		/*
   3262 		 * Unload the devid namespace
   3263 		 */
   3264 		(void) md_unload_namespace(setno, NM_DEVID);
   3265 		return (MD_KEYWILD);
   3266 	}
   3267 
   3268 	rw_enter(&nm_lock.lock, RW_READER);
   3269 
   3270 	if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) {
   3271 		rw_exit(&nm_lock.lock);
   3272 		return (MD_KEYWILD);
   3273 	}
   3274 
   3275 	for (key++; key < ((struct nm_rec_hdr *)nh->nmn_record)->r_next_key;
   3276 	    key++) {
   3277 		if ((n = (struct nm_name *)lookup_entry(nh, setno, side, key,
   3278 		    NODEV64, 0L)) != NULL)
   3279 			break;
   3280 	}
   3281 
   3282 	if (n != NULL) {
   3283 		if (cnt != NULL)
   3284 			*cnt = n->n_count;
   3285 
   3286 		retval = n->n_key;
   3287 	}
   3288 
   3289 	rw_exit(&nm_lock.lock);
   3290 	return (retval);
   3291 }
   3292 
   3293 /*
   3294  * md_update_namespace_did - update the devid portion of the namespace
   3295  */
   3296 int
   3297 md_update_namespace_did(
   3298 	set_t		setno,
   3299 	side_t		side,
   3300 	mdkey_t		key,
   3301 	md_error_t	*ep
   3302 )
   3303 {
   3304 	dev_t			devt;
   3305 	ddi_devid_t		rtn_devid = NULL;
   3306 	ddi_devid_t		devid = NULL;
   3307 	struct nm_next_hdr	*did_shr_nh;
   3308 	mdkey_t			ent_did_key;
   3309 	uint32_t		ent_did_count;
   3310 	uint32_t		ent_did_data;
   3311 	void			*record, *n_record;
   3312 	size_t			offset;
   3313 	struct did_shr_name	*shn;
   3314 	mddb_recid_t		recids[3];
   3315 	struct nm_next_hdr	*nh;
   3316 	struct nm_next_hdr	*this_did_nh;
   3317 	struct did_min_name	*n;
   3318 	struct did_shr_name	*shr_n;
   3319 	mdkey_t			devid_key;
   3320 	size_t			ent_size, size;
   3321 
   3322 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   3323 	if (!md_load_namespace(setno, NULL, 0L)) {
   3324 		(void) md_unload_namespace(setno, NM_DEVID);
   3325 		return ((int)NODEV64);
   3326 	}
   3327 	rw_enter(&nm_lock.lock, RW_WRITER);
   3328 
   3329 	offset = (sizeof (struct devid_shr_rec) - sizeof (struct did_shr_name));
   3330 	if ((nh = get_first_record(setno, 0, NM_DEVID | NM_NOTSHARED)) ==
   3331 	    NULL) {
   3332 		rw_exit(&nm_lock.lock);
   3333 		return (ENOENT);
   3334 	}
   3335 
   3336 	this_did_nh = nh->nmn_nextp;
   3337 	if (this_did_nh  == NULL) {
   3338 		rw_exit(&nm_lock.lock);
   3339 		return (ENOENT);
   3340 	}
   3341 	record = this_did_nh->nmn_record;
   3342 	if (record == NULL) {
   3343 		rw_exit(&nm_lock.lock);
   3344 		return (ENOENT);
   3345 	}
   3346 
   3347 	if ((n = (struct did_min_name *)lookup_entry(nh, setno, side, key,
   3348 	    NODEV64, NM_DEVID)) == NULL) {
   3349 		rw_exit(&nm_lock.lock);
   3350 		return (ENOENT);
   3351 	}
   3352 	devid_key = n->min_devid_key;
   3353 	rw_exit(&nm_lock.lock);
   3354 
   3355 	devt = md_dev64_to_dev(
   3356 	    md_getdevnum(setno, side, key, MD_TRUST_DEVT));
   3357 
   3358 	rw_enter(&nm_lock.lock, RW_WRITER);
   3359 	if (ddi_lyr_get_devid(devt, &rtn_devid) == DDI_SUCCESS) {
   3360 		did_shr_nh = get_first_record(setno, 0, NM_DEVID | NM_SHARED);
   3361 		if (did_shr_nh == NULL) {
   3362 			ddi_devid_free(rtn_devid);
   3363 			rw_exit(&nm_lock.lock);
   3364 			return ((int)NODEV64);
   3365 		}
   3366 
   3367 		n_record = did_shr_nh->nmn_nextp->nmn_record;
   3368 
   3369 		shr_n = (struct did_shr_name *)
   3370 		    lookup_shared_entry_record_offset(did_shr_nh, devid_key,
   3371 		    (char *)0, &recids[0], NM_DEVID, n_record, &offset);
   3372 
   3373 		if (shr_n == NULL) {
   3374 			ddi_devid_free(rtn_devid);
   3375 			rw_exit(&nm_lock.lock);
   3376 			return (ENOENT);
   3377 		}
   3378 
   3379 		devid = (ddi_devid_t)shr_n->did_devid;
   3380 		if (ddi_devid_compare(rtn_devid, devid) != 0) {
   3381 			/* remove old devid info */
   3382 			ent_did_key = shr_n->did_key;
   3383 			ent_did_count = shr_n->did_count;
   3384 			ent_did_data = shr_n->did_data;
   3385 			ent_size = DID_SHR_NAMSIZ(shr_n);
   3386 
   3387 			/*
   3388 			 * So we're going to overwrite this record; if it's the
   3389 			 * last entry, just bzero() it. If it's not, then copy
   3390 			 * the remaining entries back to the start of our entry
   3391 			 */
   3392 
   3393 			size = ((struct nm_rec_hdr *)n_record)->r_used_size
   3394 			    - offset - ent_size;
   3395 
   3396 			ASSERT(size + offset <= ((struct nm_rec_hdr *)
   3397 			    n_record)->r_used_size);
   3398 
   3399 			if (size == 0) {
   3400 				(void) bzero(shr_n, ent_size);
   3401 			} else {
   3402 				(void) ovbcopy((caddr_t)shr_n + ent_size, shr_n,
   3403 				    size);
   3404 				(void) bzero((caddr_t)shr_n + size, ent_size);
   3405 			}
   3406 			((struct nm_rec_hdr *)n_record)->r_used_size -=
   3407 			    ent_size;
   3408 			/* add in new devid info */
   3409 			if ((shn = (struct did_shr_name *)alloc_entry(
   3410 			    did_shr_nh, md_set[setno].s_did_nmid,
   3411 			    ddi_devid_sizeof(rtn_devid),
   3412 			    NM_DEVID | NM_SHARED | NM_NOCOMMIT,
   3413 			    &recids[0])) == NULL) {
   3414 				ddi_devid_free(rtn_devid);
   3415 				rw_exit(&nm_lock.lock);
   3416 				return (ENOMEM);
   3417 			}
   3418 			shn->did_key = ent_did_key;
   3419 			shn->did_count = ent_did_count;
   3420 			ent_did_data |= NM_DEVID_VALID;
   3421 			shn->did_data = ent_did_data;
   3422 			shn->did_size = ddi_devid_sizeof(rtn_devid);
   3423 			bcopy((void *)rtn_devid, (void *)shn->did_devid,
   3424 			    shn->did_size);
   3425 			recids[1] = md_set[setno].s_nmid;
   3426 			recids[2] = 0;
   3427 
   3428 			mddb_commitrecs_wrapper(recids);
   3429 		}
   3430 		ddi_devid_free(rtn_devid);
   3431 	} else {
   3432 		rw_exit(&nm_lock.lock);
   3433 		(void) mderror(ep, MDE_NODEVID);
   3434 		return (ENOENT);
   3435 	}
   3436 	rw_exit(&nm_lock.lock);
   3437 	return (0);
   3438 }
   3439 
   3440 /*
   3441  * md_update_namespace - update namespace device name and pathname
   3442  *
   3443  */
   3444 
   3445 int
   3446 md_update_namespace(
   3447 	set_t	setno,		/* which set to get name from */
   3448 	side_t	side,		/* (key 1) side number */
   3449 	mdkey_t	key,		/* (key 2) key provided by md_setdevname() */
   3450 	char	*devname,	/* device name */
   3451 	char	*pathname,	/* pathname to device */
   3452 	minor_t	mnum		/* minor numer */
   3453 )
   3454 {
   3455 	struct nm_next_hdr	*nh;
   3456 	struct nm_name		*n;
   3457 	struct nm_next_hdr	*snh;
   3458 	struct nm_shared_name	*shn;
   3459 	void			*n_record;
   3460 	mddb_recid_t		recids[3];
   3461 	size_t			size;
   3462 	mdkey_t			ent_key, ent_drv_key, ent_dir_key, new_dir_key;
   3463 	uint32_t		ent_count;
   3464 	side_t			ent_side;
   3465 	size_t			offset;
   3466 	char			*old_pathname;
   3467 	int			ent_size;
   3468 
   3469 	if (!md_load_namespace(setno, NULL, 0L)) {
   3470 		return (ENOENT);
   3471 	}
   3472 
   3473 	rw_enter(&nm_lock.lock, RW_WRITER);
   3474 
   3475 	offset = sizeof (struct nm_rec) - sizeof (struct nm_name);
   3476 	if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) {
   3477 		rw_exit(&nm_lock.lock);
   3478 		return (ENOENT);
   3479 	}
   3480 
   3481 	n_record = nh->nmn_nextp->nmn_record;
   3482 
   3483 	if ((n = (struct nm_name *)lookup_entry_record_offset(nh, setno, side,
   3484 	    key, NODEV64, 0L, n_record, &offset)) == NULL) {
   3485 		rw_exit(&nm_lock.lock);
   3486 		return (ENOENT);
   3487 	}
   3488 
   3489 	/* save the values from the old record */
   3490 	ent_side = n->n_side;
   3491 	ent_key = n->n_key;
   3492 	ent_count = n->n_count;
   3493 	ent_drv_key = n->n_drv_key;
   3494 	ent_dir_key = n->n_dir_key;
   3495 	ent_size = NAMSIZ(n);
   3496 
   3497 	/*
   3498 	 * So we're going to overwrite this record; if it's the last
   3499 	 * entry, just bzero() it. If it's not, then copy the
   3500 	 * remaining entries back to the start of our entry
   3501 	 */
   3502 
   3503 	size = ((struct nm_rec_hdr *)n_record)->r_used_size - offset - ent_size;
   3504 
   3505 	ASSERT(offset + size <= ((struct nm_rec_hdr *)n_record)->r_alloc_size);
   3506 
   3507 	if (size == 0) {
   3508 		(void) bzero(n, ent_size);    /* last entry */
   3509 	} else {
   3510 		(void) ovbcopy((caddr_t)n + ent_size, n, size);
   3511 		(void) bzero((caddr_t)n + size, ent_size);
   3512 	}
   3513 	((struct nm_rec_hdr *)n_record)->r_used_size -= ent_size;
   3514 
   3515 	rw_exit(&nm_lock.lock);
   3516 	/* check to see if we have a new pathname */
   3517 	old_pathname = md_getshared_name(setno, ent_dir_key);
   3518 	if (strcmp(old_pathname, pathname)) {
   3519 		/* now see if the new pathname actually exists in our nsp */
   3520 		if ((snh = get_first_record(setno, 0, NM_SHARED)) == NULL)
   3521 			return (ENOENT);
   3522 		shn = (struct nm_shared_name *)lookup_shared_entry(
   3523 		    snh, NULL, pathname, &recids[0], 0L);
   3524 		if (shn) {
   3525 			/* pathname exists so get it's key */
   3526 			new_dir_key = shn->sn_key;
   3527 		} else {
   3528 			/* pathname doesn't exist so create it */
   3529 			new_dir_key =
   3530 			    md_setshared_name(setno, pathname, NM_NOCOMMIT);
   3531 		}
   3532 		/* update dir key */
   3533 		ent_dir_key = new_dir_key;
   3534 	}
   3535 
   3536 	rw_enter(&nm_lock.lock, RW_WRITER);
   3537 	/* Create a name entry */
   3538 	n = (struct nm_name *)alloc_entry(nh, md_set[setno].s_nmid,
   3539 	    strlen(devname)+1, NM_NOTSHARED | NM_NOCOMMIT, &recids[0]);
   3540 
   3541 	if (n == NULL) {
   3542 		rw_exit(&nm_lock.lock);
   3543 		return (ENOMEM);
   3544 	}
   3545 
   3546 	n->n_minor = mnum;
   3547 	n->n_side = ent_side;
   3548 	n->n_key = ent_key;
   3549 	n->n_count = ent_count;
   3550 	n->n_drv_key = ent_drv_key;
   3551 
   3552 	/* fill-in filename */
   3553 	(void) strcpy(n->n_name, devname);
   3554 	n->n_namlen = (ushort_t)(strlen(devname) + 1);
   3555 
   3556 	/* directory name */
   3557 	n->n_dir_key = ent_dir_key;
   3558 
   3559 	recids[1] = md_set[setno].s_nmid;
   3560 	recids[2] = 0;
   3561 
   3562 	mddb_commitrecs_wrapper(recids);
   3563 
   3564 	rw_exit(&nm_lock.lock);
   3565 	return (0);
   3566 }
   3567 
   3568 /*
   3569  * md_getdevidminor - Get the minor name from the database. The minor
   3570  *		      name and the devid id uniquely identify the disk
   3571  *		      slice.
   3572  */
   3573 int
   3574 md_getdevidminor(
   3575 	set_t	setno,
   3576 	side_t	side,
   3577 	mdkey_t	key,
   3578 	char	*minorname,
   3579 	size_t	max_size
   3580 )
   3581 {
   3582 	struct nm_next_hdr	*nh;
   3583 	struct did_min_name	*n;
   3584 
   3585 	/*
   3586 	 * Load the devid name space if it exists
   3587 	 */
   3588 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   3589 	if (! md_load_namespace(setno, NULL, 0L)) {
   3590 		/*
   3591 		 * Unload the devid namespace
   3592 		 */
   3593 		(void) md_unload_namespace(setno, NM_DEVID);
   3594 		return (ENOENT);
   3595 	}
   3596 
   3597 	rw_enter(&nm_lock.lock, RW_READER);
   3598 
   3599 	/*
   3600 	 * The key we have is for the non-shared, regular namespace.  We
   3601 	 * have to lookup the min_key in the non-shared, devid namespace.
   3602 	 */
   3603 	if ((nh = get_first_record(setno, 0, NM_DEVID | NM_NOTSHARED))
   3604 	    == NULL) {
   3605 		rw_exit(&nm_lock.lock);
   3606 		return (ENOENT);
   3607 	}
   3608 
   3609 	if ((n = (struct did_min_name *)lookup_entry(nh, setno, side, key,
   3610 	    NODEV64, NM_DEVID)) == NULL) {
   3611 		rw_exit(&nm_lock.lock);
   3612 		return (ENOENT);
   3613 	}
   3614 
   3615 	if (n->min_namlen > max_size) {
   3616 		rw_exit(&nm_lock.lock);
   3617 		return (EFAULT);
   3618 	}
   3619 
   3620 	bcopy(&((struct did_min_name *)n)->min_name[0], minorname,
   3621 	    n->min_namlen);
   3622 
   3623 	rw_exit(&nm_lock.lock);
   3624 	return (0);
   3625 }
   3626 
   3627 /*
   3628  * md_getdevid -   Allows getting a device id from the database.
   3629  *		   A pointer to a character array is passed in for
   3630  *		   the device id to be copied to.  The size is returned
   3631  *		   in *did_size.
   3632  */
   3633 int
   3634 md_getdevid(
   3635 	set_t	setno,		/* which set to get name from */
   3636 	side_t	side,
   3637 	mdkey_t	key,		/* (key 2) key provided by md_setdevname() */
   3638 	ddi_devid_t	did,		/* pointer to did string */
   3639 	ushort_t	*did_size	/* pointer to size of did string */
   3640 )
   3641 {
   3642 	struct nm_next_hdr	*nh;
   3643 	void			*n;
   3644 	mddb_recid_t		recid;
   3645 
   3646 	/*
   3647 	 * Load the devid name space if it exists
   3648 	 */
   3649 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   3650 	if (! md_load_namespace(setno, NULL, 0L)) {
   3651 		/*
   3652 		 * Unload the devid namespace
   3653 		 */
   3654 		(void) md_unload_namespace(setno, NM_DEVID);
   3655 		return (ENOENT);
   3656 	}
   3657 
   3658 	rw_enter(&nm_lock.lock, RW_READER);
   3659 
   3660 	/*
   3661 	 * The key we have is for the non-shared, regular namespace.  We
   3662 	 * have to lookup the min_key in the non-shared, devid namespace.
   3663 	 */
   3664 	if ((nh = get_first_record(setno, 0, NM_DEVID | NM_NOTSHARED))
   3665 	    == NULL) {
   3666 		rw_exit(&nm_lock.lock);
   3667 		return (ENOENT);
   3668 	}
   3669 
   3670 	if ((n = (struct did_min_name *)lookup_entry(nh, setno, side, key,
   3671 	    NODEV64, NM_DEVID)) == NULL) {
   3672 		rw_exit(&nm_lock.lock);
   3673 		return (ENOENT);
   3674 	}
   3675 
   3676 	/*
   3677 	 * Now go get the devid.
   3678 	 */
   3679 	if ((nh = get_first_record(setno, 0, NM_DEVID | NM_SHARED)) == NULL) {
   3680 		rw_exit(&nm_lock.lock);
   3681 		return (ENOENT);
   3682 	}
   3683 
   3684 	if ((n = (struct did_shr_name *)lookup_shared_entry(nh,
   3685 	    ((struct did_min_name *)n)->min_devid_key, (char *)0, &recid,
   3686 	    NM_DEVID)) == NULL) {
   3687 		rw_exit(&nm_lock.lock);
   3688 		return (ENOENT);
   3689 	}
   3690 
   3691 	/*
   3692 	 * If did is non-zero then copy devid to buffer, else return
   3693 	 * devid size to user.  These are exclusive operations.
   3694 	 */
   3695 	if (did != NULL) {
   3696 		bcopy(&((struct did_shr_name *)n)->did_devid[0], did,
   3697 		    *did_size);
   3698 	} else {
   3699 		*did_size = ((struct did_shr_name *)n)->did_size;
   3700 	}
   3701 
   3702 	rw_exit(&nm_lock.lock);
   3703 	return (0);
   3704 }
   3705 
   3706 /*
   3707  * md_remdevname - Allows removing a device name from the database.
   3708  */
   3709 int
   3710 md_remdevname(
   3711 	set_t			setno,
   3712 	side_t			side,
   3713 	mdkey_t			key
   3714 )
   3715 {
   3716 	struct nm_next_hdr	*nh, *did_nh;
   3717 	struct nm_next_hdr	*shared_nh, *did_shr_nh;
   3718 	struct nm_name		*n;
   3719 	struct did_min_name	*did_n = NULL;
   3720 	mdkey_t			drv_key, dir_key, did_key;
   3721 	int			err;
   3722 
   3723 
   3724 	/*
   3725 	 * Load the devid name space if it exists
   3726 	 */
   3727 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   3728 	if (! md_load_namespace(setno, NULL, 0L)) {
   3729 		/*
   3730 		 * Unload the devid namespace
   3731 		 */
   3732 		(void) md_unload_namespace(setno, NM_DEVID);
   3733 		return (ENOENT);
   3734 	}
   3735 
   3736 	rw_enter(&nm_lock.lock, RW_WRITER);
   3737 
   3738 	if (((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) ||
   3739 	    ((shared_nh = get_first_record(setno, 0, NM_SHARED)) == NULL)) {
   3740 		rw_exit(&nm_lock.lock);
   3741 		return (ENOENT);
   3742 	}
   3743 
   3744 	/*
   3745 	 * If it is not in the primary name space, nothing to remove
   3746 	 */
   3747 	if ((n = (struct nm_name *)lookup_entry(nh, setno, side, key, NODEV64,
   3748 	    0L)) == NULL) {
   3749 		rw_exit(&nm_lock.lock);
   3750 		return (ENOENT);
   3751 	}
   3752 
   3753 	/*
   3754 	 * If there is non-empty device id name space
   3755 	 * Try to locate the entry
   3756 	 */
   3757 	if (md_set[setno].s_did_nm &&
   3758 	    ((did_nh = get_first_record(setno, 0, NM_DEVID | NM_NOTSHARED))
   3759 	    != NULL) &&
   3760 	    ((did_shr_nh = get_first_record(setno, 0, NM_DEVID | NM_SHARED))
   3761 	    != NULL)) {
   3762 		did_n = (struct did_min_name *)lookup_entry(did_nh, setno,
   3763 		    side, key, NODEV64, NM_DEVID);
   3764 	}
   3765 
   3766 	n->n_count--;
   3767 	if (n->n_count) {
   3768 
   3769 		err = update_entry(nh, side, key, 0L);
   3770 		/*
   3771 		 * Update the device id namespace as well
   3772 		 */
   3773 		if (did_n) {
   3774 			did_n->min_count--;
   3775 			(void) update_entry(did_nh, side, key, NM_DEVID);
   3776 		}
   3777 
   3778 		rw_exit(&nm_lock.lock);
   3779 		return (err);
   3780 	}
   3781 
   3782 	/* reference count is zero, actually remove the name entry */
   3783 	drv_key = n->n_drv_key;
   3784 	dir_key = n->n_dir_key;
   3785 	did_key = (did_n ? did_n->min_devid_key : 0);
   3786 
   3787 	if (remove_entry(nh, side, key, 0L)) {
   3788 		rw_exit(&nm_lock.lock);
   3789 		return (EINVAL);
   3790 	}
   3791 
   3792 	if (remove_shared_entry(shared_nh, drv_key, (char *)0, 0L) ||
   3793 	    remove_shared_entry(shared_nh, dir_key, (char *)0, 0L)) {
   3794 		rw_exit(&nm_lock.lock);
   3795 		return (EINVAL);
   3796 	}
   3797 
   3798 	/*
   3799 	 * Remove from the device id name space
   3800 	 */
   3801 	if (did_n) {
   3802 		if (remove_entry(did_nh, side, key, NM_DEVID)) {
   3803 			rw_exit(&nm_lock.lock);
   3804 			return (EINVAL);
   3805 		}
   3806 
   3807 		if (remove_shared_entry(did_shr_nh, did_key, (char *)0,
   3808 		    NM_DEVID)) {
   3809 			rw_exit(&nm_lock.lock);
   3810 			return (EINVAL);
   3811 		}
   3812 	}
   3813 
   3814 	rw_exit(&nm_lock.lock);
   3815 	return (0);
   3816 }
   3817 
   3818 /*
   3819  * md_setshared_name -  Puts a name into the shared namespace database, and
   3820  *			returns a key (used to get the string back).
   3821  *			If the name does not already exist in the namespace
   3822  *			then it will be added and the reference count will
   3823  *			be set to one;
   3824  *			Otherwise the reference count is incremented.
   3825  */
   3826 mdkey_t
   3827 md_setshared_name(set_t setno, char *shrname, int nocommit)
   3828 {
   3829 	mdkey_t	key;
   3830 
   3831 
   3832 	/*
   3833 	 * Load the devid name space if it exists
   3834 	 */
   3835 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   3836 	if (! md_load_namespace(setno, NULL, 0L)) {
   3837 		/*
   3838 		 * Unload the devid namespace
   3839 		 */
   3840 		(void) md_unload_namespace(setno, NM_DEVID);
   3841 		return (MD_KEYBAD);
   3842 	}
   3843 
   3844 	rw_enter(&nm_lock.lock, RW_WRITER);
   3845 
   3846 	key = setshared_name(setno, shrname, MD_KEYWILD, nocommit);
   3847 
   3848 	rw_exit(&nm_lock.lock);
   3849 	return (key);
   3850 }
   3851 
   3852 
   3853 /*
   3854  * md_getshared_name -	Allows converting a key, into the shared namespace
   3855  *			database, to the string which it represents.
   3856  */
   3857 char *
   3858 md_getshared_name(set_t setno, mdkey_t shrkey)
   3859 {
   3860 	char	*string;
   3861 
   3862 
   3863 	/*
   3864 	 * Load the devid name space if it exists
   3865 	 */
   3866 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   3867 	if (! md_load_namespace(setno, NULL, 0L)) {
   3868 		/*
   3869 		 * Unload the devid namespace
   3870 		 */
   3871 		(void) md_unload_namespace(setno, NM_DEVID);
   3872 		return ((char *)0);
   3873 	}
   3874 
   3875 	rw_enter(&nm_lock.lock, RW_READER);
   3876 	string = (char *)getshared_name(setno, shrkey, 0L);
   3877 	rw_exit(&nm_lock.lock);
   3878 
   3879 	return (string);
   3880 }
   3881 
   3882 /*
   3883  * md_remshared_name - Allows removing of shared name by key.
   3884  */
   3885 int
   3886 md_remshared_name(set_t setno, mdkey_t shrkey)
   3887 {
   3888 	struct nm_next_hdr	*nh;
   3889 
   3890 
   3891 	/*
   3892 	 * Load the devid name space if it exists
   3893 	 */
   3894 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   3895 	if (! md_load_namespace(setno, NULL, 0L)) {
   3896 		/*
   3897 		 * Unload the devid namespace
   3898 		 */
   3899 		(void) md_unload_namespace(setno, NM_DEVID);
   3900 		return (ENOENT);
   3901 	}
   3902 
   3903 	rw_enter(&nm_lock.lock, RW_WRITER);
   3904 
   3905 	if ((nh = get_first_record(setno, 0, NM_SHARED)) == NULL) {
   3906 		rw_exit(&nm_lock.lock);
   3907 		return (ENOENT);
   3908 	}
   3909 
   3910 	if (remove_shared_entry(nh, shrkey, (char *)0, 0L)) {
   3911 		rw_exit(&nm_lock.lock);
   3912 		return (ENOENT);
   3913 	}
   3914 
   3915 	rw_exit(&nm_lock.lock);
   3916 	return (0);
   3917 }
   3918 
   3919 /*
   3920  * md_getshared_key - get the key for the given string.
   3921  */
   3922 mdkey_t
   3923 md_getshared_key(set_t setno, char *shrname)
   3924 {
   3925 	mdkey_t	retval;
   3926 
   3927 
   3928 	/*
   3929 	 * Load the devid name space if it exists
   3930 	 */
   3931 	(void) md_load_namespace(setno, NULL, NM_DEVID);
   3932 	if (! md_load_namespace(setno, NULL, 0L)) {
   3933 		/*
   3934 		 * Unload the devid namespace
   3935 		 */
   3936 		(void) md_unload_namespace(setno, NM_DEVID);
   3937 		return (MD_KEYBAD);
   3938 	}
   3939 
   3940 	rw_enter(&nm_lock.lock, RW_WRITER);
   3941 	retval = getshared_key(setno, shrname, 0L);
   3942 	rw_exit(&nm_lock.lock);
   3943 	return (retval);
   3944 }
   3945 
   3946 /*
   3947  * md_load_namespace - Get all the records associated with the namespace
   3948  *			out of the database and setup all the incore
   3949  *			structures (i.e., pointers).
   3950  */
   3951 int
   3952 md_load_namespace(set_t setno, md_error_t *ep, int devid_nm)
   3953 {
   3954 	mddb_recid_t		hdr_recid;
   3955 	struct nm_header_hdr	*hdr = NULL;
   3956 	mddb_type_t		rec_type;
   3957 
   3958 	if ((md_get_setstatus(setno) & MD_SET_NM_LOADED))
   3959 		return (1);
   3960 
   3961 	if (devid_nm && (md_set[setno].s_did_nm != 0))
   3962 		return (1);
   3963 
   3964 	rec_type = (devid_nm ? MDDB_DID_NM_HDR : MDDB_NM_HDR);
   3965 
   3966 	hdr_recid = mddb_getnextrec(mddb_makerecid(setno, 0), rec_type, 0);
   3967 
   3968 	if (hdr_recid < 0) {
   3969 		if (ep != NULL)
   3970 			return (mddbstatus2error(ep, hdr_recid, NODEV32,
   3971 			    setno));
   3972 		return (0);
   3973 	}
   3974 
   3975 	if (hdr_recid != 0) {
   3976 		mddb_recstatus_t status;
   3977 
   3978 		status = mddb_getrecstatus(hdr_recid);
   3979 		if (status == MDDB_NODATA) {
   3980 			mddb_setrecprivate(hdr_recid, MD_PRV_PENDDEL);
   3981 			hdr_recid = 0;
   3982 		} else if (status == MDDB_STALE) {
   3983 			if (! (md_get_setstatus(setno) & MD_SET_STALE)) {
   3984 				md_set_setstatus(setno, MD_SET_STALE);
   3985 				cmn_err(CE_WARN, "md: state database is stale");
   3986 			}
   3987 		}
   3988 	}
   3989 
   3990 	rw_enter(&nm_lock.lock, RW_WRITER);
   3991 
   3992 	if (hdr_recid != 0) {
   3993 
   3994 		hdr = kmem_zalloc(sizeof (*hdr), KM_SLEEP);
   3995 		ASSERT(hdr != NULL);
   3996 
   3997 		if (devid_nm) {
   3998 			md_set[setno].s_did_nmid = hdr_recid;
   3999 			md_set[setno].s_did_nm = (void *)hdr;
   4000 		} else {
   4001 			md_set[setno].s_nmid = hdr_recid;
   4002 			md_set[setno].s_nm = (void *)hdr;
   4003 		}
   4004 
   4005 		hdr->hh_header = (struct nm_header *)mddb_getrecaddr(hdr_recid);
   4006 
   4007 		ASSERT(hdr->hh_header != NULL);
   4008 
   4009 		hdr->hh_names.nmn_record = &(hdr->hh_header->h_names);
   4010 		hdr->hh_shared.nmn_record = &(hdr->hh_header->h_shared);
   4011 
   4012 		mddb_setrecprivate(hdr_recid, MD_PRV_GOTIT);
   4013 
   4014 		build_rec_hdr_list(&hdr->hh_names, hdr_recid,
   4015 		    devid_nm | NM_NOTSHARED);
   4016 		build_rec_hdr_list(&hdr->hh_shared, hdr_recid,
   4017 		    devid_nm | NM_SHARED);
   4018 
   4019 		/*
   4020 		 * Only cleanup a MN diskset if this node is master.
   4021 		 * Always cleanup traditional diskset.
   4022 		 */
   4023 		if (!(MD_MNSET_SETNO(setno)) ||
   4024 		    (MD_MNSET_SETNO(setno) && md_set[setno].s_am_i_master)) {
   4025 			if (devid_nm) {
   4026 				cleanup_unused_rec(setno, NM_DEVID);
   4027 			} else {
   4028 				cleanup_unused_rec(setno, 0L);
   4029 			}
   4030 		}
   4031 	}
   4032 
   4033 	if (!devid_nm)
   4034 		md_set_setstatus(setno, MD_SET_NM_LOADED);
   4035 	if (hdr && hdr->hh_header != NULL)
   4036 		zero_data_ptrs(&hdr->hh_shared, setno);
   4037 	rw_exit(&nm_lock.lock);
   4038 	return (1);
   4039 }
   4040 
   4041 void
   4042 md_unload_namespace(set_t setno, int devid_nm)
   4043 {
   4044 	struct nm_header_hdr *hhdr;
   4045 	struct nm_next_hdr *nh, *nnh;
   4046 
   4047 	if (!devid_nm && (md_set[setno].s_nmid == 0))
   4048 		return;
   4049 
   4050 	if (devid_nm && (md_set[setno].s_did_nmid == 0))
   4051 		return;
   4052 
   4053 	rw_enter(&nm_lock.lock, RW_WRITER);
   4054 
   4055 	hhdr = ((devid_nm & NM_DEVID) ?
   4056 	    (struct nm_header_hdr *)md_set[setno].s_did_nm :
   4057 	    (struct nm_header_hdr *)md_set[setno].s_nm);
   4058 
   4059 	if (devid_nm) {
   4060 		md_set[setno].s_did_nmid = 0;
   4061 		md_set[setno].s_did_nm = NULL;
   4062 	} else {
   4063 		md_set[setno].s_nmid = 0;
   4064 		md_set[setno].s_nm = NULL;
   4065 	}
   4066 
   4067 	/*
   4068 	 * Clear MD_SET_NM_LOADED when the primary is unloaded
   4069 	 */
   4070 	if (!devid_nm)
   4071 		md_clr_setstatus(setno, MD_SET_NM_LOADED);
   4072 
   4073 	rw_exit(&nm_lock.lock);
   4074 
   4075 	/*
   4076 	 * Free the memory occupied by the namespace records if any has been
   4077 	 * allocated.  For the case of a namespace which contains drives not
   4078 	 * supporting device id's we must be careful.
   4079 	 */
   4080 	if (hhdr != NULL) {
   4081 		for (nh = hhdr->hh_names.nmn_nextp; nh; nh = nnh) {
   4082 			nnh = nh->nmn_nextp;
   4083 			kmem_free(nh, sizeof (*nh));
   4084 		}
   4085 
   4086 		for (nh = hhdr->hh_shared.nmn_nextp; nh; nh = nnh) {
   4087 			nnh = nh->nmn_nextp;
   4088 			kmem_free(nh, sizeof (*nh));
   4089 		}
   4090 		kmem_free(hhdr, sizeof (*hhdr));
   4091 	}
   4092 }
   4093 
   4094 /*
   4095  * md_nm_did_chkspace - calculate the approximate DID namespace size based
   4096  *			on the component disk devices defined in the primary
   4097  *			non-shared namespace for this set.  This is done on
   4098  *			the conservative side and may be a block or two too
   4099  *			large.  These are MDDB blocks.
   4100  *
   4101  * This is intended to be called during a replica conversion from non-devid
   4102  * format to devid format.  As such no special precautions were taken to
   4103  * insure reentrancy.  In particular the code in free_devid_list() that
   4104  * initializes the devid_list anchor linkages makes this function non-MT-safe.
   4105  */
   4106 
   4107 int
   4108 md_nm_did_chkspace(set_t setno)
   4109 {
   4110 	struct	nm_next_hdr	*nh;
   4111 	struct	nm_name		*n;
   4112 	side_t			side = MD_SIDEWILD;
   4113 	mdkey_t			key = MD_KEYWILD;
   4114 	int			total_size = 0;	/* Total required size */
   4115 	int			devid_size = 0;	/* Device id total size */
   4116 	int			mname_size = 0;	/* Minor name total size */
   4117 	int			namelen = 0;
   4118 	int			comp_count = 0;	/* Total number of components */
   4119 	int			devid_count = 0; /* Total number of devids */
   4120 	ddi_devid_t		devid = NULL;
   4121 	char			*mname = NULL;
   4122 
   4123 	rw_enter(&nm_lock.lock, RW_READER);
   4124 
   4125 	if ((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) {
   4126 		rw_exit(&nm_lock.lock);
   4127 		return (total_size);
   4128 	}
   4129 
   4130 	/*
   4131 	 * For each key in the non-shared, primary namespace, lookup the
   4132 	 * minor name and any associated device id.  These will reside in
   4133 	 * the device id namespace of the upgraded system.
   4134 	 */
   4135 	while ((key = md_getnextkey(setno, side, key, NULL)) != MD_KEYWILD) {
   4136 		if ((n = (struct nm_name *)lookup_entry(nh, setno, side, key,
   4137 		    NODEV64, 0L)) == NULL) {
   4138 			break;
   4139 		} else {
   4140 			md_dev64_t dev64 = build_device_number(setno, n);
   4141 			dev_t dev = md_dev64_to_dev(dev64);
   4142 
   4143 			if (ddi_lyr_get_minor_name(dev, S_IFBLK, &mname)
   4144 			    != DDI_SUCCESS) {
   4145 				continue;
   4146 			} else {
   4147 				if (mname) {
   4148 					namelen = strlen(mname);
   4149 					mname_size += namelen;
   4150 					kmem_free(mname, (namelen + 1));
   4151 					comp_count++;
   4152 				}
   4153 			}
   4154 			if (ddi_lyr_get_devid(dev, &devid) != DDI_SUCCESS) {
   4155 				continue;
   4156 			} else {
   4157 				if (devid_is_unique(devid)) {
   4158 					add_to_devid_list(devid);
   4159 				} else {
   4160 					ddi_devid_free(devid);
   4161 				}
   4162 			}
   4163 		}
   4164 	}
   4165 
   4166 	devid_size = free_devid_list(&devid_count);
   4167 	rw_exit(&nm_lock.lock);
   4168 
   4169 	/*
   4170 	 * Sum things up in this order:
   4171 	 * 1) # blocks to hold devid non-shared record blocks
   4172 	 * 2) # blocks to hold devid shared record blocks
   4173 	 * 3) 1 block to hold devid non-shared nm_rec_hdr's
   4174 	 * 4) 1 block to hold mddb_de's for both of these spaces
   4175 	 */
   4176 
   4177 	/*
   4178 	 * 1)
   4179 	 */
   4180 	total_size = roundup(sizeof (struct mddb_rb32) +
   4181 	    sizeof (struct nm_rec_hdr) + (sizeof (struct did_min_name) *
   4182 	    comp_count) + (mname_size + comp_count), MDDB_BSIZE);
   4183 
   4184 	/*
   4185 	 * 2)
   4186 	 */
   4187 	total_size += roundup(sizeof (struct mddb_rb32) +
   4188 	    sizeof (struct nm_rec_hdr) + (sizeof (struct did_shr_name) *
   4189 	    devid_count) + devid_size, MDDB_BSIZE);
   4190 
   4191 	/*
   4192 	 * 3) and 4)
   4193 	 */
   4194 	total_size += (2 * MDDB_BSIZE);
   4195 
   4196 	return (total_size/MDDB_BSIZE);
   4197 }
   4198 
   4199 /*
   4200  * devid_list - forward list of devid_list structs.
   4201  * Managed by routines add_to_devid_list() and free_devid_list() to keep
   4202  * track of unique devids associated with components of metadevices.  Entries
   4203  * are made at the beginning of the list.
   4204  */
   4205 static	struct	devid_list {
   4206 	size_t	devid_size;
   4207 	struct	devid_list	*next;
   4208 	ddi_devid_t		devid;
   4209 } did_list = { 0, NULL, NULL};
   4210 
   4211 static	struct	devid_list	*dlp = &did_list;
   4212 
   4213 /*
   4214  * add_to_devid_list - add a struct devid_list to the head of the devid_list
   4215  * list.
   4216  */
   4217 static void
   4218 add_to_devid_list(ddi_devid_t did)
   4219 {
   4220 	struct	devid_list	*curdlp;
   4221 
   4222 	curdlp = kmem_zalloc(sizeof (struct devid_list), KM_SLEEP);
   4223 	curdlp->devid_size = ddi_devid_sizeof(did);
   4224 	curdlp->devid = did;
   4225 	curdlp->next = dlp->next;
   4226 	dlp->next = curdlp;
   4227 }
   4228 
   4229 /*
   4230  * free_devid_list - free storage allocated to dev_list list.  Return number
   4231  * of entries on list at address supplied by argument count.  Return total
   4232  * size of all device ids that were on the list.
   4233  */
   4234 static size_t
   4235 free_devid_list(int *count)
   4236 {
   4237 	struct	devid_list	*curdlp;
   4238 	struct	devid_list	*nextlp;
   4239 	size_t	total_size = 0;
   4240 	int	n = 0;
   4241 
   4242 	/*
   4243 	 * If there's nothing on the list.
   4244 	 */
   4245 	if ((curdlp = dlp->next) == NULL) {
   4246 		*count = 0;
   4247 		return (total_size);
   4248 	}
   4249 
   4250 	while (curdlp) {
   4251 		nextlp = curdlp->next;
   4252 		total_size += curdlp->devid_size;
   4253 		(void) ddi_devid_free(curdlp->devid);
   4254 		kmem_free(curdlp, sizeof (struct devid_list));
   4255 		curdlp = nextlp;
   4256 		n++;
   4257 	}
   4258 
   4259 	/*
   4260 	 * Insure that the devid_list anchor linkages are reinitialized in
   4261 	 * case of multiple calls (eg during testsuite execution).
   4262 	 */
   4263 	dlp->next = NULL;
   4264 	dlp->devid = NULL;
   4265 
   4266 	*count = n;
   4267 	return (total_size);
   4268 }
   4269 
   4270 /*
   4271  * devid_is_unique - search for did on devid_list list.  Return "false" if
   4272  * found.
   4273  */
   4274 static int
   4275 devid_is_unique(ddi_devid_t did)
   4276 {
   4277 	struct	devid_list	*curdlp;
   4278 	int	unique = 1;	/* Default to true */
   4279 
   4280 	/*
   4281 	 * If first call.
   4282 	 */
   4283 	if ((curdlp = dlp->next) == NULL) {
   4284 		return (1);
   4285 	}
   4286 
   4287 	while (curdlp) {
   4288 		if (ddi_devid_compare(curdlp->devid, did) == 0) {
   4289 			unique = 0;
   4290 			break;
   4291 		}
   4292 		curdlp = curdlp->next;
   4293 	}
   4294 	return (unique);
   4295 }
   4296 
   4297 
   4298 /*
   4299  * Called after the unit's snarf to cleanup the device id name space
   4300  */
   4301 void
   4302 md_devid_cleanup(set_t setno, uint_t all)
   4303 {
   4304 	struct nm_next_hdr	*nh, *did_nh, *this_nh, *did_shr_nh;
   4305 	struct did_min_name	*did_n;
   4306 	size_t			offset, n_offset;
   4307 	struct devid_min_rec	*record;
   4308 	mdkey_t			did_key;
   4309 	size_t			n_size;
   4310 	int			doit;
   4311 
   4312 	/*
   4313 	 * If it is an empty name space
   4314 	 */
   4315 	if (((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) ||
   4316 	    ((did_nh = get_first_record(setno, 1, NM_DEVID | NM_NOTSHARED))
   4317 	    == NULL) ||
   4318 	    ((did_shr_nh = get_first_record(setno, 1, NM_DEVID |
   4319 	    NM_SHARED)) == NULL)) {
   4320 		return;
   4321 	}
   4322 
   4323 	/*
   4324 	 * Or the name space is empty
   4325 	 */
   4326 	this_nh = did_nh->nmn_nextp;
   4327 	record = this_nh->nmn_record;
   4328 
   4329 	if (((struct nm_rec_hdr *)record)->r_used_size ==
   4330 		sizeof (struct nm_rec_hdr)) {
   4331 		return;
   4332 	}
   4333 
   4334 	/*
   4335 	 * Not empty
   4336 	 */
   4337 	n_offset = offset = (sizeof (struct devid_min_rec) -
   4338 	    sizeof (struct did_min_name));
   4339 	did_n = &(record->minor_name[0]);
   4340 
   4341 	/*CONSTCOND*/
   4342 	while (1) {
   4343 		did_key = did_n->min_devid_key;
   4344 		n_size = DID_NAMSIZ((struct did_min_name *)did_n);
   4345 
   4346 		/*
   4347 		 * It is not in the primary, remove it from the devid nmspace
   4348 		 */
   4349 		doit = (all ? 1 :
   4350 		    (lookup_entry(nh, setno, MD_SIDEWILD, did_n->min_key,
   4351 		    NODEV64, 0L) == NULL));
   4352 		if (doit) {
   4353 			(void) remove_entry(did_nh, did_n->min_side,
   4354 			    did_n->min_key, NM_DEVID);
   4355 			(void) remove_shared_entry(did_shr_nh, did_key,
   4356 			    (char *)0, NM_DEVID);
   4357 			/*
   4358 			 * We delete something so reset scan
   4359 			 */
   4360 			offset = n_offset;
   4361 			did_n = &(record->minor_name[0]);
   4362 			if (did_n->min_key != NULL) {
   4363 				continue;
   4364 			} else {
   4365 				return;
   4366 			}
   4367 		}
   4368 
   4369 		did_n = (struct did_min_name *)get_next_entry(this_nh,
   4370 		    (caddr_t)did_n, n_size, &offset);
   4371 
   4372 		/*
   4373 		 * Next record?
   4374 		 */
   4375 		if (did_n == NULL) {
   4376 			if (offset)
   4377 				return;
   4378 			/*
   4379 			 * Goto next record
   4380 			 */
   4381 			offset = n_offset;
   4382 			this_nh = this_nh->nmn_nextp;
   4383 			record = this_nh->nmn_record;
   4384 			did_n = &(record->minor_name[0]);
   4385 		}
   4386 	}
   4387 	/*NOTREACHED*/
   4388 }
   4389 
   4390 
   4391 /*
   4392  * Resolve md_dev64_t by device id when current configure changes.  This
   4393  * can happen before the system reboot or between snarf
   4394  * and the first use of metadevice.  The configure change can
   4395  * mean poweroff before boot and poweron after boot or recable
   4396  * disks between snarf and the first open of metadevice.
   4397  */
   4398 md_dev64_t
   4399 md_resolve_bydevid(minor_t mnum, md_dev64_t device, mdkey_t key)
   4400 {
   4401 
   4402 	struct nm_name		*n;
   4403 	struct nm_next_hdr	*nh, *did_nh;
   4404 	struct did_min_name	*did_n;
   4405 	ddi_devid_t		devid;
   4406 	dev_t			*devs; /* ddi returns dev_t not md_dev64_t */
   4407 	int			ndevs,
   4408 	    cnt;
   4409 	set_t			setno;
   4410 	int			update = 0;
   4411 	md_dev64_t		targ_dev;
   4412 
   4413 	/* assign here so that lint does not complain */
   4414 	targ_dev = NODEV64;
   4415 
   4416 	if (device != NODEV64 && (md_getmajor(device) == md_major))
   4417 		return (device);
   4418 
   4419 	setno = MD_MIN2SET(mnum);
   4420 
   4421 	if (((nh = get_first_record(setno, 0, NM_NOTSHARED)) == NULL) ||
   4422 	    ((n = (struct nm_name *)lookup_entry(nh, setno, MD_SIDEWILD,
   4423 	    key, NODEV64, 0L)) == NULL)) {
   4424 		return (NODEV64);
   4425 	}
   4426 
   4427 	/*
   4428 	 * Something can be resolved by device id
   4429 	 * Resolve by the device id and if it can't be resolved
   4430 	 * then return whatever passed in
   4431 	 */
   4432 	if (((did_nh = get_first_record(setno, 0, NM_DEVID | NM_NOTSHARED))
   4433 	    != NULL) && ((did_n = (struct did_min_name *)lookup_entry
   4434 	    (did_nh, setno, MD_SIDEWILD, key, NODEV64, NM_DEVID))
   4435 	    != NULL)) {
   4436 		/*
   4437 		 * Get the current devt and update mddb devt if necessary
   4438 		 */
   4439 		devid =	(ddi_devid_t)getshared_name(setno,
   4440 		    did_n->min_devid_key, NM_DEVID);
   4441 
   4442 		if (devid && (ddi_lyr_devid_to_devlist(devid, did_n->min_name,
   4443 		    &ndevs, &devs) == DDI_SUCCESS)) {
   4444 
   4445 			/*
   4446 			 * This device has been powered off
   4447 			 */
   4448 			if (device == NODEV64) {
   4449 				device = md_expldev(devs[0]);
   4450 				update = 1;
   4451 			} else {
   4452 				for (cnt = 0; cnt < ndevs; cnt++) {
   4453 					if (device == md_expldev(devs[cnt]))
   4454 						break;
   4455 				}
   4456 				if (cnt == ndevs) {
   4457 					device = md_expldev(devs[0]);
   4458 					update = 1;
   4459 				}
   4460 			}
   4461 
   4462 			/*
   4463 			 * Have devt so update name space also
   4464 			 */
   4465 			targ_dev = md_xlate_mini_2_targ(device);
   4466 			if (targ_dev == NODEV64)
   4467 				return (NODEV64);
   4468 
   4469 			if (update &&
   4470 			    !(md_get_setstatus(setno) & MD_SET_STALE)) {
   4471 				n->n_minor = md_getminor(targ_dev);
   4472 				/*
   4473 				 * If we have the key for the driver get
   4474 				 * it and update the entry. If it's not there
   4475 				 * we need to create it.
   4476 				 */
   4477 				if ((n->n_drv_key = getshared_key(setno,
   4478 				    md_targ_major_to_name(
   4479 				    md_getmajor(targ_dev)), 0L)) == MD_KEYBAD) {
   4480 					n->n_drv_key = setshared_name(setno,
   4481 					    md_targ_major_to_name(
   4482 					    md_getmajor(targ_dev)),
   4483 					    MD_KEYWILD, 0L);
   4484 				}
   4485 				(void) update_entry(nh, MD_SIDEWILD,
   4486 				    n->n_key, 0L);
   4487 			}
   4488 			/*
   4489 			 * Free memory
   4490 			 */
   4491 			(void) ddi_lyr_free_devlist(devs, ndevs);
   4492 		} else {
   4493 			/*
   4494 			 * if input devid is null or ddi_devid_lyr_devlist
   4495 			 * does not return success then return NODEV64
   4496 			 */
   4497 			device = NODEV64;
   4498 		}
   4499 	}
   4500 	return (device);
   4501 }
   4502