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