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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <fcntl.h> 28 #include <libdevinfo.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <dirent.h> 33 #include <sys/dkio.h> 34 #include <sys/stat.h> 35 #include <sys/sunddi.h> 36 #include <sys/types.h> 37 #include <sys/vtoc.h> 38 #include <unistd.h> 39 #include <devid.h> 40 #include <dirent.h> 41 #include <sys/dktp/fdisk.h> 42 #include <sys/efi_partition.h> 43 44 #include "libdiskmgt.h" 45 #include "disks_private.h" 46 #include "partition.h" 47 #ifndef VT_ENOTSUP 48 #define VT_ENOTSUP (-5) 49 #endif 50 51 #define FMT_UNKNOWN 0 52 #define FMT_VTOC 1 53 #define FMT_EFI 2 54 55 typedef int (*detectorp)(char *, nvlist_t *, int *); 56 57 static detectorp detectors[] = { 58 inuse_mnt, 59 inuse_svm, 60 inuse_active_zpool, 61 inuse_lu, 62 inuse_dump, 63 inuse_vxvm, 64 inuse_exported_zpool, 65 inuse_fs, /* fs should always be last */ 66 NULL 67 }; 68 69 static int add_inuse(char *name, nvlist_t *attrs); 70 static int desc_ok(descriptor_t *dp); 71 static void dsk2rdsk(char *dsk, char *rdsk, int size); 72 static int get_attrs(descriptor_t *dp, int fd, nvlist_t *attrs); 73 static descriptor_t **get_fixed_assocs(descriptor_t *desc, int *errp); 74 static int get_slice_num(slice_t *devp); 75 static int match_fixed_name(disk_t *dp, char *name, int *errp); 76 static int make_fixed_descriptors(disk_t *dp); 77 78 descriptor_t ** 79 slice_get_assoc_descriptors(descriptor_t *desc, dm_desc_type_t type, 80 int *errp) 81 { 82 if (!desc_ok(desc)) { 83 *errp = ENODEV; 84 return (NULL); 85 } 86 87 switch (type) { 88 case DM_MEDIA: 89 return (media_get_assocs(desc, errp)); 90 case DM_PARTITION: 91 return (partition_get_assocs(desc, errp)); 92 } 93 94 *errp = EINVAL; 95 return (NULL); 96 } 97 98 /* 99 * This is called by media/partition to get the slice descriptors for the given 100 * media/partition descriptor. 101 * For media, just get the slices, but for a partition, it must be a solaris 102 * partition and if there are active partitions, it must be the active one. 103 */ 104 descriptor_t ** 105 slice_get_assocs(descriptor_t *desc, int *errp) 106 { 107 /* Just check the first drive name. */ 108 if (desc->p.disk->aliases == NULL) { 109 *errp = 0; 110 return (libdiskmgt_empty_desc_array(errp)); 111 } 112 113 return (get_fixed_assocs(desc, errp)); 114 } 115 116 nvlist_t * 117 slice_get_attributes(descriptor_t *dp, int *errp) 118 { 119 nvlist_t *attrs = NULL; 120 int fd; 121 char devpath[MAXPATHLEN]; 122 123 if (!desc_ok(dp)) { 124 *errp = ENODEV; 125 return (NULL); 126 } 127 128 if (nvlist_alloc(&attrs, NVATTRS, 0) != 0) { 129 *errp = ENOMEM; 130 return (NULL); 131 } 132 133 /* dp->name is /dev/dsk, need to convert back to /dev/rdsk */ 134 dsk2rdsk(dp->name, devpath, sizeof (devpath)); 135 fd = open(devpath, O_RDONLY|O_NDELAY); 136 137 if ((*errp = get_attrs(dp, fd, attrs)) != 0) { 138 nvlist_free(attrs); 139 attrs = NULL; 140 } 141 142 if (fd >= 0) { 143 (void) close(fd); 144 } 145 146 return (attrs); 147 } 148 149 /* 150 * Look for the slice by the slice devpath. 151 */ 152 descriptor_t * 153 slice_get_descriptor_by_name(char *name, int *errp) 154 { 155 int found = 0; 156 disk_t *dp; 157 158 for (dp = cache_get_disklist(); dp != NULL; dp = dp->next) { 159 found = match_fixed_name(dp, name, errp); 160 161 if (found) { 162 char mname[MAXPATHLEN]; 163 164 if (*errp != 0) { 165 return (NULL); 166 } 167 168 mname[0] = 0; 169 (void) media_read_name(dp, mname, sizeof (mname)); 170 171 return (cache_get_desc(DM_SLICE, dp, name, mname, 172 errp)); 173 } 174 } 175 176 *errp = ENODEV; 177 return (NULL); 178 } 179 180 /* ARGSUSED */ 181 descriptor_t ** 182 slice_get_descriptors(int filter[], int *errp) 183 { 184 return (cache_get_descriptors(DM_SLICE, errp)); 185 } 186 187 char * 188 slice_get_name(descriptor_t *desc) 189 { 190 return (desc->name); 191 } 192 193 nvlist_t * 194 slice_get_stats(descriptor_t *dp, int stat_type, int *errp) 195 { 196 nvlist_t *stats; 197 char *str; 198 199 if (stat_type != DM_SLICE_STAT_USE) { 200 *errp = EINVAL; 201 return (NULL); 202 } 203 204 *errp = 0; 205 206 if (nvlist_alloc(&stats, NVATTRS_STAT, 0) != 0) { 207 *errp = ENOMEM; 208 return (NULL); 209 } 210 211 if ((*errp = add_inuse(dp->name, stats)) != 0) { 212 return (NULL); 213 } 214 215 /* if no cluster use, check for a use of the local name */ 216 if (nvlist_lookup_string(stats, DM_USED_BY, &str) != 0) { 217 disk_t *diskp; 218 219 diskp = dp->p.disk; 220 if (diskp->aliases != NULL && diskp->aliases->cluster) { 221 slice_t *sp; 222 int snum = -1; 223 struct dk_minfo minfo; 224 struct dk_cinfo dkinfo; 225 char devpath[MAXPATHLEN]; 226 int fd; 227 228 /* dp->name is /dev/dsk, need to convert back to /dev/rdsk */ 229 dsk2rdsk(dp->name, devpath, sizeof (devpath)); 230 fd = open(devpath, O_RDONLY|O_NDELAY); 231 232 if (fd >= 0 && media_read_info(fd, &minfo) && 233 ioctl(fd, DKIOCINFO, &dkinfo) >= 0) { 234 snum = dkinfo.dki_partition; 235 } 236 237 if (fd >= 0) { 238 (void) close(fd); 239 } 240 241 if (snum >= 0) { 242 for (sp = diskp->aliases->orig_paths; sp != NULL; 243 sp = sp->next) { 244 245 if (sp->slice_num == snum) { 246 char localpath[MAXPATHLEN]; 247 248 slice_rdsk2dsk(sp->devpath, localpath, 249 sizeof (localpath)); 250 251 if ((*errp = add_inuse(localpath, stats)) != 0) { 252 return (NULL); 253 } 254 255 break; 256 } 257 } 258 } 259 } 260 } 261 262 return (stats); 263 } 264 265 /* 266 * A slice descriptor points to a disk, the name is the devpath and the 267 * secondary name is the media name. 268 */ 269 int 270 slice_make_descriptors() 271 { 272 disk_t *dp; 273 274 dp = cache_get_disklist(); 275 while (dp != NULL) { 276 int error; 277 278 error = make_fixed_descriptors(dp); 279 if (error != 0) { 280 return (error); 281 } 282 283 dp = dp->next; 284 } 285 286 return (0); 287 } 288 289 /* convert rdsk paths to dsk paths */ 290 void 291 slice_rdsk2dsk(char *rdsk, char *dsk, int size) 292 { 293 char *strp; 294 295 (void) strlcpy(dsk, rdsk, size); 296 297 if ((strp = strstr(dsk, "/rdsk/")) == NULL) { 298 /* not rdsk, check for floppy */ 299 strp = strstr(dsk, "/rdiskette"); 300 } 301 302 if (strp != NULL) { 303 strp++; /* move ptr to the r in rdsk or rdiskette */ 304 305 /* move the succeeding chars over by one */ 306 do { 307 *strp = *(strp + 1); 308 strp++; 309 } while (*strp); 310 } 311 } 312 313 /* 314 * Check if/how the slice is used. 315 */ 316 static int 317 add_inuse(char *name, nvlist_t *attrs) 318 { 319 int i; 320 int error; 321 322 for (i = 0; detectors[i] != NULL; i ++) { 323 if (detectors[i](name, attrs, &error) || error != 0) { 324 if (error != 0) { 325 return (error); 326 } 327 break; 328 } 329 } 330 331 return (0); 332 } 333 334 /* return 1 if the slice descriptor is still valid, 0 if not. */ 335 static int 336 desc_ok(descriptor_t *dp) 337 { 338 /* First verify the media name for removable media */ 339 if (dp->p.disk->removable) { 340 char mname[MAXPATHLEN]; 341 342 if (!media_read_name(dp->p.disk, mname, sizeof (mname))) { 343 return (0); 344 } 345 346 if (mname[0] == 0) { 347 return (libdiskmgt_str_eq(dp->secondary_name, NULL)); 348 } else { 349 return (libdiskmgt_str_eq(dp->secondary_name, mname)); 350 } 351 } 352 353 /* 354 * We could verify the slice is still there, but other code down the 355 * line already does these checks (e.g. see get_attrs). 356 */ 357 358 return (1); 359 } 360 361 /* convert dsk paths to rdsk paths */ 362 static void 363 dsk2rdsk(char *dsk, char *rdsk, int size) 364 { 365 char *slashp; 366 size_t len; 367 368 (void) strlcpy(rdsk, dsk, size); 369 370 /* make sure there is enough room to add the r to dsk */ 371 len = strlen(dsk); 372 if (len + 2 > size) { 373 return; 374 } 375 376 if ((slashp = strstr(rdsk, "/dsk/")) == NULL) { 377 /* not dsk, check for floppy */ 378 slashp = strstr(rdsk, "/diskette"); 379 } 380 381 if (slashp != NULL) { 382 char *endp; 383 384 endp = rdsk + len; /* point to terminating 0 */ 385 /* move the succeeding chars over by one */ 386 do { 387 *(endp + 1) = *endp; 388 endp--; 389 } while (endp != slashp); 390 391 *(endp + 1) = 'r'; 392 } 393 } 394 395 static int 396 get_attrs(descriptor_t *dp, int fd, nvlist_t *attrs) 397 { 398 struct dk_minfo minfo; 399 int status; 400 int data_format = FMT_UNKNOWN; 401 int snum = -1; 402 int error; 403 struct extvtoc vtoc; 404 struct dk_gpt *efip; 405 struct dk_cinfo dkinfo; 406 disk_t *diskp; 407 char localpath[MAXPATHLEN]; 408 int cooked_fd; 409 struct stat buf; 410 int mntpnt = 0; 411 412 if (fd < 0) { 413 return (ENODEV); 414 } 415 416 /* First make sure media is inserted and spun up. */ 417 if (!media_read_info(fd, &minfo)) { 418 return (ENODEV); 419 } 420 421 if ((status = read_extvtoc(fd, &vtoc)) >= 0) { 422 data_format = FMT_VTOC; 423 } else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) { 424 data_format = FMT_EFI; 425 if (nvlist_add_boolean(attrs, DM_EFI) != 0) { 426 efi_free(efip); 427 return (ENOMEM); 428 } 429 } 430 431 if (data_format == FMT_UNKNOWN) { 432 return (ENODEV); 433 } 434 435 if (ioctl(fd, DKIOCINFO, &dkinfo) >= 0) { 436 snum = dkinfo.dki_partition; 437 } 438 439 /* check the slice */ 440 if (data_format == FMT_VTOC) { 441 if (snum < 0 || snum >= vtoc.v_nparts || 442 vtoc.v_part[snum].p_size == 0) { 443 return (ENODEV); 444 } 445 } else { /* data_format == FMT_EFI */ 446 if (snum < 0 || snum >= efip->efi_nparts || 447 efip->efi_parts[snum].p_size == 0) { 448 efi_free(efip); 449 return (ENODEV); 450 } 451 } 452 453 /* the slice exists */ 454 455 if (nvlist_add_uint32(attrs, DM_INDEX, snum) != 0) { 456 if (data_format == FMT_EFI) { 457 efi_free(efip); 458 } 459 return (ENOMEM); 460 } 461 462 if (data_format == FMT_VTOC) { 463 if (nvlist_add_uint64(attrs, DM_START, vtoc.v_part[snum].p_start) 464 != 0) { 465 return (ENOMEM); 466 } 467 468 if (nvlist_add_uint64(attrs, DM_SIZE, vtoc.v_part[snum].p_size) 469 != 0) { 470 return (ENOMEM); 471 } 472 473 if (nvlist_add_uint32(attrs, DM_TAG, vtoc.v_part[snum].p_tag) 474 != 0) { 475 return (ENOMEM); 476 } 477 478 if (nvlist_add_uint32(attrs, DM_FLAG, vtoc.v_part[snum].p_flag) 479 != 0) { 480 return (ENOMEM); 481 } 482 483 } else { /* data_format == FMT_EFI */ 484 if (nvlist_add_uint64(attrs, DM_START, 485 efip->efi_parts[snum].p_start) != 0) { 486 efi_free(efip); 487 return (ENOMEM); 488 } 489 490 if (nvlist_add_uint64(attrs, DM_SIZE, efip->efi_parts[snum].p_size) 491 != 0) { 492 efi_free(efip); 493 return (ENOMEM); 494 } 495 496 if (efip->efi_parts[snum].p_name[0] != 0) { 497 char label[EFI_PART_NAME_LEN + 1]; 498 499 (void) snprintf(label, sizeof (label), "%.*s", 500 EFI_PART_NAME_LEN, efip->efi_parts[snum].p_name); 501 if (nvlist_add_string(attrs, DM_EFI_NAME, label) != 0) { 502 efi_free(efip); 503 return (ENOMEM); 504 } 505 } 506 } 507 508 if (data_format == FMT_EFI) { 509 efi_free(efip); 510 } 511 512 if (inuse_mnt(dp->name, attrs, &error)) { 513 if (error != 0) { 514 return (error); 515 } 516 mntpnt = 1; 517 } 518 519 /* 520 * Some extra attrs for cluster slices. 521 * 522 * get localname and possible mnt point for localpath 523 */ 524 localpath[0] = 0; 525 diskp = dp->p.disk; 526 if (diskp->aliases != NULL && diskp->aliases->cluster) { 527 slice_t *sp; 528 529 for (sp = diskp->aliases->orig_paths; sp != NULL; sp = sp->next) { 530 if (sp->slice_num == -1) { 531 /* determine the slice number for this path */ 532 int sfd; 533 struct dk_cinfo dkinfo; 534 535 if ((sfd = open(sp->devpath, O_RDONLY|O_NDELAY)) >= 0) { 536 if (ioctl(sfd, DKIOCINFO, &dkinfo) >= 0) { 537 sp->slice_num = dkinfo.dki_partition; 538 } 539 (void) close(sfd); 540 } 541 } 542 543 if (sp->slice_num == snum) { 544 slice_rdsk2dsk(sp->devpath, localpath, sizeof (localpath)); 545 546 if (nvlist_add_string(attrs, DM_LOCALNAME, localpath) 547 != 0) { 548 return (ENOMEM); 549 } 550 551 if (mntpnt == 0) { 552 if (inuse_mnt(localpath, attrs, &error)) { 553 if (error != 0) { 554 return (error); 555 } 556 } 557 } 558 559 break; 560 } 561 } 562 } 563 564 if (fstat(fd, &buf) != -1) { 565 if (nvlist_add_uint64(attrs, DM_DEVT, buf.st_rdev) != 0) { 566 return (ENOMEM); 567 } 568 } 569 570 /* 571 * We need to open the cooked slice (not the raw one) to get the 572 * correct devid. Also see if we need to read the localpath for the 573 * cluster disk, since the minor name is unavailable for the did pseudo 574 * device. 575 */ 576 if (localpath[0] != 0) { 577 cooked_fd = open(localpath, O_RDONLY|O_NDELAY); 578 } else { 579 cooked_fd = open(dp->name, O_RDONLY|O_NDELAY); 580 } 581 582 if (cooked_fd >= 0) { 583 int no_mem = 0; 584 ddi_devid_t devid; 585 586 if (devid_get(cooked_fd, &devid) == 0) { 587 char *minor; 588 589 if (devid_get_minor_name(cooked_fd, &minor) == 0) { 590 char *devidstr; 591 592 if ((devidstr = devid_str_encode(devid, minor)) != 0) { 593 594 if (nvlist_add_string(attrs, DM_DEVICEID, devidstr) 595 != 0) { 596 no_mem = 1; 597 } 598 599 devid_str_free(devidstr); 600 } 601 devid_str_free(minor); 602 } 603 devid_free(devid); 604 } 605 (void) close(cooked_fd); 606 607 if (no_mem) { 608 return (ENOMEM); 609 } 610 } 611 612 return (0); 613 } 614 615 static descriptor_t ** 616 get_fixed_assocs(descriptor_t *desc, int *errp) 617 { 618 int fd; 619 int status; 620 int data_format = FMT_UNKNOWN; 621 int cnt; 622 struct extvtoc vtoc; 623 struct dk_gpt *efip; 624 int pos; 625 char *media_name = NULL; 626 slice_t *devp; 627 descriptor_t **slices; 628 629 if ((fd = drive_open_disk(desc->p.disk, NULL, 0)) < 0) { 630 *errp = ENODEV; 631 return (NULL); 632 } 633 634 if ((status = read_extvtoc(fd, &vtoc)) >= 0) { 635 data_format = FMT_VTOC; 636 } else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) { 637 data_format = FMT_EFI; 638 } else { 639 (void) close(fd); 640 *errp = 0; 641 return (libdiskmgt_empty_desc_array(errp)); 642 } 643 (void) close(fd); 644 645 /* count the number of slices */ 646 for (cnt = 0, devp = desc->p.disk->aliases->devpaths; devp != NULL; 647 devp = devp->next, cnt++); 648 649 /* allocate the array for the descriptors */ 650 slices = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *)); 651 if (slices == NULL) { 652 if (data_format == FMT_EFI) { 653 efi_free(efip); 654 } 655 *errp = ENOMEM; 656 return (NULL); 657 } 658 659 /* get the media name from the descriptor */ 660 if (desc->type == DM_MEDIA) { 661 media_name = desc->name; 662 } else { 663 /* must be a DM_PARTITION */ 664 media_name = desc->secondary_name; 665 } 666 667 pos = 0; 668 for (devp = desc->p.disk->aliases->devpaths; devp != NULL; 669 devp = devp->next) { 670 671 int slice_num; 672 char devpath[MAXPATHLEN]; 673 674 slice_num = get_slice_num(devp); 675 /* can't get slicenum, so no need to keep trying the drive */ 676 if (slice_num == -1) { 677 break; 678 } 679 680 if (data_format == FMT_VTOC) { 681 if (slice_num >= vtoc.v_nparts || 682 vtoc.v_part[slice_num].p_size == 0) { 683 continue; 684 } 685 } else { /* data_format == FMT_EFI */ 686 if (slice_num >= efip->efi_nparts || 687 efip->efi_parts[slice_num].p_size == 0) { 688 continue; 689 } 690 } 691 692 slice_rdsk2dsk(devp->devpath, devpath, sizeof (devpath)); 693 slices[pos] = cache_get_desc(DM_SLICE, desc->p.disk, devpath, 694 media_name, errp); 695 if (*errp != 0) { 696 cache_free_descriptors(slices); 697 if (data_format == FMT_EFI) { 698 efi_free(efip); 699 } 700 return (NULL); 701 } 702 pos++; 703 } 704 slices[pos] = NULL; 705 706 if (data_format == FMT_EFI) { 707 efi_free(efip); 708 } 709 710 *errp = 0; 711 return (slices); 712 } 713 714 static int 715 get_slice_num(slice_t *devp) 716 { 717 /* check if we already determined the devpath slice number */ 718 if (devp->slice_num == -1) { 719 int fd; 720 721 if ((fd = open(devp->devpath, O_RDONLY|O_NDELAY)) >= 0) { 722 struct dk_cinfo dkinfo; 723 if (ioctl(fd, DKIOCINFO, &dkinfo) >= 0) { 724 devp->slice_num = dkinfo.dki_partition; 725 } 726 (void) close(fd); 727 } 728 } 729 730 return (devp->slice_num); 731 } 732 733 static int 734 make_fixed_descriptors(disk_t *dp) 735 { 736 int error = 0; 737 alias_t *ap; 738 slice_t *devp; 739 char mname[MAXPATHLEN]; 740 int data_format = FMT_UNKNOWN; 741 struct extvtoc vtoc; 742 struct dk_gpt *efip; 743 744 /* Just check the first drive name. */ 745 if ((ap = dp->aliases) == NULL) { 746 return (0); 747 } 748 749 mname[0] = 0; 750 (void) media_read_name(dp, mname, sizeof (mname)); 751 752 for (devp = ap->devpaths; devp != NULL; devp = devp->next) { 753 int slice_num; 754 char devpath[MAXPATHLEN]; 755 756 slice_num = get_slice_num(devp); 757 /* can't get slicenum, so no need to keep trying the drive */ 758 if (slice_num == -1) { 759 break; 760 } 761 762 if (data_format == FMT_UNKNOWN) { 763 int fd; 764 int status; 765 766 if ((fd = drive_open_disk(dp, NULL, 0)) >= 0) { 767 if ((status = read_extvtoc(fd, &vtoc)) >= 0) { 768 data_format = FMT_VTOC; 769 } else if (status == VT_ENOTSUP && 770 efi_alloc_and_read(fd, &efip) >= 0) { 771 data_format = FMT_EFI; 772 } 773 (void) close(fd); 774 } 775 } 776 777 /* can't get slice data, so no need to keep trying the drive */ 778 if (data_format == FMT_UNKNOWN) { 779 break; 780 } 781 782 if (data_format == FMT_VTOC) { 783 if (slice_num >= vtoc.v_nparts || 784 vtoc.v_part[slice_num].p_size == 0) { 785 continue; 786 } 787 } else { /* data_format == FMT_EFI */ 788 if (slice_num >= efip->efi_nparts || 789 efip->efi_parts[slice_num].p_size == 0) { 790 continue; 791 } 792 } 793 794 slice_rdsk2dsk(devp->devpath, devpath, sizeof (devpath)); 795 cache_load_desc(DM_SLICE, dp, devpath, mname, &error); 796 if (error != 0) { 797 break; 798 } 799 } 800 801 if (data_format == FMT_EFI) { 802 efi_free(efip); 803 } 804 805 return (error); 806 } 807 808 /* 809 * Just look for the name on the devpaths we have cached. Return 1 if we 810 * find the name and the size of that slice is non-zero. 811 */ 812 static int 813 match_fixed_name(disk_t *diskp, char *name, int *errp) 814 { 815 slice_t *dp = NULL; 816 alias_t *ap; 817 int slice_num; 818 int fd; 819 int status; 820 int data_format = FMT_UNKNOWN; 821 struct extvtoc vtoc; 822 struct dk_gpt *efip; 823 824 ap = diskp->aliases; 825 while (ap != NULL) { 826 slice_t *devp; 827 828 devp = ap->devpaths; 829 while (devp != NULL) { 830 char path[MAXPATHLEN]; 831 832 slice_rdsk2dsk(devp->devpath, path, sizeof (path)); 833 if (libdiskmgt_str_eq(path, name)) { 834 /* found it */ 835 dp = devp; 836 break; 837 } 838 839 devp = devp->next; 840 } 841 842 if (dp != NULL) { 843 break; 844 } 845 846 ap = ap->next; 847 } 848 849 if (dp == NULL) { 850 *errp = 0; 851 return (0); 852 } 853 854 /* 855 * If we found a match on the name we now have to check that this 856 * slice really exists (non-0 size). 857 */ 858 859 slice_num = get_slice_num(dp); 860 /* can't get slicenum, so no slice */ 861 if (slice_num == -1) { 862 *errp = ENODEV; 863 return (1); 864 } 865 866 if ((fd = drive_open_disk(diskp, NULL, 0)) < 0) { 867 *errp = ENODEV; 868 return (1); 869 } 870 871 if ((status = read_extvtoc(fd, &vtoc)) >= 0) { 872 data_format = FMT_VTOC; 873 } else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) { 874 data_format = FMT_EFI; 875 } else { 876 (void) close(fd); 877 *errp = ENODEV; 878 return (1); 879 } 880 (void) close(fd); 881 882 if (data_format == FMT_VTOC) { 883 if (slice_num < vtoc.v_nparts && 884 vtoc.v_part[slice_num].p_size > 0) { 885 *errp = 0; 886 return (1); 887 } 888 } else { /* data_format == FMT_EFI */ 889 if (slice_num < efip->efi_nparts && 890 efip->efi_parts[slice_num].p_size > 0) { 891 efi_free(efip); 892 *errp = 0; 893 return (1); 894 } 895 efi_free(efip); 896 } 897 898 *errp = ENODEV; 899 return (1); 900 } 901