10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
70Sstevel@tonic-gate * with the License.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate * See the License for the specific language governing permissions
120Sstevel@tonic-gate * and limitations under the License.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * CDDL HEADER END
210Sstevel@tonic-gate */
220Sstevel@tonic-gate /*
23*62Sjeanm * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include <string.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <sys/vtoc.h>
340Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
350Sstevel@tonic-gate #include <errno.h>
360Sstevel@tonic-gate #include <meta.h>
370Sstevel@tonic-gate
380Sstevel@tonic-gate #include <libdiskmgt.h>
390Sstevel@tonic-gate #include "meta_repartition.h"
400Sstevel@tonic-gate
410Sstevel@tonic-gate #define _LAYOUT_DEVICE_UTIL_C
420Sstevel@tonic-gate
430Sstevel@tonic-gate #include "volume_dlist.h"
440Sstevel@tonic-gate #include "volume_error.h"
450Sstevel@tonic-gate #include "volume_output.h"
460Sstevel@tonic-gate #include "volume_nvpair.h"
470Sstevel@tonic-gate
480Sstevel@tonic-gate #include "layout_device_cache.h"
490Sstevel@tonic-gate #include "layout_device_util.h"
500Sstevel@tonic-gate #include "layout_discovery.h"
510Sstevel@tonic-gate #include "layout_dlist_util.h"
520Sstevel@tonic-gate #include "layout_slice.h"
530Sstevel@tonic-gate
540Sstevel@tonic-gate /*
550Sstevel@tonic-gate * Macros to produce a quoted string containing the value of a
560Sstevel@tonic-gate * preprocessor macro. For example, if SIZE is defined to be 256,
570Sstevel@tonic-gate * VAL2STR(SIZE) is "256". This is used to construct format
580Sstevel@tonic-gate * strings for scanf-family functions below.
590Sstevel@tonic-gate */
600Sstevel@tonic-gate #define QUOTE(x) #x
610Sstevel@tonic-gate #define VAL2STR(x) QUOTE(x)
620Sstevel@tonic-gate
630Sstevel@tonic-gate /* private utilities for disks */
640Sstevel@tonic-gate static int disk_get_uint64_attribute(
650Sstevel@tonic-gate dm_descriptor_t disk,
660Sstevel@tonic-gate char *attr,
670Sstevel@tonic-gate uint64_t *val);
680Sstevel@tonic-gate
690Sstevel@tonic-gate static int disk_get_boolean_attribute(
700Sstevel@tonic-gate dm_descriptor_t disk,
710Sstevel@tonic-gate char *attr,
720Sstevel@tonic-gate boolean_t *bool);
730Sstevel@tonic-gate
740Sstevel@tonic-gate static int disk_get_rpm(
750Sstevel@tonic-gate dm_descriptor_t disk,
760Sstevel@tonic-gate uint32_t *val);
770Sstevel@tonic-gate
780Sstevel@tonic-gate static int disk_get_sync_speed(
790Sstevel@tonic-gate dm_descriptor_t disk,
800Sstevel@tonic-gate uint32_t *val);
810Sstevel@tonic-gate
820Sstevel@tonic-gate static int disk_has_virtual_slices(
830Sstevel@tonic-gate dm_descriptor_t disk,
840Sstevel@tonic-gate boolean_t *bool);
850Sstevel@tonic-gate
860Sstevel@tonic-gate static int disk_get_virtual_slices(
870Sstevel@tonic-gate dm_descriptor_t disk,
880Sstevel@tonic-gate dlist_t **list);
890Sstevel@tonic-gate
900Sstevel@tonic-gate static int disk_get_reserved_indexes(
910Sstevel@tonic-gate dm_descriptor_t disk,
920Sstevel@tonic-gate uint16_t **array);
930Sstevel@tonic-gate
940Sstevel@tonic-gate static int disk_get_associated_desc(
950Sstevel@tonic-gate dm_descriptor_t disk,
960Sstevel@tonic-gate dm_desc_type_t assoc_type,
970Sstevel@tonic-gate char *assoc_type_str,
980Sstevel@tonic-gate dlist_t **list);
990Sstevel@tonic-gate
1000Sstevel@tonic-gate /* utilities for slices */
1010Sstevel@tonic-gate static int slice_get_uint64_attribute(
1020Sstevel@tonic-gate dm_descriptor_t slice,
1030Sstevel@tonic-gate char *attr,
1040Sstevel@tonic-gate uint64_t *val);
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate static int slice_set_attribute(
1070Sstevel@tonic-gate dm_descriptor_t slice,
1080Sstevel@tonic-gate char *attr,
1090Sstevel@tonic-gate uint64_t val);
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate /*
1120Sstevel@tonic-gate * Virtual slices are created to represent slices that will be
1130Sstevel@tonic-gate * on the system after disks have been added to the destination
1140Sstevel@tonic-gate * diskset. For the purposes of layout, these slices must
1150Sstevel@tonic-gate * look & function just as real slices that are currently on
1160Sstevel@tonic-gate * the system.
1170Sstevel@tonic-gate */
1180Sstevel@tonic-gate static dlist_t *_virtual_slices = NULL;
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate /* temporary implementation */
1210Sstevel@tonic-gate static int virtual_repartition_drive(
1220Sstevel@tonic-gate dm_descriptor_t disk,
1230Sstevel@tonic-gate mdvtoc_t *vtocp);
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate static int disk_add_virtual_slice(
1260Sstevel@tonic-gate dm_descriptor_t disk,
1270Sstevel@tonic-gate dm_descriptor_t slice);
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate static int virtual_slice_get_disk(
1300Sstevel@tonic-gate dm_descriptor_t slice,
1310Sstevel@tonic-gate dm_descriptor_t *diskp);
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate /*
1340Sstevel@tonic-gate * attribute names for layout private information stored in
1350Sstevel@tonic-gate * device nvpair attribute lists.
1360Sstevel@tonic-gate */
1370Sstevel@tonic-gate static char *ATTR_RESERVED_INDEX = "vdu_reserved_index";
1380Sstevel@tonic-gate static char *ATTR_VIRTUAL_SLICES = "vdu_virtual_slices";
1390Sstevel@tonic-gate static char *ATTR_DISK_FOR_SLICE = "vdu_disk_for_slice";
1400Sstevel@tonic-gate static char *ATTR_DEV_CTD_NAME = "vdu_device_ctd_name";
1410Sstevel@tonic-gate static char *ATTR_HBA_N_DISKS = "vdu_hba_n_usable_disks";
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate /*
1440Sstevel@tonic-gate * FUNCTION: is_ctd_like_slice_name(char *name)
1450Sstevel@tonic-gate * INPUT: name - a char *
1460Sstevel@tonic-gate *
1470Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE - if name follows an alternate slice
1480Sstevel@tonic-gate * naming scheme similar to CTD
1490Sstevel@tonic-gate * B_FALSE - otherwise
1500Sstevel@tonic-gate *
1510Sstevel@tonic-gate * PURPOSE: Determines if the input name is of the form XXXsNNN
1520Sstevel@tonic-gate * (e.g., whizzy0s1)
1530Sstevel@tonic-gate */
1540Sstevel@tonic-gate boolean_t
is_ctd_like_slice_name(char * name)1550Sstevel@tonic-gate is_ctd_like_slice_name(
1560Sstevel@tonic-gate char *name)
1570Sstevel@tonic-gate {
1580Sstevel@tonic-gate uint_t s = 0;
1590Sstevel@tonic-gate uint_t d = 0;
1600Sstevel@tonic-gate int l = 0;
1610Sstevel@tonic-gate boolean_t is = B_FALSE;
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate /* The format strings below match and discard the non-numeric part. */
1640Sstevel@tonic-gate if ((sscanf(name, "/dev/dsk/%*[^0-9/]%us%u%n", &d, &s, &l) == 2 ||
1650Sstevel@tonic-gate sscanf(name, "/dev/rdsk/%*[^0-9/]%us%u%n", &d, &s, &l) == 2 ||
1660Sstevel@tonic-gate sscanf(name, "%*[^0-9/]%us%u%n", &d, &s, &l) == 2) &&
1670Sstevel@tonic-gate (l == strlen(name))) {
1680Sstevel@tonic-gate is = B_TRUE;
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate return (is);
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate /*
1750Sstevel@tonic-gate * FUNCTION: is_bsd_like_slice_name(char *name)
1760Sstevel@tonic-gate * INPUT: name - a char *
1770Sstevel@tonic-gate *
1780Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE - if name follows an alternate slice
1790Sstevel@tonic-gate * BSD-like naming scheme
1800Sstevel@tonic-gate * B_FALSE - otherwise
1810Sstevel@tonic-gate *
1820Sstevel@tonic-gate * PURPOSE: Determines if the input name is of the form XXXNNN[a-h]
1830Sstevel@tonic-gate * (e.g., whizzy0a)
1840Sstevel@tonic-gate */
1850Sstevel@tonic-gate boolean_t
is_bsd_like_slice_name(char * name)1860Sstevel@tonic-gate is_bsd_like_slice_name(
1870Sstevel@tonic-gate char *name)
1880Sstevel@tonic-gate {
1890Sstevel@tonic-gate uint_t d = 0;
1900Sstevel@tonic-gate int l = 0;
1910Sstevel@tonic-gate boolean_t is = B_FALSE;
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate /* The format strings below match and discard the non-numeric part. */
1940Sstevel@tonic-gate if ((sscanf(name, "/dev/dsk/%*[^0-9/]%u%*[a-h]%n", &d, &l) == 1 ||
1950Sstevel@tonic-gate sscanf(name, "/dev/rdsk/%*[^0-9/]%u%*[a-h]%n", &d, &l) == 1 ||
1960Sstevel@tonic-gate sscanf(name, "%*[^0-9/]%u%*[a-h]%n", &d, &l) == 1) &&
1970Sstevel@tonic-gate (l == strlen(name))) {
1980Sstevel@tonic-gate is = B_TRUE;
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate return (is);
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate
2040Sstevel@tonic-gate /*
2050Sstevel@tonic-gate * FUNCTION: is_did_name(char *name)
2060Sstevel@tonic-gate * INPUT: name - a char *
2070Sstevel@tonic-gate *
2080Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE - if name is from the DID namespace
2090Sstevel@tonic-gate * B_FALSE - otherwise
2100Sstevel@tonic-gate *
2110Sstevel@tonic-gate * PURPOSE: Determines if the input name is from the DID namespace.
2120Sstevel@tonic-gate */
2130Sstevel@tonic-gate boolean_t
is_did_name(char * name)2140Sstevel@tonic-gate is_did_name(
2150Sstevel@tonic-gate char *name)
2160Sstevel@tonic-gate {
2170Sstevel@tonic-gate return (is_did_slice_name(name) || is_did_disk_name(name));
2180Sstevel@tonic-gate }
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate /*
2210Sstevel@tonic-gate * FUNCTION: is_did_slice_name(char *name)
2220Sstevel@tonic-gate * INPUT: name - a char *
2230Sstevel@tonic-gate *
2240Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE - if name represents a slice from the DID
2250Sstevel@tonic-gate * namespace
2260Sstevel@tonic-gate * B_FALSE - otherwise
2270Sstevel@tonic-gate *
2280Sstevel@tonic-gate * PURPOSE: Determines if the input name is a slice from the DID namespace.
2290Sstevel@tonic-gate */
2300Sstevel@tonic-gate boolean_t
is_did_slice_name(char * name)2310Sstevel@tonic-gate is_did_slice_name(
2320Sstevel@tonic-gate char *name)
2330Sstevel@tonic-gate {
2340Sstevel@tonic-gate uint_t d = 0, s = 0;
2350Sstevel@tonic-gate int l = 0;
2360Sstevel@tonic-gate boolean_t is = B_FALSE;
2370Sstevel@tonic-gate
2380Sstevel@tonic-gate if ((sscanf(name, "/dev/did/rdsk/d%us%u%n", &d, &s, &l) == 2 ||
2390Sstevel@tonic-gate sscanf(name, "/dev/did/dsk/d%us%u%n", &d, &s, &l) == 2 ||
2400Sstevel@tonic-gate sscanf(name, "d%us%u%n", &d, &s, &l) == 2) ||
2410Sstevel@tonic-gate (l == strlen(name))) {
2420Sstevel@tonic-gate is = B_TRUE;
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate return (is);
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate /*
2490Sstevel@tonic-gate * FUNCTION: is_did_disk_name(char *name)
2500Sstevel@tonic-gate * INPUT: name - a char *
2510Sstevel@tonic-gate *
2520Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE - if name represents a disk from the DID
2530Sstevel@tonic-gate * namespace
2540Sstevel@tonic-gate * B_FALSE - otherwise
2550Sstevel@tonic-gate *
2560Sstevel@tonic-gate * PURPOSE: Determines if the input name is a disk from the DID namespace.
2570Sstevel@tonic-gate */
2580Sstevel@tonic-gate boolean_t
is_did_disk_name(char * name)2590Sstevel@tonic-gate is_did_disk_name(
2600Sstevel@tonic-gate char *name)
2610Sstevel@tonic-gate {
2620Sstevel@tonic-gate uint_t d = 0;
2630Sstevel@tonic-gate int l = 0;
2640Sstevel@tonic-gate boolean_t is = B_FALSE;
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate if ((sscanf(name, "/dev/did/rdsk/d%u%n", &d, &l) == 1 ||
2670Sstevel@tonic-gate sscanf(name, "/dev/did/dsk/d%u%n", &d, &l) == 1 ||
2680Sstevel@tonic-gate sscanf(name, "d%u%n", &d, &l) == 1) &&
2690Sstevel@tonic-gate (l == strlen(name))) {
2700Sstevel@tonic-gate is = B_TRUE;
2710Sstevel@tonic-gate }
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate return (is);
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate /*
2770Sstevel@tonic-gate * FUNCTION: is_ctd_name(char *name)
2780Sstevel@tonic-gate * INPUT: name - a char *
2790Sstevel@tonic-gate *
2800Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE - if name is from the CTD namespace
2810Sstevel@tonic-gate * B_FALSE - otherwise
2820Sstevel@tonic-gate *
2830Sstevel@tonic-gate * PURPOSE: Determines if the input name is from the CTD namespace.
2840Sstevel@tonic-gate *
2850Sstevel@tonic-gate * {/dev/dsk/, /dev/rdsk/}cXtXdXsX
2860Sstevel@tonic-gate * {/dev/dsk/, /dev/rdsk/}cXtXdX
2870Sstevel@tonic-gate * {/dev/dsk/, /dev/rdsk/}cXdXsX
2880Sstevel@tonic-gate * {/dev/dsk/, /dev/rdsk/}cXdX
2890Sstevel@tonic-gate */
2900Sstevel@tonic-gate boolean_t
is_ctd_name(char * name)2910Sstevel@tonic-gate is_ctd_name(
2920Sstevel@tonic-gate char *name)
2930Sstevel@tonic-gate {
2940Sstevel@tonic-gate return (is_ctd_slice_name(name) || is_ctd_disk_name(name) ||
2950Sstevel@tonic-gate is_ctd_target_name(name) || is_ctd_ctrl_name(name));
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate /*
2990Sstevel@tonic-gate * FUNCTION: is_ctd_slice_name(char *name)
3000Sstevel@tonic-gate * INPUT: name - a char *
3010Sstevel@tonic-gate *
3020Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE - if name represents a slice from the CTD
3030Sstevel@tonic-gate * namespace
3040Sstevel@tonic-gate * B_FALSE - otherwise
3050Sstevel@tonic-gate *
3060Sstevel@tonic-gate * PURPOSE: Determines if the input name is a slice name from the
3070Sstevel@tonic-gate * CTD namespace.
3080Sstevel@tonic-gate *
3090Sstevel@tonic-gate * {/dev/dsk/, /dev/rdsk/}cXt<WWN>dXsX
3100Sstevel@tonic-gate * {/dev/dsk/, /dev/rdsk/}cXtXdXsX
3110Sstevel@tonic-gate * {/dev/dsk/, /dev/rdsk/}cXdXsX
3120Sstevel@tonic-gate */
3130Sstevel@tonic-gate boolean_t
is_ctd_slice_name(char * name)3140Sstevel@tonic-gate is_ctd_slice_name(
3150Sstevel@tonic-gate char *name)
3160Sstevel@tonic-gate {
3170Sstevel@tonic-gate uint_t c = 0, t = 0, d = 0, s = 0;
3180Sstevel@tonic-gate char buf[MAXNAMELEN+1];
3190Sstevel@tonic-gate int l = 0;
3200Sstevel@tonic-gate boolean_t is = B_FALSE;
3210Sstevel@tonic-gate
3220Sstevel@tonic-gate if ((sscanf(name, "/dev/dsk/c%ut%ud%us%u%n", &c, &t, &d, &s, &l) == 4 ||
3230Sstevel@tonic-gate sscanf(name, "/dev/rdsk/c%ut%ud%us%u%n", &c, &t, &d, &s, &l) == 4 ||
3240Sstevel@tonic-gate sscanf(name, "c%ut%ud%us%u%n", &c, &t, &d, &s, &l) == 4 ||
3250Sstevel@tonic-gate sscanf(name, "/dev/dsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 ||
3260Sstevel@tonic-gate sscanf(name, "/dev/rdsk/c%ud%us%u%n", &c, &d, &s, &l) == 3 ||
3270Sstevel@tonic-gate sscanf(name, "c%ud%us%u%n", &c, &d, &s, &l) == 3 ||
3280Sstevel@tonic-gate sscanf(name, "c%ud%us%u%n", &c, &d, &s, &l) == 2) &&
3290Sstevel@tonic-gate (l == strlen(name))) {
3300Sstevel@tonic-gate is = B_TRUE;
3310Sstevel@tonic-gate } else if (
3320Sstevel@tonic-gate (sscanf(name, "/dev/dsk/c%ut%" VAL2STR(MAXNAMELEN) "s%n",
3330Sstevel@tonic-gate &c, buf, &l) == 2 ||
3340Sstevel@tonic-gate sscanf(name, "/dev/rdsk/c%ut%" VAL2STR(MAXNAMELEN) "s%n",
3350Sstevel@tonic-gate &c, buf, &l) == 2 ||
3360Sstevel@tonic-gate sscanf(name, "c%ut%" VAL2STR(MAXNAMELEN) "s%n",
3370Sstevel@tonic-gate &c, buf, &l) == 2) && (l == strlen(name))) {
3380Sstevel@tonic-gate char *dev_pos;
3390Sstevel@tonic-gate
3400Sstevel@tonic-gate /* see if buf ends with "dXsX" */
3410Sstevel@tonic-gate if (((dev_pos = strrchr(buf, 'd')) != NULL) &&
3420Sstevel@tonic-gate (sscanf(dev_pos, "d%us%u%n", &d, &s, &l) == 2) &&
3430Sstevel@tonic-gate (l == strlen(dev_pos))) {
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate char wwn[MAXNAMELEN+2];
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate /* buf ends with "dXsX", truncate at the 'd' */
3480Sstevel@tonic-gate *dev_pos = '\0';
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate /* prepend "0X" to remainder and try to scan as a hex WWN */
3510Sstevel@tonic-gate (void) snprintf(wwn, sizeof (wwn), "%s%s", "0X", buf);
3520Sstevel@tonic-gate if ((sscanf(wwn, "%x%n", &t, &l) == 1) && (l == strlen(wwn))) {
3530Sstevel@tonic-gate is = B_TRUE;
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate }
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate return (is);
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate /*
3620Sstevel@tonic-gate * FUNCTION: is_ctd_disk_name(char *name)
3630Sstevel@tonic-gate * INPUT: name - a char *
3640Sstevel@tonic-gate *
3650Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE - if name represents a disk from the CTD
3660Sstevel@tonic-gate * namespace
3670Sstevel@tonic-gate * B_FALSE - otherwise
3680Sstevel@tonic-gate *
3690Sstevel@tonic-gate * PURPOSE: Determines if the input name is a disk name from the
3700Sstevel@tonic-gate * CTD namespace.
3710Sstevel@tonic-gate *
3720Sstevel@tonic-gate * {/dev/dsk/, /dev/rdsk/}cXt<WWN>dX
3730Sstevel@tonic-gate * {/dev/dsk/, /dev/rdsk/}cXtXdX
3740Sstevel@tonic-gate * {/dev/dsk/, /dev/rdsk/}cXdX
3750Sstevel@tonic-gate */
3760Sstevel@tonic-gate boolean_t
is_ctd_disk_name(char * name)3770Sstevel@tonic-gate is_ctd_disk_name(
3780Sstevel@tonic-gate char *name)
3790Sstevel@tonic-gate {
3800Sstevel@tonic-gate uint_t c = 0, t = 0, d = 0;
3810Sstevel@tonic-gate int l = 0;
3820Sstevel@tonic-gate char buf[MAXNAMELEN+1];
3830Sstevel@tonic-gate boolean_t is = B_FALSE;
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate if ((sscanf(name, "/dev/dsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
3860Sstevel@tonic-gate sscanf(name, "/dev/rdsk/c%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
3870Sstevel@tonic-gate sscanf(name, "c%ut%ud%u%n", &c, &t, &d, &l) == 3 ||
3880Sstevel@tonic-gate sscanf(name, "/dev/dsk/c%ud%u%n", &c, &d, &l) == 2 ||
3890Sstevel@tonic-gate sscanf(name, "/dev/rdsk/c%ud%n%n", &c, &d, &l) == 2 ||
3900Sstevel@tonic-gate sscanf(name, "c%ud%u%n", &c, &d, &l) == 2) &&
3910Sstevel@tonic-gate (l == strlen(name))) {
3920Sstevel@tonic-gate is = B_TRUE;
3930Sstevel@tonic-gate } else if ((sscanf(name, "/dev/dsk/c%ut%" VAL2STR(MAXNAMELEN) "s%n",
3940Sstevel@tonic-gate &c, buf, &l) == 2 ||
3950Sstevel@tonic-gate sscanf(name, "/dev/rdsk/c%ut%" VAL2STR(MAXNAMELEN) "s%n",
3960Sstevel@tonic-gate &c, buf, &l) == 2 ||
3970Sstevel@tonic-gate sscanf(name, "c%ut%" VAL2STR(MAXNAMELEN) "s%n",
3980Sstevel@tonic-gate &c, buf, &l) == 2) && (l == strlen(name))) {
3990Sstevel@tonic-gate char *dev_pos;
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate /* see if buf ends with "dX" */
4020Sstevel@tonic-gate if (((dev_pos = strrchr(buf, 'd')) != NULL) &&
4030Sstevel@tonic-gate (sscanf(dev_pos, "d%u%n", &d, &l) == 1) &&
4040Sstevel@tonic-gate (l == strlen(dev_pos))) {
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate char wwn[MAXNAMELEN+2];
4070Sstevel@tonic-gate
4080Sstevel@tonic-gate /* buf ends with "dX", truncate at the 'd' */
4090Sstevel@tonic-gate *dev_pos = '\0';
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate /* prepend "0X" to remainder and try to scan as a hex WWN */
4120Sstevel@tonic-gate (void) snprintf(wwn, sizeof (wwn), "%s%s", "0X", buf);
4130Sstevel@tonic-gate if ((sscanf(wwn, "%x%n", &t, &l) == 1) && (l == strlen(wwn))) {
4140Sstevel@tonic-gate is = B_TRUE;
4150Sstevel@tonic-gate }
4160Sstevel@tonic-gate }
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate
4190Sstevel@tonic-gate return (is);
4200Sstevel@tonic-gate }
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate /*
4230Sstevel@tonic-gate * FUNCTION: is_ctd_disk_name(char *name)
4240Sstevel@tonic-gate * INPUT: name - a char *
4250Sstevel@tonic-gate *
4260Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE - if name represents a target from the CTD
4270Sstevel@tonic-gate * namespace
4280Sstevel@tonic-gate * B_FALSE - otherwise
4290Sstevel@tonic-gate *
4300Sstevel@tonic-gate * PURPOSE: Determines if the input name is a target name from the
4310Sstevel@tonic-gate * CTD namespace.
4320Sstevel@tonic-gate *
4330Sstevel@tonic-gate * {/dev/dsk/, /dev/rdsk/}cXt<WWN>
4340Sstevel@tonic-gate * {/dev/dsk/, /dev/rdsk/}cXtX
4350Sstevel@tonic-gate */
4360Sstevel@tonic-gate boolean_t
is_ctd_target_name(char * name)4370Sstevel@tonic-gate is_ctd_target_name(
4380Sstevel@tonic-gate char *name)
4390Sstevel@tonic-gate {
4400Sstevel@tonic-gate uint_t c = 0, t = 0;
4410Sstevel@tonic-gate int l = 0;
4420Sstevel@tonic-gate char buf[MAXNAMELEN+1];
4430Sstevel@tonic-gate boolean_t is = B_FALSE;
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate if ((sscanf(name, "/dev/dsk/c%ut%u%n", &c, &t, &l) == 2 ||
4460Sstevel@tonic-gate sscanf(name, "/dev/rdsk/c%ut%u%n", &c, &t, &l) == 2 ||
4470Sstevel@tonic-gate sscanf(name, "c%ut%u%n", &c, &t, &l) == 2) &&
4480Sstevel@tonic-gate (l == strlen(name))) {
4490Sstevel@tonic-gate is = B_TRUE;
4500Sstevel@tonic-gate } else if (
4510Sstevel@tonic-gate (sscanf(name, "/dev/dsk/c%ut%" VAL2STR(MAXNAMELEN) "s%n",
4520Sstevel@tonic-gate &c, buf, &l) == 2 ||
4530Sstevel@tonic-gate sscanf(name, "/dev/rdsk/c%ut%" VAL2STR(MAXNAMELEN) "s%n",
4540Sstevel@tonic-gate &c, buf, &l) == 2 ||
4550Sstevel@tonic-gate sscanf(name, "c%ut%" VAL2STR(MAXNAMELEN) "s%n",
4560Sstevel@tonic-gate &c, &buf, &l) == 2) && (l == strlen(name))) {
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate char wwn[MAXNAMELEN+2];
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate /* prepend "0X" to buf and try to scan as a hex WWN */
4610Sstevel@tonic-gate (void) snprintf(wwn, sizeof (wwn), "%s%s", "0X", buf);
4620Sstevel@tonic-gate if ((sscanf(wwn, "%x%n", &t, &l) == 1) && (l == strlen(wwn))) {
4630Sstevel@tonic-gate is = B_TRUE;
4640Sstevel@tonic-gate }
4650Sstevel@tonic-gate }
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate return (is);
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate /*
4710Sstevel@tonic-gate * FUNCTION: is_ctd_ctrl_name(char *name)
4720Sstevel@tonic-gate * INPUT: name - a char *
4730Sstevel@tonic-gate *
4740Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE - if name represents a controller/hba
4750Sstevel@tonic-gate * from the CTD namespace
4760Sstevel@tonic-gate * B_FALSE - otherwise
4770Sstevel@tonic-gate *
4780Sstevel@tonic-gate * PURPOSE: Determines if the input name is an HBA name from the
4790Sstevel@tonic-gate * CTD namespace.
4800Sstevel@tonic-gate *
4810Sstevel@tonic-gate * {/dev/dsk/, /dev/rdsk/}cX
4820Sstevel@tonic-gate */
4830Sstevel@tonic-gate boolean_t
is_ctd_ctrl_name(char * name)4840Sstevel@tonic-gate is_ctd_ctrl_name(
4850Sstevel@tonic-gate char *name)
4860Sstevel@tonic-gate {
4870Sstevel@tonic-gate uint_t c = 0;
4880Sstevel@tonic-gate int l = 0;
4890Sstevel@tonic-gate boolean_t is = B_FALSE;
4900Sstevel@tonic-gate
4910Sstevel@tonic-gate if ((sscanf(name, "/dev/dsk/c%u%n", &c, &l) == 1 ||
4920Sstevel@tonic-gate sscanf(name, "/dev/rdsk/c%u%n", &c, &l) == 1 ||
4930Sstevel@tonic-gate sscanf(name, "c%u%n", &c, &l) == 1) &&
4940Sstevel@tonic-gate (l == strlen(name))) {
4950Sstevel@tonic-gate is = B_TRUE;
4960Sstevel@tonic-gate }
4970Sstevel@tonic-gate
4980Sstevel@tonic-gate return (is);
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate
5010Sstevel@tonic-gate /*
5020Sstevel@tonic-gate * FUNCTION: set_display_name(dm_descriptor_t desc, char *name)
5030Sstevel@tonic-gate * get_display_name(dm_descriptor_t desc, char **name)
5040Sstevel@tonic-gate *
5050Sstevel@tonic-gate * INPUT: desc - a dm_descriptor_t handle for a device
5060Sstevel@tonic-gate * name - a char * name
5070Sstevel@tonic-gate *
5080Sstevel@tonic-gate * OUTPUT: **name - a pointer to a char * to hold the display
5090Sstevel@tonic-gate * name associated with the input descriptor.
5100Sstevel@tonic-gate *
5110Sstevel@tonic-gate * RETURNS: int - 0 on success
5120Sstevel@tonic-gate * !0 otherwise.
5130Sstevel@tonic-gate *
5140Sstevel@tonic-gate * PURPOSE: Helpers to set/get the input descriptor's display name.
5150Sstevel@tonic-gate *
5160Sstevel@tonic-gate * Only slices, disks and HBAs should have display names.
5170Sstevel@tonic-gate *
5180Sstevel@tonic-gate * The attribute is only set in the cached copy of
5190Sstevel@tonic-gate * the device's nvpair attribute list. This function
5200Sstevel@tonic-gate * does not affect the underlying physical device.
5210Sstevel@tonic-gate *
5220Sstevel@tonic-gate * An entry is added in the name->descriptor cache
5230Sstevel@tonic-gate * so the descriptor can be found by name quickly.
5240Sstevel@tonic-gate */
5250Sstevel@tonic-gate int
set_display_name(dm_descriptor_t desc,char * name)5260Sstevel@tonic-gate set_display_name(
5270Sstevel@tonic-gate dm_descriptor_t desc,
5280Sstevel@tonic-gate char *name)
5290Sstevel@tonic-gate {
5300Sstevel@tonic-gate nvlist_t *attrs = NULL;
5310Sstevel@tonic-gate int error = 0;
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate ((error = add_cached_descriptor(name, desc)) != 0) ||
5340Sstevel@tonic-gate (error = get_cached_attributes(desc, &attrs)) ||
5350Sstevel@tonic-gate (error = set_string(attrs, ATTR_DEV_CTD_NAME, name));
5360Sstevel@tonic-gate
5370Sstevel@tonic-gate return (error);
5380Sstevel@tonic-gate }
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate int
get_display_name(dm_descriptor_t desc,char ** name)5410Sstevel@tonic-gate get_display_name(
5420Sstevel@tonic-gate dm_descriptor_t desc,
5430Sstevel@tonic-gate char **name)
5440Sstevel@tonic-gate {
5450Sstevel@tonic-gate nvlist_t *attrs = NULL;
5460Sstevel@tonic-gate int error = 0;
5470Sstevel@tonic-gate
5480Sstevel@tonic-gate ((error = get_cached_attributes(desc, &attrs)) != 0) ||
5490Sstevel@tonic-gate (error = get_string(attrs, ATTR_DEV_CTD_NAME, name));
5500Sstevel@tonic-gate
5510Sstevel@tonic-gate return (error);
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate /*
5550Sstevel@tonic-gate * FUNCTION: disk_get_slices(dm_descriptor_t disk, dlist_t **list)
5560Sstevel@tonic-gate *
5570Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t handle for a disk
5580Sstevel@tonic-gate *
5590Sstevel@tonic-gate * OUTPUT: *list - a pointer to list to hold the results.
5600Sstevel@tonic-gate *
5610Sstevel@tonic-gate * RETURNS: int - 0 on success
5620Sstevel@tonic-gate * !0 otherwise.
5630Sstevel@tonic-gate *
5640Sstevel@tonic-gate * PURPOSE: Collect all of the known slices for the input disk.
5650Sstevel@tonic-gate *
5660Sstevel@tonic-gate * These slices may be actual slices which currently exist
5670Sstevel@tonic-gate * on the disk, or virtual slices which will exist when the
5680Sstevel@tonic-gate * disk is added to the destination diskset.
5690Sstevel@tonic-gate */
5700Sstevel@tonic-gate int
disk_get_slices(dm_descriptor_t disk,dlist_t ** list)5710Sstevel@tonic-gate disk_get_slices(
5720Sstevel@tonic-gate dm_descriptor_t disk,
5730Sstevel@tonic-gate dlist_t **list)
5740Sstevel@tonic-gate {
5750Sstevel@tonic-gate dm_descriptor_t *media = NULL;
5760Sstevel@tonic-gate boolean_t virtual = B_FALSE;
5770Sstevel@tonic-gate int i = 0;
5780Sstevel@tonic-gate int error = 0;
5790Sstevel@tonic-gate
5800Sstevel@tonic-gate *list = 0;
5810Sstevel@tonic-gate
5820Sstevel@tonic-gate if ((error = disk_has_virtual_slices(disk, &virtual)) != 0) {
5830Sstevel@tonic-gate return (error);
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate if (virtual == B_TRUE) {
5870Sstevel@tonic-gate error = disk_get_virtual_slices(disk, list);
5880Sstevel@tonic-gate }
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate /* add real slices from disk's media... */
5910Sstevel@tonic-gate media = dm_get_associated_descriptors(disk, DM_MEDIA, &error);
5920Sstevel@tonic-gate (void) add_descriptors_to_free(media);
5930Sstevel@tonic-gate
5940Sstevel@tonic-gate if (error == 0) {
5950Sstevel@tonic-gate /* if there's no media, this is a removeable drive */
5960Sstevel@tonic-gate if (media != NULL && *media != NULL) {
5970Sstevel@tonic-gate
5980Sstevel@tonic-gate /* examine media's slices... */
5990Sstevel@tonic-gate dm_descriptor_t *slices = NULL;
6000Sstevel@tonic-gate slices = dm_get_associated_descriptors(*media,
6010Sstevel@tonic-gate DM_SLICE, &error);
6020Sstevel@tonic-gate (void) add_descriptors_to_free(slices);
6030Sstevel@tonic-gate
6040Sstevel@tonic-gate if (error != 0) {
6050Sstevel@tonic-gate print_get_assoc_desc_error(disk, gettext("slice"), error);
6060Sstevel@tonic-gate } else {
6070Sstevel@tonic-gate for (i = 0; (slices[i] != NULL) && (error == 0); i++) {
608*62Sjeanm dlist_t *item =
609*62Sjeanm dlist_new_item((void *)(uintptr_t)slices[i]);
6100Sstevel@tonic-gate if (item == NULL) {
6110Sstevel@tonic-gate error = ENOMEM;
6120Sstevel@tonic-gate } else {
6130Sstevel@tonic-gate *list = dlist_append(item, *list, AT_TAIL);
6140Sstevel@tonic-gate }
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate free(slices);
6170Sstevel@tonic-gate }
6180Sstevel@tonic-gate free(media);
6190Sstevel@tonic-gate }
6200Sstevel@tonic-gate } else {
6210Sstevel@tonic-gate print_get_assoc_desc_error(disk, gettext("media"), error);
6220Sstevel@tonic-gate }
6230Sstevel@tonic-gate
6240Sstevel@tonic-gate return (error);
6250Sstevel@tonic-gate }
6260Sstevel@tonic-gate
6270Sstevel@tonic-gate int
get_virtual_slices(dlist_t ** list)6280Sstevel@tonic-gate get_virtual_slices(
6290Sstevel@tonic-gate dlist_t **list)
6300Sstevel@tonic-gate {
6310Sstevel@tonic-gate *list = _virtual_slices;
6320Sstevel@tonic-gate
6330Sstevel@tonic-gate return (0);
6340Sstevel@tonic-gate }
6350Sstevel@tonic-gate
6360Sstevel@tonic-gate /*
6370Sstevel@tonic-gate * FUNCTION: virtual_repartition_drive(dm_descriptor_t disk,
6380Sstevel@tonic-gate * mdvtoc_t *vtocp)
6390Sstevel@tonic-gate *
6400Sstevel@tonic-gate * INPUT: disk - the disk to be virtually repartitioned
6410Sstevel@tonic-gate *
6420Sstevel@tonic-gate * OUTPUT: vtocp - a poitner to a mdvtoc struct to hold the results
6430Sstevel@tonic-gate *
6440Sstevel@tonic-gate * RETURNS: int - 0 on success
6450Sstevel@tonic-gate * !0 otherwise.
6460Sstevel@tonic-gate *
6470Sstevel@tonic-gate * PURPOSE: Helper which emulates the repartitioning that is done
6480Sstevel@tonic-gate * when a disk is added to a diskset.
6490Sstevel@tonic-gate *
6500Sstevel@tonic-gate * Modified version of meta_partition_drive which uses info
6510Sstevel@tonic-gate * from libdiskmgt to accomplish the repartitioning.
6520Sstevel@tonic-gate *
6530Sstevel@tonic-gate * This exists to allow the layout module to run with a
6540Sstevel@tonic-gate * simulated hardware environment.
6550Sstevel@tonic-gate *
6560Sstevel@tonic-gate * XXX This method absolutely does not produce the exact
6570Sstevel@tonic-gate * same result as meta_repartition_drive: only information
6580Sstevel@tonic-gate * required by the layout code is returned. Basically,
6590Sstevel@tonic-gate * a slice 7 (or 6 on EFI labelled disks) is created and
6600Sstevel@tonic-gate * sized, the remained of the available cylinders are put
6610Sstevel@tonic-gate * into slice 0.
6620Sstevel@tonic-gate *
6630Sstevel@tonic-gate * XXX2 This method is required until there is resolution
6640Sstevel@tonic-gate * on whether metassist testing will be done using the
6650Sstevel@tonic-gate * hardware simulation mechanism libdiskmgt provides.
6660Sstevel@tonic-gate * Doing so will also require parts of libmeta to be
6670Sstevel@tonic-gate * simulated as well. Some research has been done into
6680Sstevel@tonic-gate * building an alternate libmeta.so containing
6690Sstevel@tonic-gate * implementations of the functions used by metassist
6700Sstevel@tonic-gate * that are compatible with the simulated hardware.
6710Sstevel@tonic-gate * Actual work is currently on hold.
6720Sstevel@tonic-gate */
6730Sstevel@tonic-gate static int
virtual_repartition_drive(dm_descriptor_t disk,mdvtoc_t * vtocp)6740Sstevel@tonic-gate virtual_repartition_drive(
6750Sstevel@tonic-gate dm_descriptor_t disk,
6760Sstevel@tonic-gate mdvtoc_t *vtocp)
6770Sstevel@tonic-gate {
6780Sstevel@tonic-gate uint_t replicaslice = 7;
6790Sstevel@tonic-gate unsigned long long cylsize;
6800Sstevel@tonic-gate unsigned long long drvsize;
6810Sstevel@tonic-gate uint_t reservedcyl;
6820Sstevel@tonic-gate ushort_t resflag;
6830Sstevel@tonic-gate unsigned long long ressize;
6840Sstevel@tonic-gate diskaddr_t replica_start;
6850Sstevel@tonic-gate diskaddr_t replica_size;
6860Sstevel@tonic-gate diskaddr_t data_start;
6870Sstevel@tonic-gate diskaddr_t data_size;
6880Sstevel@tonic-gate
6890Sstevel@tonic-gate boolean_t efi = B_FALSE;
6900Sstevel@tonic-gate uint64_t ncyls = 0;
6910Sstevel@tonic-gate uint64_t nheads = 0;
6920Sstevel@tonic-gate uint64_t nsects = 0;
6930Sstevel@tonic-gate int error = 0;
6940Sstevel@tonic-gate
6950Sstevel@tonic-gate /*
6960Sstevel@tonic-gate * At this point, ressize is used as a minimum value. Later it
6970Sstevel@tonic-gate * will be rounded up to a cylinder boundary. ressize is in
6980Sstevel@tonic-gate * units of disk sectors.
6990Sstevel@tonic-gate */
7000Sstevel@tonic-gate ressize = MD_DBSIZE + VTOC_SIZE;
7010Sstevel@tonic-gate resflag = V_UNMNT;
7020Sstevel@tonic-gate
7030Sstevel@tonic-gate ((error = disk_get_is_efi(disk, &efi)) != 0) ||
7040Sstevel@tonic-gate (error = disk_get_ncylinders(disk, &ncyls)) ||
7050Sstevel@tonic-gate (error = disk_get_nheads(disk, &nheads)) ||
7060Sstevel@tonic-gate (error = disk_get_nsectors(disk, &nsects));
7070Sstevel@tonic-gate if (error != 0) {
7080Sstevel@tonic-gate return (error);
7090Sstevel@tonic-gate }
7100Sstevel@tonic-gate
7110Sstevel@tonic-gate if (efi) {
7120Sstevel@tonic-gate replicaslice = 6;
7130Sstevel@tonic-gate }
7140Sstevel@tonic-gate
7150Sstevel@tonic-gate /*
7160Sstevel@tonic-gate * Both cylsize and drvsize are in units of disk sectors.
7170Sstevel@tonic-gate *
7180Sstevel@tonic-gate * The intended results are of type unsigned long long. Since
7190Sstevel@tonic-gate * each operand of the first multiplication is of type
7200Sstevel@tonic-gate * unsigned int, we risk overflow by multiplying and then
7210Sstevel@tonic-gate * converting the result. Therefore we explicitly cast (at
7220Sstevel@tonic-gate * least) one of the operands, forcing conversion BEFORE
7230Sstevel@tonic-gate * multiplication, and avoiding overflow. The second
7240Sstevel@tonic-gate * assignment is OK, since one of the operands is already of
7250Sstevel@tonic-gate * the desired type.
7260Sstevel@tonic-gate */
7270Sstevel@tonic-gate cylsize = ((unsigned long long)nheads) * nsects;
7280Sstevel@tonic-gate drvsize = cylsize * ncyls;
7290Sstevel@tonic-gate
7300Sstevel@tonic-gate /*
7310Sstevel@tonic-gate * How many cylinders must we reserve for slice seven to
7320Sstevel@tonic-gate * ensure that it meets the previously calculated minimum
7330Sstevel@tonic-gate * size?
7340Sstevel@tonic-gate */
7350Sstevel@tonic-gate reservedcyl = (ressize + cylsize - 1) / cylsize;
7360Sstevel@tonic-gate
7370Sstevel@tonic-gate /*
7380Sstevel@tonic-gate * It seems unlikely that someone would pass us too small a
7390Sstevel@tonic-gate * disk, but it's still worth checking for...
7400Sstevel@tonic-gate */
7410Sstevel@tonic-gate if (reservedcyl >= ncyls) {
7420Sstevel@tonic-gate volume_set_error(
7430Sstevel@tonic-gate gettext("disk is too small to hold a metadb replica"));
7440Sstevel@tonic-gate return (-1);
7450Sstevel@tonic-gate }
7460Sstevel@tonic-gate
7470Sstevel@tonic-gate replica_start = 0;
7480Sstevel@tonic-gate replica_size = reservedcyl * cylsize;
7490Sstevel@tonic-gate data_start = reservedcyl * cylsize;
7500Sstevel@tonic-gate data_size = drvsize - (reservedcyl * cylsize);
7510Sstevel@tonic-gate
7520Sstevel@tonic-gate /*
7530Sstevel@tonic-gate * fill in the proposed VTOC information.
7540Sstevel@tonic-gate */
7550Sstevel@tonic-gate
7560Sstevel@tonic-gate /* We need at least replicaslice partitions in the proposed vtoc */
7570Sstevel@tonic-gate vtocp->nparts = replicaslice + 1;
7580Sstevel@tonic-gate vtocp->parts[MD_SLICE0].start = data_start;
7590Sstevel@tonic-gate vtocp->parts[MD_SLICE0].size = data_size;
7600Sstevel@tonic-gate vtocp->parts[MD_SLICE0].tag = V_USR;
7610Sstevel@tonic-gate vtocp->parts[replicaslice].start = replica_start;
7620Sstevel@tonic-gate vtocp->parts[replicaslice].size = replica_size;
7630Sstevel@tonic-gate vtocp->parts[replicaslice].flag = resflag;
7640Sstevel@tonic-gate vtocp->parts[replicaslice].tag = V_USR;
7650Sstevel@tonic-gate
7660Sstevel@tonic-gate return (0);
7670Sstevel@tonic-gate }
7680Sstevel@tonic-gate
7690Sstevel@tonic-gate /*
7700Sstevel@tonic-gate * FUNCTION: create_virtual_slices(dlist_t *disks)
7710Sstevel@tonic-gate *
7720Sstevel@tonic-gate * INPUT: possibles - a list of dm_descriptor_t disk handles for
7730Sstevel@tonic-gate * disks known to be available for use by layout.
7740Sstevel@tonic-gate *
7750Sstevel@tonic-gate * SIDEEFFECT: populates the private of virtual slices.
7760Sstevel@tonic-gate *
7770Sstevel@tonic-gate * RETURNS: int - 0 on success
7780Sstevel@tonic-gate * !0 otherwise.
7790Sstevel@tonic-gate *
7800Sstevel@tonic-gate * PURPOSE: Helper which creates virtual slices for each disk which
7810Sstevel@tonic-gate * could be added to a diskset if necessary...
7820Sstevel@tonic-gate *
7830Sstevel@tonic-gate * Iterate the input list of available disks and see what the
7840Sstevel@tonic-gate * slicing would be if the disk were added to a diskset.
7850Sstevel@tonic-gate *
7860Sstevel@tonic-gate * For the resulting slices, create virtual slice descriptors
7870Sstevel@tonic-gate * and attributes for these slices and add them to the list of
7880Sstevel@tonic-gate * available slices.
7890Sstevel@tonic-gate */
7900Sstevel@tonic-gate int
create_virtual_slices(dlist_t * disks)7910Sstevel@tonic-gate create_virtual_slices(
7920Sstevel@tonic-gate dlist_t *disks)
7930Sstevel@tonic-gate {
7940Sstevel@tonic-gate int error = 0;
7950Sstevel@tonic-gate dlist_t *iter;
7960Sstevel@tonic-gate boolean_t sim = B_FALSE;
7970Sstevel@tonic-gate static char *simfile = "METASSISTSIMFILE";
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate sim = ((getenv(simfile) != NULL) && (strlen(getenv(simfile)) > 0));
8000Sstevel@tonic-gate
8010Sstevel@tonic-gate /* see what slices each of the disks will have when added to a set */
8020Sstevel@tonic-gate for (iter = disks; error == 0 && iter != NULL; iter = iter->next) {
8030Sstevel@tonic-gate
8040Sstevel@tonic-gate dm_descriptor_t disk = (uintptr_t)iter->obj;
8050Sstevel@tonic-gate dlist_t *slices = NULL;
8060Sstevel@tonic-gate mdvtoc_t vtoc;
8070Sstevel@tonic-gate char *dname;
8080Sstevel@tonic-gate int i = 0;
8090Sstevel@tonic-gate
8100Sstevel@tonic-gate if ((error = get_display_name(disk, &dname)) != 0) {
8110Sstevel@tonic-gate break;
8120Sstevel@tonic-gate }
8130Sstevel@tonic-gate
8140Sstevel@tonic-gate if (sim != B_TRUE) {
8150Sstevel@tonic-gate
8160Sstevel@tonic-gate /* sim disabled: use meta_repartition_drive() */
8170Sstevel@tonic-gate
8180Sstevel@tonic-gate md_error_t mderror = mdnullerror;
8190Sstevel@tonic-gate int opts = (MD_REPART_FORCE | MD_REPART_DONT_LABEL);
8200Sstevel@tonic-gate mdsetname_t *sp;
8210Sstevel@tonic-gate mddrivename_t *dnp;
8220Sstevel@tonic-gate
8230Sstevel@tonic-gate /* disk is in the local set */
8240Sstevel@tonic-gate sp = metasetname(MD_LOCAL_NAME, &mderror);
8250Sstevel@tonic-gate if (!mdisok(&mderror)) {
8260Sstevel@tonic-gate volume_set_error(mde_sperror(&mderror, NULL));
8270Sstevel@tonic-gate mdclrerror(&mderror);
8280Sstevel@tonic-gate error = -1;
8290Sstevel@tonic-gate break;
8300Sstevel@tonic-gate }
8310Sstevel@tonic-gate
8320Sstevel@tonic-gate dnp = metadrivename(&sp, dname, &mderror);
8330Sstevel@tonic-gate if (!mdisok(&mderror)) {
8340Sstevel@tonic-gate volume_set_error(mde_sperror(&mderror, NULL));
8350Sstevel@tonic-gate mdclrerror(&mderror);
8360Sstevel@tonic-gate error = -1;
8370Sstevel@tonic-gate break;
8380Sstevel@tonic-gate }
8390Sstevel@tonic-gate
8400Sstevel@tonic-gate if (meta_repartition_drive(
8410Sstevel@tonic-gate sp, dnp, opts, &vtoc, &mderror) != 0) {
8420Sstevel@tonic-gate volume_set_error(
8430Sstevel@tonic-gate gettext("failed to repartition disk %s\n"),
8440Sstevel@tonic-gate dname);
8450Sstevel@tonic-gate error = -1;
8460Sstevel@tonic-gate break;
8470Sstevel@tonic-gate }
8480Sstevel@tonic-gate
8490Sstevel@tonic-gate } else {
8500Sstevel@tonic-gate
8510Sstevel@tonic-gate /* sim enabled: use faked repartition code */
8520Sstevel@tonic-gate if (virtual_repartition_drive(disk, &vtoc) != 0) {
8530Sstevel@tonic-gate volume_set_error(
8540Sstevel@tonic-gate gettext("failed simulated repartition of %s\n"),
8550Sstevel@tonic-gate dname);
8560Sstevel@tonic-gate error = -1;
8570Sstevel@tonic-gate break;
8580Sstevel@tonic-gate }
8590Sstevel@tonic-gate }
8600Sstevel@tonic-gate
8610Sstevel@tonic-gate /* BEGIN CSTYLED */
8620Sstevel@tonic-gate /*
8630Sstevel@tonic-gate * get the existing slices on the disk, if the repartition
8640Sstevel@tonic-gate * was successful, these slices need to have their size, start
8650Sstevel@tonic-gate * blk and size in blks set to 0
8660Sstevel@tonic-gate */
8670Sstevel@tonic-gate /* END CSTYLED */
8680Sstevel@tonic-gate if ((error = disk_get_slices(disk, &slices)) == 0) {
8690Sstevel@tonic-gate dlist_t *iter2 = slices;
8700Sstevel@tonic-gate for (; iter2 != NULL; iter2 = iter2->next) {
8710Sstevel@tonic-gate dm_descriptor_t sp = (uintptr_t)iter2->obj;
8720Sstevel@tonic-gate ((error = slice_set_start_block(sp, 0)) != 0) ||
8730Sstevel@tonic-gate (error = slice_set_size_in_blocks(sp, 0)) ||
8740Sstevel@tonic-gate (error = slice_set_size(sp, 0));
8750Sstevel@tonic-gate }
8760Sstevel@tonic-gate dlist_free_items(slices, NULL);
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate /* scan VTOC, find slice with the free space */
8800Sstevel@tonic-gate for (i = 0; i < vtoc.nparts; i++) {
8810Sstevel@tonic-gate
8820Sstevel@tonic-gate if (vtoc.parts[i].tag == V_USR &&
8830Sstevel@tonic-gate vtoc.parts[i].flag != V_UNMNT) {
8840Sstevel@tonic-gate
8850Sstevel@tonic-gate /* non-replica slice with free space */
8860Sstevel@tonic-gate char buf[MAXPATHLEN];
8870Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN-1, "%ss%d", dname, i);
8880Sstevel@tonic-gate
8890Sstevel@tonic-gate if ((error = add_virtual_slice(buf,
8900Sstevel@tonic-gate (uint32_t)i,
8910Sstevel@tonic-gate (uint64_t)vtoc.parts[i].start,
8920Sstevel@tonic-gate (uint64_t)vtoc.parts[i].size,
8930Sstevel@tonic-gate disk)) != 0) {
8940Sstevel@tonic-gate break;
8950Sstevel@tonic-gate }
8960Sstevel@tonic-gate
8970Sstevel@tonic-gate } else if (vtoc.parts[i].tag == V_RESERVED) {
8980Sstevel@tonic-gate
8990Sstevel@tonic-gate /* skip EFI reserved slice */
9000Sstevel@tonic-gate continue;
9010Sstevel@tonic-gate
9020Sstevel@tonic-gate } else if (vtoc.parts[i].tag == V_USR &&
9030Sstevel@tonic-gate vtoc.parts[i].flag == V_UNMNT) {
9040Sstevel@tonic-gate
9050Sstevel@tonic-gate /* BEGIN CSTYLED */
9060Sstevel@tonic-gate /*
9070Sstevel@tonic-gate * Make the replica slice 0 sized -- this will
9080Sstevel@tonic-gate * force the disk to be repartitioned by
9090Sstevel@tonic-gate * metaset when it is added to the disk set.
9100Sstevel@tonic-gate *
9110Sstevel@tonic-gate * XXX this is a temporary workaround until
9120Sstevel@tonic-gate * 4712873 is integrated...
9130Sstevel@tonic-gate */
9140Sstevel@tonic-gate /* BEGIN CSTYLED */
9150Sstevel@tonic-gate char buf[MAXPATHLEN];
9160Sstevel@tonic-gate (void) snprintf(buf, MAXPATHLEN-1, "%ss%d", dname, i);
9170Sstevel@tonic-gate add_slice_to_remove(buf, i);
9180Sstevel@tonic-gate
9190Sstevel@tonic-gate /* replica slice, stop here */
9200Sstevel@tonic-gate break;
9210Sstevel@tonic-gate }
9220Sstevel@tonic-gate }
9230Sstevel@tonic-gate }
9240Sstevel@tonic-gate
9250Sstevel@tonic-gate return (error);
9260Sstevel@tonic-gate }
9270Sstevel@tonic-gate
9280Sstevel@tonic-gate /*
9290Sstevel@tonic-gate * FUNCTION: add_virtual_slice(char *name, uint32_t index,
9300Sstevel@tonic-gate * uint64_t startblk, uint64_t sizeblks,
9310Sstevel@tonic-gate * dm_descriptor_t disk)
9320Sstevel@tonic-gate *
9330Sstevel@tonic-gate * INPUT: name - the name of the new virtual slice
9340Sstevel@tonic-gate * index - the VTOC index ...
9350Sstevel@tonic-gate * startblk - the start block ...
9360Sstevel@tonic-gate * sizeblks - the size in blocks ...
9370Sstevel@tonic-gate * disk - the parent disk ...
9380Sstevel@tonic-gate *
9390Sstevel@tonic-gate * RETURNS: int - 0 on success
9400Sstevel@tonic-gate * !0 otherwise.
9410Sstevel@tonic-gate *
9420Sstevel@tonic-gate * PURPOSE: Helper which adds the appropriate data structures to
9430Sstevel@tonic-gate * represent a new virtual slice.
9440Sstevel@tonic-gate *
9450Sstevel@tonic-gate * allocates a new descriptor
9460Sstevel@tonic-gate * adds entries to name->desc and desc->name caches
9470Sstevel@tonic-gate * allocates an attribute nvpair list
9480Sstevel@tonic-gate * fills in the relevant attributes for the slice
9490Sstevel@tonic-gate * associates the slice with its parent disk
9500Sstevel@tonic-gate * adds an entry to the list of all virtual slices
9510Sstevel@tonic-gate * generates aliases if the associated disk has aliases.
9520Sstevel@tonic-gate */
9530Sstevel@tonic-gate int
add_virtual_slice(char * name,uint32_t index,uint64_t startblk,uint64_t sizeblks,dm_descriptor_t disk)9540Sstevel@tonic-gate add_virtual_slice(
9550Sstevel@tonic-gate char *name,
9560Sstevel@tonic-gate uint32_t index,
9570Sstevel@tonic-gate uint64_t startblk,
9580Sstevel@tonic-gate uint64_t sizeblks,
9590Sstevel@tonic-gate dm_descriptor_t disk)
9600Sstevel@tonic-gate {
9610Sstevel@tonic-gate dm_descriptor_t sp;
9620Sstevel@tonic-gate nvlist_t *attrs;
9630Sstevel@tonic-gate char *sname;
9640Sstevel@tonic-gate dlist_t *aliases = NULL;
9650Sstevel@tonic-gate dlist_t *item = NULL;
9660Sstevel@tonic-gate int error = 0;
9670Sstevel@tonic-gate
9680Sstevel@tonic-gate if ((error = nvlist_alloc(&attrs, NV_UNIQUE_NAME, 0)) != 0) {
9690Sstevel@tonic-gate return (error);
9700Sstevel@tonic-gate }
9710Sstevel@tonic-gate
9720Sstevel@tonic-gate /* create descriptor */
9730Sstevel@tonic-gate ((error = new_descriptor(&sp)) != 0) ||
9740Sstevel@tonic-gate /* cache name for the descriptor */
9750Sstevel@tonic-gate (error = add_cached_name(sp, name)) ||
9760Sstevel@tonic-gate /* cache descriptor for the name */
9770Sstevel@tonic-gate (error = add_cached_descriptor(name, sp)) ||
9780Sstevel@tonic-gate
9790Sstevel@tonic-gate /* fill in attributes */
9800Sstevel@tonic-gate (error = set_string(attrs, ATTR_DEV_CTD_NAME, name)) ||
9810Sstevel@tonic-gate (error = set_uint32(attrs, DM_INDEX, index)) ||
9820Sstevel@tonic-gate (error = set_uint64(attrs, DM_START, startblk)) ||
9830Sstevel@tonic-gate (error = set_uint64(attrs, DM_SIZE, sizeblks)) ||
9840Sstevel@tonic-gate (error = set_uint64(attrs, ATTR_DISK_FOR_SLICE, (uint64_t)disk)) ||
9850Sstevel@tonic-gate
9860Sstevel@tonic-gate /* add attributes to the cache */
9870Sstevel@tonic-gate (error = get_name(sp, &sname)) ||
9880Sstevel@tonic-gate (error = add_cached_attributes(sname, attrs)) ||
9890Sstevel@tonic-gate
9900Sstevel@tonic-gate /* connect slice to disk */
9910Sstevel@tonic-gate (error = disk_add_virtual_slice(disk, sp)) ||
9920Sstevel@tonic-gate (error = get_display_name(disk, &name)) ||
9930Sstevel@tonic-gate (error = get_aliases(disk, &aliases));
9940Sstevel@tonic-gate
9950Sstevel@tonic-gate if (error != 0) {
9960Sstevel@tonic-gate return (error);
9970Sstevel@tonic-gate }
9980Sstevel@tonic-gate
9990Sstevel@tonic-gate /* generate slice's aliases if the disk has aliases */
10000Sstevel@tonic-gate if (aliases != NULL) {
10010Sstevel@tonic-gate char buf[MAXNAMELEN];
10020Sstevel@tonic-gate
10030Sstevel@tonic-gate for (; aliases != NULL; aliases = aliases->next) {
10040Sstevel@tonic-gate (void) snprintf(buf, MAXNAMELEN-1, "%ss%d",
10050Sstevel@tonic-gate (char *)aliases->obj, index);
10060Sstevel@tonic-gate error = set_alias(sp, buf);
10070Sstevel@tonic-gate }
10080Sstevel@tonic-gate dlist_free_items(aliases, free);
10090Sstevel@tonic-gate }
10100Sstevel@tonic-gate
1011*62Sjeanm if ((item = dlist_new_item((void *)(uintptr_t)sp)) == NULL) {
10120Sstevel@tonic-gate return (ENOMEM);
10130Sstevel@tonic-gate }
10140Sstevel@tonic-gate
10150Sstevel@tonic-gate _virtual_slices = dlist_append(item, _virtual_slices, AT_HEAD);
10160Sstevel@tonic-gate
10170Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
10180Sstevel@tonic-gate gettext(" created virtual slice %s start: %llu, size: %llu\n"),
10190Sstevel@tonic-gate sname, startblk, sizeblks);
10200Sstevel@tonic-gate
10210Sstevel@tonic-gate return (error);
10220Sstevel@tonic-gate }
10230Sstevel@tonic-gate
10240Sstevel@tonic-gate /*
10250Sstevel@tonic-gate * FUNCTION: release_virtual_slices()
10260Sstevel@tonic-gate *
10270Sstevel@tonic-gate * PURPOSE: Helper which cleans up the module private list of virtual
10280Sstevel@tonic-gate * slices.
10290Sstevel@tonic-gate *
10300Sstevel@tonic-gate * The descriptors for the virtual slices are cleaned up
10310Sstevel@tonic-gate * in device_cache_util.free_cached_descriptors
10320Sstevel@tonic-gate */
10330Sstevel@tonic-gate void
release_virtual_slices()10340Sstevel@tonic-gate release_virtual_slices()
10350Sstevel@tonic-gate {
10360Sstevel@tonic-gate dlist_free_items(_virtual_slices, NULL);
10370Sstevel@tonic-gate _virtual_slices = NULL;
10380Sstevel@tonic-gate }
10390Sstevel@tonic-gate
10400Sstevel@tonic-gate /*
10410Sstevel@tonic-gate * FUNCTION: disk_add_virtual_slice(dm_descriptor_t disk,
10420Sstevel@tonic-gate * dm_descriptor_t slice)
10430Sstevel@tonic-gate *
10440Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t disk handle
10450Sstevel@tonic-gate * slice - a dm_descriptor_t virtual slice handle
10460Sstevel@tonic-gate *
10470Sstevel@tonic-gate * RETURNS: int - 0 on success
10480Sstevel@tonic-gate * !0 otherwise
10490Sstevel@tonic-gate *
10500Sstevel@tonic-gate * PURPOSE: Helper which adds a virtual slice to the input disk's
10510Sstevel@tonic-gate * list of virtual slices.
10520Sstevel@tonic-gate *
10530Sstevel@tonic-gate * The disk's virtual slice dm_descriptor_t handles are
10540Sstevel@tonic-gate * stored in the disk's nvpair attribute list.
10550Sstevel@tonic-gate */
10560Sstevel@tonic-gate static int
disk_add_virtual_slice(dm_descriptor_t disk,dm_descriptor_t slice)10570Sstevel@tonic-gate disk_add_virtual_slice(
10580Sstevel@tonic-gate dm_descriptor_t disk,
10590Sstevel@tonic-gate dm_descriptor_t slice)
10600Sstevel@tonic-gate {
10610Sstevel@tonic-gate nvlist_t *attrs = NULL;
10620Sstevel@tonic-gate uint64_t *old_slices = NULL;
10630Sstevel@tonic-gate uint64_t *new_slices = NULL;
10640Sstevel@tonic-gate uint_t nelem = 0;
10650Sstevel@tonic-gate int i = 0;
10660Sstevel@tonic-gate int error = 0;
10670Sstevel@tonic-gate
10680Sstevel@tonic-gate if ((error = get_cached_attributes(disk, &attrs)) != 0) {
10690Sstevel@tonic-gate return (error);
10700Sstevel@tonic-gate }
10710Sstevel@tonic-gate
10720Sstevel@tonic-gate if ((error = get_uint64_array(
10730Sstevel@tonic-gate attrs, ATTR_VIRTUAL_SLICES, &old_slices, &nelem)) != 0) {
10740Sstevel@tonic-gate if (error != ENOENT) {
10750Sstevel@tonic-gate return (error);
10760Sstevel@tonic-gate }
10770Sstevel@tonic-gate error = 0;
10780Sstevel@tonic-gate }
10790Sstevel@tonic-gate
10800Sstevel@tonic-gate /* make a new array */
10810Sstevel@tonic-gate new_slices = (uint64_t *)calloc(nelem + 1, sizeof (uint64_t));
10820Sstevel@tonic-gate if (new_slices != NULL) {
10830Sstevel@tonic-gate
10840Sstevel@tonic-gate for (i = 0; i < nelem; i++) {
10850Sstevel@tonic-gate new_slices[i] = old_slices[i];
10860Sstevel@tonic-gate }
10870Sstevel@tonic-gate new_slices[i] = slice;
10880Sstevel@tonic-gate
10890Sstevel@tonic-gate error = set_uint64_array(
10900Sstevel@tonic-gate attrs, ATTR_VIRTUAL_SLICES, new_slices, nelem);
10910Sstevel@tonic-gate
10920Sstevel@tonic-gate free(new_slices);
10930Sstevel@tonic-gate
10940Sstevel@tonic-gate } else {
10950Sstevel@tonic-gate error = ENOMEM;
10960Sstevel@tonic-gate }
10970Sstevel@tonic-gate
10980Sstevel@tonic-gate return (error);
10990Sstevel@tonic-gate }
11000Sstevel@tonic-gate
11010Sstevel@tonic-gate /*
11020Sstevel@tonic-gate * FUNCTION: disk_has_virtual_slices(dm_descriptor_t disk, boolean_t *bool)
11030Sstevel@tonic-gate *
11040Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t disk handle
11050Sstevel@tonic-gate *
11060Sstevel@tonic-gate * OUTPUT: bool - B_TRUE - if the disk has virtual slices
11070Sstevel@tonic-gate * B_FALSE - otherwise
11080Sstevel@tonic-gate *
11090Sstevel@tonic-gate * RETURNS: int - 0 on success
11100Sstevel@tonic-gate * !0 otherwise
11110Sstevel@tonic-gate *
11120Sstevel@tonic-gate * PURPOSE: Helper which determines if the input disk has virtual slices.
11130Sstevel@tonic-gate *
11140Sstevel@tonic-gate * If a disk has virtual slices, their dm_descriptor_t handles
11150Sstevel@tonic-gate * will be stored in the disk's nvpair attribute list.
11160Sstevel@tonic-gate */
11170Sstevel@tonic-gate static int
disk_has_virtual_slices(dm_descriptor_t disk,boolean_t * bool)11180Sstevel@tonic-gate disk_has_virtual_slices(
11190Sstevel@tonic-gate dm_descriptor_t disk,
11200Sstevel@tonic-gate boolean_t *bool)
11210Sstevel@tonic-gate {
11220Sstevel@tonic-gate nvlist_t *attrs = NULL;
11230Sstevel@tonic-gate uint64_t *slices = NULL;
11240Sstevel@tonic-gate uint_t nelem = 0;
11250Sstevel@tonic-gate int error = 0;
11260Sstevel@tonic-gate
11270Sstevel@tonic-gate *bool = B_FALSE;
11280Sstevel@tonic-gate
11290Sstevel@tonic-gate if ((error = get_cached_attributes(disk, &attrs)) != 0) {
11300Sstevel@tonic-gate return (error);
11310Sstevel@tonic-gate }
11320Sstevel@tonic-gate
11330Sstevel@tonic-gate if ((error = get_uint64_array(
11340Sstevel@tonic-gate attrs, ATTR_VIRTUAL_SLICES, &slices, &nelem)) != 0) {
11350Sstevel@tonic-gate if (error == ENOENT) {
11360Sstevel@tonic-gate error = 0;
11370Sstevel@tonic-gate nelem = 0;
11380Sstevel@tonic-gate } else {
11390Sstevel@tonic-gate /* count actual number of elements */
11400Sstevel@tonic-gate int i = 0;
11410Sstevel@tonic-gate while (i < nelem) {
11420Sstevel@tonic-gate if (slices[i] != -1) {
11430Sstevel@tonic-gate ++i;
11440Sstevel@tonic-gate }
11450Sstevel@tonic-gate }
11460Sstevel@tonic-gate nelem = i;
11470Sstevel@tonic-gate }
11480Sstevel@tonic-gate }
11490Sstevel@tonic-gate
11500Sstevel@tonic-gate *bool = (nelem != 0);
11510Sstevel@tonic-gate
11520Sstevel@tonic-gate return (error);
11530Sstevel@tonic-gate }
11540Sstevel@tonic-gate
11550Sstevel@tonic-gate /*
11560Sstevel@tonic-gate * FUNCTION: disk_get_virtual_slices(dm_descriptor_t disk, boolean_t *bool)
11570Sstevel@tonic-gate *
11580Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t disk handle
11590Sstevel@tonic-gate *
11600Sstevel@tonic-gate * OUTPUT: list - a dlist_t list of dm_descriptor_t handles for the
11610Sstevel@tonic-gate * disk's virtual slices.
11620Sstevel@tonic-gate *
11630Sstevel@tonic-gate * RETURNS: int - 0 on success
11640Sstevel@tonic-gate * !0 otherwise
11650Sstevel@tonic-gate *
11660Sstevel@tonic-gate * PURPOSE: Helper which retrieves a list of the input disk's virtual
11670Sstevel@tonic-gate * slices.
11680Sstevel@tonic-gate *
11690Sstevel@tonic-gate * If a disk has virtual slices, their dm_descriptor_t handles
11700Sstevel@tonic-gate * will be stored in the disk's nvpair attribute list.
11710Sstevel@tonic-gate */
11720Sstevel@tonic-gate static int
disk_get_virtual_slices(dm_descriptor_t disk,dlist_t ** list)11730Sstevel@tonic-gate disk_get_virtual_slices(
11740Sstevel@tonic-gate dm_descriptor_t disk,
11750Sstevel@tonic-gate dlist_t **list)
11760Sstevel@tonic-gate {
11770Sstevel@tonic-gate nvlist_t *attrs = NULL;
11780Sstevel@tonic-gate uint64_t *slices = NULL;
11790Sstevel@tonic-gate uint_t nelem = 0;
11800Sstevel@tonic-gate int error = 0;
11810Sstevel@tonic-gate int i = 0;
11820Sstevel@tonic-gate
11830Sstevel@tonic-gate if ((error = get_cached_attributes(disk, &attrs)) != 0) {
11840Sstevel@tonic-gate return (error);
11850Sstevel@tonic-gate }
11860Sstevel@tonic-gate
11870Sstevel@tonic-gate if ((error = get_uint64_array(
11880Sstevel@tonic-gate attrs, ATTR_VIRTUAL_SLICES, &slices, &nelem)) != 0) {
11890Sstevel@tonic-gate if (error != ENOENT) {
11900Sstevel@tonic-gate return (error);
11910Sstevel@tonic-gate }
11920Sstevel@tonic-gate
11930Sstevel@tonic-gate return (0);
11940Sstevel@tonic-gate }
11950Sstevel@tonic-gate
11960Sstevel@tonic-gate for (i = 0; i < nelem && slices[i] != -1; i++) {
11970Sstevel@tonic-gate dlist_t *item = NULL;
11980Sstevel@tonic-gate
1199*62Sjeanm if ((item = dlist_new_item((void*)(uintptr_t)slices[i])) == NULL) {
12000Sstevel@tonic-gate error = ENOMEM;
12010Sstevel@tonic-gate break;
12020Sstevel@tonic-gate }
12030Sstevel@tonic-gate
12040Sstevel@tonic-gate *list = dlist_append(item, *list, AT_TAIL);
12050Sstevel@tonic-gate }
12060Sstevel@tonic-gate
12070Sstevel@tonic-gate return (error);
12080Sstevel@tonic-gate }
12090Sstevel@tonic-gate
12100Sstevel@tonic-gate /*
12110Sstevel@tonic-gate * FUNCTION: is_virtual_slice(dm_descriptor_t desc)
12120Sstevel@tonic-gate *
12130Sstevel@tonic-gate * INPUT: desc - a dm_descriptor_t handle
12140Sstevel@tonic-gate *
12150Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE if the input descriptor is for
12160Sstevel@tonic-gate * a virtual slice.
12170Sstevel@tonic-gate * B_FALSE otherwise
12180Sstevel@tonic-gate *
12190Sstevel@tonic-gate * PURPOSE: Helper which determines whether the input descriptor
12200Sstevel@tonic-gate * corresponds to a virtual slice.
12210Sstevel@tonic-gate *
12220Sstevel@tonic-gate * All virtual slices are stored in a module private list.
12230Sstevel@tonic-gate * This list is iterated to see if it contains the input
12240Sstevel@tonic-gate * descriptor.
12250Sstevel@tonic-gate */
12260Sstevel@tonic-gate boolean_t
is_virtual_slice(dm_descriptor_t desc)12270Sstevel@tonic-gate is_virtual_slice(
12280Sstevel@tonic-gate dm_descriptor_t desc)
12290Sstevel@tonic-gate {
12300Sstevel@tonic-gate return (dlist_contains(_virtual_slices,
1231*62Sjeanm (void*)(uintptr_t)desc, compare_descriptors));
12320Sstevel@tonic-gate }
12330Sstevel@tonic-gate
12340Sstevel@tonic-gate /*
12350Sstevel@tonic-gate * FUNCTION: disk_get_available_slice_index(dm_descriptor_t disk,
12360Sstevel@tonic-gate * uint32_t *newindex)
12370Sstevel@tonic-gate *
12380Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t handle for a disk
12390Sstevel@tonic-gate *
12400Sstevel@tonic-gate * OUTPUT: *newindex - a pointer to a uint32_t to hold the available
12410Sstevel@tonic-gate * index. If no index is available, the value pointed
12420Sstevel@tonic-gate * to is not modified.
12430Sstevel@tonic-gate *
12440Sstevel@tonic-gate * RETURNS: int - 0 on success
12450Sstevel@tonic-gate * !0 otherwise.
12460Sstevel@tonic-gate *
12470Sstevel@tonic-gate * PURPOSE: examine the input disk's list of slices and find an unused
12480Sstevel@tonic-gate * slice index. The replica slice (index 7 or 6) is always
12490Sstevel@tonic-gate * off-limits -- it shows up as in use. Slice 0 should only
12500Sstevel@tonic-gate * be used as a last resort.
12510Sstevel@tonic-gate *
12520Sstevel@tonic-gate * If an available index is found, it is stored into newindex.
12530Sstevel@tonic-gate * Otherwise, newindex is unchanged. This allows the caller to
12540Sstevel@tonic-gate * pass in an index and check if it has been modified on return.
12550Sstevel@tonic-gate *
12560Sstevel@tonic-gate * V_NUMPAR is used as the number of available slices,
12570Sstevel@tonic-gate * SPARC systems have V_NUMPAR == 8, X86 have V_NUMPAR == 16.
12580Sstevel@tonic-gate *
12590Sstevel@tonic-gate * EFI disks have only 7.
12600Sstevel@tonic-gate */
12610Sstevel@tonic-gate int
disk_get_available_slice_index(dm_descriptor_t disk,uint32_t * newindex)12620Sstevel@tonic-gate disk_get_available_slice_index(
12630Sstevel@tonic-gate dm_descriptor_t disk,
12640Sstevel@tonic-gate uint32_t *newindex)
12650Sstevel@tonic-gate {
12660Sstevel@tonic-gate dlist_t *iter = NULL;
12670Sstevel@tonic-gate dlist_t *slices = NULL;
12680Sstevel@tonic-gate uint32_t index = 0;
12690Sstevel@tonic-gate uint16_t *reserved = NULL;
12700Sstevel@tonic-gate boolean_t *used = NULL;
12710Sstevel@tonic-gate boolean_t is_efi = B_FALSE;
12720Sstevel@tonic-gate int error = 0;
12730Sstevel@tonic-gate int i = 0;
12740Sstevel@tonic-gate int nslices = V_NUMPAR;
12750Sstevel@tonic-gate
12760Sstevel@tonic-gate if (((error = disk_get_slices(disk, &slices)) != 0) ||
12770Sstevel@tonic-gate (error = disk_get_is_efi(disk, &is_efi)) != 0) {
12780Sstevel@tonic-gate return (error);
12790Sstevel@tonic-gate }
12800Sstevel@tonic-gate
12810Sstevel@tonic-gate if (is_efi == B_TRUE) {
12820Sstevel@tonic-gate /* limit possible indexes to 7 for EFI */
12830Sstevel@tonic-gate nslices = 7;
12840Sstevel@tonic-gate }
12850Sstevel@tonic-gate
12860Sstevel@tonic-gate used = (boolean_t *)calloc(nslices, sizeof (boolean_t));
12870Sstevel@tonic-gate if (used == NULL) {
12880Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
12890Sstevel@tonic-gate gettext("failed allocating slice index array\n"),
12900Sstevel@tonic-gate NULL);
12910Sstevel@tonic-gate return (ENOMEM);
12920Sstevel@tonic-gate }
12930Sstevel@tonic-gate
12940Sstevel@tonic-gate /* eliminate indexes that are reserved */
12950Sstevel@tonic-gate if ((error = disk_get_reserved_indexes(disk, &reserved)) != 0) {
12960Sstevel@tonic-gate return (error);
12970Sstevel@tonic-gate }
12980Sstevel@tonic-gate
12990Sstevel@tonic-gate if (reserved != NULL) {
13000Sstevel@tonic-gate for (i = 0; i < nslices; i++) {
13010Sstevel@tonic-gate if (reserved[i] == 1) {
13020Sstevel@tonic-gate used[i] = B_TRUE;
13030Sstevel@tonic-gate }
13040Sstevel@tonic-gate }
13050Sstevel@tonic-gate }
13060Sstevel@tonic-gate
13070Sstevel@tonic-gate /* eliminate slices that are in use (have a size > 0) */
13080Sstevel@tonic-gate /* 0 sized slices unused slices */
13090Sstevel@tonic-gate for (iter = slices; iter != NULL; iter = iter->next) {
13100Sstevel@tonic-gate dm_descriptor_t sp = (uintptr_t)iter->obj;
13110Sstevel@tonic-gate uint64_t size = 0;
13120Sstevel@tonic-gate
13130Sstevel@tonic-gate ((error = slice_get_index(sp, &index)) != 0) ||
13140Sstevel@tonic-gate (error = slice_get_size_in_blocks(sp, &size));
13150Sstevel@tonic-gate if (error != 0) {
13160Sstevel@tonic-gate return (error);
13170Sstevel@tonic-gate }
13180Sstevel@tonic-gate
13190Sstevel@tonic-gate if (size > 0) {
13200Sstevel@tonic-gate used[(int)index] = B_TRUE;
13210Sstevel@tonic-gate }
13220Sstevel@tonic-gate }
13230Sstevel@tonic-gate dlist_free_items(slices, NULL);
13240Sstevel@tonic-gate
13250Sstevel@tonic-gate for (i = 0; i < nslices; i++) {
13260Sstevel@tonic-gate
13270Sstevel@tonic-gate /* skip the index passed in */
13280Sstevel@tonic-gate if (i == *newindex) {
13290Sstevel@tonic-gate continue;
13300Sstevel@tonic-gate }
13310Sstevel@tonic-gate
13320Sstevel@tonic-gate if (used[i] != B_TRUE) {
13330Sstevel@tonic-gate index = i;
13340Sstevel@tonic-gate break;
13350Sstevel@tonic-gate }
13360Sstevel@tonic-gate }
13370Sstevel@tonic-gate
13380Sstevel@tonic-gate if (i != nslices) {
13390Sstevel@tonic-gate /* return unused slice index */
13400Sstevel@tonic-gate *newindex = index;
13410Sstevel@tonic-gate }
13420Sstevel@tonic-gate
13430Sstevel@tonic-gate free((void *)used);
13440Sstevel@tonic-gate
13450Sstevel@tonic-gate return (0);
13460Sstevel@tonic-gate }
13470Sstevel@tonic-gate
13480Sstevel@tonic-gate /*
13490Sstevel@tonic-gate * FUNCTION: disk_get_media_type(dm_descriptor_t slice, uint32_t *type)
13500Sstevel@tonic-gate *
13510Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t handle for a disk
13520Sstevel@tonic-gate *
13530Sstevel@tonic-gate * OUTPUT: *type - a pointer to a uint32_t to hold the
13540Sstevel@tonic-gate * current type value for the media on which
13550Sstevel@tonic-gate * the input slice resides.
13560Sstevel@tonic-gate *
13570Sstevel@tonic-gate * RETURNS: int - 0 on success
13580Sstevel@tonic-gate * !0 otherwise.
13590Sstevel@tonic-gate *
13600Sstevel@tonic-gate * PURPOSE: Retrieves the media type for the disk.
13610Sstevel@tonic-gate *
13620Sstevel@tonic-gate * Get the media associate with the input disk descriptor
13630Sstevel@tonic-gate * and determine its type.
13640Sstevel@tonic-gate */
13650Sstevel@tonic-gate int
disk_get_media_type(dm_descriptor_t disk,uint32_t * type)13660Sstevel@tonic-gate disk_get_media_type(
13670Sstevel@tonic-gate dm_descriptor_t disk,
13680Sstevel@tonic-gate uint32_t *type)
13690Sstevel@tonic-gate {
13700Sstevel@tonic-gate int error = 0;
13710Sstevel@tonic-gate dm_descriptor_t *mdp = NULL;
13720Sstevel@tonic-gate
13730Sstevel@tonic-gate mdp = dm_get_associated_descriptors(disk, DM_MEDIA, &error);
13740Sstevel@tonic-gate (void) add_descriptors_to_free(mdp);
13750Sstevel@tonic-gate
13760Sstevel@tonic-gate if (error != 0) {
13770Sstevel@tonic-gate print_get_assoc_desc_error(disk, gettext("media"), error);
13780Sstevel@tonic-gate } else {
13790Sstevel@tonic-gate /* disk should have exactly 1 media */
13800Sstevel@tonic-gate if ((mdp != NULL) && (*mdp != NULL)) {
13810Sstevel@tonic-gate nvlist_t *attrs = dm_get_attributes(*mdp, &error);
13820Sstevel@tonic-gate if ((error == 0) && (attrs != NULL)) {
13830Sstevel@tonic-gate error = get_uint32(attrs, DM_MTYPE, type);
13840Sstevel@tonic-gate }
13850Sstevel@tonic-gate
13860Sstevel@tonic-gate nvlist_free(attrs);
13870Sstevel@tonic-gate }
13880Sstevel@tonic-gate /* no media: removeable drive */
13890Sstevel@tonic-gate }
13900Sstevel@tonic-gate
13910Sstevel@tonic-gate if (mdp != NULL) {
13920Sstevel@tonic-gate free(mdp);
13930Sstevel@tonic-gate }
13940Sstevel@tonic-gate
13950Sstevel@tonic-gate return (error);
13960Sstevel@tonic-gate }
13970Sstevel@tonic-gate
13980Sstevel@tonic-gate /*
13990Sstevel@tonic-gate * FUNCTION: disk_get_rpm(dm_descriptor_t disk, uint32_t *val)
14000Sstevel@tonic-gate * disk_get_sync_speed(dm_descriptor_t disk, uint32_t *val)
14010Sstevel@tonic-gate * disk_get_size_in_blocks(dm_descriptor_t disk, uint64_t *val)
14020Sstevel@tonic-gate * disk_get_blocksize(dm_descriptor_t disk, uint64_t *val)
14030Sstevel@tonic-gate * disk_get_ncylinders(dm_descriptor_t disk, uint64_t *val)
14040Sstevel@tonic-gate * disk_get_nheads(dm_descriptor_t disk, uint64_t *val)
14050Sstevel@tonic-gate * disk_get_nsectors(dm_descriptor_t disk, uint64_t *val)
14060Sstevel@tonic-gate * disk_get_is_efi(dm_descriptor_t disk, boolean_t *val)
14070Sstevel@tonic-gate * disk_get_is_online(dm_descriptor_t disk, boolean_t *val)
14080Sstevel@tonic-gate * disk_get_media_type(dm_descriptor_t disk, uint32_t *type)
14090Sstevel@tonic-gate * disk_get_has_fdisk(dm_descriptor_t disk, boolean_t *val)
14100Sstevel@tonic-gate * disk_get_start_block(dm_descriptor_t disk, uint64_t *val)
14110Sstevel@tonic-gate *
14120Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t handle for a disk
14130Sstevel@tonic-gate *
14140Sstevel@tonic-gate * OUTPUT: *bool - a pointer to a variable of the appropriate
14150Sstevel@tonic-gate * type to hold the current value for the attribute
14160Sstevel@tonic-gate * of interest.
14170Sstevel@tonic-gate *
14180Sstevel@tonic-gate * RETURNS: int - 0 on success
14190Sstevel@tonic-gate * !0 otherwise.
14200Sstevel@tonic-gate *
14210Sstevel@tonic-gate * PURPOSE: Wrappers around disk_get_XXX_attribute that know
14220Sstevel@tonic-gate * which attribute needs to be retrieved and also handle
14230Sstevel@tonic-gate * any necesasry type or units conversions.
14240Sstevel@tonic-gate */
14250Sstevel@tonic-gate static int
disk_get_rpm(dm_descriptor_t disk,uint32_t * val)14260Sstevel@tonic-gate disk_get_rpm(
14270Sstevel@tonic-gate dm_descriptor_t disk,
14280Sstevel@tonic-gate uint32_t *val)
14290Sstevel@tonic-gate {
14300Sstevel@tonic-gate uint64_t val64 = 0;
14310Sstevel@tonic-gate int error = 0;
14320Sstevel@tonic-gate
14330Sstevel@tonic-gate if ((error = disk_get_uint64_attribute(
14340Sstevel@tonic-gate disk, DM_RPM, &val64)) != 0) {
14350Sstevel@tonic-gate return (error);
14360Sstevel@tonic-gate }
14370Sstevel@tonic-gate
14380Sstevel@tonic-gate *val = (uint32_t)val64;
14390Sstevel@tonic-gate
14400Sstevel@tonic-gate return (error);
14410Sstevel@tonic-gate }
14420Sstevel@tonic-gate
14430Sstevel@tonic-gate int
disk_get_drive_type(dm_descriptor_t disk,uint32_t * val)14440Sstevel@tonic-gate disk_get_drive_type(
14450Sstevel@tonic-gate dm_descriptor_t disk,
14460Sstevel@tonic-gate uint32_t *val)
14470Sstevel@tonic-gate {
14480Sstevel@tonic-gate uint64_t val64 = 0;
14490Sstevel@tonic-gate int error = 0;
14500Sstevel@tonic-gate
14510Sstevel@tonic-gate if ((error = disk_get_uint64_attribute(
14520Sstevel@tonic-gate disk, DM_DRVTYPE, &val64)) != 0) {
14530Sstevel@tonic-gate return (error);
14540Sstevel@tonic-gate }
14550Sstevel@tonic-gate
14560Sstevel@tonic-gate *val = (uint32_t)val64;
14570Sstevel@tonic-gate
14580Sstevel@tonic-gate return (error);
14590Sstevel@tonic-gate }
14600Sstevel@tonic-gate
14610Sstevel@tonic-gate static int
disk_get_sync_speed(dm_descriptor_t disk,uint32_t * val)14620Sstevel@tonic-gate disk_get_sync_speed(
14630Sstevel@tonic-gate dm_descriptor_t disk,
14640Sstevel@tonic-gate uint32_t *val)
14650Sstevel@tonic-gate {
14660Sstevel@tonic-gate uint64_t val64 = 0;
14670Sstevel@tonic-gate int error = 0;
14680Sstevel@tonic-gate
14690Sstevel@tonic-gate if ((error = disk_get_uint64_attribute(
14700Sstevel@tonic-gate disk, DM_SYNC_SPEED, &val64)) != 0) {
14710Sstevel@tonic-gate return (error);
14720Sstevel@tonic-gate }
14730Sstevel@tonic-gate
14740Sstevel@tonic-gate *val = (uint32_t)val64;
14750Sstevel@tonic-gate
14760Sstevel@tonic-gate return (error);
14770Sstevel@tonic-gate }
14780Sstevel@tonic-gate
14790Sstevel@tonic-gate /* returns number of usable blocks */
14800Sstevel@tonic-gate int
disk_get_size_in_blocks(dm_descriptor_t disk,uint64_t * val)14810Sstevel@tonic-gate disk_get_size_in_blocks(
14820Sstevel@tonic-gate dm_descriptor_t disk,
14830Sstevel@tonic-gate uint64_t *val)
14840Sstevel@tonic-gate {
14850Sstevel@tonic-gate return (disk_get_uint64_attribute(disk, DM_NACCESSIBLE, val));
14860Sstevel@tonic-gate }
14870Sstevel@tonic-gate
14880Sstevel@tonic-gate /* returns first usable block on disk */
14890Sstevel@tonic-gate int
disk_get_start_block(dm_descriptor_t disk,uint64_t * val)14900Sstevel@tonic-gate disk_get_start_block(
14910Sstevel@tonic-gate dm_descriptor_t disk,
14920Sstevel@tonic-gate uint64_t *val)
14930Sstevel@tonic-gate {
14940Sstevel@tonic-gate return (disk_get_uint64_attribute(disk, DM_START, val));
14950Sstevel@tonic-gate }
14960Sstevel@tonic-gate
14970Sstevel@tonic-gate int
disk_get_blocksize(dm_descriptor_t disk,uint64_t * val)14980Sstevel@tonic-gate disk_get_blocksize(
14990Sstevel@tonic-gate dm_descriptor_t disk,
15000Sstevel@tonic-gate uint64_t *val)
15010Sstevel@tonic-gate {
15020Sstevel@tonic-gate return (disk_get_uint64_attribute(disk, DM_BLOCKSIZE, val));
15030Sstevel@tonic-gate }
15040Sstevel@tonic-gate
15050Sstevel@tonic-gate int
disk_get_ncylinders(dm_descriptor_t disk,uint64_t * val)15060Sstevel@tonic-gate disk_get_ncylinders(
15070Sstevel@tonic-gate dm_descriptor_t disk,
15080Sstevel@tonic-gate uint64_t *val)
15090Sstevel@tonic-gate {
15100Sstevel@tonic-gate return (disk_get_uint64_attribute(disk, DM_NCYLINDERS, val));
15110Sstevel@tonic-gate }
15120Sstevel@tonic-gate
15130Sstevel@tonic-gate int
disk_get_nheads(dm_descriptor_t disk,uint64_t * val)15140Sstevel@tonic-gate disk_get_nheads(
15150Sstevel@tonic-gate dm_descriptor_t disk,
15160Sstevel@tonic-gate uint64_t *val)
15170Sstevel@tonic-gate {
15180Sstevel@tonic-gate return (disk_get_uint64_attribute(disk, DM_NHEADS, val));
15190Sstevel@tonic-gate }
15200Sstevel@tonic-gate
15210Sstevel@tonic-gate int
disk_get_nsectors(dm_descriptor_t disk,uint64_t * val)15220Sstevel@tonic-gate disk_get_nsectors(
15230Sstevel@tonic-gate dm_descriptor_t disk,
15240Sstevel@tonic-gate uint64_t *val)
15250Sstevel@tonic-gate {
15260Sstevel@tonic-gate return (disk_get_uint64_attribute(disk, DM_NSECTORS, val));
15270Sstevel@tonic-gate }
15280Sstevel@tonic-gate
15290Sstevel@tonic-gate /*
15300Sstevel@tonic-gate * FUNCTION: disk_get_is_online(dm_descriptor_t disk, boolean_t *val)
15310Sstevel@tonic-gate *
15320Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t handle for a disk
15330Sstevel@tonic-gate *
15340Sstevel@tonic-gate * OUTPUT: *bool - a pointer to a boolean_t to hold the result.
15350Sstevel@tonic-gate *
15360Sstevel@tonic-gate * RETURNS: int - 0 on success
15370Sstevel@tonic-gate * !0 otherwise.
15380Sstevel@tonic-gate *
15390Sstevel@tonic-gate * PURPOSE: Determine if the input disk is "online".
15400Sstevel@tonic-gate *
15410Sstevel@tonic-gate * Check the status bit of the drive, if it is 1 the drive
15420Sstevel@tonic-gate * is online, if it is 0 the drive is offline.
15430Sstevel@tonic-gate */
15440Sstevel@tonic-gate int
disk_get_is_online(dm_descriptor_t disk,boolean_t * val)15450Sstevel@tonic-gate disk_get_is_online(
15460Sstevel@tonic-gate dm_descriptor_t disk,
15470Sstevel@tonic-gate boolean_t *val)
15480Sstevel@tonic-gate {
15490Sstevel@tonic-gate uint64_t status = 0;
15500Sstevel@tonic-gate int error = 0;
15510Sstevel@tonic-gate
15520Sstevel@tonic-gate *val = B_FALSE;
15530Sstevel@tonic-gate
15540Sstevel@tonic-gate error = disk_get_uint64_attribute(disk, DM_STATUS, &status);
15550Sstevel@tonic-gate if (error == 0) {
15560Sstevel@tonic-gate *val = (status == 1) ? B_TRUE : B_FALSE;
15570Sstevel@tonic-gate }
15580Sstevel@tonic-gate
15590Sstevel@tonic-gate return (error);
15600Sstevel@tonic-gate }
15610Sstevel@tonic-gate
15620Sstevel@tonic-gate /*
15630Sstevel@tonic-gate * FUNCTION: disk_get_is_efi(dm_descriptor_t disk, boolean_t *bool)
15640Sstevel@tonic-gate *
15650Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t handle for a disk
15660Sstevel@tonic-gate *
15670Sstevel@tonic-gate * OUTPUT: *bool - a pointer to a boolean_t to hold the result.
15680Sstevel@tonic-gate *
15690Sstevel@tonic-gate * RETURNS: int - 0 on success
15700Sstevel@tonic-gate * !0 otherwise.
15710Sstevel@tonic-gate *
15720Sstevel@tonic-gate * PURPOSE: Determine if the input disk is labeled with an EFI label.
15730Sstevel@tonic-gate *
15740Sstevel@tonic-gate * The label type is actually a property of the media
15750Sstevel@tonic-gate * associated with the disk, so retrieve the media and
15760Sstevel@tonic-gate * check if it is EFI labeled.
15770Sstevel@tonic-gate */
15780Sstevel@tonic-gate int
disk_get_is_efi(dm_descriptor_t disk,boolean_t * bool)15790Sstevel@tonic-gate disk_get_is_efi(
15800Sstevel@tonic-gate dm_descriptor_t disk,
15810Sstevel@tonic-gate boolean_t *bool)
15820Sstevel@tonic-gate {
15830Sstevel@tonic-gate return (disk_get_boolean_attribute(disk, DM_EFI, bool));
15840Sstevel@tonic-gate }
15850Sstevel@tonic-gate
15860Sstevel@tonic-gate /*
15870Sstevel@tonic-gate * FUNCTION: disk_get_has_fdisk(dm_descriptor_t disk, boolean_t *bool)
15880Sstevel@tonic-gate *
15890Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t handle for a disk
15900Sstevel@tonic-gate *
15910Sstevel@tonic-gate * OUTPUT: *bool - a pointer to a boolean_t to hold the result.
15920Sstevel@tonic-gate *
15930Sstevel@tonic-gate * RETURNS: int - 0 on success
15940Sstevel@tonic-gate * !0 otherwise.
15950Sstevel@tonic-gate *
15960Sstevel@tonic-gate * PURPOSE: Determine if the input disk has an FDISK partition.
15970Sstevel@tonic-gate */
15980Sstevel@tonic-gate int
disk_get_has_fdisk(dm_descriptor_t disk,boolean_t * bool)15990Sstevel@tonic-gate disk_get_has_fdisk(
16000Sstevel@tonic-gate dm_descriptor_t disk,
16010Sstevel@tonic-gate boolean_t *bool)
16020Sstevel@tonic-gate {
16030Sstevel@tonic-gate return (disk_get_boolean_attribute(disk, DM_FDISK, bool));
16040Sstevel@tonic-gate }
16050Sstevel@tonic-gate
16060Sstevel@tonic-gate /*
16070Sstevel@tonic-gate * FUNCTION: disk_get_has_solaris_partition(dm_descriptor_t disk, boolean_t *bool)
16080Sstevel@tonic-gate *
16090Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t handle for a disk
16100Sstevel@tonic-gate *
16110Sstevel@tonic-gate * OUTPUT: *bool - a pointer to a boolean_t to hold the result.
16120Sstevel@tonic-gate *
16130Sstevel@tonic-gate * RETURNS: int - 0 on success
16140Sstevel@tonic-gate * !0 otherwise.
16150Sstevel@tonic-gate *
16160Sstevel@tonic-gate * PURPOSE: Determine if the input disk has a Solaris FDISK partition.
16170Sstevel@tonic-gate */
16180Sstevel@tonic-gate int
disk_get_has_solaris_partition(dm_descriptor_t disk,boolean_t * bool)16190Sstevel@tonic-gate disk_get_has_solaris_partition(
16200Sstevel@tonic-gate dm_descriptor_t disk,
16210Sstevel@tonic-gate boolean_t *bool)
16220Sstevel@tonic-gate {
16230Sstevel@tonic-gate boolean_t has_fdisk = B_FALSE;
16240Sstevel@tonic-gate int error = 0;
16250Sstevel@tonic-gate
16260Sstevel@tonic-gate if ((error = disk_get_has_fdisk(disk, &has_fdisk)) != 0) {
16270Sstevel@tonic-gate return (error);
16280Sstevel@tonic-gate }
16290Sstevel@tonic-gate
16300Sstevel@tonic-gate *bool = B_FALSE;
16310Sstevel@tonic-gate
16320Sstevel@tonic-gate if (has_fdisk == B_TRUE) {
16330Sstevel@tonic-gate /* get disk's media */
16340Sstevel@tonic-gate dm_descriptor_t *media;
16350Sstevel@tonic-gate media = dm_get_associated_descriptors(disk, DM_MEDIA, &error);
16360Sstevel@tonic-gate (void) add_descriptors_to_free(media);
16370Sstevel@tonic-gate if (error != 0) {
16380Sstevel@tonic-gate print_get_assoc_desc_error(disk, gettext("media"), error);
16390Sstevel@tonic-gate } else if ((media != NULL) && (*media != NULL)) {
16400Sstevel@tonic-gate /* get media's partitions */
16410Sstevel@tonic-gate dm_descriptor_t *parts;
16420Sstevel@tonic-gate parts = dm_get_associated_descriptors(
16430Sstevel@tonic-gate media[0], DM_PARTITION, &error);
16440Sstevel@tonic-gate (void) add_descriptors_to_free(parts);
16450Sstevel@tonic-gate if (error != 0) {
16460Sstevel@tonic-gate print_get_assoc_desc_error(media[0],
16470Sstevel@tonic-gate gettext("partitions"), error);
16480Sstevel@tonic-gate } else {
16490Sstevel@tonic-gate /* search partitions for one with type Solaris */
16500Sstevel@tonic-gate int i = 0;
16510Sstevel@tonic-gate for (; (parts != NULL) && (parts[i] != NULL) &&
16520Sstevel@tonic-gate (error == 0) && (*bool == B_FALSE); i++) {
16530Sstevel@tonic-gate nvlist_t *attrs = dm_get_attributes(parts[i], &error);
16540Sstevel@tonic-gate uint32_t ptype = 0;
16550Sstevel@tonic-gate if ((error == 0) && (attrs != NULL)) {
16560Sstevel@tonic-gate error = get_uint32(attrs, DM_PTYPE, &ptype);
16570Sstevel@tonic-gate if ((error == 0) &&
16580Sstevel@tonic-gate (ptype == SUNIXOS || ptype == SUNIXOS2)) {
16590Sstevel@tonic-gate *bool = B_TRUE;
16600Sstevel@tonic-gate }
16610Sstevel@tonic-gate }
16620Sstevel@tonic-gate nvlist_free(attrs);
16630Sstevel@tonic-gate }
16640Sstevel@tonic-gate }
16650Sstevel@tonic-gate
16660Sstevel@tonic-gate free(parts);
16670Sstevel@tonic-gate free(media);
16680Sstevel@tonic-gate }
16690Sstevel@tonic-gate
16700Sstevel@tonic-gate /* if there was no media, it was a removeable drive */
16710Sstevel@tonic-gate }
16720Sstevel@tonic-gate
16730Sstevel@tonic-gate return (error);
16740Sstevel@tonic-gate }
16750Sstevel@tonic-gate
16760Sstevel@tonic-gate static int
disk_get_boolean_attribute(dm_descriptor_t disk,char * attr,boolean_t * bool)16770Sstevel@tonic-gate disk_get_boolean_attribute(
16780Sstevel@tonic-gate dm_descriptor_t disk,
16790Sstevel@tonic-gate char *attr,
16800Sstevel@tonic-gate boolean_t *bool)
16810Sstevel@tonic-gate {
16820Sstevel@tonic-gate nvlist_t *attrs = NULL;
16830Sstevel@tonic-gate int error = 0;
16840Sstevel@tonic-gate
16850Sstevel@tonic-gate *bool = B_FALSE;
16860Sstevel@tonic-gate
16870Sstevel@tonic-gate if ((strcmp(attr, DM_EFI) == 0) ||
16880Sstevel@tonic-gate (strcmp(attr, DM_FDISK) == 0)) {
16890Sstevel@tonic-gate
16900Sstevel@tonic-gate /*
16910Sstevel@tonic-gate * these attributes are actually on the media,
16920Sstevel@tonic-gate * not the disk... so get the media descriptor
16930Sstevel@tonic-gate * for this disk
16940Sstevel@tonic-gate */
16950Sstevel@tonic-gate dm_descriptor_t *media;
16960Sstevel@tonic-gate
16970Sstevel@tonic-gate media = dm_get_associated_descriptors(disk, DM_MEDIA, &error);
16980Sstevel@tonic-gate (void) add_descriptors_to_free(media);
16990Sstevel@tonic-gate
17000Sstevel@tonic-gate if (error != 0) {
17010Sstevel@tonic-gate print_get_assoc_desc_error(disk, gettext("media"), error);
17020Sstevel@tonic-gate } else if ((media != NULL) && (*media != NULL)) {
17030Sstevel@tonic-gate /* if there's no media, it is a removeable drive */
17040Sstevel@tonic-gate error = get_cached_attributes(media[0], &attrs);
17050Sstevel@tonic-gate }
17060Sstevel@tonic-gate free(media);
17070Sstevel@tonic-gate
17080Sstevel@tonic-gate } else {
17090Sstevel@tonic-gate error = get_cached_attributes(disk, &attrs);
17100Sstevel@tonic-gate if (error != 0) {
17110Sstevel@tonic-gate print_get_desc_attr_error(disk, gettext("drive"), attr, error);
17120Sstevel@tonic-gate }
17130Sstevel@tonic-gate }
17140Sstevel@tonic-gate
17150Sstevel@tonic-gate if (error != 0) {
17160Sstevel@tonic-gate return (error);
17170Sstevel@tonic-gate }
17180Sstevel@tonic-gate
17190Sstevel@tonic-gate if (nvlist_lookup_boolean(attrs, attr) == 0) {
17200Sstevel@tonic-gate *bool = B_TRUE;
17210Sstevel@tonic-gate }
17220Sstevel@tonic-gate
17230Sstevel@tonic-gate return (error);
17240Sstevel@tonic-gate }
17250Sstevel@tonic-gate
17260Sstevel@tonic-gate static int
disk_get_uint64_attribute(dm_descriptor_t disk,char * attr,uint64_t * val)17270Sstevel@tonic-gate disk_get_uint64_attribute(
17280Sstevel@tonic-gate dm_descriptor_t disk,
17290Sstevel@tonic-gate char *attr,
17300Sstevel@tonic-gate uint64_t *val)
17310Sstevel@tonic-gate {
17320Sstevel@tonic-gate nvlist_t *attrs = NULL;
17330Sstevel@tonic-gate uint32_t ui32 = 0;
17340Sstevel@tonic-gate int error = 0;
17350Sstevel@tonic-gate
17360Sstevel@tonic-gate /*
17370Sstevel@tonic-gate * these attributes are actually on the media,
17380Sstevel@tonic-gate * not the disk... so get the media descriptor
17390Sstevel@tonic-gate * for this disk
17400Sstevel@tonic-gate */
17410Sstevel@tonic-gate if ((strcmp(attr, DM_SIZE) == 0) ||
17420Sstevel@tonic-gate (strcmp(attr, DM_START) == 0) ||
17430Sstevel@tonic-gate (strcmp(attr, DM_NACCESSIBLE) == 0) ||
17440Sstevel@tonic-gate (strcmp(attr, DM_BLOCKSIZE) == 0) ||
17450Sstevel@tonic-gate (strcmp(attr, DM_NCYLINDERS) == 0) ||
17460Sstevel@tonic-gate (strcmp(attr, DM_NHEADS) == 0) ||
17470Sstevel@tonic-gate (strcmp(attr, DM_NSECTORS) == 0)) {
17480Sstevel@tonic-gate
17490Sstevel@tonic-gate dm_descriptor_t *media;
17500Sstevel@tonic-gate
17510Sstevel@tonic-gate media = dm_get_associated_descriptors(disk, DM_MEDIA, &error);
17520Sstevel@tonic-gate (void) add_descriptors_to_free(media);
17530Sstevel@tonic-gate
17540Sstevel@tonic-gate if (error != 0) {
17550Sstevel@tonic-gate print_get_assoc_desc_error(disk, gettext("media"), error);
17560Sstevel@tonic-gate } else if ((media == NULL) || (*media == NULL)) {
17570Sstevel@tonic-gate print_get_assoc_desc_error(disk, gettext("media"), error);
17580Sstevel@tonic-gate error = -1;
17590Sstevel@tonic-gate } else {
17600Sstevel@tonic-gate error = get_cached_attributes(media[0], &attrs);
17610Sstevel@tonic-gate free(media);
17620Sstevel@tonic-gate }
17630Sstevel@tonic-gate
17640Sstevel@tonic-gate } else {
17650Sstevel@tonic-gate error = get_cached_attributes(disk, &attrs);
17660Sstevel@tonic-gate if (error != 0) {
17670Sstevel@tonic-gate print_get_desc_attr_error(disk, gettext("drive"), attr, error);
17680Sstevel@tonic-gate }
17690Sstevel@tonic-gate }
17700Sstevel@tonic-gate
17710Sstevel@tonic-gate if (error != 0) {
17720Sstevel@tonic-gate return (error);
17730Sstevel@tonic-gate }
17740Sstevel@tonic-gate
17750Sstevel@tonic-gate if (strcmp(attr, DM_SIZE) == 0 ||
17760Sstevel@tonic-gate strcmp(attr, DM_NACCESSIBLE) == 0 ||
17770Sstevel@tonic-gate strcmp(attr, DM_START) == 0) {
17780Sstevel@tonic-gate error = get_uint64(attrs, attr, val);
17790Sstevel@tonic-gate } else if (strcmp(attr, DM_BLOCKSIZE) == 0 ||
17800Sstevel@tonic-gate strcmp(attr, DM_NCYLINDERS) == 0 ||
17810Sstevel@tonic-gate strcmp(attr, DM_NHEADS) == 0 ||
17820Sstevel@tonic-gate strcmp(attr, DM_NSECTORS) == 0 ||
17830Sstevel@tonic-gate strcmp(attr, DM_RPM) == 0 ||
17840Sstevel@tonic-gate strcmp(attr, DM_DRVTYPE) == 0 ||
17850Sstevel@tonic-gate strcmp(attr, DM_SYNC_SPEED) == 0 ||
17860Sstevel@tonic-gate strcmp(attr, DM_STATUS) == 0) {
17870Sstevel@tonic-gate error = get_uint32(attrs, attr, &ui32);
17880Sstevel@tonic-gate *val = (uint64_t)ui32;
17890Sstevel@tonic-gate }
17900Sstevel@tonic-gate
17910Sstevel@tonic-gate return (error);
17920Sstevel@tonic-gate }
17930Sstevel@tonic-gate
17940Sstevel@tonic-gate /*
17950Sstevel@tonic-gate * FUNCTION: group_similar_hbas(dlist_t *hbas, dlist_t **list)
17960Sstevel@tonic-gate *
17970Sstevel@tonic-gate * INPUT: hbas - a list of HBA dm_descriptor_t handles.
17980Sstevel@tonic-gate *
17990Sstevel@tonic-gate * OUTPUT: **list - a pointer to a list to hold the lists of HBAs
18000Sstevel@tonic-gate * grouped by characteristics.
18010Sstevel@tonic-gate *
18020Sstevel@tonic-gate * RETURNS: int - 0 on success
18030Sstevel@tonic-gate * !0 otherwise.
18040Sstevel@tonic-gate *
18050Sstevel@tonic-gate * PURPOSE: Examine the input HBAs and collate them into separate
18060Sstevel@tonic-gate * lists, grouped by their type and the protocols they
18070Sstevel@tonic-gate * support.
18080Sstevel@tonic-gate *
18090Sstevel@tonic-gate * The returned list of list is arranged in decreasing order
18100Sstevel@tonic-gate * of preference, "better" HBAs come first.
18110Sstevel@tonic-gate *
18120Sstevel@tonic-gate * find all MPXIO controllers
18130Sstevel@tonic-gate * find all similar FC HBAs
18140Sstevel@tonic-gate * find all similar SCSI HBAs
18150Sstevel@tonic-gate * fast{wide}80
18160Sstevel@tonic-gate * fast{wide}40
18170Sstevel@tonic-gate * fast{wide}20
18180Sstevel@tonic-gate * clock uint32 ??
18190Sstevel@tonic-gate * find all similar ATA/IDE HBAs
18200Sstevel@tonic-gate * find all similar USB HBAs
18210Sstevel@tonic-gate */
18220Sstevel@tonic-gate int
group_similar_hbas(dlist_t * hbas,dlist_t ** list)18230Sstevel@tonic-gate group_similar_hbas(
18240Sstevel@tonic-gate dlist_t *hbas,
18250Sstevel@tonic-gate dlist_t **list)
18260Sstevel@tonic-gate {
18270Sstevel@tonic-gate /* preference order of HBAs */
18280Sstevel@tonic-gate enum {
18290Sstevel@tonic-gate HBA_FIBRE_MPXIO = 0,
18300Sstevel@tonic-gate HBA_SCSI_MPXIO,
18310Sstevel@tonic-gate HBA_FIBRE,
18320Sstevel@tonic-gate HBA_SCSI_FW80,
18330Sstevel@tonic-gate HBA_SCSI_FW40,
18340Sstevel@tonic-gate HBA_SCSI_FW20,
18350Sstevel@tonic-gate HBA_SCSI_F80,
18360Sstevel@tonic-gate HBA_SCSI_F40,
18370Sstevel@tonic-gate HBA_SCSI_F20,
18380Sstevel@tonic-gate HBA_SCSI,
18390Sstevel@tonic-gate HBA_ATA,
18400Sstevel@tonic-gate HBA_USB,
18410Sstevel@tonic-gate HBA_LAST
18420Sstevel@tonic-gate };
18430Sstevel@tonic-gate
18440Sstevel@tonic-gate dlist_t *groups = NULL;
18450Sstevel@tonic-gate dlist_t *iter = NULL;
18460Sstevel@tonic-gate dlist_t *item = NULL;
18470Sstevel@tonic-gate dlist_t *lists[HBA_LAST];
18480Sstevel@tonic-gate
18490Sstevel@tonic-gate int error = 0;
18500Sstevel@tonic-gate int i = 0;
18510Sstevel@tonic-gate
18520Sstevel@tonic-gate (void) memset(lists, '\0', HBA_LAST * sizeof (dlist_t *));
18530Sstevel@tonic-gate
18540Sstevel@tonic-gate for (iter = hbas;
18550Sstevel@tonic-gate (iter != NULL) && (error == 0);
18560Sstevel@tonic-gate iter = iter->next) {
18570Sstevel@tonic-gate
18580Sstevel@tonic-gate dm_descriptor_t hba = (uintptr_t)iter->obj;
18590Sstevel@tonic-gate char *type = NULL;
18600Sstevel@tonic-gate
18610Sstevel@tonic-gate /* if item doesn't go into a list it must be freed */
1862*62Sjeanm if ((item = dlist_new_item((void *)(uintptr_t)hba)) == NULL) {
18630Sstevel@tonic-gate error = ENOMEM;
18640Sstevel@tonic-gate continue;
18650Sstevel@tonic-gate }
18660Sstevel@tonic-gate
18670Sstevel@tonic-gate if ((error = hba_get_type(hba, &type)) != 0) {
18680Sstevel@tonic-gate free(item);
18690Sstevel@tonic-gate continue;
18700Sstevel@tonic-gate }
18710Sstevel@tonic-gate
18720Sstevel@tonic-gate if (strcmp(type, DM_CTYPE_FIBRE) == 0) {
18730Sstevel@tonic-gate
18740Sstevel@tonic-gate boolean_t ismpxio = B_FALSE;
18750Sstevel@tonic-gate
18760Sstevel@tonic-gate if ((error = hba_is_multiplex(hba, &ismpxio)) == 0) {
18770Sstevel@tonic-gate if (ismpxio) {
18780Sstevel@tonic-gate lists[HBA_FIBRE_MPXIO] =
18790Sstevel@tonic-gate dlist_append(item,
18800Sstevel@tonic-gate lists[HBA_FIBRE_MPXIO], AT_TAIL);
18810Sstevel@tonic-gate } else {
18820Sstevel@tonic-gate lists[HBA_FIBRE] =
18830Sstevel@tonic-gate dlist_append(item,
18840Sstevel@tonic-gate lists[HBA_FIBRE], AT_TAIL);
18850Sstevel@tonic-gate }
18860Sstevel@tonic-gate } else {
18870Sstevel@tonic-gate free(item);
18880Sstevel@tonic-gate }
18890Sstevel@tonic-gate
18900Sstevel@tonic-gate } else if (strcmp(type, DM_CTYPE_SCSI) == 0) {
18910Sstevel@tonic-gate
18920Sstevel@tonic-gate /* determine subtype */
18930Sstevel@tonic-gate boolean_t iswide = B_FALSE;
18940Sstevel@tonic-gate boolean_t ismpxio = B_FALSE;
18950Sstevel@tonic-gate boolean_t is80 = B_FALSE;
18960Sstevel@tonic-gate boolean_t is40 = B_FALSE;
18970Sstevel@tonic-gate boolean_t is20 = B_FALSE;
18980Sstevel@tonic-gate
18990Sstevel@tonic-gate ((error = hba_supports_wide(hba, &iswide)) != 0) ||
19000Sstevel@tonic-gate (error = hba_is_multiplex(hba, &ismpxio)) ||
19010Sstevel@tonic-gate (error = hba_is_fast_80(hba, &is80)) ||
19020Sstevel@tonic-gate (error = hba_is_fast_40(hba, &is40)) ||
19030Sstevel@tonic-gate (error = hba_is_fast_20(hba, &is20));
19040Sstevel@tonic-gate
19050Sstevel@tonic-gate if (error == 0) {
19060Sstevel@tonic-gate
19070Sstevel@tonic-gate if (ismpxio) {
19080Sstevel@tonic-gate
19090Sstevel@tonic-gate lists[HBA_SCSI_MPXIO] =
19100Sstevel@tonic-gate dlist_append(item,
19110Sstevel@tonic-gate lists[HBA_SCSI_MPXIO], AT_TAIL);
19120Sstevel@tonic-gate
19130Sstevel@tonic-gate } else if (is80) {
19140Sstevel@tonic-gate
19150Sstevel@tonic-gate if (iswide) {
19160Sstevel@tonic-gate lists[HBA_SCSI_FW80] =
19170Sstevel@tonic-gate dlist_append(item,
19180Sstevel@tonic-gate lists[HBA_SCSI_FW80], AT_TAIL);
19190Sstevel@tonic-gate } else {
19200Sstevel@tonic-gate lists[HBA_SCSI_F80] =
19210Sstevel@tonic-gate dlist_append(item,
19220Sstevel@tonic-gate lists[HBA_SCSI_F80], AT_TAIL);
19230Sstevel@tonic-gate }
19240Sstevel@tonic-gate
19250Sstevel@tonic-gate } else if (is40) {
19260Sstevel@tonic-gate
19270Sstevel@tonic-gate if (iswide) {
19280Sstevel@tonic-gate lists[HBA_SCSI_FW40] =
19290Sstevel@tonic-gate dlist_append(item,
19300Sstevel@tonic-gate lists[HBA_SCSI_FW40], AT_TAIL);
19310Sstevel@tonic-gate } else {
19320Sstevel@tonic-gate lists[HBA_SCSI_F40] =
19330Sstevel@tonic-gate dlist_append(item,
19340Sstevel@tonic-gate lists[HBA_SCSI_F40], AT_TAIL);
19350Sstevel@tonic-gate }
19360Sstevel@tonic-gate
19370Sstevel@tonic-gate } else if (is20) {
19380Sstevel@tonic-gate
19390Sstevel@tonic-gate if (iswide) {
19400Sstevel@tonic-gate lists[HBA_SCSI_FW20] =
19410Sstevel@tonic-gate dlist_append(item,
19420Sstevel@tonic-gate lists[HBA_SCSI_FW20], AT_TAIL);
19430Sstevel@tonic-gate } else {
19440Sstevel@tonic-gate lists[HBA_SCSI_F20] =
19450Sstevel@tonic-gate dlist_append(item,
19460Sstevel@tonic-gate lists[HBA_SCSI_F20], AT_TAIL);
19470Sstevel@tonic-gate }
19480Sstevel@tonic-gate
19490Sstevel@tonic-gate } else {
19500Sstevel@tonic-gate lists[HBA_SCSI] =
19510Sstevel@tonic-gate dlist_append(item, lists[HBA_SCSI], AT_TAIL);
19520Sstevel@tonic-gate }
19530Sstevel@tonic-gate
19540Sstevel@tonic-gate } else {
19550Sstevel@tonic-gate free(item);
19560Sstevel@tonic-gate }
19570Sstevel@tonic-gate
19580Sstevel@tonic-gate } else if (strcmp(type, DM_CTYPE_ATA) == 0) {
19590Sstevel@tonic-gate lists[HBA_ATA] =
19600Sstevel@tonic-gate dlist_append(item, lists[HBA_ATA], AT_TAIL);
19610Sstevel@tonic-gate } else if (strcmp(type, DM_CTYPE_USB) == 0) {
19620Sstevel@tonic-gate lists[HBA_USB] =
19630Sstevel@tonic-gate dlist_append(item, lists[HBA_USB], AT_TAIL);
19640Sstevel@tonic-gate } else if (strcmp(type, DM_CTYPE_UNKNOWN) == 0) {
19650Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
19660Sstevel@tonic-gate gettext("found an HBA with unknown type\n"));
19670Sstevel@tonic-gate free(item);
19680Sstevel@tonic-gate }
19690Sstevel@tonic-gate }
19700Sstevel@tonic-gate
19710Sstevel@tonic-gate if (error == 0) {
19720Sstevel@tonic-gate /* collect individual lists into a list of lists */
19730Sstevel@tonic-gate for (i = 0; (i < HBA_LAST) && (error == 0); i++) {
19740Sstevel@tonic-gate if (lists[i] != NULL) {
19750Sstevel@tonic-gate if ((item = dlist_new_item(lists[i])) == NULL) {
19760Sstevel@tonic-gate error = ENOMEM;
19770Sstevel@tonic-gate } else {
19780Sstevel@tonic-gate groups = dlist_append(item, groups, AT_TAIL);
19790Sstevel@tonic-gate }
19800Sstevel@tonic-gate }
19810Sstevel@tonic-gate }
19820Sstevel@tonic-gate }
19830Sstevel@tonic-gate
19840Sstevel@tonic-gate if (error != 0) {
19850Sstevel@tonic-gate for (i = 0; i < HBA_LAST; i++) {
19860Sstevel@tonic-gate dlist_free_items(lists[i], NULL);
19870Sstevel@tonic-gate lists[i] = NULL;
19880Sstevel@tonic-gate }
19890Sstevel@tonic-gate
19900Sstevel@tonic-gate if (groups != NULL) {
19910Sstevel@tonic-gate dlist_free_items(groups, NULL);
19920Sstevel@tonic-gate }
19930Sstevel@tonic-gate }
19940Sstevel@tonic-gate
19950Sstevel@tonic-gate *list = groups;
19960Sstevel@tonic-gate
19970Sstevel@tonic-gate return (error);
19980Sstevel@tonic-gate }
19990Sstevel@tonic-gate
20000Sstevel@tonic-gate /*
20010Sstevel@tonic-gate * FUNCTION: hba_group_usable_disks(dm_descriptor_t hba, dlist_t **list)
20020Sstevel@tonic-gate *
20030Sstevel@tonic-gate * INPUT: hba - a dm_descriptor_t handle for a slice
20040Sstevel@tonic-gate *
20050Sstevel@tonic-gate * OUTPUT: **list - a pointer to a list to hold the lists of disks
20060Sstevel@tonic-gate * grouped by characteristics.
20070Sstevel@tonic-gate *
20080Sstevel@tonic-gate * RETURNS: int - 0 on success
20090Sstevel@tonic-gate * !0 otherwise.
20100Sstevel@tonic-gate *
20110Sstevel@tonic-gate * PURPOSE: Examine the disks assocated with the HBA and collates them
20120Sstevel@tonic-gate * into separate lists, grouped by similar characteristics.
20130Sstevel@tonic-gate *
20140Sstevel@tonic-gate * get disks on HBA
20150Sstevel@tonic-gate * check disks against _usable_disks list
20160Sstevel@tonic-gate * group disks by similarities:
20170Sstevel@tonic-gate * sync-speed uint32
20180Sstevel@tonic-gate * wide boolean
20190Sstevel@tonic-gate * rpm uint32
20200Sstevel@tonic-gate *
20210Sstevel@tonic-gate * XXX this function is currently unused. At some point,
20220Sstevel@tonic-gate * it may be useful to group disks by performance
20230Sstevel@tonic-gate * characteristics and use "better" disks before others.
20240Sstevel@tonic-gate */
20250Sstevel@tonic-gate int
hba_group_usable_disks(dm_descriptor_t hba,dlist_t ** list)20260Sstevel@tonic-gate hba_group_usable_disks(
20270Sstevel@tonic-gate dm_descriptor_t hba,
20280Sstevel@tonic-gate dlist_t **list)
20290Sstevel@tonic-gate {
20300Sstevel@tonic-gate dm_descriptor_t *disk = NULL;
20310Sstevel@tonic-gate char *name = NULL;
20320Sstevel@tonic-gate int i = 0;
20330Sstevel@tonic-gate int error = 0;
20340Sstevel@tonic-gate
20350Sstevel@tonic-gate disk = dm_get_associated_descriptors(hba, DM_DRIVE, &error);
20360Sstevel@tonic-gate (void) add_descriptors_to_free(disk);
20370Sstevel@tonic-gate
20380Sstevel@tonic-gate if (error != 0) {
20390Sstevel@tonic-gate print_get_assoc_desc_error(hba, gettext("drive"), error);
20400Sstevel@tonic-gate return (error);
20410Sstevel@tonic-gate } else if ((disk == NULL) || (*disk == NULL)) {
20420Sstevel@tonic-gate print_get_assoc_desc_error(hba, gettext("drive"), error);
20430Sstevel@tonic-gate error = -1;
20440Sstevel@tonic-gate }
20450Sstevel@tonic-gate
20460Sstevel@tonic-gate for (i = 0; (disk[i] != NULL) && (error == 0); i++) {
20470Sstevel@tonic-gate
20480Sstevel@tonic-gate uint32_t dtype = DM_DT_UNKNOWN;
20490Sstevel@tonic-gate dlist_t *usable = NULL;
20500Sstevel@tonic-gate
20510Sstevel@tonic-gate /* ignore non fixed media drives */
20520Sstevel@tonic-gate if (((error = disk_get_drive_type(disk[i], &dtype)) != 0) ||
20530Sstevel@tonic-gate (dtype != DM_DT_FIXED)) {
20540Sstevel@tonic-gate continue;
20550Sstevel@tonic-gate }
20560Sstevel@tonic-gate
20570Sstevel@tonic-gate if (dlist_contains(usable, &disk[i],
20580Sstevel@tonic-gate compare_descriptor_names) == B_TRUE) {
20590Sstevel@tonic-gate
20600Sstevel@tonic-gate uint64_t bsize = 0;
20610Sstevel@tonic-gate uint64_t ncyls = 0;
20620Sstevel@tonic-gate uint64_t nsects = 0;
20630Sstevel@tonic-gate uint64_t nheads = 0;
20640Sstevel@tonic-gate uint32_t rpm = 0;
20650Sstevel@tonic-gate uint32_t sync = 0;
20660Sstevel@tonic-gate
20670Sstevel@tonic-gate name = NULL;
20680Sstevel@tonic-gate ((error = get_display_name(disk[i], &name)) != 0) ||
20690Sstevel@tonic-gate (error = disk_get_blocksize(disk[i], &bsize)) ||
20700Sstevel@tonic-gate (error = disk_get_nheads(disk[i], &nheads)) ||
20710Sstevel@tonic-gate (error = disk_get_nsectors(disk[i], &nsects)) ||
20720Sstevel@tonic-gate (error = disk_get_ncylinders(disk[i], &ncyls)) ||
20730Sstevel@tonic-gate (error = disk_get_rpm(disk[i], &rpm)) ||
20740Sstevel@tonic-gate (error = disk_get_sync_speed(disk[i], &sync));
20750Sstevel@tonic-gate if (error != 0) {
20760Sstevel@tonic-gate continue;
20770Sstevel@tonic-gate }
20780Sstevel@tonic-gate
20790Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE,
20800Sstevel@tonic-gate gettext("found an available disk: %s\n\t"
20810Sstevel@tonic-gate "sync_speed = %u, rpm = %u, "
20820Sstevel@tonic-gate "nsect = %llu, blksiz = %llu\n"),
20830Sstevel@tonic-gate name, sync, rpm, nsects, bsize);
20840Sstevel@tonic-gate
20850Sstevel@tonic-gate /* add to the appropriate list */
20860Sstevel@tonic-gate }
20870Sstevel@tonic-gate }
20880Sstevel@tonic-gate
20890Sstevel@tonic-gate if (disk != NULL) {
20900Sstevel@tonic-gate free(disk);
20910Sstevel@tonic-gate }
20920Sstevel@tonic-gate
20930Sstevel@tonic-gate return (error);
20940Sstevel@tonic-gate }
20950Sstevel@tonic-gate
20960Sstevel@tonic-gate /*
20970Sstevel@tonic-gate * FUNCTION: hba_get_n_avail_disks(dm_descriptor_t hba, uint16_t *val)
20980Sstevel@tonic-gate * hba_set_n_avail_disks(dm_descriptor_t hba, uint16_t val)
20990Sstevel@tonic-gate *
21000Sstevel@tonic-gate * INPUT: hba - a dm_descriptor_t handle for a slice
21010Sstevel@tonic-gate *
21020Sstevel@tonic-gate * OUTPUT: *val - a pointer to a uint16_t to hold the current number
21030Sstevel@tonic-gate * of available disks for the input HBA.
21040Sstevel@tonic-gate *
21050Sstevel@tonic-gate * RETURNS: int - 0 on success
21060Sstevel@tonic-gate * !0 otherwise.
21070Sstevel@tonic-gate */
21080Sstevel@tonic-gate int
hba_set_n_avail_disks(dm_descriptor_t hba,uint16_t val)21090Sstevel@tonic-gate hba_set_n_avail_disks(
21100Sstevel@tonic-gate dm_descriptor_t hba,
21110Sstevel@tonic-gate uint16_t val)
21120Sstevel@tonic-gate {
21130Sstevel@tonic-gate nvlist_t *attrs;
21140Sstevel@tonic-gate int error = 0;
21150Sstevel@tonic-gate
21160Sstevel@tonic-gate ((error = get_cached_attributes(hba, &attrs)) != 0) ||
21170Sstevel@tonic-gate (error = set_uint16(attrs, ATTR_HBA_N_DISKS, val));
21180Sstevel@tonic-gate
21190Sstevel@tonic-gate return (error);
21200Sstevel@tonic-gate }
21210Sstevel@tonic-gate
21220Sstevel@tonic-gate int
hba_get_n_avail_disks(dm_descriptor_t hba,uint16_t * val)21230Sstevel@tonic-gate hba_get_n_avail_disks(
21240Sstevel@tonic-gate dm_descriptor_t hba,
21250Sstevel@tonic-gate uint16_t *val)
21260Sstevel@tonic-gate {
21270Sstevel@tonic-gate nvlist_t *attrs;
21280Sstevel@tonic-gate int error = 0;
21290Sstevel@tonic-gate
21300Sstevel@tonic-gate *val = 0;
21310Sstevel@tonic-gate
21320Sstevel@tonic-gate ((error = get_cached_attributes(hba, &attrs)) != 0) ||
21330Sstevel@tonic-gate (error = get_uint16(attrs, ATTR_HBA_N_DISKS, val));
21340Sstevel@tonic-gate
21350Sstevel@tonic-gate return (error);
21360Sstevel@tonic-gate }
21370Sstevel@tonic-gate
21380Sstevel@tonic-gate /*
21390Sstevel@tonic-gate * FUNCTION: hba_get_type(dm_descriptor_t hba, char **type)
21400Sstevel@tonic-gate *
21410Sstevel@tonic-gate * INPUT: hba - a dm_descriptor_t handle for a HBA
21420Sstevel@tonic-gate *
21430Sstevel@tonic-gate * OUTPUT: **type - a char * to hold the current type value for
21440Sstevel@tonic-gate * the HBA.
21450Sstevel@tonic-gate *
21460Sstevel@tonic-gate * RETURNS: int - 0 on success
21470Sstevel@tonic-gate * !0 otherwise.
21480Sstevel@tonic-gate *
21490Sstevel@tonic-gate * PURPOSE: Retrieves the type attribute for the HBA.
21500Sstevel@tonic-gate */
21510Sstevel@tonic-gate int
hba_get_type(dm_descriptor_t hba,char ** type)21520Sstevel@tonic-gate hba_get_type(
21530Sstevel@tonic-gate dm_descriptor_t hba,
21540Sstevel@tonic-gate char **type)
21550Sstevel@tonic-gate {
21560Sstevel@tonic-gate nvlist_t *attrs;
21570Sstevel@tonic-gate int error = 0;
21580Sstevel@tonic-gate
21590Sstevel@tonic-gate *type = NULL;
21600Sstevel@tonic-gate
21610Sstevel@tonic-gate ((error = get_cached_attributes(hba, &attrs)) != 0) ||
21620Sstevel@tonic-gate (error = get_string(attrs, DM_CTYPE, type));
21630Sstevel@tonic-gate
21640Sstevel@tonic-gate return (error);
21650Sstevel@tonic-gate }
21660Sstevel@tonic-gate
21670Sstevel@tonic-gate /*
21680Sstevel@tonic-gate * FUNCTION: hba_is_fast(dm_descriptor_t hba, boolean_t *bool)
21690Sstevel@tonic-gate * hba_is_fast20(dm_descriptor_t hba, boolean_t *bool)
21700Sstevel@tonic-gate * hba_is_fast40(dm_descriptor_t hba, boolean_t *bool)
21710Sstevel@tonic-gate * hba_is_fast80(dm_descriptor_t hba, boolean_t *bool)
21720Sstevel@tonic-gate * hba_is_multiplex(dm_descriptor_t hba, boolean_t *bool)
21730Sstevel@tonic-gate * hba_is_wide(dm_descriptor_t hba, boolean_t *bool)
21740Sstevel@tonic-gate *
21750Sstevel@tonic-gate * INPUT: hba - a dm_descriptor_t handle for a HBA
21760Sstevel@tonic-gate *
21770Sstevel@tonic-gate * OUTPUT: *bool - a pointer to a boolean_t to hold the
21780Sstevel@tonic-gate * boolean value of the predicate.
21790Sstevel@tonic-gate *
21800Sstevel@tonic-gate * RETURNS: int - 0 on success
21810Sstevel@tonic-gate * !0 otherwise.
21820Sstevel@tonic-gate *
21830Sstevel@tonic-gate * PURPOSE: Wrappers around hba_supports_protocol which determines
21840Sstevel@tonic-gate * if the input HBA supports the protocol of interest.
21850Sstevel@tonic-gate */
21860Sstevel@tonic-gate int
hba_is_fast(dm_descriptor_t hba,boolean_t * bool)21870Sstevel@tonic-gate hba_is_fast(
21880Sstevel@tonic-gate dm_descriptor_t hba,
21890Sstevel@tonic-gate boolean_t *bool)
21900Sstevel@tonic-gate {
21910Sstevel@tonic-gate return (hba_supports_protocol(hba, DM_FAST, bool));
21920Sstevel@tonic-gate }
21930Sstevel@tonic-gate
21940Sstevel@tonic-gate int
hba_is_fast_20(dm_descriptor_t hba,boolean_t * bool)21950Sstevel@tonic-gate hba_is_fast_20(
21960Sstevel@tonic-gate dm_descriptor_t hba,
21970Sstevel@tonic-gate boolean_t *bool)
21980Sstevel@tonic-gate {
21990Sstevel@tonic-gate return (hba_supports_protocol(hba, DM_FAST20, bool));
22000Sstevel@tonic-gate }
22010Sstevel@tonic-gate
22020Sstevel@tonic-gate int
hba_is_fast_40(dm_descriptor_t hba,boolean_t * bool)22030Sstevel@tonic-gate hba_is_fast_40(
22040Sstevel@tonic-gate dm_descriptor_t hba,
22050Sstevel@tonic-gate boolean_t *bool)
22060Sstevel@tonic-gate {
22070Sstevel@tonic-gate return (hba_supports_protocol(hba, DM_FAST40, bool));
22080Sstevel@tonic-gate }
22090Sstevel@tonic-gate
22100Sstevel@tonic-gate int
hba_is_fast_80(dm_descriptor_t hba,boolean_t * bool)22110Sstevel@tonic-gate hba_is_fast_80(
22120Sstevel@tonic-gate dm_descriptor_t hba,
22130Sstevel@tonic-gate boolean_t *bool)
22140Sstevel@tonic-gate {
22150Sstevel@tonic-gate return (hba_supports_protocol(hba, DM_FAST80, bool));
22160Sstevel@tonic-gate }
22170Sstevel@tonic-gate
22180Sstevel@tonic-gate int
hba_is_multiplex(dm_descriptor_t hba,boolean_t * bool)22190Sstevel@tonic-gate hba_is_multiplex(
22200Sstevel@tonic-gate dm_descriptor_t hba,
22210Sstevel@tonic-gate boolean_t *bool)
22220Sstevel@tonic-gate {
22230Sstevel@tonic-gate return (hba_supports_protocol(hba, DM_MULTIPLEX, bool));
22240Sstevel@tonic-gate }
22250Sstevel@tonic-gate
22260Sstevel@tonic-gate int
hba_supports_wide(dm_descriptor_t hba,boolean_t * bool)22270Sstevel@tonic-gate hba_supports_wide(
22280Sstevel@tonic-gate dm_descriptor_t hba,
22290Sstevel@tonic-gate boolean_t *bool)
22300Sstevel@tonic-gate {
22310Sstevel@tonic-gate nvlist_t *attrs = NULL;
22320Sstevel@tonic-gate int error = 0;
22330Sstevel@tonic-gate
22340Sstevel@tonic-gate *bool = B_FALSE;
22350Sstevel@tonic-gate
22360Sstevel@tonic-gate if ((error = get_cached_attributes(hba, &attrs)) != 0) {
22370Sstevel@tonic-gate return (error);
22380Sstevel@tonic-gate }
22390Sstevel@tonic-gate
22400Sstevel@tonic-gate *bool = (0 == nvlist_lookup_boolean(attrs, DM_WIDE));
22410Sstevel@tonic-gate
22420Sstevel@tonic-gate return (error);
22430Sstevel@tonic-gate }
22440Sstevel@tonic-gate
22450Sstevel@tonic-gate /*
22460Sstevel@tonic-gate * FUNCTION: hba_supports_protocol(dm_descriptor_t hba, char *attr,
22470Sstevel@tonic-gate * boolean_t *bool)
22480Sstevel@tonic-gate *
22490Sstevel@tonic-gate * INPUT: hba - a dm_descriptor_t handle for a HBA
22500Sstevel@tonic-gate * attr - a protocol "name"
22510Sstevel@tonic-gate *
22520Sstevel@tonic-gate * OUTPUT: *bool - a pointer to a boolean_t to hold the
22530Sstevel@tonic-gate * boolean value of the predicate.
22540Sstevel@tonic-gate *
22550Sstevel@tonic-gate * RETURNS: int - 0 on success
22560Sstevel@tonic-gate * !0 otherwise.
22570Sstevel@tonic-gate *
22580Sstevel@tonic-gate * PURPOSE: Checks the HBAs attributes to see if it is known to
22590Sstevel@tonic-gate * support the protocol of interest.
22600Sstevel@tonic-gate *
22610Sstevel@tonic-gate * If the protocol is supported, it will have an entry
22620Sstevel@tonic-gate * in the nvpair attribute list that can be retrieved.
22630Sstevel@tonic-gate *
22640Sstevel@tonic-gate * If the entry cannot be retrieved, the protocol is not
22650Sstevel@tonic-gate * supported.
22660Sstevel@tonic-gate */
22670Sstevel@tonic-gate int
hba_supports_protocol(dm_descriptor_t hba,char * attr,boolean_t * bool)22680Sstevel@tonic-gate hba_supports_protocol(
22690Sstevel@tonic-gate dm_descriptor_t hba,
22700Sstevel@tonic-gate char *attr,
22710Sstevel@tonic-gate boolean_t *bool)
22720Sstevel@tonic-gate {
22730Sstevel@tonic-gate nvlist_t *attrs = NULL;
22740Sstevel@tonic-gate int error = 0;
22750Sstevel@tonic-gate
22760Sstevel@tonic-gate *bool = B_FALSE;
22770Sstevel@tonic-gate
22780Sstevel@tonic-gate if ((error = get_cached_attributes(hba, &attrs)) != 0) {
22790Sstevel@tonic-gate return (error);
22800Sstevel@tonic-gate }
22810Sstevel@tonic-gate
22820Sstevel@tonic-gate *bool = (0 == nvlist_lookup_boolean(attrs, attr));
22830Sstevel@tonic-gate
22840Sstevel@tonic-gate return (error);
22850Sstevel@tonic-gate }
22860Sstevel@tonic-gate
22870Sstevel@tonic-gate /*
22880Sstevel@tonic-gate * FUNCTION: slice_set_size(dm_descriptor_t slice, uint64_t size)
22890Sstevel@tonic-gate *
22900Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t handle for a slice
22910Sstevel@tonic-gate *
22920Sstevel@tonic-gate * OUTPUT: size - a uint64_t value representing the size of the
22930Sstevel@tonic-gate * slice.
22940Sstevel@tonic-gate *
22950Sstevel@tonic-gate * RETURNS: int - 0 on success
22960Sstevel@tonic-gate * !0 otherwise.
22970Sstevel@tonic-gate *
22980Sstevel@tonic-gate * PURPOSE: Wrapper around slice_set_uint64_attribute which converts
22990Sstevel@tonic-gate * the input size in bytes to blocks prior to storing it.
23000Sstevel@tonic-gate *
23010Sstevel@tonic-gate * This function is used when an existing slice gets resized
23020Sstevel@tonic-gate * to provide space for a new slice. It is necessary to update
23030Sstevel@tonic-gate * the slice's size so that it is accurate.
23040Sstevel@tonic-gate */
23050Sstevel@tonic-gate int
slice_set_size(dm_descriptor_t slice,uint64_t size)23060Sstevel@tonic-gate slice_set_size(
23070Sstevel@tonic-gate dm_descriptor_t slice,
23080Sstevel@tonic-gate uint64_t size)
23090Sstevel@tonic-gate {
23100Sstevel@tonic-gate dm_descriptor_t disk = NULL;
23110Sstevel@tonic-gate uint64_t blksize = 0;
23120Sstevel@tonic-gate int error = 0;
23130Sstevel@tonic-gate
23140Sstevel@tonic-gate ((error = slice_get_disk(slice, &disk)) != 0) ||
23150Sstevel@tonic-gate (error = disk_get_blocksize(disk, &blksize)) ||
23160Sstevel@tonic-gate (error = slice_set_size_in_blocks(slice, (uint64_t)(size / blksize)));
23170Sstevel@tonic-gate
23180Sstevel@tonic-gate return (error);
23190Sstevel@tonic-gate }
23200Sstevel@tonic-gate
23210Sstevel@tonic-gate /*
23220Sstevel@tonic-gate * FUNCTION: slice_set_size_in_blocks(dm_descriptor_t slice, uint64_t size)
23230Sstevel@tonic-gate *
23240Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t handle for a slice
23250Sstevel@tonic-gate *
23260Sstevel@tonic-gate * OUTPUT: size - a uint64_t value representing the size of the
23270Sstevel@tonic-gate * slice.
23280Sstevel@tonic-gate *
23290Sstevel@tonic-gate * RETURNS: int - 0 on success
23300Sstevel@tonic-gate * !0 otherwise.
23310Sstevel@tonic-gate *
23320Sstevel@tonic-gate * PURPOSE: Wrapper around slice_set_uint64_attribute to set the slice
23330Sstevel@tonic-gate * size.
23340Sstevel@tonic-gate *
23350Sstevel@tonic-gate * This function is used when an existing slice gets resized
23360Sstevel@tonic-gate * to provide space for a new slice. It is necessary to update
23370Sstevel@tonic-gate * the slice's size so that it is accurate.
23380Sstevel@tonic-gate */
23390Sstevel@tonic-gate int
slice_set_size_in_blocks(dm_descriptor_t slice,uint64_t size)23400Sstevel@tonic-gate slice_set_size_in_blocks(
23410Sstevel@tonic-gate dm_descriptor_t slice,
23420Sstevel@tonic-gate uint64_t size)
23430Sstevel@tonic-gate {
23440Sstevel@tonic-gate return (slice_set_attribute(slice, DM_SIZE, size));
23450Sstevel@tonic-gate }
23460Sstevel@tonic-gate
23470Sstevel@tonic-gate /*
23480Sstevel@tonic-gate * FUNCTION: slice_set_start_block(dm_descriptor_t slice, uint64_t start)
23490Sstevel@tonic-gate *
23500Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t handle for a slice
23510Sstevel@tonic-gate *
23520Sstevel@tonic-gate * OUTPUT: size - a uint64_t value representing the start block of the
23530Sstevel@tonic-gate * slice.
23540Sstevel@tonic-gate *
23550Sstevel@tonic-gate * RETURNS: int - 0 on success
23560Sstevel@tonic-gate * !0 otherwise.
23570Sstevel@tonic-gate *
23580Sstevel@tonic-gate * PURPOSE: Wrapper around slice_set_attribute.
23590Sstevel@tonic-gate *
23600Sstevel@tonic-gate * This function is used when an existing slice gets adjusted
23610Sstevel@tonic-gate * due to being resized or combined with another slice.
23620Sstevel@tonic-gate */
23630Sstevel@tonic-gate int
slice_set_start_block(dm_descriptor_t slice,uint64_t start)23640Sstevel@tonic-gate slice_set_start_block(
23650Sstevel@tonic-gate dm_descriptor_t slice,
23660Sstevel@tonic-gate uint64_t start)
23670Sstevel@tonic-gate {
23680Sstevel@tonic-gate return (slice_set_attribute(slice, DM_START, start));
23690Sstevel@tonic-gate }
23700Sstevel@tonic-gate
23710Sstevel@tonic-gate /*
23720Sstevel@tonic-gate * FUNCTION: slice_get_start_block(dm_descriptor_t slice, uint64_t *val)
23730Sstevel@tonic-gate * slice_get_size_in_blocks(dm_descriptor_t slice, uint64_t *val)
23740Sstevel@tonic-gate * slice_get_start(dm_descriptor_t slice, uint64_t *val)
23750Sstevel@tonic-gate * slice_get_size(dm_descriptor_t slice, uint64_t *val)
23760Sstevel@tonic-gate * slice_get_index(dm_descriptor_t slice, uint64_t *val)
23770Sstevel@tonic-gate *
23780Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t handle for a slice
23790Sstevel@tonic-gate *
23800Sstevel@tonic-gate * OUTPUT: *val - a pointer to a uint64_t to hold the
23810Sstevel@tonic-gate * current value of the desired attribute.
23820Sstevel@tonic-gate *
23830Sstevel@tonic-gate * RETURNS: int - 0 on success
23840Sstevel@tonic-gate * !0 otherwise.
23850Sstevel@tonic-gate *
23860Sstevel@tonic-gate * PURPOSE: Wrappers around slice_get_uint64_attribute which retrieve
23870Sstevel@tonic-gate * specific attribute values.
23880Sstevel@tonic-gate */
23890Sstevel@tonic-gate int
slice_get_start_block(dm_descriptor_t slice,uint64_t * val)23900Sstevel@tonic-gate slice_get_start_block(
23910Sstevel@tonic-gate dm_descriptor_t slice,
23920Sstevel@tonic-gate uint64_t *val)
23930Sstevel@tonic-gate {
23940Sstevel@tonic-gate return (slice_get_uint64_attribute(slice, DM_START, val));
23950Sstevel@tonic-gate }
23960Sstevel@tonic-gate
23970Sstevel@tonic-gate int
slice_get_size_in_blocks(dm_descriptor_t slice,uint64_t * val)23980Sstevel@tonic-gate slice_get_size_in_blocks(
23990Sstevel@tonic-gate dm_descriptor_t slice,
24000Sstevel@tonic-gate uint64_t *val)
24010Sstevel@tonic-gate {
24020Sstevel@tonic-gate return (slice_get_uint64_attribute(slice, DM_SIZE, val));
24030Sstevel@tonic-gate }
24040Sstevel@tonic-gate
24050Sstevel@tonic-gate int
slice_get_start(dm_descriptor_t slice,uint64_t * val)24060Sstevel@tonic-gate slice_get_start(
24070Sstevel@tonic-gate dm_descriptor_t slice,
24080Sstevel@tonic-gate uint64_t *val)
24090Sstevel@tonic-gate {
24100Sstevel@tonic-gate dm_descriptor_t disk = NULL;
24110Sstevel@tonic-gate uint64_t blksize = 0;
24120Sstevel@tonic-gate uint64_t nblks = 0;
24130Sstevel@tonic-gate int error = 0;
24140Sstevel@tonic-gate
24150Sstevel@tonic-gate ((error = slice_get_disk(slice, &disk)) != 0) ||
24160Sstevel@tonic-gate (error = disk_get_blocksize(disk, &blksize)) ||
24170Sstevel@tonic-gate (error = slice_get_start_block(slice, &nblks));
24180Sstevel@tonic-gate
24190Sstevel@tonic-gate if (error == 0) {
24200Sstevel@tonic-gate *val = (blksize * nblks);
24210Sstevel@tonic-gate }
24220Sstevel@tonic-gate
24230Sstevel@tonic-gate return (error);
24240Sstevel@tonic-gate }
24250Sstevel@tonic-gate
24260Sstevel@tonic-gate int
slice_get_size(dm_descriptor_t slice,uint64_t * val)24270Sstevel@tonic-gate slice_get_size(
24280Sstevel@tonic-gate dm_descriptor_t slice,
24290Sstevel@tonic-gate uint64_t *val)
24300Sstevel@tonic-gate {
24310Sstevel@tonic-gate dm_descriptor_t disk = NULL;
24320Sstevel@tonic-gate uint64_t blksize = 0;
24330Sstevel@tonic-gate uint64_t nblks = 0;
24340Sstevel@tonic-gate int error = 0;
24350Sstevel@tonic-gate
24360Sstevel@tonic-gate *val = 0;
24370Sstevel@tonic-gate
24380Sstevel@tonic-gate ((error = slice_get_disk(slice, &disk)) != 0) ||
24390Sstevel@tonic-gate (error = slice_get_size_in_blocks(slice, &nblks)) ||
24400Sstevel@tonic-gate (error = disk_get_blocksize(disk, &blksize));
24410Sstevel@tonic-gate
24420Sstevel@tonic-gate if (error == 0) {
24430Sstevel@tonic-gate *val = (blksize * nblks);
24440Sstevel@tonic-gate }
24450Sstevel@tonic-gate
24460Sstevel@tonic-gate return (error);
24470Sstevel@tonic-gate }
24480Sstevel@tonic-gate
24490Sstevel@tonic-gate int
slice_get_index(dm_descriptor_t slice,uint32_t * val)24500Sstevel@tonic-gate slice_get_index(
24510Sstevel@tonic-gate dm_descriptor_t slice,
24520Sstevel@tonic-gate uint32_t *val)
24530Sstevel@tonic-gate {
24540Sstevel@tonic-gate uint64_t index = 0;
24550Sstevel@tonic-gate int error = 0;
24560Sstevel@tonic-gate
24570Sstevel@tonic-gate if ((error = slice_get_uint64_attribute(
24580Sstevel@tonic-gate slice, DM_INDEX, &index)) != 0) {
24590Sstevel@tonic-gate return (error);
24600Sstevel@tonic-gate }
24610Sstevel@tonic-gate
24620Sstevel@tonic-gate *val = (uint32_t)index;
24630Sstevel@tonic-gate
24640Sstevel@tonic-gate return (0);
24650Sstevel@tonic-gate }
24660Sstevel@tonic-gate
24670Sstevel@tonic-gate /*
24680Sstevel@tonic-gate * FUNCTION: slice_set_uint64_attribute(dm_descriptor_t slice,
24690Sstevel@tonic-gate * char *attr, uint64_t val)
24700Sstevel@tonic-gate * slice_get_uint64_attribute(dm_descriptor_t slice,
24710Sstevel@tonic-gate * char *attr, uint64_t *val)
24720Sstevel@tonic-gate *
24730Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t handle for a slice
24740Sstevel@tonic-gate * attr - a char * attribute name
24750Sstevel@tonic-gate * val - auint64_t value
24760Sstevel@tonic-gate *
24770Sstevel@tonic-gate * OUTPUT: *val - a pointer to a uint64_t to hold the
24780Sstevel@tonic-gate * current value of the named attribute.
24790Sstevel@tonic-gate *
24800Sstevel@tonic-gate * RETURNS: int - 0 on success
24810Sstevel@tonic-gate * !0 otherwise.
24820Sstevel@tonic-gate *
24830Sstevel@tonic-gate * PURPOSE: Helpers to set/get the value for a slice's attribute.
24840Sstevel@tonic-gate *
24850Sstevel@tonic-gate * Consolidate the details of getting/setting slice
24860Sstevel@tonic-gate * attributes. Some attributes are actually stored as
24870Sstevel@tonic-gate * uint32_t or uint16_t values, these functions mask
24880Sstevel@tonic-gate * the type conversions.
24890Sstevel@tonic-gate */
24900Sstevel@tonic-gate static int
slice_get_uint64_attribute(dm_descriptor_t slice,char * attr,uint64_t * val)24910Sstevel@tonic-gate slice_get_uint64_attribute(
24920Sstevel@tonic-gate dm_descriptor_t slice,
24930Sstevel@tonic-gate char *attr,
24940Sstevel@tonic-gate uint64_t *val)
24950Sstevel@tonic-gate {
24960Sstevel@tonic-gate nvlist_t *attrs = NULL;
24970Sstevel@tonic-gate uint32_t ui32 = 0;
24980Sstevel@tonic-gate int error = 0;
24990Sstevel@tonic-gate
25000Sstevel@tonic-gate if ((error = get_cached_attributes(slice, &attrs)) != 0) {
25010Sstevel@tonic-gate return (error);
25020Sstevel@tonic-gate }
25030Sstevel@tonic-gate
25040Sstevel@tonic-gate if (strcmp(attr, DM_INDEX) == 0) {
25050Sstevel@tonic-gate error = get_uint32(attrs, attr, &ui32);
25060Sstevel@tonic-gate *val = (uint64_t)ui32;
25070Sstevel@tonic-gate } else if (strcmp(attr, DM_START) == 0) {
25080Sstevel@tonic-gate error = get_uint64(attrs, attr, val);
25090Sstevel@tonic-gate } else if (strcmp(attr, DM_SIZE) == 0) {
25100Sstevel@tonic-gate error = get_uint64(attrs, attr, val);
25110Sstevel@tonic-gate } else if (strcmp(attr, ATTR_DISK_FOR_SLICE) == 0) {
25120Sstevel@tonic-gate error = get_uint64(attrs, attr, val);
25130Sstevel@tonic-gate }
25140Sstevel@tonic-gate
25150Sstevel@tonic-gate if (error != 0) {
25160Sstevel@tonic-gate print_get_desc_attr_error(slice, "slice", attr, error);
25170Sstevel@tonic-gate }
25180Sstevel@tonic-gate
25190Sstevel@tonic-gate return (error);
25200Sstevel@tonic-gate }
25210Sstevel@tonic-gate
25220Sstevel@tonic-gate /*
25230Sstevel@tonic-gate * Set a slice attribute. The attribute is only set in the cached
25240Sstevel@tonic-gate * copy of the slice's nvpair attribute list. This function does
25250Sstevel@tonic-gate * NOT affect the underlying physical device.
25260Sstevel@tonic-gate */
25270Sstevel@tonic-gate static int
slice_set_attribute(dm_descriptor_t slice,char * attr,uint64_t val)25280Sstevel@tonic-gate slice_set_attribute(
25290Sstevel@tonic-gate dm_descriptor_t slice,
25300Sstevel@tonic-gate char *attr,
25310Sstevel@tonic-gate uint64_t val)
25320Sstevel@tonic-gate {
25330Sstevel@tonic-gate nvlist_t *attrs = NULL;
25340Sstevel@tonic-gate int error = 0;
25350Sstevel@tonic-gate
25360Sstevel@tonic-gate if ((error = get_cached_attributes(slice, &attrs)) != 0) {
25370Sstevel@tonic-gate return (error);
25380Sstevel@tonic-gate }
25390Sstevel@tonic-gate
25400Sstevel@tonic-gate if (strcmp(attr, DM_INDEX) == 0) {
25410Sstevel@tonic-gate error = set_uint32(attrs, attr, (uint32_t)val);
25420Sstevel@tonic-gate } else if (strcmp(attr, DM_START) == 0) {
25430Sstevel@tonic-gate error = set_uint64(attrs, attr, val);
25440Sstevel@tonic-gate } else if (strcmp(attr, DM_SIZE) == 0) {
25450Sstevel@tonic-gate error = set_uint64(attrs, attr, val);
25460Sstevel@tonic-gate } else if (strcmp(attr, ATTR_DISK_FOR_SLICE) == 0) {
25470Sstevel@tonic-gate error = set_uint64(attrs, attr, val);
25480Sstevel@tonic-gate }
25490Sstevel@tonic-gate
25500Sstevel@tonic-gate if (error != 0) {
25510Sstevel@tonic-gate print_set_desc_attr_error(slice, "slice", attr, error);
25520Sstevel@tonic-gate }
25530Sstevel@tonic-gate
25540Sstevel@tonic-gate return (error);
25550Sstevel@tonic-gate }
25560Sstevel@tonic-gate
25570Sstevel@tonic-gate /*
25580Sstevel@tonic-gate * FUNCTION: virtual_slice_get_disk(dm_descriptor_t slice,
25590Sstevel@tonic-gate * dm_descriptor_t *diskp)
25600Sstevel@tonic-gate *
25610Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t virtual slice handle
25620Sstevel@tonic-gate * diskp - pointer to a dm_descriptor_t disk handle
25630Sstevel@tonic-gate * to return the slice's disk
25640Sstevel@tonic-gate *
25650Sstevel@tonic-gate * OUTPUT: the disk associated with the virtual slice.
25660Sstevel@tonic-gate *
25670Sstevel@tonic-gate * RETURNS: int - 0 on success
25680Sstevel@tonic-gate * !0 otherwise
25690Sstevel@tonic-gate *
25700Sstevel@tonic-gate * PURPOSE: Helper which determines the disk that the input virtual
25710Sstevel@tonic-gate * slice "belongs" to.
25720Sstevel@tonic-gate *
25730Sstevel@tonic-gate * The virtual slice's disk is stored in the slice's nvpair
25740Sstevel@tonic-gate * attribute list when the slice gets created.
25750Sstevel@tonic-gate */
25760Sstevel@tonic-gate static int
virtual_slice_get_disk(dm_descriptor_t slice,dm_descriptor_t * diskp)25770Sstevel@tonic-gate virtual_slice_get_disk(
25780Sstevel@tonic-gate dm_descriptor_t slice,
25790Sstevel@tonic-gate dm_descriptor_t *diskp)
25800Sstevel@tonic-gate {
25810Sstevel@tonic-gate uint64_t disk = 0;
25820Sstevel@tonic-gate int error = 0;
25830Sstevel@tonic-gate
25840Sstevel@tonic-gate if ((error = slice_get_uint64_attribute(
25850Sstevel@tonic-gate slice, ATTR_DISK_FOR_SLICE, &disk)) != 0) {
25860Sstevel@tonic-gate return (error);
25870Sstevel@tonic-gate }
25880Sstevel@tonic-gate
25890Sstevel@tonic-gate *diskp = (dm_descriptor_t)disk;
25900Sstevel@tonic-gate
25910Sstevel@tonic-gate if (disk == 0) {
25920Sstevel@tonic-gate print_get_desc_attr_error(slice, "virtual slice", "disk", error);
25930Sstevel@tonic-gate return (-1);
25940Sstevel@tonic-gate }
25950Sstevel@tonic-gate
25960Sstevel@tonic-gate return (0);
25970Sstevel@tonic-gate }
25980Sstevel@tonic-gate
25990Sstevel@tonic-gate /*
26000Sstevel@tonic-gate * FUNCTION: slice_get_disk(dm_descriptor_t disk, dm_descriptor_t *diskp)
26010Sstevel@tonic-gate *
26020Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t handle for a slice
26030Sstevel@tonic-gate *
26040Sstevel@tonic-gate * OUTPUT: diskp - a pointer to a dm_descriptor_t to hold the
26050Sstevel@tonic-gate * disk associated with the input slice
26060Sstevel@tonic-gate *
26070Sstevel@tonic-gate * RETURNS: int - 0 on success
26080Sstevel@tonic-gate * !0 otherwise.
26090Sstevel@tonic-gate *
26100Sstevel@tonic-gate * PURPOSE: Helper which retrieves the disk for a slice device.
26110Sstevel@tonic-gate *
26120Sstevel@tonic-gate * A slice is actually connected to its disk thru an intermediate
26130Sstevel@tonic-gate * device known as the "media". The media concept exists to
26140Sstevel@tonic-gate * model drives with removeable disk media. For the purposes
26150Sstevel@tonic-gate * of layout, such devices aren't relevant and the intermediate
26160Sstevel@tonic-gate * media can mostly be ignored.
26170Sstevel@tonic-gate */
26180Sstevel@tonic-gate int
slice_get_disk(dm_descriptor_t slice,dm_descriptor_t * diskp)26190Sstevel@tonic-gate slice_get_disk(
26200Sstevel@tonic-gate dm_descriptor_t slice,
26210Sstevel@tonic-gate dm_descriptor_t *diskp)
26220Sstevel@tonic-gate {
26230Sstevel@tonic-gate dm_descriptor_t *media = NULL;
26240Sstevel@tonic-gate
26250Sstevel@tonic-gate int i = 0;
26260Sstevel@tonic-gate int error = 0;
26270Sstevel@tonic-gate
26280Sstevel@tonic-gate *diskp = 0;
26290Sstevel@tonic-gate
26300Sstevel@tonic-gate if (is_virtual_slice(slice)) {
26310Sstevel@tonic-gate return (virtual_slice_get_disk(slice, diskp));
26320Sstevel@tonic-gate }
26330Sstevel@tonic-gate
26340Sstevel@tonic-gate media = dm_get_associated_descriptors(slice, DM_MEDIA, &error);
26350Sstevel@tonic-gate (void) add_descriptors_to_free(media);
26360Sstevel@tonic-gate
26370Sstevel@tonic-gate if (error != 0) {
26380Sstevel@tonic-gate print_get_assoc_desc_error(slice, gettext("media"), error);
26390Sstevel@tonic-gate } else if ((media == NULL) || (*media == NULL)) {
26400Sstevel@tonic-gate print_get_assoc_desc_error(slice, gettext("media"), error);
26410Sstevel@tonic-gate error = -1;
26420Sstevel@tonic-gate }
26430Sstevel@tonic-gate
26440Sstevel@tonic-gate if (error != 0) {
26450Sstevel@tonic-gate return (error);
26460Sstevel@tonic-gate }
26470Sstevel@tonic-gate
26480Sstevel@tonic-gate /* slice should have exactly 1 media */
26490Sstevel@tonic-gate for (i = 0; (media[i] != NULL) && (*diskp == NULL); i++) {
26500Sstevel@tonic-gate /* get disk from media */
26510Sstevel@tonic-gate dm_descriptor_t *disks = NULL;
26520Sstevel@tonic-gate disks = dm_get_associated_descriptors(media[i], DM_DRIVE, &error);
26530Sstevel@tonic-gate (void) add_descriptors_to_free(disks);
26540Sstevel@tonic-gate
26550Sstevel@tonic-gate if ((error == 0) && (disks != NULL) && (disks[0] != NULL)) {
26560Sstevel@tonic-gate *diskp = disks[0];
26570Sstevel@tonic-gate }
26580Sstevel@tonic-gate free(disks);
26590Sstevel@tonic-gate }
26600Sstevel@tonic-gate
26610Sstevel@tonic-gate if (media != NULL) {
26620Sstevel@tonic-gate free(media);
26630Sstevel@tonic-gate }
26640Sstevel@tonic-gate
26650Sstevel@tonic-gate if (*diskp == 0) {
26660Sstevel@tonic-gate print_get_desc_attr_error(slice,
26670Sstevel@tonic-gate gettext("slice"), gettext("disk"), ENODEV);
26680Sstevel@tonic-gate error = -1;
26690Sstevel@tonic-gate }
26700Sstevel@tonic-gate
26710Sstevel@tonic-gate return (error);
26720Sstevel@tonic-gate }
26730Sstevel@tonic-gate
26740Sstevel@tonic-gate /*
26750Sstevel@tonic-gate * FUNCTION: slice_get_hbas(dm_descriptor_t slice, dlist_t **list)
26760Sstevel@tonic-gate *
26770Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t handle for a slice
26780Sstevel@tonic-gate *
26790Sstevel@tonic-gate * OUTPUT: list - a pointer to a dlist_t list to hold the
26800Sstevel@tonic-gate * HBAs associated with the input slice
26810Sstevel@tonic-gate *
26820Sstevel@tonic-gate * RETURNS: int - 0 on success
26830Sstevel@tonic-gate * !0 otherwise.
26840Sstevel@tonic-gate *
26850Sstevel@tonic-gate * PURPOSE: Helper which retrieves the known HBAs for a slice device.
26860Sstevel@tonic-gate *
26870Sstevel@tonic-gate */
26880Sstevel@tonic-gate int
slice_get_hbas(dm_descriptor_t slice,dlist_t ** list)26890Sstevel@tonic-gate slice_get_hbas(
26900Sstevel@tonic-gate dm_descriptor_t slice,
26910Sstevel@tonic-gate dlist_t **list)
26920Sstevel@tonic-gate {
26930Sstevel@tonic-gate dm_descriptor_t disk = NULL;
26940Sstevel@tonic-gate int error = 0;
26950Sstevel@tonic-gate
26960Sstevel@tonic-gate *list = NULL;
26970Sstevel@tonic-gate
26980Sstevel@tonic-gate ((error = slice_get_disk(slice, &disk)) != 0) ||
26990Sstevel@tonic-gate (error = disk_get_hbas(disk, list));
27000Sstevel@tonic-gate
27010Sstevel@tonic-gate if (*list == NULL) {
27020Sstevel@tonic-gate print_get_desc_attr_error(slice, "slice", "HBA", ENODEV);
27030Sstevel@tonic-gate error = -1;
27040Sstevel@tonic-gate }
27050Sstevel@tonic-gate
27060Sstevel@tonic-gate return (error);
27070Sstevel@tonic-gate }
27080Sstevel@tonic-gate
27090Sstevel@tonic-gate /*
27100Sstevel@tonic-gate * FUNCTION: disk_get_associated_desc(dm_descriptor_t disk,
27110Sstevel@tonic-gate * dm_desc_type_t assoc_type, char *assoc_type_str,
27120Sstevel@tonic-gate * dlist_t **list)
27130Sstevel@tonic-gate *
27140Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t handle for a disk
27150Sstevel@tonic-gate * assoc_type - the type of associated object to get
27160Sstevel@tonic-gate * assoc_type_str - a char * string for the associated type
27170Sstevel@tonic-gate *
27180Sstevel@tonic-gate * OUTPUT: list - a pointer to a dlist_t list to hold the
27190Sstevel@tonic-gate * objects associated with the input disk
27200Sstevel@tonic-gate *
27210Sstevel@tonic-gate * RETURNS: int - 0 on success
27220Sstevel@tonic-gate * !0 otherwise.
27230Sstevel@tonic-gate *
27240Sstevel@tonic-gate * PURPOSE: Helper which retrieves the associated objects of the
27250Sstevel@tonic-gate * requested type for a disk device.
27260Sstevel@tonic-gate */
27270Sstevel@tonic-gate static int
disk_get_associated_desc(dm_descriptor_t disk,dm_desc_type_t assoc_type,char * assoc_type_str,dlist_t ** list)27280Sstevel@tonic-gate disk_get_associated_desc(
27290Sstevel@tonic-gate dm_descriptor_t disk,
27300Sstevel@tonic-gate dm_desc_type_t assoc_type,
27310Sstevel@tonic-gate char *assoc_type_str,
27320Sstevel@tonic-gate dlist_t **list)
27330Sstevel@tonic-gate {
27340Sstevel@tonic-gate int i = 0;
27350Sstevel@tonic-gate int error = 0;
27360Sstevel@tonic-gate
27370Sstevel@tonic-gate dm_descriptor_t *assoc =
27380Sstevel@tonic-gate dm_get_associated_descriptors(disk, assoc_type, &error);
27390Sstevel@tonic-gate
27400Sstevel@tonic-gate (void) add_descriptors_to_free(assoc);
27410Sstevel@tonic-gate
27420Sstevel@tonic-gate if (error == 0) {
27430Sstevel@tonic-gate for (i = 0;
27440Sstevel@tonic-gate (assoc != NULL) && (assoc[i] != NULL) && (error == 0);
27450Sstevel@tonic-gate i++) {
2746*62Sjeanm dlist_t *item = dlist_new_item((void *)(uintptr_t)assoc[i]);
27470Sstevel@tonic-gate if (item == NULL) {
27480Sstevel@tonic-gate error = ENOMEM;
27490Sstevel@tonic-gate } else {
27500Sstevel@tonic-gate *list = dlist_append(item, *list, AT_TAIL);
27510Sstevel@tonic-gate }
27520Sstevel@tonic-gate }
27530Sstevel@tonic-gate } else {
27540Sstevel@tonic-gate print_get_assoc_desc_error(disk, assoc_type_str, error);
27550Sstevel@tonic-gate }
27560Sstevel@tonic-gate
27570Sstevel@tonic-gate if (assoc != NULL) {
27580Sstevel@tonic-gate free(assoc);
27590Sstevel@tonic-gate }
27600Sstevel@tonic-gate
27610Sstevel@tonic-gate if (error != 0) {
27620Sstevel@tonic-gate dlist_free_items(*list, NULL);
27630Sstevel@tonic-gate *list = NULL;
27640Sstevel@tonic-gate }
27650Sstevel@tonic-gate
27660Sstevel@tonic-gate return (error);
27670Sstevel@tonic-gate }
27680Sstevel@tonic-gate
27690Sstevel@tonic-gate /*
27700Sstevel@tonic-gate * FUNCTION: disk_get_hbas(dm_descriptor_t disk, dlist_t **list)
27710Sstevel@tonic-gate *
27720Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t handle for a disk
27730Sstevel@tonic-gate *
27740Sstevel@tonic-gate * OUTPUT: list - a pointer to a dlist_t list to hold the
27750Sstevel@tonic-gate * HBAs associated with the input disk
27760Sstevel@tonic-gate *
27770Sstevel@tonic-gate * RETURNS: int - 0 on success
27780Sstevel@tonic-gate * !0 otherwise.
27790Sstevel@tonic-gate *
27800Sstevel@tonic-gate * PURPOSE: Helper which retrieves the known HBAs for a disk device.
27810Sstevel@tonic-gate *
27820Sstevel@tonic-gate */
27830Sstevel@tonic-gate int
disk_get_hbas(dm_descriptor_t disk,dlist_t ** list)27840Sstevel@tonic-gate disk_get_hbas(
27850Sstevel@tonic-gate dm_descriptor_t disk,
27860Sstevel@tonic-gate dlist_t **list)
27870Sstevel@tonic-gate {
27880Sstevel@tonic-gate return (disk_get_associated_desc(disk, DM_CONTROLLER,
27890Sstevel@tonic-gate gettext("controller"), list));
27900Sstevel@tonic-gate }
27910Sstevel@tonic-gate
27920Sstevel@tonic-gate /*
27930Sstevel@tonic-gate * FUNCTION: disk_get_paths(dm_descriptor_t disk, dlist_t **list)
27940Sstevel@tonic-gate *
27950Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t handle for a disk
27960Sstevel@tonic-gate *
27970Sstevel@tonic-gate * OUTPUT: list - a pointer to a dlist_t list to hold the
27980Sstevel@tonic-gate * paths associated with the input disk
27990Sstevel@tonic-gate *
28000Sstevel@tonic-gate * RETURNS: int - 0 on success
28010Sstevel@tonic-gate * !0 otherwise.
28020Sstevel@tonic-gate *
28030Sstevel@tonic-gate * PURPOSE: Helper which retrieves the known paths for a disk device.
28040Sstevel@tonic-gate *
28050Sstevel@tonic-gate * Paths are managed by the MPXIO driver, they represent hardware
28060Sstevel@tonic-gate * paths to the disk drive managed by the MPXIO and not visible
28070Sstevel@tonic-gate * externally, unlike aliases which are.
28080Sstevel@tonic-gate */
28090Sstevel@tonic-gate int
disk_get_paths(dm_descriptor_t disk,dlist_t ** list)28100Sstevel@tonic-gate disk_get_paths(
28110Sstevel@tonic-gate dm_descriptor_t disk,
28120Sstevel@tonic-gate dlist_t **list)
28130Sstevel@tonic-gate {
28140Sstevel@tonic-gate return (disk_get_associated_desc(disk, DM_PATH,
28150Sstevel@tonic-gate gettext("path"), list));
28160Sstevel@tonic-gate }
28170Sstevel@tonic-gate
28180Sstevel@tonic-gate /*
28190Sstevel@tonic-gate * FUNCTION: disk_get_aliases(dm_descriptor_t disk, dlist_t **list)
28200Sstevel@tonic-gate *
28210Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t handle for a disk
28220Sstevel@tonic-gate *
28230Sstevel@tonic-gate * OUTPUT: list - a pointer to a dlist_t list to hold the
28240Sstevel@tonic-gate * alias descriptors associated with the input disk
28250Sstevel@tonic-gate *
28260Sstevel@tonic-gate * RETURNS: int - 0 on success
28270Sstevel@tonic-gate * !0 otherwise.
28280Sstevel@tonic-gate *
28290Sstevel@tonic-gate * PURPOSE: Helper which retrieves the known aliases for a disk device.
28300Sstevel@tonic-gate *
28310Sstevel@tonic-gate * Aliases are the different CTD names for the disk drive when
28320Sstevel@tonic-gate * MPXIO is not enabled for multipathed drives.
28330Sstevel@tonic-gate */
28340Sstevel@tonic-gate int
disk_get_aliases(dm_descriptor_t disk,dlist_t ** list)28350Sstevel@tonic-gate disk_get_aliases(
28360Sstevel@tonic-gate dm_descriptor_t disk,
28370Sstevel@tonic-gate dlist_t **list)
28380Sstevel@tonic-gate {
28390Sstevel@tonic-gate return (disk_get_associated_desc(disk, DM_ALIAS,
28400Sstevel@tonic-gate gettext("alias"), list));
28410Sstevel@tonic-gate }
28420Sstevel@tonic-gate
28430Sstevel@tonic-gate /*
28440Sstevel@tonic-gate * FUNCTION: compare_string_to_desc_name_or_alias(
28450Sstevel@tonic-gate * void *str, void *desc)
28460Sstevel@tonic-gate *
28470Sstevel@tonic-gate * INPUT: str - opaque pointer
28480Sstevel@tonic-gate * descr - opaque pointer
28490Sstevel@tonic-gate *
28500Sstevel@tonic-gate * RETURNS: int - <0 - if str < desc.name
28510Sstevel@tonic-gate * 0 - if str == desc.name
28520Sstevel@tonic-gate * >0 - if str > desc.name
28530Sstevel@tonic-gate *
28540Sstevel@tonic-gate * PURPOSE: dlist_t helper which compares a string to the name
28550Sstevel@tonic-gate * and aliases associated with the input dm_descriptor_t
28560Sstevel@tonic-gate * handle.
28570Sstevel@tonic-gate *
28580Sstevel@tonic-gate * Comparison is done via compare_device_names.
28590Sstevel@tonic-gate */
28600Sstevel@tonic-gate static int
compare_string_to_desc_name_or_alias(void * str,void * desc)28610Sstevel@tonic-gate compare_string_to_desc_name_or_alias(
28620Sstevel@tonic-gate void *str,
28630Sstevel@tonic-gate void *desc)
28640Sstevel@tonic-gate {
28650Sstevel@tonic-gate char *dname = NULL;
28660Sstevel@tonic-gate int result = -1;
28670Sstevel@tonic-gate
28680Sstevel@tonic-gate assert(str != (char *)NULL);
28690Sstevel@tonic-gate assert(desc != (dm_descriptor_t)0);
28700Sstevel@tonic-gate
28710Sstevel@tonic-gate (void) get_display_name((uintptr_t)desc, &dname);
28720Sstevel@tonic-gate
28730Sstevel@tonic-gate /* try name first, then aliases */
28740Sstevel@tonic-gate if ((result = compare_device_names(str, dname)) != 0) {
28750Sstevel@tonic-gate dlist_t *aliases = NULL;
28760Sstevel@tonic-gate
28770Sstevel@tonic-gate (void) get_aliases((uintptr_t)desc, &aliases);
28780Sstevel@tonic-gate if ((aliases != NULL) && (dlist_contains(aliases,
28790Sstevel@tonic-gate str, compare_device_names) == B_TRUE)) {
28800Sstevel@tonic-gate result = 0;
28810Sstevel@tonic-gate }
28820Sstevel@tonic-gate dlist_free_items(aliases, free);
28830Sstevel@tonic-gate }
28840Sstevel@tonic-gate
28850Sstevel@tonic-gate return (result);
28860Sstevel@tonic-gate }
28870Sstevel@tonic-gate
28880Sstevel@tonic-gate /*
28890Sstevel@tonic-gate * FUNCTION: hba_get_by_name(char *name, dm_descriptor_t *hba)
28900Sstevel@tonic-gate *
28910Sstevel@tonic-gate * INPUT: name - a char * disk name
28920Sstevel@tonic-gate *
28930Sstevel@tonic-gate * OUTPUT: hba - a pointer to a dm_descriptor_t to hold the
28940Sstevel@tonic-gate * HBA corresponding to the input name, if found
28950Sstevel@tonic-gate *
28960Sstevel@tonic-gate * RETURNS: int - 0 on success
28970Sstevel@tonic-gate * !0 otherwise
28980Sstevel@tonic-gate *
28990Sstevel@tonic-gate * PURPOSE: Helper which iterates the known HBAs, searching for
29000Sstevel@tonic-gate * the one matching name.
29010Sstevel@tonic-gate *
29020Sstevel@tonic-gate * If no HBA matches the name, 0 is returned and the
29030Sstevel@tonic-gate * value of 'hba' will be (dm_descriptor_t)0;
29040Sstevel@tonic-gate */
29050Sstevel@tonic-gate int
hba_get_by_name(char * name,dm_descriptor_t * hba)29060Sstevel@tonic-gate hba_get_by_name(
29070Sstevel@tonic-gate char *name,
29080Sstevel@tonic-gate dm_descriptor_t *hba)
29090Sstevel@tonic-gate {
29100Sstevel@tonic-gate int error = 0;
29110Sstevel@tonic-gate dlist_t *list = NULL;
29120Sstevel@tonic-gate dlist_t *item = NULL;
29130Sstevel@tonic-gate
29140Sstevel@tonic-gate *hba = (dm_descriptor_t)0;
29150Sstevel@tonic-gate
29160Sstevel@tonic-gate if (name == NULL) {
29170Sstevel@tonic-gate return (0);
29180Sstevel@tonic-gate }
29190Sstevel@tonic-gate
29200Sstevel@tonic-gate if ((error = get_known_hbas(&list)) != 0) {
29210Sstevel@tonic-gate return (error);
29220Sstevel@tonic-gate }
29230Sstevel@tonic-gate
29240Sstevel@tonic-gate if ((item = dlist_find(list, name,
29250Sstevel@tonic-gate compare_string_to_desc_name_or_alias)) != NULL) {
29260Sstevel@tonic-gate *hba = (uintptr_t)item->obj;
29270Sstevel@tonic-gate }
29280Sstevel@tonic-gate
29290Sstevel@tonic-gate return (error);
29300Sstevel@tonic-gate }
29310Sstevel@tonic-gate
29320Sstevel@tonic-gate /*
29330Sstevel@tonic-gate * FUNCTION: disk_get_by_name(char *name, dm_descriptor_t *disk)
29340Sstevel@tonic-gate *
29350Sstevel@tonic-gate * INPUT: name - a char * disk name
29360Sstevel@tonic-gate *
29370Sstevel@tonic-gate * OUTPUT: disk - a pointer to a dm_descriptor_t to hold the
29380Sstevel@tonic-gate * disk corresponding to the input name, if found
29390Sstevel@tonic-gate *
29400Sstevel@tonic-gate * RETURNS: int - 0 on success
29410Sstevel@tonic-gate * !0 otherwise.
29420Sstevel@tonic-gate *
29430Sstevel@tonic-gate * PURPOSE: Helper which retrieves a dm_descriptor_t disk handle
29440Sstevel@tonic-gate * by name.
29450Sstevel@tonic-gate *
29460Sstevel@tonic-gate * If no disk is found for the input name, variations of
29470Sstevel@tonic-gate * the name are tried.
29480Sstevel@tonic-gate *
29490Sstevel@tonic-gate * If the input name is unqualified, an appropriate leading
29500Sstevel@tonic-gate * path is prepended.
29510Sstevel@tonic-gate *
29520Sstevel@tonic-gate * If the input name is qualified, the leading path is
29530Sstevel@tonic-gate * removed.
29540Sstevel@tonic-gate *
29550Sstevel@tonic-gate * If no disk is found for the variations, 0 is returned
29560Sstevel@tonic-gate * and the value of 'disk' will be (dm_descriptor_t)0;
29570Sstevel@tonic-gate */
29580Sstevel@tonic-gate int
disk_get_by_name(char * name,dm_descriptor_t * disk)29590Sstevel@tonic-gate disk_get_by_name(
29600Sstevel@tonic-gate char *name,
29610Sstevel@tonic-gate dm_descriptor_t *disk)
29620Sstevel@tonic-gate {
29630Sstevel@tonic-gate assert(name != (char *)NULL);
29640Sstevel@tonic-gate
29650Sstevel@tonic-gate *disk = find_cached_descriptor(name);
29660Sstevel@tonic-gate if (*disk == (dm_descriptor_t)0) {
29670Sstevel@tonic-gate if (name[0] == '/') {
29680Sstevel@tonic-gate /* fully qualified, try unqualified */
29690Sstevel@tonic-gate char *cp = strrchr(name, '/');
29700Sstevel@tonic-gate if (cp != NULL) {
29710Sstevel@tonic-gate *disk = find_cached_descriptor(cp + 1);
29720Sstevel@tonic-gate }
29730Sstevel@tonic-gate } else {
29740Sstevel@tonic-gate /* unqualified, try fully qualified */
29750Sstevel@tonic-gate char buf[MAXNAMELEN+1];
29760Sstevel@tonic-gate if (is_ctd_disk_name(name)) {
29770Sstevel@tonic-gate (void) snprintf(buf, MAXNAMELEN, "/dev/dsk/%s", name);
29780Sstevel@tonic-gate } else if (is_did_disk_name(name)) {
29790Sstevel@tonic-gate (void) snprintf(buf, MAXNAMELEN, "/dev/did/dsk/%s", name);
29800Sstevel@tonic-gate }
29810Sstevel@tonic-gate *disk = find_cached_descriptor(buf);
29820Sstevel@tonic-gate }
29830Sstevel@tonic-gate }
29840Sstevel@tonic-gate
29850Sstevel@tonic-gate /*
29860Sstevel@tonic-gate * since the descriptor cache includes HBAs, disks and slices,
29870Sstevel@tonic-gate * what gets returned may not be a disk... make sure it is
29880Sstevel@tonic-gate */
29890Sstevel@tonic-gate if (*disk != (dm_descriptor_t)0) {
29900Sstevel@tonic-gate if (dm_get_type(*disk) != DM_DRIVE) {
29910Sstevel@tonic-gate *disk = (dm_descriptor_t)0;
29920Sstevel@tonic-gate }
29930Sstevel@tonic-gate }
29940Sstevel@tonic-gate
29950Sstevel@tonic-gate return (0);
29960Sstevel@tonic-gate }
29970Sstevel@tonic-gate
29980Sstevel@tonic-gate /*
29990Sstevel@tonic-gate * FUNCTION: slice_get_by_name(char *name, dm_descriptor_t *slice)
30000Sstevel@tonic-gate *
30010Sstevel@tonic-gate * INPUT: name - a char * slice name
30020Sstevel@tonic-gate *
30030Sstevel@tonic-gate * OUTPUT: slice - a pointer to a dm_descriptor_t to hold the
30040Sstevel@tonic-gate * slice corresponding to the input name, if found.
30050Sstevel@tonic-gate *
30060Sstevel@tonic-gate * RETURNS: int - 0 on success
30070Sstevel@tonic-gate * !0 otherwise.
30080Sstevel@tonic-gate *
30090Sstevel@tonic-gate * PURPOSE: Helper which iterates the known slices, searching for
30100Sstevel@tonic-gate * the one matching name.
30110Sstevel@tonic-gate *
30120Sstevel@tonic-gate * If no slice is found for the input name, variations of
30130Sstevel@tonic-gate * the name are tried.
30140Sstevel@tonic-gate *
30150Sstevel@tonic-gate * If the input name is unqualified, an appropriate leading
30160Sstevel@tonic-gate * path is prepended.
30170Sstevel@tonic-gate *
30180Sstevel@tonic-gate * If the input name is qualified, the leading path is
30190Sstevel@tonic-gate * removed.
30200Sstevel@tonic-gate *
30210Sstevel@tonic-gate * If no slice matches the variations, 0 is returned and the
30220Sstevel@tonic-gate * value of 'slice' will be (dm_descriptor_t)0;
30230Sstevel@tonic-gate */
30240Sstevel@tonic-gate int
slice_get_by_name(char * name,dm_descriptor_t * slice)30250Sstevel@tonic-gate slice_get_by_name(
30260Sstevel@tonic-gate char *name,
30270Sstevel@tonic-gate dm_descriptor_t *slice)
30280Sstevel@tonic-gate {
30290Sstevel@tonic-gate assert(name != (char *)NULL);
30300Sstevel@tonic-gate
30310Sstevel@tonic-gate *slice = find_cached_descriptor(name);
30320Sstevel@tonic-gate if (*slice == (dm_descriptor_t)0) {
30330Sstevel@tonic-gate if (name[0] == '/') {
30340Sstevel@tonic-gate /* fully qualified, try unqualified */
30350Sstevel@tonic-gate char *cp = strrchr(name, '/');
30360Sstevel@tonic-gate if (cp != NULL) {
30370Sstevel@tonic-gate *slice = find_cached_descriptor(cp + 1);
30380Sstevel@tonic-gate }
30390Sstevel@tonic-gate } else {
30400Sstevel@tonic-gate /* unqualified, try fully qualified */
30410Sstevel@tonic-gate char buf[MAXNAMELEN+1];
30420Sstevel@tonic-gate if (is_ctd_slice_name(name) || is_ctd_like_slice_name(name) ||
30430Sstevel@tonic-gate is_bsd_like_slice_name(name)) {
30440Sstevel@tonic-gate (void) snprintf(buf, MAXNAMELEN, "/dev/dsk/%s", name);
30450Sstevel@tonic-gate } else if (is_did_slice_name(name)) {
30460Sstevel@tonic-gate (void) snprintf(buf, MAXNAMELEN, "/dev/did/dsk/%s", name);
30470Sstevel@tonic-gate }
30480Sstevel@tonic-gate *slice = find_cached_descriptor(buf);
30490Sstevel@tonic-gate }
30500Sstevel@tonic-gate }
30510Sstevel@tonic-gate
30520Sstevel@tonic-gate /*
30530Sstevel@tonic-gate * since the descriptor cache includes HBAs, disks and slices,
30540Sstevel@tonic-gate * what gets returned may not be a slice... make sure it is
30550Sstevel@tonic-gate */
30560Sstevel@tonic-gate if (*slice != (dm_descriptor_t)0) {
30570Sstevel@tonic-gate if (dm_get_type(*slice) != DM_SLICE &&
30580Sstevel@tonic-gate is_virtual_slice(*slice) != B_TRUE) {
30590Sstevel@tonic-gate *slice = (dm_descriptor_t)0;
30600Sstevel@tonic-gate }
30610Sstevel@tonic-gate }
30620Sstevel@tonic-gate
30630Sstevel@tonic-gate return (0);
30640Sstevel@tonic-gate }
30650Sstevel@tonic-gate
30660Sstevel@tonic-gate /*
30670Sstevel@tonic-gate * FUNCTION: extract_hbaname(char *name, char **hbaname)
30680Sstevel@tonic-gate *
30690Sstevel@tonic-gate * INPUT: slicename - a char * device name
30700Sstevel@tonic-gate *
30710Sstevel@tonic-gate * OUTPUT: hbaname - a pointer to a char * to hold the hbaname derived
30720Sstevel@tonic-gate * from the input name.
30730Sstevel@tonic-gate *
30740Sstevel@tonic-gate * RETURNS: int - 0 on success
30750Sstevel@tonic-gate * !0 otherwise.
30760Sstevel@tonic-gate *
30770Sstevel@tonic-gate * PURPOSE: Helper which extracts the HBA name from the input name.
30780Sstevel@tonic-gate *
30790Sstevel@tonic-gate * If the input name is in ctd form, extracts just the cX part,
30800Sstevel@tonic-gate * by truncating everything following the last 't'.
30810Sstevel@tonic-gate *
30820Sstevel@tonic-gate * Of course on X86, with IDE drives, there is no 't' in the
30830Sstevel@tonic-gate * ctd name, so start by truncating everything following 'd'
30840Sstevel@tonic-gate * and then look for 't'.
30850Sstevel@tonic-gate *
30860Sstevel@tonic-gate * The returned string must be passed to free().
30870Sstevel@tonic-gate */
30880Sstevel@tonic-gate int
extract_hbaname(char * name,char ** hbaname)30890Sstevel@tonic-gate extract_hbaname(
30900Sstevel@tonic-gate char *name,
30910Sstevel@tonic-gate char **hbaname)
30920Sstevel@tonic-gate {
30930Sstevel@tonic-gate char *cp;
30940Sstevel@tonic-gate
30950Sstevel@tonic-gate if (is_ctd_name(name)) {
30960Sstevel@tonic-gate if ((*hbaname = strdup(name)) == NULL) {
30970Sstevel@tonic-gate return (ENOMEM);
30980Sstevel@tonic-gate }
30990Sstevel@tonic-gate if ((cp = strrchr(*hbaname, 'd')) != NULL) {
31000Sstevel@tonic-gate *cp = '\0';
31010Sstevel@tonic-gate }
31020Sstevel@tonic-gate if ((cp = strrchr(*hbaname, 't')) != NULL) {
31030Sstevel@tonic-gate *cp = '\0';
31040Sstevel@tonic-gate }
31050Sstevel@tonic-gate }
31060Sstevel@tonic-gate
31070Sstevel@tonic-gate return (0);
31080Sstevel@tonic-gate }
31090Sstevel@tonic-gate
31100Sstevel@tonic-gate /*
31110Sstevel@tonic-gate * FUNCTION: extract_diskname(char *slicename, char **diskname)
31120Sstevel@tonic-gate *
31130Sstevel@tonic-gate * INPUT: slicename - a char * slice name
31140Sstevel@tonic-gate *
31150Sstevel@tonic-gate * OUTPUT: diskname - a pointer to a char * to hold the diskname derived
31160Sstevel@tonic-gate * from the input slicename.
31170Sstevel@tonic-gate *
31180Sstevel@tonic-gate * RETURNS: int - 0 on success
31190Sstevel@tonic-gate * !0 otherwise.
31200Sstevel@tonic-gate *
31210Sstevel@tonic-gate * PURPOSE: Helper which extracts the disk's name from a slice name.
31220Sstevel@tonic-gate *
31230Sstevel@tonic-gate * Checks to see if the input slicename is in ctd or did form,
31240Sstevel@tonic-gate * and if so, truncates everything following the last 's'.
31250Sstevel@tonic-gate *
31260Sstevel@tonic-gate * If the input slicename is BSD-like, truncate the last
31270Sstevel@tonic-gate * character (a-h).
31280Sstevel@tonic-gate *
31290Sstevel@tonic-gate * The returned string must be passed to free().
31300Sstevel@tonic-gate */
31310Sstevel@tonic-gate int
extract_diskname(char * slicename,char ** diskname)31320Sstevel@tonic-gate extract_diskname(
31330Sstevel@tonic-gate char *slicename,
31340Sstevel@tonic-gate char **diskname)
31350Sstevel@tonic-gate {
31360Sstevel@tonic-gate char *cp;
31370Sstevel@tonic-gate
31380Sstevel@tonic-gate if (is_ctd_slice_name(slicename) || is_did_slice_name(slicename) ||
31390Sstevel@tonic-gate is_ctd_like_slice_name(slicename)) {
31400Sstevel@tonic-gate
31410Sstevel@tonic-gate if ((*diskname = strdup(slicename)) == NULL) {
31420Sstevel@tonic-gate return (ENOMEM);
31430Sstevel@tonic-gate }
31440Sstevel@tonic-gate if ((cp = strrchr(*diskname, 's')) != NULL) {
31450Sstevel@tonic-gate *cp = '\0';
31460Sstevel@tonic-gate }
31470Sstevel@tonic-gate
31480Sstevel@tonic-gate } else if (is_bsd_like_slice_name(slicename)) {
31490Sstevel@tonic-gate
31500Sstevel@tonic-gate if ((*diskname = strdup(slicename)) == NULL) {
31510Sstevel@tonic-gate return (ENOMEM);
31520Sstevel@tonic-gate }
31530Sstevel@tonic-gate (*diskname)[strlen((*diskname)-1)] = '\0';
31540Sstevel@tonic-gate
31550Sstevel@tonic-gate }
31560Sstevel@tonic-gate
31570Sstevel@tonic-gate return (0);
31580Sstevel@tonic-gate }
31590Sstevel@tonic-gate
31600Sstevel@tonic-gate /*
31610Sstevel@tonic-gate * FUNCTION: get_disk_for_named_slice(char *slicename,
31620Sstevel@tonic-gate * dm_descriptor_t disk)
31630Sstevel@tonic-gate *
31640Sstevel@tonic-gate * INPUT: slicename - a char * slice name
31650Sstevel@tonic-gate *
31660Sstevel@tonic-gate * OUTPUT: disk - a pointer to a dm_descriptor_t to hold the
31670Sstevel@tonic-gate * disk corresponding to the input name, if found
31680Sstevel@tonic-gate *
31690Sstevel@tonic-gate * RETURNS: int - 0 on success
31700Sstevel@tonic-gate * !0 otherwise.
31710Sstevel@tonic-gate *
31720Sstevel@tonic-gate * PURPOSE: Helper which locates the disk dm_descriptor_t handle for
31730Sstevel@tonic-gate * the input slice name.
31740Sstevel@tonic-gate *
31750Sstevel@tonic-gate * If no disk matches the name, 0 is returned and the
31760Sstevel@tonic-gate * value of 'disk' will be (dm_descriptor_t)0;
31770Sstevel@tonic-gate */
31780Sstevel@tonic-gate int
get_disk_for_named_slice(char * slicename,dm_descriptor_t * disk)31790Sstevel@tonic-gate get_disk_for_named_slice(
31800Sstevel@tonic-gate char *slicename,
31810Sstevel@tonic-gate dm_descriptor_t *disk)
31820Sstevel@tonic-gate {
31830Sstevel@tonic-gate dm_descriptor_t slice = (dm_descriptor_t)0;
31840Sstevel@tonic-gate int error = 0;
31850Sstevel@tonic-gate
31860Sstevel@tonic-gate assert(slicename != NULL);
31870Sstevel@tonic-gate
31880Sstevel@tonic-gate /* find disk for slice */
31890Sstevel@tonic-gate if ((error = slice_get_by_name(slicename, &slice)) == 0) {
31900Sstevel@tonic-gate
31910Sstevel@tonic-gate if (slice != (dm_descriptor_t)0) {
31920Sstevel@tonic-gate error = slice_get_disk(slice, disk);
31930Sstevel@tonic-gate } else {
31940Sstevel@tonic-gate /* named slice was created by layout: */
31950Sstevel@tonic-gate /* need to find disk by name */
31960Sstevel@tonic-gate char *dname;
31970Sstevel@tonic-gate
31980Sstevel@tonic-gate error = extract_diskname(slicename, &dname);
31990Sstevel@tonic-gate if (error == 0) {
32000Sstevel@tonic-gate error = disk_get_by_name(dname, disk);
32010Sstevel@tonic-gate }
32020Sstevel@tonic-gate free(dname);
32030Sstevel@tonic-gate }
32040Sstevel@tonic-gate }
32050Sstevel@tonic-gate
32060Sstevel@tonic-gate assert(*disk != (dm_descriptor_t)0);
32070Sstevel@tonic-gate
32080Sstevel@tonic-gate return (error);
32090Sstevel@tonic-gate }
32100Sstevel@tonic-gate
32110Sstevel@tonic-gate /*
32120Sstevel@tonic-gate * FUNCTION: disk_get_reserved_indexes(dm_descriptor_t disk,
32130Sstevel@tonic-gate * uint16_t **array)
32140Sstevel@tonic-gate *
32150Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t disk handle
32160Sstevel@tonic-gate *
32170Sstevel@tonic-gate * RETURNS: int - 0 on success
32180Sstevel@tonic-gate * !0 otherwise
32190Sstevel@tonic-gate *
32200Sstevel@tonic-gate * PURPOSE: Retrieves the input disk's list of reserved slice indices.
32210Sstevel@tonic-gate *
32220Sstevel@tonic-gate * The list of reserved indices is stored as an array in
32230Sstevel@tonic-gate * the disk's nvpair attribute list.
32240Sstevel@tonic-gate */
32250Sstevel@tonic-gate static int
disk_get_reserved_indexes(dm_descriptor_t disk,uint16_t ** array)32260Sstevel@tonic-gate disk_get_reserved_indexes(
32270Sstevel@tonic-gate dm_descriptor_t disk,
32280Sstevel@tonic-gate uint16_t **array)
32290Sstevel@tonic-gate {
32300Sstevel@tonic-gate nvlist_t *attrs = NULL;
32310Sstevel@tonic-gate uint_t nelem = 0;
32320Sstevel@tonic-gate int error = 0;
32330Sstevel@tonic-gate
32340Sstevel@tonic-gate if ((error = get_cached_attributes(disk, &attrs)) != 0) {
32350Sstevel@tonic-gate return (error);
32360Sstevel@tonic-gate }
32370Sstevel@tonic-gate
32380Sstevel@tonic-gate if ((error = get_uint16_array(
32390Sstevel@tonic-gate attrs, ATTR_RESERVED_INDEX, array, &nelem)) != 0) {
32400Sstevel@tonic-gate if (error == ENOENT) {
32410Sstevel@tonic-gate /* no reserved indices yet */
32420Sstevel@tonic-gate error = 0;
32430Sstevel@tonic-gate }
32440Sstevel@tonic-gate }
32450Sstevel@tonic-gate
32460Sstevel@tonic-gate return (error);
32470Sstevel@tonic-gate }
32480Sstevel@tonic-gate
32490Sstevel@tonic-gate /*
32500Sstevel@tonic-gate * FUNCTION: disk_reserve_index(dm_descriptor_t disk, uint16_t index)
32510Sstevel@tonic-gate *
32520Sstevel@tonic-gate * INPUT: disk - a disk dm_descirptor_t handle
32530Sstevel@tonic-gate * undex - a VTOC slice index
32540Sstevel@tonic-gate *
32550Sstevel@tonic-gate * RETURNS: int - 0 on success
32560Sstevel@tonic-gate * !0 otherwise
32570Sstevel@tonic-gate *
32580Sstevel@tonic-gate * PURPOSE: Reserves the input VTOC slice index for the input disk.
32590Sstevel@tonic-gate *
32600Sstevel@tonic-gate * The list of reserved indices is stored as an array in
32610Sstevel@tonic-gate * the disk's nvpair attribute list.
32620Sstevel@tonic-gate */
32630Sstevel@tonic-gate int
disk_reserve_index(dm_descriptor_t disk,uint16_t index)32640Sstevel@tonic-gate disk_reserve_index(
32650Sstevel@tonic-gate dm_descriptor_t disk,
32660Sstevel@tonic-gate uint16_t index)
32670Sstevel@tonic-gate {
32680Sstevel@tonic-gate nvlist_t *attrs = NULL;
32690Sstevel@tonic-gate uint16_t *oldindexes = NULL;
32700Sstevel@tonic-gate uint16_t *newindexes = NULL;
32710Sstevel@tonic-gate uint_t nelem = 0;
32720Sstevel@tonic-gate int error = 0;
32730Sstevel@tonic-gate int i = 0;
32740Sstevel@tonic-gate
32750Sstevel@tonic-gate if ((error = get_cached_attributes(disk, &attrs)) != 0) {
32760Sstevel@tonic-gate return (error);
32770Sstevel@tonic-gate }
32780Sstevel@tonic-gate
32790Sstevel@tonic-gate if ((error = get_uint16_array(
32800Sstevel@tonic-gate attrs, ATTR_RESERVED_INDEX, &oldindexes, &nelem)) != 0) {
32810Sstevel@tonic-gate if (error != ENOENT) {
32820Sstevel@tonic-gate return (error);
32830Sstevel@tonic-gate }
32840Sstevel@tonic-gate /* no reserved indices yet */
32850Sstevel@tonic-gate error = 0;
32860Sstevel@tonic-gate }
32870Sstevel@tonic-gate
32880Sstevel@tonic-gate /* add new index */
32890Sstevel@tonic-gate newindexes = (uint16_t *)calloc(VTOC_SIZE, sizeof (uint16_t));
32900Sstevel@tonic-gate if (newindexes != NULL) {
32910Sstevel@tonic-gate for (i = 0; i < nelem; i++) {
32920Sstevel@tonic-gate newindexes[i] = oldindexes[i];
32930Sstevel@tonic-gate }
32940Sstevel@tonic-gate newindexes[(int)index] = 1;
32950Sstevel@tonic-gate
32960Sstevel@tonic-gate error = set_uint16_array(attrs, ATTR_RESERVED_INDEX,
32970Sstevel@tonic-gate newindexes, VTOC_SIZE);
32980Sstevel@tonic-gate
32990Sstevel@tonic-gate free(newindexes);
33000Sstevel@tonic-gate } else {
33010Sstevel@tonic-gate error = ENOMEM;
33020Sstevel@tonic-gate }
33030Sstevel@tonic-gate return (error);
33040Sstevel@tonic-gate }
33050Sstevel@tonic-gate
33060Sstevel@tonic-gate /*
33070Sstevel@tonic-gate * FUNCTION: disk_release_index(dm_descriptor_t disk, uint16_t index)
33080Sstevel@tonic-gate *
33090Sstevel@tonic-gate * INPUT: disk - a disk dm_descirptor_t handle
33100Sstevel@tonic-gate * undex - a VTOC slice index
33110Sstevel@tonic-gate *
33120Sstevel@tonic-gate * RETURNS: int - 0 on success
33130Sstevel@tonic-gate * !0 otherwise
33140Sstevel@tonic-gate *
33150Sstevel@tonic-gate * PURPOSE: Releases the input VTOC slice index for the input disk.
33160Sstevel@tonic-gate * The index was previously reserved by disk_reserve_index()
33170Sstevel@tonic-gate */
33180Sstevel@tonic-gate int
disk_release_index(dm_descriptor_t disk,uint16_t index)33190Sstevel@tonic-gate disk_release_index(
33200Sstevel@tonic-gate dm_descriptor_t disk,
33210Sstevel@tonic-gate uint16_t index)
33220Sstevel@tonic-gate {
33230Sstevel@tonic-gate nvlist_t *attrs = NULL;
33240Sstevel@tonic-gate uint16_t *oldindexes = NULL;
33250Sstevel@tonic-gate uint16_t *newindexes = NULL;
33260Sstevel@tonic-gate uint_t nelem = 0;
33270Sstevel@tonic-gate int error = 0;
33280Sstevel@tonic-gate int i = 0;
33290Sstevel@tonic-gate
33300Sstevel@tonic-gate if ((error = get_cached_attributes(disk, &attrs)) != 0) {
33310Sstevel@tonic-gate return (error);
33320Sstevel@tonic-gate }
33330Sstevel@tonic-gate
33340Sstevel@tonic-gate if ((error = get_uint16_array(
33350Sstevel@tonic-gate attrs, ATTR_RESERVED_INDEX, &oldindexes, &nelem)) != 0) {
33360Sstevel@tonic-gate if (error != ENOENT) {
33370Sstevel@tonic-gate return (error);
33380Sstevel@tonic-gate }
33390Sstevel@tonic-gate error = 0;
33400Sstevel@tonic-gate }
33410Sstevel@tonic-gate
33420Sstevel@tonic-gate newindexes = (uint16_t *)calloc(VTOC_SIZE, sizeof (uint16_t));
33430Sstevel@tonic-gate if (newindexes != NULL) {
33440Sstevel@tonic-gate for (i = 0; i < nelem; i++) {
33450Sstevel@tonic-gate newindexes[i] = oldindexes[i];
33460Sstevel@tonic-gate }
33470Sstevel@tonic-gate
33480Sstevel@tonic-gate /* release index */
33490Sstevel@tonic-gate newindexes[(int)index] = 0;
33500Sstevel@tonic-gate
33510Sstevel@tonic-gate error = set_uint16_array(attrs, ATTR_RESERVED_INDEX,
33520Sstevel@tonic-gate newindexes, VTOC_SIZE);
33530Sstevel@tonic-gate
33540Sstevel@tonic-gate free(newindexes);
33550Sstevel@tonic-gate } else {
33560Sstevel@tonic-gate error = ENOMEM;
33570Sstevel@tonic-gate }
33580Sstevel@tonic-gate
33590Sstevel@tonic-gate return (error);
33600Sstevel@tonic-gate }
33610Sstevel@tonic-gate
33620Sstevel@tonic-gate /*
33630Sstevel@tonic-gate * FUNCTION: print_get_assoc_desc_error(dm_descriptor_t desc, char *which,
33640Sstevel@tonic-gate * int error)
33650Sstevel@tonic-gate *
33660Sstevel@tonic-gate * INPUT: desc - a dm_descriptor_t handle
33670Sstevel@tonic-gate * which - a char * indicating which association
33680Sstevel@tonic-gate * error - an integer error value
33690Sstevel@tonic-gate *
33700Sstevel@tonic-gate * PURPOSE: Utility function to print an error message for a failed
33710Sstevel@tonic-gate * call to dm_get_associated_descriptors().
33720Sstevel@tonic-gate *
33730Sstevel@tonic-gate * Extracts the device's CTD name and formats an error message.
33740Sstevel@tonic-gate */
33750Sstevel@tonic-gate void
print_get_assoc_desc_error(dm_descriptor_t desc,char * which,int error)33760Sstevel@tonic-gate print_get_assoc_desc_error(
33770Sstevel@tonic-gate dm_descriptor_t desc,
33780Sstevel@tonic-gate char *which,
33790Sstevel@tonic-gate int error)
33800Sstevel@tonic-gate {
33810Sstevel@tonic-gate char *name = "";
33820Sstevel@tonic-gate
33830Sstevel@tonic-gate (void) get_display_name(desc, &name);
33840Sstevel@tonic-gate oprintf(OUTPUT_TERSE,
33850Sstevel@tonic-gate gettext("dm_get_associated_descriptors(%s) for "
33860Sstevel@tonic-gate "'%s' failed: %d\n"),
33870Sstevel@tonic-gate which, name, error);
33880Sstevel@tonic-gate
33890Sstevel@tonic-gate volume_set_error(
33900Sstevel@tonic-gate gettext("Unexpected error getting associated "
33910Sstevel@tonic-gate "descriptors for '%s'"),
33920Sstevel@tonic-gate name);
33930Sstevel@tonic-gate }
33940Sstevel@tonic-gate
33950Sstevel@tonic-gate /*
33960Sstevel@tonic-gate * FUNCTION: print_get_desc_attr_error(dm_descriptor_t desc,
33970Sstevel@tonic-gate * char *devtype, char *attr, int error)
33980Sstevel@tonic-gate *
33990Sstevel@tonic-gate * INPUT: desc - a dm_descriptor_t handle
34000Sstevel@tonic-gate * devtype - a char * device type that's being accessed
34010Sstevel@tonic-gate * attr - a char * attribute name
34020Sstevel@tonic-gate * error - an integer error value
34030Sstevel@tonic-gate *
34040Sstevel@tonic-gate * PURPOSE: Shared utility function to print an error message for a failed
34050Sstevel@tonic-gate * call to retrieve an attribute for a descriptor.
34060Sstevel@tonic-gate *
34070Sstevel@tonic-gate * Extracts the device's CTD name and formats an error message.
34080Sstevel@tonic-gate */
34090Sstevel@tonic-gate void
print_get_desc_attr_error(dm_descriptor_t desc,char * devtype,char * attr,int error)34100Sstevel@tonic-gate print_get_desc_attr_error(
34110Sstevel@tonic-gate dm_descriptor_t desc,
34120Sstevel@tonic-gate char *devtype,
34130Sstevel@tonic-gate char *attr,
34140Sstevel@tonic-gate int error)
34150Sstevel@tonic-gate {
34160Sstevel@tonic-gate char *name = "";
34170Sstevel@tonic-gate
34180Sstevel@tonic-gate (void) get_display_name(desc, &name);
34190Sstevel@tonic-gate oprintf(OUTPUT_TERSE,
34200Sstevel@tonic-gate gettext("'%s' get attribute (%s.%s) error: %d\n"),
34210Sstevel@tonic-gate name, devtype, attr, error);
34220Sstevel@tonic-gate
34230Sstevel@tonic-gate volume_set_error(
34240Sstevel@tonic-gate gettext("Unexpected error getting attribute '%s.%s' for '%s'"),
34250Sstevel@tonic-gate devtype, attr, name);
34260Sstevel@tonic-gate }
34270Sstevel@tonic-gate
34280Sstevel@tonic-gate /*
34290Sstevel@tonic-gate * FUNCTION: print_set_desc_attr_error(dm_descriptor_t desc,
34300Sstevel@tonic-gate * char *devtype, char *attr, int error)
34310Sstevel@tonic-gate *
34320Sstevel@tonic-gate * INPUT: desc - a dm_descriptor_t handle
34330Sstevel@tonic-gate * devtype - a char * device type that's being accessed
34340Sstevel@tonic-gate * attr - a char * attribute name
34350Sstevel@tonic-gate * error - an integer error value
34360Sstevel@tonic-gate *
34370Sstevel@tonic-gate * PURPOSE: Shared utility function to print an error message for a failed
34380Sstevel@tonic-gate * call to set an attribute for a descriptor.
34390Sstevel@tonic-gate *
34400Sstevel@tonic-gate * Extracts the device's CTD name and formats an error message.
34410Sstevel@tonic-gate */
34420Sstevel@tonic-gate void
print_set_desc_attr_error(dm_descriptor_t desc,char * devtype,char * attr,int error)34430Sstevel@tonic-gate print_set_desc_attr_error(
34440Sstevel@tonic-gate dm_descriptor_t desc,
34450Sstevel@tonic-gate char *devtype,
34460Sstevel@tonic-gate char *attr,
34470Sstevel@tonic-gate int error)
34480Sstevel@tonic-gate {
34490Sstevel@tonic-gate char *name = "";
34500Sstevel@tonic-gate
34510Sstevel@tonic-gate (void) get_display_name(desc, &name);
34520Sstevel@tonic-gate oprintf(OUTPUT_TERSE,
34530Sstevel@tonic-gate gettext("'%s' set attribute (%s.%s) error: %d\n"),
34540Sstevel@tonic-gate name, devtype, attr, error);
34550Sstevel@tonic-gate
34560Sstevel@tonic-gate volume_set_error(
34570Sstevel@tonic-gate gettext("Unexpected error setting attribute '%s.%s' for '%s'"),
34580Sstevel@tonic-gate devtype, attr, name);
34590Sstevel@tonic-gate }
3460