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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Just in case we're not in a build environment, make sure that 31 * TEXT_DOMAIN gets set to something. 32 */ 33 #if !defined(TEXT_DOMAIN) 34 #define TEXT_DOMAIN "SYS_TEST" 35 #endif 36 37 /* 38 * MH ioctl functions 39 */ 40 41 #include <meta.h> 42 #include <metamhd.h> 43 #include <string.h> 44 45 #include "meta_runtime.h" 46 47 #define DEFAULTDEV "/dev/rdsk" 48 /* 49 * default timeout values 50 */ 51 mhd_mhiargs_t defmhiargs = { 52 1000, /* failfast */ 53 { 6000, 6000, 30000 } /* take ownership */ 54 }; 55 56 /* RPC timeouts */ 57 static md_timeval32_t tk_own_timeout = { 24 * 60 * 60, 0 }; /* 1 day */ 58 static md_timeval32_t rel_own_timeout = { 24 * 60 * 60, 0 }; /* 1 day */ 59 60 /* 61 * RPC handle 62 */ 63 typedef struct { 64 char *hostname; 65 CLIENT *clientp; 66 } mhd_handle_t; 67 68 /* 69 * close RPC connection 70 */ 71 static void 72 close_metamhd( 73 mhd_handle_t *hp 74 ) 75 { 76 assert(hp != NULL); 77 if (hp->hostname != NULL) { 78 Free(hp->hostname); 79 } 80 if (hp->clientp != NULL) { 81 auth_destroy(hp->clientp->cl_auth); 82 clnt_destroy(hp->clientp); 83 } 84 Free(hp); 85 } 86 87 /* 88 * open RPC connection to rpc.metamhd 89 */ 90 static mhd_handle_t * 91 open_metamhd( 92 char *hostname, 93 md_error_t *ep 94 ) 95 { 96 CLIENT *clientp; 97 mhd_handle_t *hp; 98 99 /* default to local host */ 100 if ((hostname == NULL) || (*hostname == '\0')) 101 hostname = mynode(); 102 103 /* open RPC connection */ 104 assert(hostname != NULL); 105 if ((clientp = meta_client_create(hostname, METAMHD, METAMHD_VERSION, 106 "tcp")) == NULL) { 107 clnt_pcreateerror(hostname); 108 (void) mdrpccreateerror(ep, hostname, "metamhd clnt_create"); 109 return (NULL); 110 } else { 111 auth_destroy(clientp->cl_auth); 112 clientp->cl_auth = authsys_create_default(); 113 assert(clientp->cl_auth != NULL); 114 } 115 116 /* return connection */ 117 hp = Zalloc(sizeof (*hp)); 118 hp->hostname = Strdup(hostname); 119 hp->clientp = clientp; 120 return (hp); 121 } 122 123 /* 124 * steal and convert mherror_t 125 */ 126 int 127 mhstealerror( 128 mhd_error_t *mhep, 129 md_error_t *ep 130 ) 131 { 132 int rval = -1; 133 134 /* no error */ 135 if (mhep->errnum == 0) { 136 /* assert(mhep->name == NULL); */ 137 rval = 0; 138 goto out; 139 } 140 141 /* steal error */ 142 switch (mhep->errnum) { 143 case MHD_E_MAJORITY: 144 (void) mderror(ep, MDE_TAKE_OWN, mhep->name); 145 break; 146 case MHD_E_RESERVED: 147 (void) mderror(ep, MDE_RESERVED, mhep->name); 148 break; 149 default: 150 (void) mdsyserror(ep, mhep->errnum, mhep->name); 151 break; 152 } 153 154 /* cleanup, return success */ 155 out: 156 if (mhep->name != NULL) 157 Free(mhep->name); 158 (void) memset(mhep, 0, sizeof (*mhep)); 159 return (rval); 160 } 161 162 /* 163 * should we do MHIOCTLs ? 164 */ 165 static int 166 do_mhioctl() 167 { 168 if (getenv("MD_NOMHIOCTL") != NULL) { 169 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 170 "NOT doing MH ioctls\n")); 171 (void) fflush(stderr); 172 return (0); 173 } 174 return (1); 175 } 176 177 /* 178 * take ownership of drives 179 */ 180 int 181 meta_take_own( 182 char *sname, 183 mddrivenamelist_t *dnlp, 184 mhd_mhiargs_t *mhiargsp, 185 int partial_set, 186 md_error_t *ep 187 ) 188 { 189 mddrivenamelist_t *p; 190 uint_t ndev = 0; 191 mhd_tkown_args_t args; 192 mhd_error_t mherror; 193 mhd_set_t *mhsp = &args.set; 194 uint_t i; 195 char *e; 196 mhd_handle_t *hp = NULL; 197 int rval = -1; 198 199 /* 200 * RFE 4126509. Check the runtime parameters to see if 201 * they're set to disable MHIOCTKOWN ioctl() operations 202 * on the disks. If so, return immediately without 203 * performing the operations. 204 */ 205 206 if (do_owner_ioctls() == B_FALSE) { 207 return (0); 208 } 209 210 /* count drives, get set */ 211 for (p = dnlp; (p != NULL); p = p->next) 212 ++ndev; 213 if (ndev == 0) 214 return (0); 215 216 /* initialize */ 217 (void) memset(&args, 0, sizeof (args)); 218 (void) memset(&mherror, 0, sizeof (mherror)); 219 220 /* build arguments */ 221 mhsp->setname = Strdup(sname); 222 mhsp->drives.drives_len = ndev; 223 mhsp->drives.drives_val 224 = Calloc(ndev, sizeof (*mhsp->drives.drives_val)); 225 for (p = dnlp, i = 0; (i < ndev); p = p->next, ++i) { 226 mhsp->drives.drives_val[i] = Strdup(p->drivenamep->rname); 227 } 228 args.timeouts = *mhiargsp; 229 args.ff_mode = MHD_FF_DRIVER; 230 if (((e = getenv("MD_DEBUG")) != NULL) && 231 ((e = strstr(e, "FAILFAST=")) != NULL) && 232 ((e = strchr(e, '=')) != NULL)) { 233 ++e; 234 if (strcmp(e, "NONE") == 0) 235 args.ff_mode = MHD_FF_NONE; 236 else if (strcmp(e, "DRIVER") == 0) 237 args.ff_mode = MHD_FF_DRIVER; 238 else if (strcmp(e, "DEBUG") == 0) 239 args.ff_mode = MHD_FF_DEBUG; 240 else if (strcmp(e, "HALT") == 0) 241 args.ff_mode = MHD_FF_HALT; 242 else if (strcmp(e, "PANIC") == 0) 243 args.ff_mode = MHD_FF_PANIC; 244 } 245 if (partial_set) 246 args.options |= MHD_PARTIAL_SET; 247 if (((e = getenv("MD_DEBUG")) != NULL) && 248 (strstr(e, "NOTHREAD") != NULL)) { 249 args.options |= MHD_SERIAL; 250 } 251 252 /* open connection */ 253 if ((hp = open_metamhd(NULL, ep)) == NULL) 254 return (-1); 255 clnt_control(hp->clientp, CLSET_TIMEOUT, (char *)&tk_own_timeout); 256 257 /* take ownership */ 258 if (mhd_tkown_1(&args, &mherror, hp->clientp) != RPC_SUCCESS) { 259 (void) mdrpcerror(ep, hp->clientp, hp->hostname, 260 "metamhd tkown"); 261 } else if (mhstealerror(&mherror, ep) == 0) { 262 rval = 0; /* success */ 263 } 264 265 /* cleanup, return success */ 266 out: 267 xdr_free(xdr_mhd_tkown_args_t, (char *)&args); 268 xdr_free(xdr_mhd_error_t, (char *)&mherror); 269 if (hp != NULL) 270 close_metamhd(hp); 271 return (rval); 272 } 273 274 /* 275 * take ownership of drives 276 */ 277 int 278 tk_own_bydd( 279 mdsetname_t *sp, 280 md_drive_desc *ddlp, 281 mhd_mhiargs_t *mhiargsp, 282 int partial_set, 283 md_error_t *ep 284 ) 285 { 286 mddrivenamelist_t *dnlp = NULL; 287 mddrivenamelist_t **tailpp = &dnlp; 288 md_drive_desc *p; 289 int rval; 290 291 /* 292 * Add the drivename struct to the end of the 293 * drivenamelist but keep a pointer to the last 294 * element so that we don't incur the overhead 295 * of traversing the list each time 296 */ 297 for (p = ddlp; (p != NULL); p = p->dd_next) 298 tailpp = meta_drivenamelist_append_wrapper(tailpp, p->dd_dnp); 299 300 /* take ownership */ 301 rval = meta_take_own(sp->setname, dnlp, mhiargsp, partial_set, ep); 302 303 /* cleanup, return success */ 304 metafreedrivenamelist(dnlp); 305 return (rval); 306 } 307 308 /* 309 * release ownership of drives 310 */ 311 int 312 meta_rel_own( 313 char *sname, 314 mddrivenamelist_t *dnlp, 315 int partial_set, 316 md_error_t *ep 317 ) 318 { 319 mddrivenamelist_t *p; 320 uint_t ndev = 0; 321 mhd_relown_args_t args; 322 mhd_error_t mherror; 323 mhd_set_t *mhsp = &args.set; 324 uint_t i; 325 char *e; 326 mhd_handle_t *hp = NULL; 327 int rval = -1; 328 329 /* 330 * RFE 4126509. Check the runtime parameters to see if 331 * they're set to disable MHIOCRELEASE and MHIOCENFAILFAST 332 * ioctl() operations on the disks. If so, return 333 * immediately without performing the operations. 334 */ 335 336 if (do_owner_ioctls() == B_FALSE) { 337 return (0); 338 } 339 340 /* 341 * if not doing ioctls (HK 98/10/28: the following code tests 342 * an environment variable, and was apparently inserted to 343 * make testing easier.) 344 */ 345 346 if (! do_mhioctl()) 347 return (0); 348 349 /* count drives, get set */ 350 for (p = dnlp; (p != NULL); p = p->next) 351 ++ndev; 352 if (ndev == 0) 353 return (0); 354 355 /* initialize */ 356 (void) memset(&args, 0, sizeof (args)); 357 (void) memset(&mherror, 0, sizeof (mherror)); 358 359 /* build arguments */ 360 mhsp->setname = Strdup(sname); 361 mhsp->drives.drives_len = ndev; 362 mhsp->drives.drives_val 363 = Calloc(ndev, sizeof (*mhsp->drives.drives_val)); 364 for (p = dnlp, i = 0; (i < ndev); p = p->next, ++i) { 365 mhsp->drives.drives_val[i] = Strdup(p->drivenamep->rname); 366 } 367 if (partial_set) 368 args.options |= MHD_PARTIAL_SET; 369 if (((e = getenv("MD_DEBUG")) != NULL) && 370 (strstr(e, "NOTHREAD") != NULL)) { 371 args.options |= MHD_SERIAL; 372 } 373 374 /* open connection */ 375 if ((hp = open_metamhd(NULL, ep)) == NULL) 376 return (-1); 377 clnt_control(hp->clientp, CLSET_TIMEOUT, (char *)&rel_own_timeout); 378 379 /* take ownership */ 380 if (mhd_relown_1(&args, &mherror, hp->clientp) != RPC_SUCCESS) { 381 (void) mdrpcerror(ep, hp->clientp, hp->hostname, 382 "metamhd relown"); 383 } else if (mhstealerror(&mherror, ep) == 0) { 384 rval = 0; /* success */ 385 } 386 387 /* cleanup, return success */ 388 out: 389 xdr_free(xdr_mhd_relown_args_t, (char *)&args); 390 xdr_free(xdr_mhd_error_t, (char *)&mherror); 391 if (hp != NULL) 392 close_metamhd(hp); 393 return (rval); 394 } 395 396 /* 397 * release ownership of drives 398 */ 399 int 400 rel_own_bydd( 401 mdsetname_t *sp, 402 md_drive_desc *ddlp, 403 int partial_set, 404 md_error_t *ep 405 ) 406 { 407 mddrivenamelist_t *dnlp = NULL; 408 mddrivenamelist_t **tailpp = &dnlp; 409 md_drive_desc *p; 410 int rval; 411 412 /* 413 * Add the drivename struct to the end of the 414 * drivenamelist but keep a pointer to the last 415 * element so that we don't incur the overhead 416 * of traversing the list each time 417 */ 418 for (p = ddlp; (p != NULL); p = p->dd_next) 419 tailpp = meta_drivenamelist_append_wrapper(tailpp, p->dd_dnp); 420 421 /* release ownership */ 422 rval = meta_rel_own(sp->setname, dnlp, partial_set, ep); 423 424 /* cleanup, return success */ 425 metafreedrivenamelist(dnlp); 426 return (rval); 427 } 428 429 /* 430 * get status of drives 431 */ 432 int 433 meta_status_own( 434 char *sname, 435 md_disk_status_list_t *dslp, 436 int partial_set, 437 md_error_t *ep 438 ) 439 { 440 md_disk_status_list_t *p; 441 uint_t ndev = 0; 442 mhd_status_args_t args; 443 mhd_status_res_t results; 444 mhd_error_t *mhep = &results.status; 445 mhd_set_t *mhsp = &args.set; 446 uint_t i; 447 char *e; 448 mhd_handle_t *hp = NULL; 449 int rval = -1; 450 451 /* if not doing ioctls */ 452 if (! do_mhioctl()) 453 return (0); 454 455 /* count drives, get set */ 456 for (p = dslp; (p != NULL); p = p->next) 457 ++ndev; 458 if (ndev == 0) 459 return (0); 460 461 /* initialize */ 462 (void) memset(&args, 0, sizeof (args)); 463 (void) memset(&results, 0, sizeof (results)); 464 465 /* build arguments */ 466 mhsp->setname = Strdup(sname); 467 mhsp->drives.drives_len = ndev; 468 mhsp->drives.drives_val 469 = Calloc(ndev, sizeof (*mhsp->drives.drives_val)); 470 for (p = dslp, i = 0; (i < ndev); p = p->next, ++i) { 471 mhsp->drives.drives_val[i] = Strdup(p->drivenamep->rname); 472 } 473 if (partial_set) 474 args.options |= MHD_PARTIAL_SET; 475 if (((e = getenv("MD_DEBUG")) != NULL) && 476 (strstr(e, "NOTHREAD") != NULL)) { 477 args.options |= MHD_SERIAL; 478 } 479 480 /* open connection */ 481 if ((hp = open_metamhd(NULL, ep)) == NULL) 482 return (-1); 483 clnt_control(hp->clientp, CLSET_TIMEOUT, (char *)&tk_own_timeout); 484 485 /* get status */ 486 if (mhd_status_1(&args, &results, hp->clientp) != RPC_SUCCESS) { 487 (void) mdrpcerror(ep, hp->clientp, hp->hostname, 488 dgettext(TEXT_DOMAIN, "metamhd status")); 489 goto out; 490 } else if (mhstealerror(mhep, ep) != 0) { 491 goto out; 492 } 493 494 /* do something with it */ 495 assert(results.results.results_len == ndev); 496 for (p = dslp, i = 0; (i < ndev); p = p->next, ++i) { 497 mhd_drive_status_t *resp = &results.results.results_val[i]; 498 mddrivename_t *dp = p->drivenamep; 499 mhd_error_t mherror; 500 501 /* make sure we have the right drive */ 502 assert(strcmp(dp->rname, resp->drive) == 0); 503 504 /* copy status */ 505 if (resp->errnum != 0) { 506 (void) memset(&mherror, 0, sizeof (mherror)); 507 mherror.errnum = resp->errnum; 508 mherror.name = Strdup(resp->drive); 509 (void) mhstealerror(&mherror, &p->status); 510 } 511 } 512 rval = 0; /* success */ 513 514 /* cleanup, return success */ 515 out: 516 xdr_free(xdr_mhd_status_args_t, (char *)&args); 517 xdr_free(xdr_mhd_status_res_t, (char *)&results); 518 if (hp != NULL) 519 close_metamhd(hp); 520 return (rval); 521 } 522 523 /* 524 * build disk status list from drivename list 525 */ 526 md_disk_status_list_t * 527 meta_drive_to_disk_status_list( 528 mddrivenamelist_t *dnlp 529 ) 530 { 531 md_disk_status_list_t *head = NULL; 532 md_disk_status_list_t **tailp = &head; 533 mddrivenamelist_t *p; 534 535 /* copy list */ 536 for (p = dnlp; (p != NULL); p = p->next) { 537 md_disk_status_list_t *dsp; 538 539 dsp = *tailp = Zalloc(sizeof (*dsp)); 540 tailp = &dsp->next; 541 dsp->drivenamep = p->drivenamep; 542 } 543 544 /* return list */ 545 return (head); 546 } 547 548 /* 549 * free disk status list 550 */ 551 void 552 meta_free_disk_status_list( 553 md_disk_status_list_t *dslp 554 ) 555 { 556 md_disk_status_list_t *next = NULL; 557 558 for (/* void */; (dslp != NULL); dslp = next) { 559 next = dslp->next; 560 mdclrerror(&dslp->status); 561 Free(dslp); 562 } 563 } 564 565 /* 566 * free drive info list 567 */ 568 void 569 meta_free_drive_info_list( 570 mhd_drive_info_list_t *listp 571 ) 572 { 573 xdr_free(xdr_mhd_drive_info_list_t, (char *)listp); 574 (void) memset(listp, 0, sizeof (*listp)); 575 } 576 577 /* 578 * sort drive info list 579 */ 580 static int 581 compare_drives( 582 const void *p1, 583 const void *p2 584 ) 585 { 586 const mhd_drive_info_t *di1 = p1; 587 const mhd_drive_info_t *di2 = p2; 588 const char *n1 = di1->dif_name; 589 const char *n2 = di2->dif_name; 590 uint_t c1 = 0, t1 = 0, d1 = 0, s1 = 0; 591 uint_t c2 = 0, t2 = 0, d2 = 0, s2 = 0; 592 uint_t l, cl; 593 594 if (n1 == NULL) 595 n1 = ""; 596 if (n2 == NULL) 597 n2 = ""; 598 599 /* attempt to sort correctly for c0t1d0s0 .vs. c0t18d0s0 */ 600 if ((n1 = strrchr(n1, '/')) == NULL) 601 goto u; 602 n1 += (n1[1] != 'c') ? 2 : 1; 603 cl = strlen(n1); 604 if ((sscanf(n1, "c%ut%ud%us%u%n", &c1, &t1, &d1, &s1, &l) != 4 && 605 sscanf(n1, "c%ud%us%u%n", &c1, &d1, &s1, &l) != 3 && 606 sscanf(n1, "c%ut%ud%u%n", &c1, &t1, &d1, &l) != 3 && 607 sscanf(n1, "c%ud%u%n", &c1, &d1, &l) != 2) || (l != cl)) 608 goto u; 609 610 if ((n2 = strrchr(n2, '/')) == NULL) 611 goto u; 612 n2 += (n2[1] != 'c') ? 2 : 1; 613 cl = strlen(n2); 614 if ((sscanf(n2, "c%ut%ud%us%u%n", &c2, &t2, &d2, &s2, &l) != 4 && 615 sscanf(n2, "c%ud%us%u%n", &c2, &d2, &s2, &l) != 3 && 616 sscanf(n2, "c%ut%ud%u%n", &c2, &t2, &d2, &l) != 3 && 617 sscanf(n2, "c%ud%u%n", &c2, &d2, &l) != 2) || (l != cl)) 618 goto u; 619 if (c1 != c2) 620 return ((c1 > c2) ? 1 : -1); 621 if (t1 != t2) 622 return ((t1 > t2) ? 1 : -1); 623 if (d1 != d2) 624 return ((d1 > d2) ? 1 : -1); 625 if (s1 != s2) 626 return ((s1 > s2) ? 1 : -1); 627 return (0); 628 629 u: return (strcmp(di1->dif_name, di2->dif_name)); 630 } 631 632 static void 633 sort_drives( 634 mhd_drive_info_list_t *listp 635 ) 636 { 637 qsort(listp->mhd_drive_info_list_t_val, 638 listp->mhd_drive_info_list_t_len, 639 sizeof (*listp->mhd_drive_info_list_t_val), 640 compare_drives); 641 } 642 643 /* 644 * return list of all drives 645 */ 646 int 647 meta_list_drives( 648 char *hostname, 649 char *path, 650 mhd_did_flags_t flags, 651 mhd_drive_info_list_t *listp, 652 md_error_t *ep 653 ) 654 { 655 mhd_list_args_t args; 656 mhd_list_res_t results; 657 mhd_error_t *mhep = &results.status; 658 mhd_handle_t *hp = NULL; 659 int rval = -1; 660 661 /* if not doing ioctls */ 662 if (! do_mhioctl()) 663 return (0); 664 665 /* initialize */ 666 (void) memset(&args, 0, sizeof (args)); 667 (void) memset(&results, 0, sizeof (results)); 668 669 /* build arguments */ 670 if (path == NULL) 671 path = getenv("MD_DRIVE_ROOT"); 672 if ((path != NULL) && (*path != '\0')) 673 args.path = Strdup(path); 674 args.flags = flags; 675 676 /* open connection */ 677 if ((hp = open_metamhd(hostname, ep)) == NULL) 678 return (-1); 679 clnt_control(hp->clientp, CLSET_TIMEOUT, (char *)&tk_own_timeout); 680 681 /* get list */ 682 if (mhd_list_1(&args, &results, hp->clientp) != RPC_SUCCESS) { 683 (void) mdrpcerror(ep, hp->clientp, hp->hostname, 684 dgettext(TEXT_DOMAIN, "metamhd list")); 685 goto out; 686 } else if (mhstealerror(mhep, ep) != 0) { 687 goto out; 688 } 689 690 /* sort list */ 691 sort_drives(&results.results); 692 693 /* steal list */ 694 *listp = results.results; 695 results.results.mhd_drive_info_list_t_len = 0; 696 results.results.mhd_drive_info_list_t_val = NULL; 697 rval = listp->mhd_drive_info_list_t_len; /* success */ 698 699 /* cleanup, return success */ 700 out: 701 xdr_free(xdr_mhd_list_args_t, (char *)&args); 702 xdr_free(xdr_mhd_list_res_t, (char *)&results); 703 if (hp != NULL) 704 close_metamhd(hp); 705 return (rval); 706 } 707 708 static void 709 load_paths_to_metamhd() 710 { 711 FILE *cfp; /* config file pointer */ 712 char buf[BUFSIZ], 713 *p, 714 *x; 715 mhd_drive_info_list_t list; 716 md_error_t ep; 717 mhd_did_flags_t flags = MHD_DID_SERIAL; 718 719 if ((cfp = fopen(METADEVPATH, "r")) != NULL) { 720 /* 721 * Read each line from the file. Lines will be either 722 * comments or path names to pass to rpc.metamhd. If 723 * path names check to see if their a colon seperate 724 * list of names which must be processed one at a time. 725 */ 726 727 while (fgets(buf, BUFSIZ, cfp) != NULL) { 728 if (buf[0] == '#') { 729 /* 730 * Ignore comment lines 731 */ 732 continue; 733 734 } else if (strchr(buf, ':') != NULL) { 735 p = buf; 736 while ((x = strchr(p, ':')) != NULL) { 737 *x = '\0'; 738 (void) memset(&ep, '\0', sizeof (ep)); 739 (void) meta_list_drives(NULL, p, 0, 740 &list, &ep); 741 meta_free_drive_info_list(&list); 742 p = x + 1; 743 } 744 /* 745 * We won't pick up the last path name 746 * because the line ends with a newline 747 * not a ':'. So p will still point to 748 * a valid path in this case. Copy the 749 * data that p points to to the beginning 750 * of the buf and let the default case 751 * handle this buffer. 752 * NOTE: 753 * If the file does end with a ":\n", p at 754 * will point to the newline. The default 755 * cause would then set the newline to a 756 * NULL which is okay because meta_list_drives 757 * interprets a null string as /dev/rdsk. 758 */ 759 (void) memcpy(buf, p, strlen(p)); 760 } 761 /* 762 * Remove any newlines in the buffer. 763 */ 764 if ((p = strchr(buf, '\n')) != NULL) 765 *p = '\0'; 766 (void) memset(&ep, '\0', sizeof (ep)); 767 (void) memset(&list, '\0', sizeof (list)); 768 (void) meta_list_drives(NULL, buf, flags, &list, &ep); 769 meta_free_drive_info_list(&list); 770 } 771 (void) fclose(cfp); 772 } 773 } 774 775 /* 776 * build list of all drives in set 777 */ 778 /*ARGSUSED*/ 779 int 780 meta_get_drive_names( 781 mdsetname_t *sp, 782 mddrivenamelist_t **dnlpp, 783 int options, 784 md_error_t *ep 785 ) 786 { 787 mhd_did_flags_t flags = MHD_DID_SERIAL; 788 mhd_drive_info_list_t list; 789 mhd_drive_info_t *mp; 790 uint_t i; 791 unsigned cnt = 0; 792 int rval = -1; 793 mddrivenamelist_t **tailpp = dnlpp; 794 795 /* must have a set */ 796 assert(sp != NULL); 797 798 load_paths_to_metamhd(); 799 (void) memset(&list, 0, sizeof (list)); 800 if ((meta_list_drives(NULL, NULL, flags, &list, ep)) < 0) 801 return (-1); 802 803 /* find drives in set */ 804 for (i = 0; (i < list.mhd_drive_info_list_t_len); ++i) { 805 mddrivename_t *dnp; 806 mdname_t *np; 807 808 mp = &list.mhd_drive_info_list_t_val[i]; 809 810 if (mp->dif_id.did_flags & MHD_DID_DUPLICATE) 811 continue; 812 813 /* quietly skip drives which don't conform */ 814 if ((dnp = metadrivename(&sp, mp->dif_name, ep)) == NULL) { 815 mdclrerror(ep); 816 continue; 817 } 818 819 /* check in set */ 820 if ((np = metaslicename(dnp, MD_SLICE0, ep)) == NULL) 821 goto out; 822 if (meta_check_inset(sp, np, ep) != 0) { 823 mdclrerror(ep); 824 continue; 825 } 826 827 /* 828 * Add the drivename struct to the end of the 829 * drivenamelist but keep a pointer to the last 830 * element so that we don't incur the overhead 831 * of traversing the list each time 832 */ 833 tailpp = meta_drivenamelist_append_wrapper(tailpp, dnp); 834 ++cnt; 835 } 836 rval = cnt; 837 838 /* cleanup, return error */ 839 out: 840 meta_free_drive_info_list(&list); 841 return (rval); 842 } 843