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