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