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