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 nvlist_free(stats); 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 nvlist_free(stats); 253 return (NULL); 254 } 255 256 break; 257 } 258 } 259 } 260 } 261 } 262 263 return (stats); 264 } 265 266 /* 267 * A slice descriptor points to a disk, the name is the devpath and the 268 * secondary name is the media name. 269 */ 270 int 271 slice_make_descriptors() 272 { 273 disk_t *dp; 274 275 dp = cache_get_disklist(); 276 while (dp != NULL) { 277 int error; 278 279 error = make_fixed_descriptors(dp); 280 if (error != 0) { 281 return (error); 282 } 283 284 dp = dp->next; 285 } 286 287 return (0); 288 } 289 290 /* convert rdsk paths to dsk paths */ 291 void 292 slice_rdsk2dsk(char *rdsk, char *dsk, int size) 293 { 294 char *strp; 295 296 (void) strlcpy(dsk, rdsk, size); 297 298 if ((strp = strstr(dsk, "/rdsk/")) == NULL) { 299 /* not rdsk, check for floppy */ 300 strp = strstr(dsk, "/rdiskette"); 301 } 302 303 if (strp != NULL) { 304 strp++; /* move ptr to the r in rdsk or rdiskette */ 305 306 /* move the succeeding chars over by one */ 307 do { 308 *strp = *(strp + 1); 309 strp++; 310 } while (*strp); 311 } 312 } 313 314 /* 315 * Check if/how the slice is used. 316 */ 317 static int 318 add_inuse(char *name, nvlist_t *attrs) 319 { 320 int i; 321 int error; 322 323 for (i = 0; detectors[i] != NULL; i ++) { 324 if (detectors[i](name, attrs, &error) || error != 0) { 325 if (error != 0) { 326 return (error); 327 } 328 break; 329 } 330 } 331 332 return (0); 333 } 334 335 /* return 1 if the slice descriptor is still valid, 0 if not. */ 336 static int 337 desc_ok(descriptor_t *dp) 338 { 339 /* First verify the media name for removable media */ 340 if (dp->p.disk->removable) { 341 char mname[MAXPATHLEN]; 342 343 if (!media_read_name(dp->p.disk, mname, sizeof (mname))) { 344 return (0); 345 } 346 347 if (mname[0] == 0) { 348 return (libdiskmgt_str_eq(dp->secondary_name, NULL)); 349 } else { 350 return (libdiskmgt_str_eq(dp->secondary_name, mname)); 351 } 352 } 353 354 /* 355 * We could verify the slice is still there, but other code down the 356 * line already does these checks (e.g. see get_attrs). 357 */ 358 359 return (1); 360 } 361 362 /* convert dsk paths to rdsk paths */ 363 static void 364 dsk2rdsk(char *dsk, char *rdsk, int size) 365 { 366 char *slashp; 367 size_t len; 368 369 (void) strlcpy(rdsk, dsk, size); 370 371 /* make sure there is enough room to add the r to dsk */ 372 len = strlen(dsk); 373 if (len + 2 > size) { 374 return; 375 } 376 377 if ((slashp = strstr(rdsk, "/dsk/")) == NULL) { 378 /* not dsk, check for floppy */ 379 slashp = strstr(rdsk, "/diskette"); 380 } 381 382 if (slashp != NULL) { 383 char *endp; 384 385 endp = rdsk + len; /* point to terminating 0 */ 386 /* move the succeeding chars over by one */ 387 do { 388 *(endp + 1) = *endp; 389 endp--; 390 } while (endp != slashp); 391 392 *(endp + 1) = 'r'; 393 } 394 } 395 396 static int 397 get_attrs(descriptor_t *dp, int fd, nvlist_t *attrs) 398 { 399 struct dk_minfo minfo; 400 int status; 401 int data_format = FMT_UNKNOWN; 402 int snum = -1; 403 int error; 404 struct extvtoc vtoc; 405 struct dk_gpt *efip; 406 struct dk_cinfo dkinfo; 407 disk_t *diskp; 408 char localpath[MAXPATHLEN]; 409 int cooked_fd; 410 struct stat buf; 411 int mntpnt = 0; 412 413 if (fd < 0) { 414 return (ENODEV); 415 } 416 417 /* First make sure media is inserted and spun up. */ 418 if (!media_read_info(fd, &minfo)) { 419 return (ENODEV); 420 } 421 422 if ((status = read_extvtoc(fd, &vtoc)) >= 0) { 423 data_format = FMT_VTOC; 424 } else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) { 425 data_format = FMT_EFI; 426 if (nvlist_add_boolean(attrs, DM_EFI) != 0) { 427 efi_free(efip); 428 return (ENOMEM); 429 } 430 } 431 432 if (data_format == FMT_UNKNOWN) { 433 return (ENODEV); 434 } 435 436 if (ioctl(fd, DKIOCINFO, &dkinfo) >= 0) { 437 snum = dkinfo.dki_partition; 438 } 439 440 /* check the slice */ 441 if (data_format == FMT_VTOC) { 442 if (snum < 0 || snum >= vtoc.v_nparts || 443 vtoc.v_part[snum].p_size == 0) { 444 return (ENODEV); 445 } 446 } else { /* data_format == FMT_EFI */ 447 if (snum < 0 || snum >= efip->efi_nparts || 448 efip->efi_parts[snum].p_size == 0) { 449 efi_free(efip); 450 return (ENODEV); 451 } 452 } 453 454 /* the slice exists */ 455 456 if (nvlist_add_uint32(attrs, DM_INDEX, snum) != 0) { 457 if (data_format == FMT_EFI) { 458 efi_free(efip); 459 } 460 return (ENOMEM); 461 } 462 463 if (data_format == FMT_VTOC) { 464 if (nvlist_add_uint64(attrs, DM_START, vtoc.v_part[snum].p_start) 465 != 0) { 466 return (ENOMEM); 467 } 468 469 if (nvlist_add_uint64(attrs, DM_SIZE, vtoc.v_part[snum].p_size) 470 != 0) { 471 return (ENOMEM); 472 } 473 474 if (nvlist_add_uint32(attrs, DM_TAG, vtoc.v_part[snum].p_tag) 475 != 0) { 476 return (ENOMEM); 477 } 478 479 if (nvlist_add_uint32(attrs, DM_FLAG, vtoc.v_part[snum].p_flag) 480 != 0) { 481 return (ENOMEM); 482 } 483 484 } else { /* data_format == FMT_EFI */ 485 if (nvlist_add_uint64(attrs, DM_START, 486 efip->efi_parts[snum].p_start) != 0) { 487 efi_free(efip); 488 return (ENOMEM); 489 } 490 491 if (nvlist_add_uint64(attrs, DM_SIZE, efip->efi_parts[snum].p_size) 492 != 0) { 493 efi_free(efip); 494 return (ENOMEM); 495 } 496 497 if (efip->efi_parts[snum].p_name[0] != 0) { 498 char label[EFI_PART_NAME_LEN + 1]; 499 500 (void) snprintf(label, sizeof (label), "%.*s", 501 EFI_PART_NAME_LEN, efip->efi_parts[snum].p_name); 502 if (nvlist_add_string(attrs, DM_EFI_NAME, label) != 0) { 503 efi_free(efip); 504 return (ENOMEM); 505 } 506 } 507 } 508 509 if (data_format == FMT_EFI) { 510 efi_free(efip); 511 } 512 513 if (inuse_mnt(dp->name, attrs, &error)) { 514 if (error != 0) { 515 return (error); 516 } 517 mntpnt = 1; 518 } 519 520 /* 521 * Some extra attrs for cluster slices. 522 * 523 * get localname and possible mnt point for localpath 524 */ 525 localpath[0] = 0; 526 diskp = dp->p.disk; 527 if (diskp->aliases != NULL && diskp->aliases->cluster) { 528 slice_t *sp; 529 530 for (sp = diskp->aliases->orig_paths; sp != NULL; sp = sp->next) { 531 if (sp->slice_num == -1) { 532 /* determine the slice number for this path */ 533 int sfd; 534 struct dk_cinfo dkinfo; 535 536 if ((sfd = open(sp->devpath, O_RDONLY|O_NDELAY)) >= 0) { 537 if (ioctl(sfd, DKIOCINFO, &dkinfo) >= 0) { 538 sp->slice_num = dkinfo.dki_partition; 539 } 540 (void) close(sfd); 541 } 542 } 543 544 if (sp->slice_num == snum) { 545 slice_rdsk2dsk(sp->devpath, localpath, sizeof (localpath)); 546 547 if (nvlist_add_string(attrs, DM_LOCALNAME, localpath) 548 != 0) { 549 return (ENOMEM); 550 } 551 552 if (mntpnt == 0) { 553 if (inuse_mnt(localpath, attrs, &error)) { 554 if (error != 0) { 555 return (error); 556 } 557 } 558 } 559 560 break; 561 } 562 } 563 } 564 565 if (fstat(fd, &buf) != -1) { 566 if (nvlist_add_uint64(attrs, DM_DEVT, buf.st_rdev) != 0) { 567 return (ENOMEM); 568 } 569 } 570 571 /* 572 * We need to open the cooked slice (not the raw one) to get the 573 * correct devid. Also see if we need to read the localpath for the 574 * cluster disk, since the minor name is unavailable for the did pseudo 575 * device. 576 */ 577 if (localpath[0] != 0) { 578 cooked_fd = open(localpath, O_RDONLY|O_NDELAY); 579 } else { 580 cooked_fd = open(dp->name, O_RDONLY|O_NDELAY); 581 } 582 583 if (cooked_fd >= 0) { 584 int no_mem = 0; 585 ddi_devid_t devid; 586 587 if (devid_get(cooked_fd, &devid) == 0) { 588 char *minor; 589 590 if (devid_get_minor_name(cooked_fd, &minor) == 0) { 591 char *devidstr; 592 593 if ((devidstr = devid_str_encode(devid, minor)) != 0) { 594 595 if (nvlist_add_string(attrs, DM_DEVICEID, devidstr) 596 != 0) { 597 no_mem = 1; 598 } 599 600 devid_str_free(devidstr); 601 } 602 devid_str_free(minor); 603 } 604 devid_free(devid); 605 } 606 (void) close(cooked_fd); 607 608 if (no_mem) { 609 return (ENOMEM); 610 } 611 } 612 613 return (0); 614 } 615 616 static descriptor_t ** 617 get_fixed_assocs(descriptor_t *desc, int *errp) 618 { 619 int fd; 620 int status; 621 int data_format = FMT_UNKNOWN; 622 int cnt; 623 struct extvtoc vtoc; 624 struct dk_gpt *efip; 625 int pos; 626 char *media_name = NULL; 627 slice_t *devp; 628 descriptor_t **slices; 629 630 if ((fd = drive_open_disk(desc->p.disk, NULL, 0)) < 0) { 631 *errp = ENODEV; 632 return (NULL); 633 } 634 635 if ((status = read_extvtoc(fd, &vtoc)) >= 0) { 636 data_format = FMT_VTOC; 637 } else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) { 638 data_format = FMT_EFI; 639 } else { 640 (void) close(fd); 641 *errp = 0; 642 return (libdiskmgt_empty_desc_array(errp)); 643 } 644 (void) close(fd); 645 646 /* count the number of slices */ 647 for (cnt = 0, devp = desc->p.disk->aliases->devpaths; devp != NULL; 648 devp = devp->next, cnt++); 649 650 /* allocate the array for the descriptors */ 651 slices = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *)); 652 if (slices == NULL) { 653 if (data_format == FMT_EFI) { 654 efi_free(efip); 655 } 656 *errp = ENOMEM; 657 return (NULL); 658 } 659 660 /* get the media name from the descriptor */ 661 if (desc->type == DM_MEDIA) { 662 media_name = desc->name; 663 } else { 664 /* must be a DM_PARTITION */ 665 media_name = desc->secondary_name; 666 } 667 668 pos = 0; 669 for (devp = desc->p.disk->aliases->devpaths; devp != NULL; 670 devp = devp->next) { 671 672 int slice_num; 673 char devpath[MAXPATHLEN]; 674 675 slice_num = get_slice_num(devp); 676 /* can't get slicenum, so no need to keep trying the drive */ 677 if (slice_num == -1) { 678 break; 679 } 680 681 if (data_format == FMT_VTOC) { 682 if (slice_num >= vtoc.v_nparts || 683 vtoc.v_part[slice_num].p_size == 0) { 684 continue; 685 } 686 } else { /* data_format == FMT_EFI */ 687 if (slice_num >= efip->efi_nparts || 688 efip->efi_parts[slice_num].p_size == 0) { 689 continue; 690 } 691 } 692 693 slice_rdsk2dsk(devp->devpath, devpath, sizeof (devpath)); 694 slices[pos] = cache_get_desc(DM_SLICE, desc->p.disk, devpath, 695 media_name, errp); 696 if (*errp != 0) { 697 cache_free_descriptors(slices); 698 if (data_format == FMT_EFI) { 699 efi_free(efip); 700 } 701 return (NULL); 702 } 703 pos++; 704 } 705 slices[pos] = NULL; 706 707 if (data_format == FMT_EFI) { 708 efi_free(efip); 709 } 710 711 *errp = 0; 712 return (slices); 713 } 714 715 static int 716 get_slice_num(slice_t *devp) 717 { 718 /* check if we already determined the devpath slice number */ 719 if (devp->slice_num == -1) { 720 int fd; 721 722 if ((fd = open(devp->devpath, O_RDONLY|O_NDELAY)) >= 0) { 723 struct dk_cinfo dkinfo; 724 if (ioctl(fd, DKIOCINFO, &dkinfo) >= 0) { 725 devp->slice_num = dkinfo.dki_partition; 726 } 727 (void) close(fd); 728 } 729 } 730 731 return (devp->slice_num); 732 } 733 734 static int 735 make_fixed_descriptors(disk_t *dp) 736 { 737 int error = 0; 738 alias_t *ap; 739 slice_t *devp; 740 char mname[MAXPATHLEN]; 741 int data_format = FMT_UNKNOWN; 742 struct extvtoc vtoc; 743 struct dk_gpt *efip; 744 745 /* Just check the first drive name. */ 746 if ((ap = dp->aliases) == NULL) { 747 return (0); 748 } 749 750 mname[0] = 0; 751 (void) media_read_name(dp, mname, sizeof (mname)); 752 753 for (devp = ap->devpaths; devp != NULL; devp = devp->next) { 754 int slice_num; 755 char devpath[MAXPATHLEN]; 756 757 slice_num = get_slice_num(devp); 758 /* can't get slicenum, so no need to keep trying the drive */ 759 if (slice_num == -1) { 760 break; 761 } 762 763 if (data_format == FMT_UNKNOWN) { 764 int fd; 765 int status; 766 767 if ((fd = drive_open_disk(dp, NULL, 0)) >= 0) { 768 if ((status = read_extvtoc(fd, &vtoc)) >= 0) { 769 data_format = FMT_VTOC; 770 } else if (status == VT_ENOTSUP && 771 efi_alloc_and_read(fd, &efip) >= 0) { 772 data_format = FMT_EFI; 773 } 774 (void) close(fd); 775 } 776 } 777 778 /* can't get slice data, so no need to keep trying the drive */ 779 if (data_format == FMT_UNKNOWN) { 780 break; 781 } 782 783 if (data_format == FMT_VTOC) { 784 if (slice_num >= vtoc.v_nparts || 785 vtoc.v_part[slice_num].p_size == 0) { 786 continue; 787 } 788 } else { /* data_format == FMT_EFI */ 789 if (slice_num >= efip->efi_nparts || 790 efip->efi_parts[slice_num].p_size == 0) { 791 continue; 792 } 793 } 794 795 slice_rdsk2dsk(devp->devpath, devpath, sizeof (devpath)); 796 cache_load_desc(DM_SLICE, dp, devpath, mname, &error); 797 if (error != 0) { 798 break; 799 } 800 } 801 802 if (data_format == FMT_EFI) { 803 efi_free(efip); 804 } 805 806 return (error); 807 } 808 809 /* 810 * Just look for the name on the devpaths we have cached. Return 1 if we 811 * find the name and the size of that slice is non-zero. 812 */ 813 static int 814 match_fixed_name(disk_t *diskp, char *name, int *errp) 815 { 816 slice_t *dp = NULL; 817 alias_t *ap; 818 int slice_num; 819 int fd; 820 int status; 821 int data_format = FMT_UNKNOWN; 822 struct extvtoc vtoc; 823 struct dk_gpt *efip; 824 825 ap = diskp->aliases; 826 while (ap != NULL) { 827 slice_t *devp; 828 829 devp = ap->devpaths; 830 while (devp != NULL) { 831 char path[MAXPATHLEN]; 832 833 slice_rdsk2dsk(devp->devpath, path, sizeof (path)); 834 if (libdiskmgt_str_eq(path, name)) { 835 /* found it */ 836 dp = devp; 837 break; 838 } 839 840 devp = devp->next; 841 } 842 843 if (dp != NULL) { 844 break; 845 } 846 847 ap = ap->next; 848 } 849 850 if (dp == NULL) { 851 *errp = 0; 852 return (0); 853 } 854 855 /* 856 * If we found a match on the name we now have to check that this 857 * slice really exists (non-0 size). 858 */ 859 860 slice_num = get_slice_num(dp); 861 /* can't get slicenum, so no slice */ 862 if (slice_num == -1) { 863 *errp = ENODEV; 864 return (1); 865 } 866 867 if ((fd = drive_open_disk(diskp, NULL, 0)) < 0) { 868 *errp = ENODEV; 869 return (1); 870 } 871 872 if ((status = read_extvtoc(fd, &vtoc)) >= 0) { 873 data_format = FMT_VTOC; 874 } else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) { 875 data_format = FMT_EFI; 876 } else { 877 (void) close(fd); 878 *errp = ENODEV; 879 return (1); 880 } 881 (void) close(fd); 882 883 if (data_format == FMT_VTOC) { 884 if (slice_num < vtoc.v_nparts && 885 vtoc.v_part[slice_num].p_size > 0) { 886 *errp = 0; 887 return (1); 888 } 889 } else { /* data_format == FMT_EFI */ 890 if (slice_num < efip->efi_nparts && 891 efip->efi_parts[slice_num].p_size > 0) { 892 efi_free(efip); 893 *errp = 0; 894 return (1); 895 } 896 efi_free(efip); 897 } 898 899 *errp = ENODEV; 900 return (1); 901 } 902