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