xref: /onnv-gate/usr/src/cmd/lvm/metassist/layout/layout_slice.c (revision 62:5e51ad5d0496)
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 <sys/param.h>
300Sstevel@tonic-gate #include <meta.h>
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include "volume_string.h"
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include "volume_devconfig.h"
350Sstevel@tonic-gate #include "volume_error.h"
360Sstevel@tonic-gate #include "volume_dlist.h"
370Sstevel@tonic-gate #include "volume_output.h"
380Sstevel@tonic-gate 
390Sstevel@tonic-gate #include "layout_device_cache.h"
400Sstevel@tonic-gate #include "layout_device_util.h"
410Sstevel@tonic-gate #include "layout_discovery.h"
420Sstevel@tonic-gate #include "layout_dlist_util.h"
430Sstevel@tonic-gate #include "layout_messages.h"
440Sstevel@tonic-gate #include "layout_request.h"
450Sstevel@tonic-gate #include "layout_slice.h"
460Sstevel@tonic-gate 
470Sstevel@tonic-gate #define	_LAYOUT_SLICE_C
480Sstevel@tonic-gate 
490Sstevel@tonic-gate static int pick_from_best_hba_and_disk(
500Sstevel@tonic-gate 	dlist_t   	*list,
510Sstevel@tonic-gate 	dlist_t   	*used,
520Sstevel@tonic-gate 	dm_descriptor_t *chosen);
530Sstevel@tonic-gate 
540Sstevel@tonic-gate static int slice_has_same_disk_geom(
550Sstevel@tonic-gate 	dm_descriptor_t slice,
560Sstevel@tonic-gate 	dlist_t		*used,
570Sstevel@tonic-gate 	boolean_t	*bool);
580Sstevel@tonic-gate 
590Sstevel@tonic-gate static int slice_on_unique_disk(
600Sstevel@tonic-gate 	dm_descriptor_t slice,
610Sstevel@tonic-gate 	dlist_t		*used,
620Sstevel@tonic-gate 	dlist_t		*othervols,
630Sstevel@tonic-gate 	boolean_t	*bool);
640Sstevel@tonic-gate 
650Sstevel@tonic-gate static int slice_on_unique_hba(
660Sstevel@tonic-gate 	dm_descriptor_t slice,
670Sstevel@tonic-gate 	dlist_t		*used,
680Sstevel@tonic-gate 	dlist_t		*othervols,
690Sstevel@tonic-gate 	boolean_t	*bool);
700Sstevel@tonic-gate 
710Sstevel@tonic-gate static int slice_on_similar_bus(
720Sstevel@tonic-gate 	dm_descriptor_t slice,
730Sstevel@tonic-gate 	dlist_t		*used,
740Sstevel@tonic-gate 	boolean_t	*bool);
750Sstevel@tonic-gate 
760Sstevel@tonic-gate static int slice_has_n_paths(
770Sstevel@tonic-gate 	dm_descriptor_t	slice,
780Sstevel@tonic-gate 	uint16_t	npaths,
790Sstevel@tonic-gate 	boolean_t	*bool);
800Sstevel@tonic-gate 
810Sstevel@tonic-gate static int compare_modslice_names(
820Sstevel@tonic-gate 	void 		*obj1,
830Sstevel@tonic-gate 	void		*obj2);
840Sstevel@tonic-gate 
850Sstevel@tonic-gate static int compare_string_to_modslice_name(
860Sstevel@tonic-gate 	void		*str,
870Sstevel@tonic-gate 	void		*modslice);
880Sstevel@tonic-gate 
890Sstevel@tonic-gate static int create_new_slice(
900Sstevel@tonic-gate 	dm_descriptor_t oslice,
910Sstevel@tonic-gate 	uint64_t	nbytes,
920Sstevel@tonic-gate 	boolean_t	add_extra_cyl,
930Sstevel@tonic-gate 	devconfig_t	**nslice);
940Sstevel@tonic-gate 
950Sstevel@tonic-gate static int create_modified_slice(
960Sstevel@tonic-gate 	dm_descriptor_t	oslice,
970Sstevel@tonic-gate 	char		*oname,
980Sstevel@tonic-gate 	uint32_t	oindex,
990Sstevel@tonic-gate 	uint64_t	ostart,
1000Sstevel@tonic-gate 	uint64_t	osize,
1010Sstevel@tonic-gate 	uint64_t	bps,
1020Sstevel@tonic-gate 	char		*nname,
1030Sstevel@tonic-gate 	uint32_t	nindex,
1040Sstevel@tonic-gate 	uint64_t	nsize,
1050Sstevel@tonic-gate 	devconfig_t	**nslice);
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate /*
1080Sstevel@tonic-gate  * list to track resized slices
1090Sstevel@tonic-gate  */
1100Sstevel@tonic-gate static  dlist_t	*_modified_slices = NULL;
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate /*
1130Sstevel@tonic-gate  * struct to track used slices and their disks...
1140Sstevel@tonic-gate  */
1150Sstevel@tonic-gate typedef struct {
1160Sstevel@tonic-gate 	char		*slicename;
1170Sstevel@tonic-gate 	dm_descriptor_t	disk;
1180Sstevel@tonic-gate } usedslice_t;
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate /*
1210Sstevel@tonic-gate  * list to of usedslice_t to track slices that have been
1220Sstevel@tonic-gate  * used for any reason.
1230Sstevel@tonic-gate  */
1240Sstevel@tonic-gate static dlist_t	*_used_slices = NULL;
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate static int add_used_slice_list_entry(char *slicename, dm_descriptor_t disk);
1270Sstevel@tonic-gate static int compare_usedslice_name_to_string(void *obj1, void *obj2);
1280Sstevel@tonic-gate static void free_used_slice(void *obj);
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate /*
1310Sstevel@tonic-gate  * list of slices reserved to be used for explicit
1320Sstevel@tonic-gate  * volume requests
1330Sstevel@tonic-gate  */
1340Sstevel@tonic-gate static dlist_t *_rsvd_slices = NULL;
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate /*
1370Sstevel@tonic-gate  * list of slices needing to be removed (zeroed out) prior to
1380Sstevel@tonic-gate  * applying any metassist modifications to the system.
1390Sstevel@tonic-gate  */
1400Sstevel@tonic-gate static dlist_t *_rmvd_slices = NULL;
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate /*
1430Sstevel@tonic-gate  * FUNCTION:	choose_slice(
1440Sstevel@tonic-gate  *		uint64_t	nbytes,
1450Sstevel@tonic-gate  *		uint16_t	npaths,
1460Sstevel@tonic-gate  *		dlist_t		*slices,
1470Sstevel@tonic-gate  *		dlist_t		*used,
1480Sstevel@tonic-gate  *		dlist_t		*used_hbas,
1490Sstevel@tonic-gate  *		dlist_t		*used_disks,
1500Sstevel@tonic-gate  *		boolean_t	unused_disk,
1510Sstevel@tonic-gate  *		boolean_t	nbytes_is_min,
1520Sstevel@tonic-gate  *		boolean_t	add_extra_cyl,
1530Sstevel@tonic-gate  *		devconfig_t	**chosen)
1540Sstevel@tonic-gate  *
1550Sstevel@tonic-gate  * INPUT:	nbytes -	required size
1560Sstevel@tonic-gate  *		npaths -	minimum required data paths
1570Sstevel@tonic-gate  *		*slices -	slices from which to choose
1580Sstevel@tonic-gate  *		*used -		slices used by the volume under construction
1590Sstevel@tonic-gate  *		*used_hbas -	hbas used by other volumes relevant to
1600Sstevel@tonic-gate  *					the volume under construction
1610Sstevel@tonic-gate  *		*used_disks -	disks used by other volumes relevant to
1620Sstevel@tonic-gate  *					the volume under construction
1630Sstevel@tonic-gate  *		unused_disk -	if true, the chosen slice must be from an
1640Sstevel@tonic-gate  *					unused disk
1650Sstevel@tonic-gate  *		nbytes_is_min -	if true, the chosen slice may be larger than
1660Sstevel@tonic-gate  *					nbytes.
1670Sstevel@tonic-gate  *		add_extra_cyl -	passed to create_new_slice, see comment there.
1680Sstevel@tonic-gate  *		**chosen -	pointer to hold the chosen slice
1690Sstevel@tonic-gate  *
1700Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
1710Sstevel@tonic-gate  *			 !0 otherwise
1720Sstevel@tonic-gate  *
1730Sstevel@tonic-gate  * PURPOSE:	Choosen a slice from the list of those available.
1740Sstevel@tonic-gate  *
1750Sstevel@tonic-gate  *		Of those available, choose in order of preference:
1760Sstevel@tonic-gate  *
1770Sstevel@tonic-gate  *		- one on a unique HBA and disk that is of the exact size
1780Sstevel@tonic-gate  *		- one on a unique HBA and disk that is of sufficient size
1790Sstevel@tonic-gate  *		- one on unique HBA that is of the exact size
1800Sstevel@tonic-gate  *		- one on unique HBA that is of sufficient size
1810Sstevel@tonic-gate  *		- one on unique disk that is of the exact size
1820Sstevel@tonic-gate  *		- one on unique disk that is of sufficient size
1830Sstevel@tonic-gate  *		- one on any HBA that is of exact size
1840Sstevel@tonic-gate  *		- one on any HBA that is of sufficient size
1850Sstevel@tonic-gate  *		- one on a unique HBA that is the largest size
1860Sstevel@tonic-gate  *		- one on a unique disk that is the largest size
1870Sstevel@tonic-gate  *		- one on any HBA that is the largest size
1880Sstevel@tonic-gate  *
1890Sstevel@tonic-gate  *		The function scans the available slices and builds lists of
1900Sstevel@tonic-gate  *		those meeting the criteria above.  After the scan is complete,
1910Sstevel@tonic-gate  *		the lists are examined in order, the first non-empty list is
1920Sstevel@tonic-gate  *		chosen.  If there are several possibilities in the chosen list,
1930Sstevel@tonic-gate  *		see if it is possible select the slice from the least used HBA
1940Sstevel@tonic-gate  *		and/or disk.
1950Sstevel@tonic-gate  *
1960Sstevel@tonic-gate  *		If nbytes_is_min is true, the returned slice will be
1970Sstevel@tonic-gate  *		at least nbytes in capacity.
1980Sstevel@tonic-gate  *
1990Sstevel@tonic-gate  *		If unused_disk is true, the returned slice will be from
2000Sstevel@tonic-gate  *		a disk with no other known uses.
2010Sstevel@tonic-gate  */
2020Sstevel@tonic-gate int
choose_slice(uint64_t nbytes,uint16_t npaths,dlist_t * slices,dlist_t * used,dlist_t * used_hbas,dlist_t * used_disks,boolean_t unused_disk,boolean_t nbytes_is_min,boolean_t add_extra_cyl,devconfig_t ** chosen)2030Sstevel@tonic-gate choose_slice(
2040Sstevel@tonic-gate 	uint64_t	nbytes,
2050Sstevel@tonic-gate 	uint16_t	npaths,
2060Sstevel@tonic-gate 	dlist_t		*slices,
2070Sstevel@tonic-gate 	dlist_t		*used,
2080Sstevel@tonic-gate 	dlist_t		*used_hbas,
2090Sstevel@tonic-gate 	dlist_t		*used_disks,
2100Sstevel@tonic-gate 	boolean_t	unused_disk,
2110Sstevel@tonic-gate 	boolean_t	nbytes_is_min,
2120Sstevel@tonic-gate 	boolean_t	add_extra_cyl,
2130Sstevel@tonic-gate 	devconfig_t	**chosen)
2140Sstevel@tonic-gate {
2150Sstevel@tonic-gate 	dlist_t		*iter	= NULL;
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 	dm_descriptor_t	slice	= NULL;
2180Sstevel@tonic-gate 	boolean_t	resize  = B_FALSE;
2190Sstevel@tonic-gate 	boolean_t	verbose = (get_max_verbosity() == OUTPUT_VERBOSE);
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 	int		error	= 0;
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 	/*
2240Sstevel@tonic-gate 	 * indexes into the list array:
2250Sstevel@tonic-gate 	 * i -> unique controller	0 = yes, 1 = no
2260Sstevel@tonic-gate 	 * j -> same bus type		0 = yes, 1 = no
2270Sstevel@tonic-gate 	 * k -> unique disk		0 = yes, 1 = no
2280Sstevel@tonic-gate 	 * l -> same disk geom		0 = yes, 1 = no
2290Sstevel@tonic-gate 	 * m -> size			0 == exact, 1 = larger, 2 = any
2300Sstevel@tonic-gate 	 */
2310Sstevel@tonic-gate 	int		i, j, k, l, m;
2320Sstevel@tonic-gate 	dlist_t		*list[2][2][2][2][3];
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	/* output string arrays for each array dimension and index */
2350Sstevel@tonic-gate 	char	*uniqhba[2];
2360Sstevel@tonic-gate 	char	*samebus[2];
2370Sstevel@tonic-gate 	char	*uniqdisk[2];
2380Sstevel@tonic-gate 	char	*samegeom[2];
2390Sstevel@tonic-gate 	char	*sizes[3];
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	/* other output strings */
2420Sstevel@tonic-gate 	char	*look_msg = NULL;
2430Sstevel@tonic-gate 	char	*npaths_msg = NULL;
2440Sstevel@tonic-gate 	char	*samegeom_msg = NULL;
2450Sstevel@tonic-gate 	char	*samebus_msg = NULL;
2460Sstevel@tonic-gate 	char	*uniqhba_msg = NULL;
2470Sstevel@tonic-gate 	char	*uniqdisk_msg = NULL;
2480Sstevel@tonic-gate 	char	*exact_msg = NULL;
2490Sstevel@tonic-gate 	char	*larger_msg = NULL;
2500Sstevel@tonic-gate 	char	*smaller_msg = NULL;
2510Sstevel@tonic-gate 	char	*insuff_paths = NULL;
2520Sstevel@tonic-gate 	char	*too_small = NULL;
2530Sstevel@tonic-gate 	char	*useddisk_msg = NULL;
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	if (verbose == B_TRUE) {
2560Sstevel@tonic-gate 	    /* only initialize the output strings if needed */
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	    /* BEGIN CSTYLED */
2590Sstevel@tonic-gate 	    look_msg = gettext(
2600Sstevel@tonic-gate 		    "\tlooking at slice: %s (%s)\n");
2610Sstevel@tonic-gate 	    npaths_msg = gettext(
2620Sstevel@tonic-gate 		    "\t    has the requested number of data paths (%d)\n");
2630Sstevel@tonic-gate 	    samegeom_msg = gettext(
2640Sstevel@tonic-gate 		    "\t    has the same disk geometry relative to used slices\n");
2650Sstevel@tonic-gate 	    samebus_msg = gettext(
2660Sstevel@tonic-gate 		    "\t    on a similar I/O bus/HBA relative to used slices\n");
2670Sstevel@tonic-gate 	    uniqhba_msg = gettext(
2680Sstevel@tonic-gate 		    "\t    on a unique HBA relative to used slices\n");
2690Sstevel@tonic-gate 	    uniqdisk_msg = gettext(
2700Sstevel@tonic-gate 		    "\t    on a unique disk relative to used slices\n");
2710Sstevel@tonic-gate 	    exact_msg = gettext(
2720Sstevel@tonic-gate 		    "\t    the exact size necessary\n");
2730Sstevel@tonic-gate 	    larger_msg = gettext(
2740Sstevel@tonic-gate 		    "\t    larger than necessary\n");
2750Sstevel@tonic-gate 	    smaller_msg = gettext(
2760Sstevel@tonic-gate 		    "\t    smaller than necessary\n");
2770Sstevel@tonic-gate 	    insuff_paths = gettext(
2780Sstevel@tonic-gate 		    "\t    rejected: not enough paths (%d requested)\n");
2790Sstevel@tonic-gate 	    too_small = gettext(
2800Sstevel@tonic-gate 		    "\t    rejected: too small\n");
2810Sstevel@tonic-gate 	    useddisk_msg = gettext(
2820Sstevel@tonic-gate 		    "\t    rejected: on a disk with other volume component(s)\n");
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 	    uniqhba[0] = gettext("unique HBA");
2850Sstevel@tonic-gate 	    uniqhba[1] = gettext("non unique HBA");
2860Sstevel@tonic-gate 	    samebus[0] = gettext("same bus type");
2870Sstevel@tonic-gate 	    samebus[1] = gettext("different bus type");
2880Sstevel@tonic-gate 	    uniqdisk[0] = gettext("unique disk");
2890Sstevel@tonic-gate 	    uniqdisk[1] = gettext("non unique disk");
2900Sstevel@tonic-gate 	    samegeom[0] = gettext("same geometry");
2910Sstevel@tonic-gate 	    samegeom[1] = gettext("different geometry");
2920Sstevel@tonic-gate 	    sizes[0] = gettext("an exact size slice");
2930Sstevel@tonic-gate 	    sizes[1] = gettext("a larger slice");
2940Sstevel@tonic-gate 	    sizes[2] = gettext("a smaller slice");
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	    /* END CSTYLED */
2970Sstevel@tonic-gate 	}
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	/* init list array pointers */
3000Sstevel@tonic-gate 	(void) memset(list, 0,  2*2*2*2*3 * sizeof (dlist_t *));
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 	for (iter = slices;
3030Sstevel@tonic-gate 	    (iter != NULL) && (error == 0); iter = iter->next) {
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 	    dm_descriptor_t	slice = (uintptr_t)iter->obj;
3060Sstevel@tonic-gate 	    uint64_t		snbytes = 0;
3070Sstevel@tonic-gate 	    boolean_t		uniqdisk = B_FALSE;
3080Sstevel@tonic-gate 	    boolean_t		uniqhba = B_FALSE;
3090Sstevel@tonic-gate 	    boolean_t		samegeom = B_FALSE;
3100Sstevel@tonic-gate 	    boolean_t		samebus = B_FALSE;
3110Sstevel@tonic-gate 	    boolean_t		paths = B_FALSE;
3120Sstevel@tonic-gate 	    dlist_t		*item = NULL;
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	    ((error = slice_get_size(slice, &snbytes)) != 0) ||
3150Sstevel@tonic-gate 	    (error = slice_has_n_paths(slice, npaths, &paths)) ||
3160Sstevel@tonic-gate 	    (error = slice_on_unique_hba(slice, used, used_hbas, &uniqhba)) ||
3170Sstevel@tonic-gate 	    (error = slice_on_unique_disk(slice, used, used_disks,
3180Sstevel@tonic-gate 		    &uniqdisk)) ||
3190Sstevel@tonic-gate 	    (error = slice_on_similar_bus(slice, used, &samebus)) ||
3200Sstevel@tonic-gate 	    (error = slice_has_same_disk_geom(slice, used, &samegeom));
3210Sstevel@tonic-gate 	    if (error != 0) {
3220Sstevel@tonic-gate 		continue;
3230Sstevel@tonic-gate 	    }
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	    if (verbose == B_TRUE) {
3260Sstevel@tonic-gate 		char *sname = NULL;
3270Sstevel@tonic-gate 		char *sizestr = NULL;
3280Sstevel@tonic-gate 		(void) get_display_name(slice, &sname);
3290Sstevel@tonic-gate 		if (bytes_to_sizestr(snbytes, &sizestr,
3300Sstevel@tonic-gate 			    universal_units, B_FALSE) == 0) {
3310Sstevel@tonic-gate 		    oprintf(OUTPUT_VERBOSE, look_msg, sname, sizestr);
3320Sstevel@tonic-gate 		    free(sizestr);
3330Sstevel@tonic-gate 		}
3340Sstevel@tonic-gate 	    }
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	    if (npaths > 1) {
3370Sstevel@tonic-gate 		if (paths && verbose) {
3380Sstevel@tonic-gate 		    /* specifically asked for more paths, ... */
3390Sstevel@tonic-gate 		    oprintf(OUTPUT_VERBOSE, npaths_msg);
3400Sstevel@tonic-gate 		}
3410Sstevel@tonic-gate 	    } else if (npaths == 1) {
3420Sstevel@tonic-gate 		/* every disk has at least 1 path */
3430Sstevel@tonic-gate 		paths = B_TRUE;
3440Sstevel@tonic-gate 	    }
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 	    if (verbose == B_TRUE) {
3470Sstevel@tonic-gate 		if (uniqhba) {
3480Sstevel@tonic-gate 		    oprintf(OUTPUT_VERBOSE, uniqhba_msg);
3490Sstevel@tonic-gate 		}
3500Sstevel@tonic-gate 		if (uniqdisk) {
3510Sstevel@tonic-gate 		    oprintf(OUTPUT_VERBOSE, uniqdisk_msg);
3520Sstevel@tonic-gate 		}
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 		if (used != NULL) {
3550Sstevel@tonic-gate 		    if (samebus) {
3560Sstevel@tonic-gate 			oprintf(OUTPUT_VERBOSE, samebus_msg);
3570Sstevel@tonic-gate 		    }
3580Sstevel@tonic-gate 		    if (samegeom) {
3590Sstevel@tonic-gate 			oprintf(OUTPUT_VERBOSE, samegeom_msg);
3600Sstevel@tonic-gate 		    }
3610Sstevel@tonic-gate 		}
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 		if (snbytes > nbytes) {
3640Sstevel@tonic-gate 		    oprintf(OUTPUT_VERBOSE, larger_msg);
3650Sstevel@tonic-gate 		} else if (snbytes == nbytes) {
3660Sstevel@tonic-gate 		    oprintf(OUTPUT_VERBOSE, exact_msg);
3670Sstevel@tonic-gate 		} else {
3680Sstevel@tonic-gate 		    oprintf(OUTPUT_VERBOSE, smaller_msg);
3690Sstevel@tonic-gate 		}
3700Sstevel@tonic-gate 	    }
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	    /* filter slices not meeting minimum criteria */
3730Sstevel@tonic-gate 	    if (nbytes_is_min && (snbytes < nbytes)) {
3740Sstevel@tonic-gate 		/* not large enough */
3750Sstevel@tonic-gate 		if (verbose == B_TRUE) {
3760Sstevel@tonic-gate 		    oprintf(OUTPUT_VERBOSE, too_small);
3770Sstevel@tonic-gate 		}
3780Sstevel@tonic-gate 		continue;
3790Sstevel@tonic-gate 	    }
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate 	    if (paths == B_FALSE) {
3820Sstevel@tonic-gate 		/* not connected thru enough paths */
3830Sstevel@tonic-gate 		if (verbose == B_TRUE) {
3840Sstevel@tonic-gate 		    oprintf(OUTPUT_VERBOSE, insuff_paths, npaths);
3850Sstevel@tonic-gate 		}
3860Sstevel@tonic-gate 		continue;
3870Sstevel@tonic-gate 	    }
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 	    if (uniqdisk != B_TRUE && unused_disk == TRUE) {
3900Sstevel@tonic-gate 		/* not on a unique disk */
3910Sstevel@tonic-gate 		if (verbose == B_TRUE) {
3920Sstevel@tonic-gate 		    oprintf(OUTPUT_VERBOSE, useddisk_msg);
3930Sstevel@tonic-gate 		}
3940Sstevel@tonic-gate 		continue;
3950Sstevel@tonic-gate 	    }
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	    /* map slice properties into array indices */
3980Sstevel@tonic-gate 	    i = (uniqhba ? 0 : 1);
3990Sstevel@tonic-gate 	    j = (samebus ? 0 : 1);
4000Sstevel@tonic-gate 	    k = (uniqdisk ? 0 : 1);
4010Sstevel@tonic-gate 	    l = (samegeom ? 0 : 1);
4020Sstevel@tonic-gate 	    m = (snbytes == nbytes ? 0 : (snbytes > nbytes ? 1 : 2));
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 		/*
4050Sstevel@tonic-gate 		 * insert slice into the list array using derived indices.
4060Sstevel@tonic-gate 		 * NB: lists of slices larger than necessary are kept in
4070Sstevel@tonic-gate 		 * ascending order (results in best fit, not worst fit)
4080Sstevel@tonic-gate 		 */
409*62Sjeanm 	    if ((item = dlist_new_item((void*)(uintptr_t)slice)) == NULL) {
4100Sstevel@tonic-gate 		error = ENOMEM;
4110Sstevel@tonic-gate 	    } else {
4120Sstevel@tonic-gate 		list[i][j][k][l][m] =
4130Sstevel@tonic-gate 		    dlist_insert_ordered(
4140Sstevel@tonic-gate 			    item,
4150Sstevel@tonic-gate 			    list[i][j][k][l][m],
4160Sstevel@tonic-gate 			    (m == 1 ? ASCENDING : DESCENDING),
4170Sstevel@tonic-gate 			    compare_slice_sizes);
4180Sstevel@tonic-gate 	    }
4190Sstevel@tonic-gate 	}
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	/*
4220Sstevel@tonic-gate 	 * Select a slice from one of the lists.
4230Sstevel@tonic-gate 	 *
4240Sstevel@tonic-gate 	 * The list with the combination of lowest indices
4250Sstevel@tonic-gate 	 * is the most preferred list... in rough order:
4260Sstevel@tonic-gate 	 *
4270Sstevel@tonic-gate 	 *   one on a unique HBA and disk that is of the exact size
4280Sstevel@tonic-gate 	 *   one on a unique HBA and disk that is of sufficient size (resize)
4290Sstevel@tonic-gate 	 *   one on unique HBA that is of the exact size
4300Sstevel@tonic-gate 	 *   one on unique HBA that is of sufficient size (resize)
4310Sstevel@tonic-gate 	 *   one on unique disk that is of the exact size
4320Sstevel@tonic-gate 	 *   one on unique disk that is of sufficient size (resize)
4330Sstevel@tonic-gate 	 *   one on any HBA that is of exact size
4340Sstevel@tonic-gate 	 *   one on any HBA that is of sufficient size (resize)
4350Sstevel@tonic-gate 	 *   one on a unique HBA that is the largest size
4360Sstevel@tonic-gate 	 *   one on a unique disk that is the largest size
4370Sstevel@tonic-gate 	 *   one on any HBA that is the largest size
4380Sstevel@tonic-gate 	 */
4390Sstevel@tonic-gate 	slice = NULL;
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 	for (i = 0; i < 2; i++) {
4420Sstevel@tonic-gate 	    for (j = 0; j < 2; j++) {
4430Sstevel@tonic-gate 		for (k = 0; k < 2; k++) {
4440Sstevel@tonic-gate 		    for (l = 0; l < 2; l++) {
4450Sstevel@tonic-gate 			for (m = 0; m < 3; m++) {
4460Sstevel@tonic-gate 			    if (list[i][j][k][l][m] != NULL) {
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 				/* pick least used slice from this list */
4490Sstevel@tonic-gate 				error = pick_from_best_hba_and_disk(
4500Sstevel@tonic-gate 					list[i][j][k][l][m],
4510Sstevel@tonic-gate 					used, &slice);
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 				resize = (m == 1);
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate 				/* terminate all loops */
4560Sstevel@tonic-gate 				goto stop;
4570Sstevel@tonic-gate 			    }
4580Sstevel@tonic-gate 			}
4590Sstevel@tonic-gate 		    }
4600Sstevel@tonic-gate 		}
4610Sstevel@tonic-gate 	    }
4620Sstevel@tonic-gate 	}
4630Sstevel@tonic-gate stop:
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	/*
4660Sstevel@tonic-gate 	 * Slice chosen, is a resize necessary?
4670Sstevel@tonic-gate 	 */
4680Sstevel@tonic-gate 	if ((error == 0) && (slice != NULL)) {
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 	    if (error == 0) {
4710Sstevel@tonic-gate 		if (verbose == B_TRUE) {
4720Sstevel@tonic-gate 		    uint64_t	snbytes = 0;
4730Sstevel@tonic-gate 		    char	*sname = NULL;
4740Sstevel@tonic-gate 		    char	*sizestr = NULL;
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 		    (void) get_display_name(slice, &sname);
4770Sstevel@tonic-gate 		    (void) slice_get_size(slice, &snbytes);
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 		    if (bytes_to_sizestr(snbytes, &sizestr,
4800Sstevel@tonic-gate 				universal_units, B_FALSE) == 0) {
4810Sstevel@tonic-gate 			oprintf(OUTPUT_VERBOSE,
4820Sstevel@tonic-gate 				gettext("      selected %s (%s)\n"
4830Sstevel@tonic-gate 					"        it is %s on a\n"
4840Sstevel@tonic-gate 					"          %s (%s) and a\n"
4850Sstevel@tonic-gate 					"          %s (%s)\n"),
4860Sstevel@tonic-gate 				sname, sizestr,
4870Sstevel@tonic-gate 				sizes[m],
4880Sstevel@tonic-gate 				uniqhba[i], samebus[j],
4890Sstevel@tonic-gate 				uniqdisk[k], samegeom[l]);
4900Sstevel@tonic-gate 			free(sizestr);
4910Sstevel@tonic-gate 		    }
4920Sstevel@tonic-gate 		}
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 		if (resize) {
4950Sstevel@tonic-gate 		    if (verbose == B_TRUE) {
4960Sstevel@tonic-gate 			oprintf(OUTPUT_VERBOSE,
4970Sstevel@tonic-gate 				gettext("        it has excess space, "
4980Sstevel@tonic-gate 					"resizing...\n"));
4990Sstevel@tonic-gate 		    }
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 		    error = create_new_slice(slice, nbytes, add_extra_cyl,
5020Sstevel@tonic-gate 			    chosen);
5030Sstevel@tonic-gate 		    if ((error == 0) &&	(*chosen != NULL) && verbose) {
5040Sstevel@tonic-gate 			oprintf(OUTPUT_VERBOSE,
5050Sstevel@tonic-gate 				gettext("        exactly resized\n"));
5060Sstevel@tonic-gate 		    }
5070Sstevel@tonic-gate 		}
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 		if (error == 0) {
5100Sstevel@tonic-gate 		    /* either no resize was necessary or the resize failed */
5110Sstevel@tonic-gate 		    if (*chosen == NULL) {
5120Sstevel@tonic-gate 			/*
5130Sstevel@tonic-gate 			 * use the original slice as it is.
5140Sstevel@tonic-gate 			 * Make a devconfig_t for it.
5150Sstevel@tonic-gate 			 */
5160Sstevel@tonic-gate 			error = create_devconfig_for_slice(slice, chosen);
5170Sstevel@tonic-gate 		    }
5180Sstevel@tonic-gate 		}
5190Sstevel@tonic-gate 	    }
5200Sstevel@tonic-gate 	} else if (slice == NULL) {
5210Sstevel@tonic-gate 	    oprintf(OUTPUT_DEBUG,
5220Sstevel@tonic-gate 		    gettext("      no possible slice\n"));
5230Sstevel@tonic-gate 	}
5240Sstevel@tonic-gate 
5250Sstevel@tonic-gate 	for (i = 0; i < 2; i++) {
5260Sstevel@tonic-gate 	    for (j = 0; j < 2; j++) {
5270Sstevel@tonic-gate 		for (k = 0; k < 2; k++) {
5280Sstevel@tonic-gate 		    for (l = 0; l < 2; l++) {
5290Sstevel@tonic-gate 			for (m = 0; m < 3; m++) {
5300Sstevel@tonic-gate 			    if (list[i][j][k][l][m] != NULL) {
5310Sstevel@tonic-gate 				dlist_free_items(list[i][j][k][l][m], NULL);
5320Sstevel@tonic-gate 			    }
5330Sstevel@tonic-gate 			}
5340Sstevel@tonic-gate 		    }
5350Sstevel@tonic-gate 		}
5360Sstevel@tonic-gate 	    }
5370Sstevel@tonic-gate 	}
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 	return (error);
5400Sstevel@tonic-gate }
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate /*
5430Sstevel@tonic-gate  * FUNCTION:	create_devconfig_for_slice(dm_descriptor_t slice,
5440Sstevel@tonic-gate  *			devconfig_t **nslice)
5450Sstevel@tonic-gate  *
5460Sstevel@tonic-gate  * INPUT:	slice	- dm_descriptor_t handle to an existing slice
5470Sstevel@tonic-gate  *		nslice	- devconfig_t pointer to hold the new slice
5480Sstevel@tonic-gate  *
5490Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
5500Sstevel@tonic-gate  *			 !0 otherwise
5510Sstevel@tonic-gate  *
5520Sstevel@tonic-gate  * PURPOSE:	Creates a devconfig_t struct representation of the input
5530Sstevel@tonic-gate  *		slice dm_descriptor.
5540Sstevel@tonic-gate  */
5550Sstevel@tonic-gate int
create_devconfig_for_slice(dm_descriptor_t slice,devconfig_t ** nslice)5560Sstevel@tonic-gate create_devconfig_for_slice(
5570Sstevel@tonic-gate 	dm_descriptor_t slice,
5580Sstevel@tonic-gate 	devconfig_t 	**nslice)
5590Sstevel@tonic-gate {
5600Sstevel@tonic-gate 	uint64_t 	nbytes = 0;
5610Sstevel@tonic-gate 	uint64_t 	nblks = 0;
5620Sstevel@tonic-gate 	uint64_t 	stblk = 0;
5630Sstevel@tonic-gate 	uint32_t 	index = 0;
5640Sstevel@tonic-gate 	char		*name = NULL;
5650Sstevel@tonic-gate 	int		error = 0;
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate 	((error = get_display_name(slice, &name)) != 0) ||
5680Sstevel@tonic-gate 	(error = slice_get_size(slice, &nbytes)) ||
5690Sstevel@tonic-gate 	(error = slice_get_size_in_blocks(slice, &nblks)) ||
5700Sstevel@tonic-gate 	(error = slice_get_start_block(slice, &stblk)) ||
5710Sstevel@tonic-gate 	(error = slice_get_index(slice, &index));
5720Sstevel@tonic-gate 	if (error != 0) {
5730Sstevel@tonic-gate 	    return (error);
5740Sstevel@tonic-gate 	}
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate 	((error = new_devconfig(nslice, TYPE_SLICE)) != 0) ||
5770Sstevel@tonic-gate 	(error = devconfig_set_name(*nslice, name)) ||
5780Sstevel@tonic-gate 	(error = devconfig_set_slice_index(*nslice, index)) ||
5790Sstevel@tonic-gate 	(error = devconfig_set_slice_start_block(*nslice, stblk)) ||
5800Sstevel@tonic-gate 	(error = devconfig_set_size_in_blocks(*nslice, nblks)) ||
5810Sstevel@tonic-gate 	(error = devconfig_set_size(*nslice, nbytes));
5820Sstevel@tonic-gate 	if (error != 0) {
5830Sstevel@tonic-gate 	    free_devconfig(*nslice);
5840Sstevel@tonic-gate 	}
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 	return (error);
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate /*
5900Sstevel@tonic-gate  * FUNCTION:	make_slicename_for_disk_and_index(dm_descriptor_t disk,
5910Sstevel@tonic-gate  *			uint32_t index, char **slicename)
5920Sstevel@tonic-gate  *
5930Sstevel@tonic-gate  * INPUT:	disk	- a dm_descriptor_t disk handle
5940Sstevel@tonic-gate  *		index	- a slice index
5950Sstevel@tonic-gate  *
5960Sstevel@tonic-gate  * OUTPUT	slicename - a char * pointer to hold the resulting slicename
5970Sstevel@tonic-gate  *
5980Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
5990Sstevel@tonic-gate  *			 !0 otherwise
6000Sstevel@tonic-gate  *
6010Sstevel@tonic-gate  * PURPOSE:	Utility function to manufacture a new slice name given the
6020Sstevel@tonic-gate  *		"parent" disk and an available slice index.
6030Sstevel@tonic-gate  *
6040Sstevel@tonic-gate  *		The caller should free the returned name when done with it.
6050Sstevel@tonic-gate  */
6060Sstevel@tonic-gate static int
make_slicename_for_disk_and_index(dm_descriptor_t disk,uint16_t index,char ** slicename)6070Sstevel@tonic-gate make_slicename_for_disk_and_index(
6080Sstevel@tonic-gate 	dm_descriptor_t	disk,
6090Sstevel@tonic-gate 	uint16_t	index,
6100Sstevel@tonic-gate 	char		**slicename)
6110Sstevel@tonic-gate {
6120Sstevel@tonic-gate 	char *dname;
6130Sstevel@tonic-gate 	int error = 0;
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 	if ((error = get_display_name(disk, &dname)) == 0) {
6160Sstevel@tonic-gate 	    error = make_slicename_for_diskname_and_index(dname,
6170Sstevel@tonic-gate 		    index, slicename);
6180Sstevel@tonic-gate 	}
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 	return (error);
6210Sstevel@tonic-gate }
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate /*
6240Sstevel@tonic-gate  * FUNCTION:	make_slicename_for_diskname_and_index(char *diskname,
6250Sstevel@tonic-gate  *			uint32_t index, char **slicename)
6260Sstevel@tonic-gate  *
6270Sstevel@tonic-gate  * INPUT:	diskname - a char * disk name
6280Sstevel@tonic-gate  *		index	- a slice index
6290Sstevel@tonic-gate  *
6300Sstevel@tonic-gate  * OUTPUT	slicename - a char * pointer to hold the resulting slicename
6310Sstevel@tonic-gate  *
6320Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
6330Sstevel@tonic-gate  *			 !0 otherwise
6340Sstevel@tonic-gate  *
6350Sstevel@tonic-gate  * PURPOSE:	Utility function to manufacture a new slice name given the
6360Sstevel@tonic-gate  *		name of a disk and an available slice index.
6370Sstevel@tonic-gate  *
6380Sstevel@tonic-gate  *		The caller should free the returned name when done with it.
6390Sstevel@tonic-gate  */
6400Sstevel@tonic-gate int
make_slicename_for_diskname_and_index(char * diskname,uint16_t index,char ** slicename)6410Sstevel@tonic-gate make_slicename_for_diskname_and_index(
6420Sstevel@tonic-gate 	char	*diskname,
6430Sstevel@tonic-gate 	uint16_t index,
6440Sstevel@tonic-gate 	char	**slicename)
6450Sstevel@tonic-gate {
6460Sstevel@tonic-gate 	int error = 0;
6470Sstevel@tonic-gate 	char buf[MAXNAMELEN+1];
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate 	(void) snprintf(buf, sizeof (buf), "%ss%u", diskname, index);
6500Sstevel@tonic-gate 	if ((*slicename = strdup(buf)) == NULL) {
6510Sstevel@tonic-gate 	    *slicename = NULL;
6520Sstevel@tonic-gate 	    error = ENOMEM;
6530Sstevel@tonic-gate 	}
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 	return (error);
6560Sstevel@tonic-gate }
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate /*
6590Sstevel@tonic-gate  * FUNCTION:	create_new_slice(dm_descriptor_t oslice, uint64_t nbytes,
6600Sstevel@tonic-gate  *			boolean_t add_extra_cyl, devconfig_t **nslice)
6610Sstevel@tonic-gate  *
6620Sstevel@tonic-gate  * INPUT:	oslice	- dm_descriptor_t handle to an existing slice
6630Sstevel@tonic-gate  *		nbytes	- desired minimum size of the new slice
6640Sstevel@tonic-gate  *		add_extra_cyl - boolean indicating whether the resized slice
6650Sstevel@tonic-gate  *			needs to be oversized by 1 cylinder to account for
6660Sstevel@tonic-gate  *			interlace rounding done for stripe components.
6670Sstevel@tonic-gate  *		nslice	- devconfig_t pointer to hold the new slice
6680Sstevel@tonic-gate  *
6690Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
6700Sstevel@tonic-gate  *			 !0 otherwise
6710Sstevel@tonic-gate  *
6720Sstevel@tonic-gate  * PURPOSE:	Creates a new slice object using space from the input slice.
6730Sstevel@tonic-gate  *
6740Sstevel@tonic-gate  *		If there is an open slice slot in the disk VTOC, it will be
6750Sstevel@tonic-gate  *		reserved for the new slice.  Space for the new slice will be
6760Sstevel@tonic-gate  *		taken from the original slice.
6770Sstevel@tonic-gate  *
6780Sstevel@tonic-gate  *		If there is no open slice slot, the original slice will be
6790Sstevel@tonic-gate  *		returned as the usable new slice.
6800Sstevel@tonic-gate  *
6810Sstevel@tonic-gate  *		The new slice will be of at least 'nbytes' bytes and possibly
6820Sstevel@tonic-gate  *		larger due to sector and cylinder boundary alignment.
6830Sstevel@tonic-gate  *
6840Sstevel@tonic-gate  *		For EFI labeled disks, nbytes is rounded up to the next block
6850Sstevel@tonic-gate  *		boundary.
6860Sstevel@tonic-gate  *
6870Sstevel@tonic-gate  *		For VTOC labeled disks, nbytes is rounded up to the next
6880Sstevel@tonic-gate  *		cylinder boundary.
6890Sstevel@tonic-gate  *
6900Sstevel@tonic-gate  *		Additionally, if add_extra_cyl is true, the new slice will be
6910Sstevel@tonic-gate  *		made 1 cylinder larger than necessary. This accounts for the
6920Sstevel@tonic-gate  *		interlace rounding done within libmeta when computing the
6930Sstevel@tonic-gate  *		usable size of stripe components on disks with VTOC labels.
6940Sstevel@tonic-gate  *		Rounding the size up to the next cylinder boundary is not
6950Sstevel@tonic-gate  *		sufficient because libmeta will round this size down to an
6960Sstevel@tonic-gate  *		integral multiple of the stripe	interlace and then round that
6970Sstevel@tonic-gate  *		result down to a cylinder boundary.  This makes the usable
6980Sstevel@tonic-gate  *		size of the slice one cylinder smaller and possibly less than
6990Sstevel@tonic-gate  *		nbytes.  Adding an extra cylinder ensures the usable size is
7000Sstevel@tonic-gate  *		greater than nbytes despite the rounding.
7010Sstevel@tonic-gate  *
7020Sstevel@tonic-gate  *		If the resize is successful a pointer to the devconfig_t
7030Sstevel@tonic-gate  *		representing the new slice will be returned in "newslice".
7040Sstevel@tonic-gate  *
7050Sstevel@tonic-gate  *		If the resize cannot be done, the newslice pointer will
7060Sstevel@tonic-gate  *		be NULL.
7070Sstevel@tonic-gate  */
7080Sstevel@tonic-gate static int
create_new_slice(dm_descriptor_t oslice,uint64_t nbytes,boolean_t add_extra_cyl,devconfig_t ** nslice)7090Sstevel@tonic-gate create_new_slice(
7100Sstevel@tonic-gate 	dm_descriptor_t	oslice,
7110Sstevel@tonic-gate 	uint64_t	nbytes,
7120Sstevel@tonic-gate 	boolean_t	add_extra_cyl,
7130Sstevel@tonic-gate 	devconfig_t	**nslice)
7140Sstevel@tonic-gate {
7150Sstevel@tonic-gate 	dm_descriptor_t odisk = NULL;
7160Sstevel@tonic-gate 	boolean_t	efi = B_FALSE;
7170Sstevel@tonic-gate 
7180Sstevel@tonic-gate 	char		*oname = NULL;
7190Sstevel@tonic-gate 	uint64_t	osize = 0;	/* orig size (bytes) */
7200Sstevel@tonic-gate 	uint64_t	ostart = 0;	/* orig start (byte) */
7210Sstevel@tonic-gate 	uint64_t	ostblk = 0;	/* orig start (blk) */
7220Sstevel@tonic-gate 	uint64_t	nsize = 0;	/* new size (bytes) */
7230Sstevel@tonic-gate 	uint64_t	bytes_per_sect = 0;
7240Sstevel@tonic-gate 
7250Sstevel@tonic-gate 	uint32_t 	oindex = 0;
7260Sstevel@tonic-gate 	uint32_t	nindex = oindex;
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 	int		error = 0;
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate 	*nslice = NULL;
7310Sstevel@tonic-gate 
7320Sstevel@tonic-gate 	((error = slice_get_disk(oslice, &odisk)) != 0) ||
7330Sstevel@tonic-gate 	(error = slice_get_index(oslice, &oindex));
7340Sstevel@tonic-gate 	if (error != 0) {
7350Sstevel@tonic-gate 	    return (error);
7360Sstevel@tonic-gate 	}
7370Sstevel@tonic-gate 
7380Sstevel@tonic-gate 	/* find an unused slice number, default to oindex */
7390Sstevel@tonic-gate 	nindex = oindex;
7400Sstevel@tonic-gate 	if ((error = disk_get_available_slice_index(odisk, &nindex)) != 0) {
7410Sstevel@tonic-gate 	    return (error);
7420Sstevel@tonic-gate 	}
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	((error = get_display_name(oslice, &oname)) != 0) ||
7450Sstevel@tonic-gate 	(error = slice_get_size(oslice, &osize)) ||
7460Sstevel@tonic-gate 	(error = slice_get_start(oslice, &ostart)) ||
7470Sstevel@tonic-gate 	(error = slice_get_start_block(oslice, &ostblk)) ||
7480Sstevel@tonic-gate 	(error = disk_get_is_efi(odisk, &efi)) ||
7490Sstevel@tonic-gate 	(error = disk_get_blocksize(odisk, &bytes_per_sect));
7500Sstevel@tonic-gate 	if (error != 0) {
7510Sstevel@tonic-gate 	    return (error);
7520Sstevel@tonic-gate 	}
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 	if (efi) {
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 	    /* EFI: round size to an integral number of blocks (sectors) */
7570Sstevel@tonic-gate 	    nsize = bytes_per_sect *
7580Sstevel@tonic-gate 		((nbytes + (bytes_per_sect - 1)) / bytes_per_sect);
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 	    oprintf(OUTPUT_DEBUG,
7610Sstevel@tonic-gate 		    gettext("          "
7620Sstevel@tonic-gate 			    "rounded up to %10.2f blocks\n"),
7630Sstevel@tonic-gate 		    (double)(nsize/bytes_per_sect));
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 	} else {
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate 	    /* VTOC: round size to an integral number of cylinders */
7680Sstevel@tonic-gate 	    uint64_t	nhead = 0;
7690Sstevel@tonic-gate 	    uint64_t	nsect = 0;
7700Sstevel@tonic-gate 	    uint64_t	ncyls = 0;
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate 	    ((error = disk_get_ncylinders(odisk, &ncyls)) != 0) ||
7730Sstevel@tonic-gate 	    (error = disk_get_nheads(odisk, &nhead)) ||
7740Sstevel@tonic-gate 	    (error = disk_get_nsectors(odisk, &nsect));
7750Sstevel@tonic-gate 	    if (error == 0) {
7760Sstevel@tonic-gate 		uint64_t bytes_per_cyl = nhead * nsect * bytes_per_sect;
7770Sstevel@tonic-gate 		nsize = bytes_per_cyl *
7780Sstevel@tonic-gate 		    ((nbytes + (bytes_per_cyl - 1)) / bytes_per_cyl);
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 		if (add_extra_cyl == TRUE) {
7810Sstevel@tonic-gate 		    nsize += bytes_per_cyl;
7820Sstevel@tonic-gate 		}
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 		oprintf(OUTPUT_DEBUG,
7850Sstevel@tonic-gate 			gettext("          "
7860Sstevel@tonic-gate 				"rounded VTOC slice to %10.2f cylinders "
7870Sstevel@tonic-gate 				"(out of %llu)\n"),
7880Sstevel@tonic-gate 			(double)(nsize/bytes_per_cyl), ncyls);
7890Sstevel@tonic-gate 	    }
7900Sstevel@tonic-gate 	}
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate 	/* is sufficient space still available? */
7930Sstevel@tonic-gate 	if (error == 0) {
7940Sstevel@tonic-gate 	    if (osize == nsize) {
7950Sstevel@tonic-gate 		/* use existing slice as is */
7960Sstevel@tonic-gate 		((error = create_devconfig_for_slice(oslice, nslice)) != 0) ||
7970Sstevel@tonic-gate 		(error = disk_reserve_index(odisk, (uint16_t)nindex));
7980Sstevel@tonic-gate 	    } else if (osize > nsize) {
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate 		if (nindex == oindex) {
8010Sstevel@tonic-gate 		    /* no more slices, resize existing slice */
8020Sstevel@tonic-gate 		    ((error = create_devconfig_for_slice(oslice,
8030Sstevel@tonic-gate 			nslice)) != 0) ||
8040Sstevel@tonic-gate 		    (error = devconfig_set_size(*nslice, nsize)) ||
8050Sstevel@tonic-gate 		    (error = devconfig_set_size_in_blocks(*nslice,
8060Sstevel@tonic-gate 			nsize/bytes_per_sect));
8070Sstevel@tonic-gate 		    (error = disk_reserve_index(odisk, (uint16_t)nindex));
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 		} else {
8100Sstevel@tonic-gate 		    /* make a new slice */
8110Sstevel@tonic-gate 		    char *nname = NULL;
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate 		    ((error = make_slicename_for_disk_and_index(odisk,
8140Sstevel@tonic-gate 			nindex, &nname)) != 0) ||
8150Sstevel@tonic-gate 		    (error = create_modified_slice(oslice, oname, oindex,
8160Sstevel@tonic-gate 			ostart, osize, bytes_per_sect, nname, nindex, nsize,
8170Sstevel@tonic-gate 			nslice)) ||
8180Sstevel@tonic-gate 			/* mark the new slice's index as used */
8190Sstevel@tonic-gate 		    (error = disk_reserve_index(odisk, (uint16_t)nindex));
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate 		    if ((error != 0) && (*nslice == NULL)) {
8220Sstevel@tonic-gate 			free(nname);
8230Sstevel@tonic-gate 		    }
8240Sstevel@tonic-gate 		}
8250Sstevel@tonic-gate 	    }
8260Sstevel@tonic-gate 	}
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 	return (error);
8290Sstevel@tonic-gate }
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate /*
8320Sstevel@tonic-gate  * FUNCTION:	create_modified_slice(dm_descriptor_t oslice, char *oname,
8330Sstevel@tonic-gate  *			uint32_t oindex, uint64_t ostart, uint64_t osize,
8340Sstevel@tonic-gate  *			uint64_t bytes_per_sect, uint64_t nsize,
8350Sstevel@tonic-gate  *			char *nname, uint32_t nindex, devconfig_t **nslice)
8360Sstevel@tonic-gate  *
8370Sstevel@tonic-gate  * INPUT:	oslice	- dm_descriptor_t handle for the original slice
8380Sstevel@tonic-gate  *		oname - existing source slice name
8390Sstevel@tonic-gate  *		oindex - existing source slice VTOC index
8400Sstevel@tonic-gate  *		ostart - existing source slice start byte
8410Sstevel@tonic-gate  *		osize - existing source slice size in bytes
8420Sstevel@tonic-gate  *		bytes_per_sect - bytes per block (sector) for the disk
8430Sstevel@tonic-gate  *		nname - new slice name
8440Sstevel@tonic-gate  *		nindex - new slice VTOC index
8450Sstevel@tonic-gate  *		nsize - new slice size in bytes (cylinder and block aligned)
8460Sstevel@tonic-gate  *
8470Sstevel@tonic-gate  * SIDEEFFECTS: updates the module private list of modified slices
8480Sstevel@tonic-gate  *
8490Sstevel@tonic-gate  * OUTPUT:	nslice - pointer to a devconfig_t to hold the new slice
8500Sstevel@tonic-gate  *
8510Sstevel@tonic-gate  * PURPOSE:	create a new VTOC slice by taking space from an
8520Sstevel@tonic-gate  *		existing slice.
8530Sstevel@tonic-gate  *
8540Sstevel@tonic-gate  *		The input size for the new slice is expected to be
8550Sstevel@tonic-gate  *		cylinder aligned.
8560Sstevel@tonic-gate  */
8570Sstevel@tonic-gate static int
create_modified_slice(dm_descriptor_t oslice,char * oname,uint32_t oindex,uint64_t ostart,uint64_t osize,uint64_t bytes_per_sect,char * nname,uint32_t nindex,uint64_t nsize,devconfig_t ** nslice)8580Sstevel@tonic-gate create_modified_slice(
8590Sstevel@tonic-gate 	dm_descriptor_t	oslice,
8600Sstevel@tonic-gate 	char		*oname,
8610Sstevel@tonic-gate 	uint32_t	oindex,
8620Sstevel@tonic-gate 	uint64_t	ostart,
8630Sstevel@tonic-gate 	uint64_t	osize,
8640Sstevel@tonic-gate 	uint64_t	bytes_per_sect,
8650Sstevel@tonic-gate 	char		*nname,
8660Sstevel@tonic-gate 	uint32_t	nindex,
8670Sstevel@tonic-gate 	uint64_t	nsize,
8680Sstevel@tonic-gate 	devconfig_t	**nslice)
8690Sstevel@tonic-gate {
8700Sstevel@tonic-gate 	int		error = 0;
8710Sstevel@tonic-gate 
8720Sstevel@tonic-gate 	/* compute start sector and size in sectors for the new slice */
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate 	/* subtract nsize from original slice to get starting byte */
8750Sstevel@tonic-gate 	uint64_t	nstart = (ostart + osize) - nsize;
8760Sstevel@tonic-gate 
8770Sstevel@tonic-gate 	/* convert starting byte to a sector */
8780Sstevel@tonic-gate 	uint64_t	nstblk = (uint64_t)(nstart / bytes_per_sect);
8790Sstevel@tonic-gate 
8800Sstevel@tonic-gate 	/* convert nsize to an integral number of blocks (sectors) */
8810Sstevel@tonic-gate 	uint64_t	nblks = (uint64_t)(nsize / bytes_per_sect);
8820Sstevel@tonic-gate 
8830Sstevel@tonic-gate 	/* create a modified slice record for the new slice */
8840Sstevel@tonic-gate 	error = assemble_modified_slice(oslice, nname, nindex,
8850Sstevel@tonic-gate 		nstblk, nblks, nsize, nslice);
8860Sstevel@tonic-gate 	if (error != 0) {
8870Sstevel@tonic-gate 	    free(nname);
8880Sstevel@tonic-gate 	    return (error);
8890Sstevel@tonic-gate 	}
8900Sstevel@tonic-gate 
8910Sstevel@tonic-gate 	/* update the existing source slice's new size */
8920Sstevel@tonic-gate 	osize = osize - nsize;
8930Sstevel@tonic-gate 	(void) slice_set_size(oslice, osize);
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate 	/* update/create the modified slice record gfor the source slice */
8960Sstevel@tonic-gate 	error = assemble_modified_slice((dm_descriptor_t)0,
8970Sstevel@tonic-gate 		oname, oindex, (uint64_t)(ostart / bytes_per_sect),
8980Sstevel@tonic-gate 		(uint64_t)(osize / bytes_per_sect),
8990Sstevel@tonic-gate 		osize, NULL);
9000Sstevel@tonic-gate 
9010Sstevel@tonic-gate 	return (error);
9020Sstevel@tonic-gate }
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate /*
9050Sstevel@tonic-gate  * FUNCTION:	assemble_modified_slice(dm_descriptor_t src_slice,
9060Sstevel@tonic-gate  *			char *mod_name,	uint32_t mod_index,
9070Sstevel@tonic-gate  *			uint64_t mod_stblk, uint64_t mod_nblks,
9080Sstevel@tonic-gate  *			uint64_t mod_size, devconfig_t **modslice)
9090Sstevel@tonic-gate  *
9100Sstevel@tonic-gate  * INPUT:	src_slice - dm_descriptor_t handle of the slice space
9110Sstevel@tonic-gate  *			was taken from to create the modified slice
9120Sstevel@tonic-gate  *		mod_name - name of the modified slice
9130Sstevel@tonic-gate  *		mod_index - name of the modified slice
9140Sstevel@tonic-gate  *		mod_stblk - start block of the modified slice
9150Sstevel@tonic-gate  *		mod_nblks - size in blocks of the modified slice
9160Sstevel@tonic-gate  *		mod_size - size in bytes of the modified slice
9170Sstevel@tonic-gate  *
9180Sstevel@tonic-gate  * OUTPUT:	mod_slice	- if non-NULL, will be populated with a
9190Sstevel@tonic-gate  *			devconfig_t representing the modified slice.
9200Sstevel@tonic-gate  *
9210Sstevel@tonic-gate  * SIDEEFFECTS: adds or updates an entry in the modified slice list
9220Sstevel@tonic-gate  *		tracking the slices that have been explicitly modified
9230Sstevel@tonic-gate  *		by the layout code.
9240Sstevel@tonic-gate  *
9250Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
9260Sstevel@tonic-gate  *			 !0 otherwise
9270Sstevel@tonic-gate  *
9280Sstevel@tonic-gate  * PURPOSE:	Utility function to which updates or creates a devconfig_t
9290Sstevel@tonic-gate  *		representing a slice that needs to be modified.
9300Sstevel@tonic-gate  *
9310Sstevel@tonic-gate  *		If a modified slice record does not exist for the named
9320Sstevel@tonic-gate  *		slice, a new devconfig_t struct is allocated and added
9330Sstevel@tonic-gate  *		to the modified slice list.
9340Sstevel@tonic-gate  *
9350Sstevel@tonic-gate  *		The existing or created devconfig_t struct is updated with
9360Sstevel@tonic-gate  *		the input values.
9370Sstevel@tonic-gate  *
9380Sstevel@tonic-gate  *		The information about the slices in the modified slice list
9390Sstevel@tonic-gate  *		will eventually be handed to fmthard.
9400Sstevel@tonic-gate  */
9410Sstevel@tonic-gate int
assemble_modified_slice(dm_descriptor_t src_slice,char * mod_name,uint32_t mod_index,uint64_t mod_stblk,uint64_t mod_nblks,uint64_t mod_size,devconfig_t ** mod_slice)9420Sstevel@tonic-gate assemble_modified_slice(
9430Sstevel@tonic-gate 	dm_descriptor_t	src_slice,
9440Sstevel@tonic-gate 	char		*mod_name,
9450Sstevel@tonic-gate 	uint32_t	mod_index,
9460Sstevel@tonic-gate 	uint64_t	mod_stblk,
9470Sstevel@tonic-gate 	uint64_t	mod_nblks,
9480Sstevel@tonic-gate 	uint64_t	mod_size,
9490Sstevel@tonic-gate 	devconfig_t	**mod_slice)
9500Sstevel@tonic-gate {
9510Sstevel@tonic-gate 	devconfig_t	*slice = NULL;
9520Sstevel@tonic-gate 	modslice_t	*mstp = NULL;
9530Sstevel@tonic-gate 	dlist_t		*item = NULL;
9540Sstevel@tonic-gate 	int		error = 0;
9550Sstevel@tonic-gate 
9560Sstevel@tonic-gate 	/* see if the slice has been modified before */
9570Sstevel@tonic-gate 	if ((item = dlist_find(_modified_slices, mod_name,
9580Sstevel@tonic-gate 	    compare_string_to_modslice_name)) != NULL) {
9590Sstevel@tonic-gate 
9600Sstevel@tonic-gate 	    /* yes, update the resize count and attributes */
9610Sstevel@tonic-gate 	    mstp = (modslice_t *)item->obj;
9620Sstevel@tonic-gate 	    slice = mstp->slice_devcfg;
9630Sstevel@tonic-gate 
9640Sstevel@tonic-gate 	    mstp->times_modified += 1;
9650Sstevel@tonic-gate 	    mstp->src_slice_desc = src_slice;
9660Sstevel@tonic-gate 
9670Sstevel@tonic-gate 	    ((error = devconfig_set_slice_start_block(slice,
9680Sstevel@tonic-gate 		mod_stblk)) != 0) ||
9690Sstevel@tonic-gate 	    (error = devconfig_set_size(slice, mod_size)) ||
9700Sstevel@tonic-gate 	    (error = devconfig_set_size_in_blocks(slice, mod_nblks));
9710Sstevel@tonic-gate 
9720Sstevel@tonic-gate 	} else {
9730Sstevel@tonic-gate 
9740Sstevel@tonic-gate 	    /* no, first modification... */
9750Sstevel@tonic-gate 	    /* create a devconfig_t representing the new slice */
9760Sstevel@tonic-gate 	    ((error = new_devconfig(&slice, TYPE_SLICE)) != 0) ||
9770Sstevel@tonic-gate 	    (error = devconfig_set_name(slice, mod_name)) ||
9780Sstevel@tonic-gate 	    (error = devconfig_set_slice_index(slice, mod_index)) ||
9790Sstevel@tonic-gate 	    (error = devconfig_set_slice_start_block(slice, mod_stblk)) ||
9800Sstevel@tonic-gate 	    (error = devconfig_set_size_in_blocks(slice, mod_nblks)) ||
9810Sstevel@tonic-gate 	    (error = devconfig_set_size(slice, mod_size));
9820Sstevel@tonic-gate 	    if (error == 0) {
9830Sstevel@tonic-gate 		/* add to list of modified slices */
9840Sstevel@tonic-gate 		if ((mstp = (modslice_t *)
9850Sstevel@tonic-gate 		    calloc(1, sizeof (modslice_t))) != NULL) {
9860Sstevel@tonic-gate 
9870Sstevel@tonic-gate 		    /* count # of times source slice has been modified */
9880Sstevel@tonic-gate 		    if (src_slice != (dm_descriptor_t)0) {
9890Sstevel@tonic-gate 			mstp->times_modified = 0;
9900Sstevel@tonic-gate 		    } else {
9910Sstevel@tonic-gate 			mstp->times_modified = 1;
9920Sstevel@tonic-gate 		    }
9930Sstevel@tonic-gate 		    mstp->src_slice_desc = src_slice;
9940Sstevel@tonic-gate 		    mstp->slice_devcfg = slice;
9950Sstevel@tonic-gate 
9960Sstevel@tonic-gate 		    if ((item = dlist_new_item(mstp)) != NULL) {
9970Sstevel@tonic-gate 			_modified_slices =
9980Sstevel@tonic-gate 			    dlist_insert_ordered(
9990Sstevel@tonic-gate 				    item,
10000Sstevel@tonic-gate 				    _modified_slices,
10010Sstevel@tonic-gate 				    ASCENDING,
10020Sstevel@tonic-gate 				    compare_modslice_names);
10030Sstevel@tonic-gate 		    } else {
10040Sstevel@tonic-gate 			error = ENOMEM;
10050Sstevel@tonic-gate 		    }
10060Sstevel@tonic-gate 		} else {
10070Sstevel@tonic-gate 		    error = ENOMEM;
10080Sstevel@tonic-gate 		}
10090Sstevel@tonic-gate 	    }
10100Sstevel@tonic-gate 
10110Sstevel@tonic-gate 	    if (error != 0) {
10120Sstevel@tonic-gate 		free_devconfig(mstp);
10130Sstevel@tonic-gate 		free_devconfig(slice);
10140Sstevel@tonic-gate 	    }
10150Sstevel@tonic-gate 	}
10160Sstevel@tonic-gate 
10170Sstevel@tonic-gate 	if (error == 0) {
10180Sstevel@tonic-gate 	    oprintf(OUTPUT_DEBUG,
10190Sstevel@tonic-gate 		    "          "
10200Sstevel@tonic-gate 		    "modified %s (start blk: %9llu, nblks: %9llu)\n",
10210Sstevel@tonic-gate 		    mod_name, mod_stblk, mod_nblks);
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate 	    /* return devconfig_t for modified slice */
10240Sstevel@tonic-gate 	    if (mod_slice != NULL) {
10250Sstevel@tonic-gate 		*mod_slice = slice;
10260Sstevel@tonic-gate 		mstp->volume_component = B_TRUE;
10270Sstevel@tonic-gate 	    }
10280Sstevel@tonic-gate 	}
10290Sstevel@tonic-gate 
10300Sstevel@tonic-gate 	return (error);
10310Sstevel@tonic-gate }
10320Sstevel@tonic-gate 
10330Sstevel@tonic-gate /*
10340Sstevel@tonic-gate  * FUNCTION:	dlist_t *get_modified_slices()
10350Sstevel@tonic-gate  *
10360Sstevel@tonic-gate  * RETURNS:	pointer to the list of modslice_t structs representing
10370Sstevel@tonic-gate  *		modified slices
10380Sstevel@tonic-gate  *
10390Sstevel@tonic-gate  * PURPOSE:	public accessor to the list of slices modified while
10400Sstevel@tonic-gate  *		processing a request.
10410Sstevel@tonic-gate  */
10420Sstevel@tonic-gate dlist_t *
get_modified_slices()10430Sstevel@tonic-gate get_modified_slices()
10440Sstevel@tonic-gate {
10450Sstevel@tonic-gate 	return (_modified_slices);
10460Sstevel@tonic-gate }
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate /*
10490Sstevel@tonic-gate  * FUNCTION:	free_modslice_object(void *obj)
10500Sstevel@tonic-gate  *
10510Sstevel@tonic-gate  * INPUT:	obj	- opaque pointer
10520Sstevel@tonic-gate  *
10530Sstevel@tonic-gate  * PURPOSE:	Frees memory associated with a modslice_t struct.
10540Sstevel@tonic-gate  */
10550Sstevel@tonic-gate static void
free_modslice_object(void * obj)10560Sstevel@tonic-gate free_modslice_object(
10570Sstevel@tonic-gate 	void	*obj)
10580Sstevel@tonic-gate {
10590Sstevel@tonic-gate 	assert(obj != (modslice_t *)NULL);
10600Sstevel@tonic-gate 
10610Sstevel@tonic-gate 	if (((modslice_t *)obj)->slice_devcfg != NULL) {
10620Sstevel@tonic-gate 	    if (((modslice_t *)obj)->volume_component != B_TRUE) {
10630Sstevel@tonic-gate 		free_devconfig(((modslice_t *)obj)->slice_devcfg);
10640Sstevel@tonic-gate 	    }
10650Sstevel@tonic-gate 	}
10660Sstevel@tonic-gate 
10670Sstevel@tonic-gate 	free(obj);
10680Sstevel@tonic-gate }
10690Sstevel@tonic-gate 
10700Sstevel@tonic-gate /*
10710Sstevel@tonic-gate  * FUNCTION:	void release_modified_slices()
10720Sstevel@tonic-gate  *
10730Sstevel@tonic-gate  * INPUT:	none   -
10740Sstevel@tonic-gate  * OUTPUT:	none   -
10750Sstevel@tonic-gate  *
10760Sstevel@tonic-gate  * PURPOSE:	cleanup the module global list of slices modified
10770Sstevel@tonic-gate  *		while processing a request.
10780Sstevel@tonic-gate  */
10790Sstevel@tonic-gate int
release_modified_slices()10800Sstevel@tonic-gate release_modified_slices()
10810Sstevel@tonic-gate {
10820Sstevel@tonic-gate 	dlist_free_items(_modified_slices, free_modslice_object);
10830Sstevel@tonic-gate 	_modified_slices = NULL;
10840Sstevel@tonic-gate 
10850Sstevel@tonic-gate 	return (0);
10860Sstevel@tonic-gate }
10870Sstevel@tonic-gate 
10880Sstevel@tonic-gate /*
10890Sstevel@tonic-gate  * FUNCTION:	destroy_new_slice(devconfig_t *dev)
10900Sstevel@tonic-gate  *
10910Sstevel@tonic-gate  * INPUT:	dev	- a devconfig_t pointer to a slice object
10920Sstevel@tonic-gate  *
10930Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
10940Sstevel@tonic-gate  *			 !0 otherwise
10950Sstevel@tonic-gate  *
10960Sstevel@tonic-gate  * PURPOSE:	Undoes slice creation done by create_new_slice():
10970Sstevel@tonic-gate  *
10980Sstevel@tonic-gate  *		release index
10990Sstevel@tonic-gate  *		remove from used_slices
11000Sstevel@tonic-gate  *		remove from modified_slices
11010Sstevel@tonic-gate  *		return space to source slice
11020Sstevel@tonic-gate  *		free memory
11030Sstevel@tonic-gate  */
11040Sstevel@tonic-gate int
destroy_new_slice(devconfig_t * dev)11050Sstevel@tonic-gate destroy_new_slice(
11060Sstevel@tonic-gate 	devconfig_t	*dev)
11070Sstevel@tonic-gate {
11080Sstevel@tonic-gate 	dm_descriptor_t disk = NULL;
11090Sstevel@tonic-gate 	uint64_t	size = 0;
11100Sstevel@tonic-gate 	uint16_t	index = 0;
11110Sstevel@tonic-gate 	modslice_t	*modified = NULL;
11120Sstevel@tonic-gate 	dlist_t		*item = NULL;
11130Sstevel@tonic-gate 	char		*name = NULL;
11140Sstevel@tonic-gate 	int		error = 0;
11150Sstevel@tonic-gate 
11160Sstevel@tonic-gate 	((error = devconfig_get_name(dev, &name)) != 0) ||
11170Sstevel@tonic-gate 	(error = devconfig_get_slice_index(dev, &index)) ||
11180Sstevel@tonic-gate 	(error = devconfig_get_size(dev, &size)) ||
11190Sstevel@tonic-gate 	(error = get_disk_for_named_slice(name, &disk)) ||
11200Sstevel@tonic-gate 	(error = disk_release_index(disk, index)) ||
11210Sstevel@tonic-gate 	(error = remove_used_slice_by_name(name));
11220Sstevel@tonic-gate 	if (error != 0) {
11230Sstevel@tonic-gate 	    return (error);
11240Sstevel@tonic-gate 	}
11250Sstevel@tonic-gate 
11260Sstevel@tonic-gate 	/* remove from the modified_slices list */
11270Sstevel@tonic-gate 	_modified_slices =
11280Sstevel@tonic-gate 	    dlist_remove_equivalent_item(
11290Sstevel@tonic-gate 		    _modified_slices, name,
11300Sstevel@tonic-gate 		    compare_string_to_modslice_name, &item);
11310Sstevel@tonic-gate 
11320Sstevel@tonic-gate 	if (item != NULL) {
11330Sstevel@tonic-gate 	    modified = (modslice_t *)item->obj;
11340Sstevel@tonic-gate 	    free((void*) item);
11350Sstevel@tonic-gate 	}
11360Sstevel@tonic-gate 
11370Sstevel@tonic-gate 	/* space from an existing slice? if so reclaim it. */
11380Sstevel@tonic-gate 	if (modified != NULL) {
11390Sstevel@tonic-gate 
11400Sstevel@tonic-gate 	    dm_descriptor_t src = modified->src_slice_desc;
11410Sstevel@tonic-gate 	    char	*srcname = NULL;
11420Sstevel@tonic-gate 	    dlist_t	*srcitem = NULL;
11430Sstevel@tonic-gate 
11440Sstevel@tonic-gate 	    if (src != (dm_descriptor_t)0) {
11450Sstevel@tonic-gate 		if ((error = get_display_name(src, &srcname)) == 0) {
11460Sstevel@tonic-gate 		    srcitem =
11470Sstevel@tonic-gate 			dlist_find(
11480Sstevel@tonic-gate 				_modified_slices,
11490Sstevel@tonic-gate 				srcname,
11500Sstevel@tonic-gate 				compare_string_to_modslice_name);
11510Sstevel@tonic-gate 		}
11520Sstevel@tonic-gate 	    }
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate 	    if ((error == 0) && (srcitem != NULL)) {
11550Sstevel@tonic-gate 
11560Sstevel@tonic-gate 		modslice_t	*source = (modslice_t *)srcitem->obj;
11570Sstevel@tonic-gate 		devconfig_t	*srcdevcfg = NULL;
11580Sstevel@tonic-gate 		uint64_t	srcsize = NULL;
11590Sstevel@tonic-gate 		uint64_t	srcsizeblks = NULL;
11600Sstevel@tonic-gate 		uint64_t	inblks = NULL;
11610Sstevel@tonic-gate 
11620Sstevel@tonic-gate 		srcdevcfg = source->slice_devcfg;
11630Sstevel@tonic-gate 		source->times_modified -= 1;
11640Sstevel@tonic-gate 
11650Sstevel@tonic-gate 		((error = devconfig_get_size(srcdevcfg, &srcsize)) != 0) ||
11660Sstevel@tonic-gate 		(error = devconfig_set_size(srcdevcfg, srcsize + size)) ||
11670Sstevel@tonic-gate 		(error = slice_set_size(src, srcsize + size)) ||
11680Sstevel@tonic-gate 		(error = slice_get_size_in_blocks(src, &srcsizeblks)) ||
11690Sstevel@tonic-gate 		(error = devconfig_get_size_in_blocks(srcdevcfg, &inblks));
11700Sstevel@tonic-gate 		(error = devconfig_set_size_in_blocks(srcdevcfg, srcsizeblks));
11710Sstevel@tonic-gate 
11720Sstevel@tonic-gate 		if (error == 0) {
11730Sstevel@tonic-gate 
11740Sstevel@tonic-gate 		    /* was only modification undone? */
11750Sstevel@tonic-gate 		    if (source->times_modified == 0) {
11760Sstevel@tonic-gate 
11770Sstevel@tonic-gate 			_modified_slices =
11780Sstevel@tonic-gate 			    dlist_remove_equivalent_item(
11790Sstevel@tonic-gate 				    _modified_slices, srcname,
11800Sstevel@tonic-gate 				    compare_string_to_modslice_name,
11810Sstevel@tonic-gate 				    &srcitem);
11820Sstevel@tonic-gate 
11830Sstevel@tonic-gate 			free_modslice_object((modslice_t *)srcitem->obj);
11840Sstevel@tonic-gate 			free((void *)srcitem);
11850Sstevel@tonic-gate 		    }
11860Sstevel@tonic-gate 		}
11870Sstevel@tonic-gate 	    }
11880Sstevel@tonic-gate 
11890Sstevel@tonic-gate 	    free_modslice_object(modified);
11900Sstevel@tonic-gate 	}
11910Sstevel@tonic-gate 
11920Sstevel@tonic-gate 	return (error);
11930Sstevel@tonic-gate }
11940Sstevel@tonic-gate 
11950Sstevel@tonic-gate /*
11960Sstevel@tonic-gate  * FUNCTION:	pick_from_best_hba_and_disk(dlist_t *slices,
11970Sstevel@tonic-gate  *			dlist_t *used, dm_descriptor_t *chosen)
11980Sstevel@tonic-gate  *
11990Sstevel@tonic-gate  * INPUT:	slices	- a dlist_t poitner to a list of slices
12000Sstevel@tonic-gate  *		used	- a dlist_t pointer to a list of used slices
12010Sstevel@tonic-gate  *		chosen  - a dm_descriptor_t pointer to hold the result
12020Sstevel@tonic-gate  *
12030Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
12040Sstevel@tonic-gate  *			 !0 otherwise
12050Sstevel@tonic-gate  *
12060Sstevel@tonic-gate  * PURPOSE:	Examines the input list of slices and chooses the one
12070Sstevel@tonic-gate  *		that is on the least used HBA and disk.
12080Sstevel@tonic-gate  *
12090Sstevel@tonic-gate  *		HBA and disk usage is determined by examining the input
12100Sstevel@tonic-gate  *		list of used slices and counting the number of slices
12110Sstevel@tonic-gate  *		each HBA and disk contributes.
12120Sstevel@tonic-gate  *
12130Sstevel@tonic-gate  * 		The HBA which contributes the fewest is selected, and
12140Sstevel@tonic-gate  *		then the disk on that HBA which contributes the fewest
12150Sstevel@tonic-gate  *		is selected.
12160Sstevel@tonic-gate  *
12170Sstevel@tonic-gate  *		The largest slice from that disk is then returned.
12180Sstevel@tonic-gate  */
12190Sstevel@tonic-gate static int
pick_from_best_hba_and_disk(dlist_t * slices,dlist_t * used,dm_descriptor_t * chosen)12200Sstevel@tonic-gate pick_from_best_hba_and_disk(
12210Sstevel@tonic-gate 	dlist_t		*slices,
12220Sstevel@tonic-gate 	dlist_t		*used,
12230Sstevel@tonic-gate 	dm_descriptor_t *chosen)
12240Sstevel@tonic-gate {
12250Sstevel@tonic-gate 	dlist_t		*iter = NULL;
12260Sstevel@tonic-gate 	dlist_t		*iter1 = NULL;
12270Sstevel@tonic-gate 	dlist_t		*iter2 = NULL;
12280Sstevel@tonic-gate 	dlist_t		*item = NULL;
12290Sstevel@tonic-gate 
12300Sstevel@tonic-gate 	dlist_t		*used_slice_hbas = NULL;
12310Sstevel@tonic-gate 
12320Sstevel@tonic-gate 	int		maxuses = 128;
12330Sstevel@tonic-gate 	int		maxslices = VTOC_SIZE;  /* meta.h */
12340Sstevel@tonic-gate 
12350Sstevel@tonic-gate 	int		i = 0;
12360Sstevel@tonic-gate 	int 		error = 0;
12370Sstevel@tonic-gate 
12380Sstevel@tonic-gate 	/*
12390Sstevel@tonic-gate 	 * allocate an array to hold lists of slices grouped by
12400Sstevel@tonic-gate 	 * HBA contribution... the list indexed by N is the list
12410Sstevel@tonic-gate 	 * of slices that are on HBAs contributing N slices
12420Sstevel@tonic-gate 	 */
12430Sstevel@tonic-gate 	dlist_t **prefhbas = (dlist_t **)calloc(maxuses, sizeof (dlist_t *));
12440Sstevel@tonic-gate 
12450Sstevel@tonic-gate 	/*
12460Sstevel@tonic-gate 	 * allocate an array to hold lists of slices grouped by
12470Sstevel@tonic-gate 	 * disk contribution... the list indexed by N is the list
12480Sstevel@tonic-gate 	 * of slices that are on disks contributing N slices
12490Sstevel@tonic-gate 	 */
12500Sstevel@tonic-gate 	dlist_t **prefdisks = (dlist_t **)calloc(maxslices, sizeof (dlist_t *));
12510Sstevel@tonic-gate 
12520Sstevel@tonic-gate 	*chosen = (dm_descriptor_t)0;
12530Sstevel@tonic-gate 
12540Sstevel@tonic-gate 	if (prefhbas == NULL || prefdisks == NULL) {
12550Sstevel@tonic-gate 	    free(prefhbas);
12560Sstevel@tonic-gate 	    free(prefdisks);
12570Sstevel@tonic-gate 	    return (ENOMEM);
12580Sstevel@tonic-gate 	}
12590Sstevel@tonic-gate 
12600Sstevel@tonic-gate 	/*
12610Sstevel@tonic-gate 	 * precompute the used slices' lists of HBAS: iterate the list
12620Sstevel@tonic-gate 	 * of used slices and determine the HBA(s) each is connected thru.
12630Sstevel@tonic-gate 	 * construct a list of lists containing the HBAs.
12640Sstevel@tonic-gate 	 */
12650Sstevel@tonic-gate 	for (iter = used;
12660Sstevel@tonic-gate 	    (iter != NULL) && (error == 0);
12670Sstevel@tonic-gate 	    iter = iter->next) {
12680Sstevel@tonic-gate 
12690Sstevel@tonic-gate 	    devconfig_t	*uslice = (devconfig_t *)iter->obj;
12700Sstevel@tonic-gate 	    dm_descriptor_t udisk = NULL;
12710Sstevel@tonic-gate 	    char	*uname = NULL;
12720Sstevel@tonic-gate 	    dlist_t	*uhbas = NULL;
12730Sstevel@tonic-gate 
12740Sstevel@tonic-gate 	    /* need to use disk to get to HBAs because */
12750Sstevel@tonic-gate 	    /* the slice doesn't exist yet */
12760Sstevel@tonic-gate 	    ((error = devconfig_get_name(uslice, &uname)) != 0) ||
12770Sstevel@tonic-gate 	    (error = get_disk_for_named_slice(uname, &udisk)) ||
12780Sstevel@tonic-gate 	    (error = disk_get_hbas(udisk, &uhbas));
12790Sstevel@tonic-gate 	    if (error == 0) {
12800Sstevel@tonic-gate 		if ((item = dlist_new_item((void *)uhbas)) == NULL) {
12810Sstevel@tonic-gate 		    error = ENOMEM;
12820Sstevel@tonic-gate 		} else {
12830Sstevel@tonic-gate 		    used_slice_hbas = dlist_append(
12840Sstevel@tonic-gate 			    item, used_slice_hbas, AT_HEAD);
12850Sstevel@tonic-gate 		}
12860Sstevel@tonic-gate 	    }
12870Sstevel@tonic-gate 	}
12880Sstevel@tonic-gate 
12890Sstevel@tonic-gate 	/*
12900Sstevel@tonic-gate 	 * iterate the list of chosen slices and for each,
12910Sstevel@tonic-gate 	 * determine how many other slices from its HBA(s)
12920Sstevel@tonic-gate 	 * are already being used...
12930Sstevel@tonic-gate 	 *
12940Sstevel@tonic-gate 	 * iter steps thru the list of slices
12950Sstevel@tonic-gate 	 * iter1 steps thru each of the slice's HBAs
12960Sstevel@tonic-gate 	 * iter2 steps thru the precomputed list of used slice's HBAs
12970Sstevel@tonic-gate 	 * dlist_contains then searches each used slice's HBAs
12980Sstevel@tonic-gate 	 *   to see if it contains iter1's HBA
12990Sstevel@tonic-gate 	 *
13000Sstevel@tonic-gate 	 * If it does, increment the count for that HBA.
13010Sstevel@tonic-gate 	 */
13020Sstevel@tonic-gate 	for (iter = slices;
13030Sstevel@tonic-gate 	    (iter != NULL) && (error == 0);
13040Sstevel@tonic-gate 	    iter = iter->next) {
13050Sstevel@tonic-gate 
13060Sstevel@tonic-gate 	    dm_descriptor_t slice = (uintptr_t)iter->obj;
13070Sstevel@tonic-gate 	    dlist_t	*hbas = NULL;
13080Sstevel@tonic-gate 	    int		n = 0; /* # slices each HBA contributes */
13090Sstevel@tonic-gate 
13100Sstevel@tonic-gate 	    if ((error = slice_get_hbas(slice, &hbas)) != 0) {
13110Sstevel@tonic-gate 		continue;
13120Sstevel@tonic-gate 	    }
13130Sstevel@tonic-gate 
13140Sstevel@tonic-gate 	    for (iter1 = hbas; iter1 != NULL; iter1 = iter1->next) {
13150Sstevel@tonic-gate 		for (iter2 = used_slice_hbas; iter2 != NULL;
13160Sstevel@tonic-gate 		    iter2 = iter2->next) {
13170Sstevel@tonic-gate 
13180Sstevel@tonic-gate 		    dlist_t *uhbas = (dlist_t *)iter2->obj;
13190Sstevel@tonic-gate 		    if (dlist_contains(uhbas, iter1->obj,
13200Sstevel@tonic-gate 				compare_descriptor_names) == B_TRUE) {
13210Sstevel@tonic-gate 			n++;
13220Sstevel@tonic-gate 		    }
13230Sstevel@tonic-gate 		}
13240Sstevel@tonic-gate 	    }
13250Sstevel@tonic-gate 
13260Sstevel@tonic-gate 	    dlist_free_items(hbas, NULL);
13270Sstevel@tonic-gate 
13280Sstevel@tonic-gate 	    /* group slices from HBAs contributing more than maxuses */
13290Sstevel@tonic-gate 	    if (n >= maxuses) {
13300Sstevel@tonic-gate 		n = maxuses - 1;
13310Sstevel@tonic-gate 	    }
13320Sstevel@tonic-gate 
13330Sstevel@tonic-gate 	    /* add slice to list in descending size order */
1334*62Sjeanm 	    if ((item = dlist_new_item((void*)(uintptr_t)slice)) == NULL) {
13350Sstevel@tonic-gate 		error = ENOMEM;
13360Sstevel@tonic-gate 	    } else {
13370Sstevel@tonic-gate 		prefhbas[n] =
13380Sstevel@tonic-gate 		    dlist_insert_ordered(
13390Sstevel@tonic-gate 			    item,
13400Sstevel@tonic-gate 			    prefhbas[n],
13410Sstevel@tonic-gate 			    DESCENDING,
13420Sstevel@tonic-gate 			    compare_slice_sizes);
13430Sstevel@tonic-gate 	    }
13440Sstevel@tonic-gate 	}
13450Sstevel@tonic-gate 
13460Sstevel@tonic-gate 	/* free list of lists of used slices HBAs */
13470Sstevel@tonic-gate 	for (iter = used_slice_hbas; iter != NULL; iter = iter->next) {
13480Sstevel@tonic-gate 	    dlist_free_items((dlist_t *)iter->obj, NULL);
13490Sstevel@tonic-gate 	}
13500Sstevel@tonic-gate 	dlist_free_items(used_slice_hbas, NULL);
13510Sstevel@tonic-gate 
13520Sstevel@tonic-gate 	/*
13530Sstevel@tonic-gate 	 * Select the list of slices that are on the HBA(s) contributing
13540Sstevel@tonic-gate 	 * the fewest slices... iterate these slices and for each, detemmine
13550Sstevel@tonic-gate 	 * how many other slices from its disk are already being used...
13560Sstevel@tonic-gate 	 */
13570Sstevel@tonic-gate 	for (i = 0; (i < maxuses) && (error == 0); i++) {
13580Sstevel@tonic-gate 
13590Sstevel@tonic-gate 	    for (iter = (dlist_t *)prefhbas[i];
13600Sstevel@tonic-gate 		(iter != NULL) && (error == 0);
13610Sstevel@tonic-gate 		iter = iter->next) {
13620Sstevel@tonic-gate 
13630Sstevel@tonic-gate 		dm_descriptor_t slice = (uintptr_t)iter->obj;
13640Sstevel@tonic-gate 		dm_descriptor_t disk;
13650Sstevel@tonic-gate 		int		n = 0;
13660Sstevel@tonic-gate 
13670Sstevel@tonic-gate 		(void) slice_get_disk(slice, &disk);
13680Sstevel@tonic-gate 
13690Sstevel@tonic-gate 		/*
13700Sstevel@tonic-gate 		 * count how many slices this slice's disk is contributing
13710Sstevel@tonic-gate 		 * by comparing it to the list of used slices
13720Sstevel@tonic-gate 		 */
13730Sstevel@tonic-gate 		for (iter1 = _used_slices; iter1 != NULL; iter1 = iter1->next) {
13740Sstevel@tonic-gate 		    usedslice_t *used = (usedslice_t *)iter1->obj;
1375*62Sjeanm 		    if (compare_descriptors((void *)(uintptr_t)disk,
1376*62Sjeanm 			(void *)(uintptr_t)used->disk) == 0) {
13770Sstevel@tonic-gate 			n++;
13780Sstevel@tonic-gate 		    }
13790Sstevel@tonic-gate 		}
13800Sstevel@tonic-gate 
13810Sstevel@tonic-gate 		/* add slice to list in descending size order */
1382*62Sjeanm 		if ((item = dlist_new_item((void *)(uintptr_t)slice)) == NULL) {
13830Sstevel@tonic-gate 		    error = ENOMEM;
13840Sstevel@tonic-gate 		} else {
13850Sstevel@tonic-gate 		    prefdisks[n] =
13860Sstevel@tonic-gate 			dlist_insert_ordered(
13870Sstevel@tonic-gate 				item,
13880Sstevel@tonic-gate 				prefdisks[n],
13890Sstevel@tonic-gate 				DESCENDING,
13900Sstevel@tonic-gate 				compare_slice_sizes);
13910Sstevel@tonic-gate 		}
13920Sstevel@tonic-gate 	    }
13930Sstevel@tonic-gate 	}
13940Sstevel@tonic-gate 
13950Sstevel@tonic-gate 	if (error == 0) {
13960Sstevel@tonic-gate 	    /* select largest slice from least used disk */
13970Sstevel@tonic-gate 	    for (i = 0; (i < maxslices) && (*chosen == NULL); i++) {
13980Sstevel@tonic-gate 		if (prefdisks[i] != NULL) {
13990Sstevel@tonic-gate 		    *chosen = (uintptr_t)prefdisks[i]->obj;
14000Sstevel@tonic-gate 		}
14010Sstevel@tonic-gate 	    }
14020Sstevel@tonic-gate 	}
14030Sstevel@tonic-gate 
14040Sstevel@tonic-gate 	for (i = 0; i < maxuses; i++) {
14050Sstevel@tonic-gate 	    dlist_free_items(prefhbas[i], NULL);
14060Sstevel@tonic-gate 	}
14070Sstevel@tonic-gate 	for (i = 0; i < maxslices; i++) {
14080Sstevel@tonic-gate 	    dlist_free_items(prefdisks[i], NULL);
14090Sstevel@tonic-gate 	}
14100Sstevel@tonic-gate 
14110Sstevel@tonic-gate 	free((void*)prefhbas);
14120Sstevel@tonic-gate 	free((void*)prefdisks);
14130Sstevel@tonic-gate 
14140Sstevel@tonic-gate 	return (error);
14150Sstevel@tonic-gate }
14160Sstevel@tonic-gate 
14170Sstevel@tonic-gate /*
14180Sstevel@tonic-gate  * FUNCTION:	slice_on_unique_hba(dm_descriptor_t slice,
14190Sstevel@tonic-gate  *			dlist_t *used, dlist_t *used_hbas,
14200Sstevel@tonic-gate  *			boolean_t *unique)
14210Sstevel@tonic-gate  *
14220Sstevel@tonic-gate  * INPUT:	slice	- a dm_descriptor_t handle for the slice of interest
14230Sstevel@tonic-gate  *		used	- a dlist_t pointer to a list of used slices
14240Sstevel@tonic-gate  *		used_hbas - a dlist_t pointer to a list of used_hbas
14250Sstevel@tonic-gate  *		unique	- a boolean_t pointer to hold the result
14260Sstevel@tonic-gate  *
14270Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
14280Sstevel@tonic-gate  *			 !0 otherwise
14290Sstevel@tonic-gate  *
14300Sstevel@tonic-gate  * PURPOSE:	Determines if the input slice is connected thru the same HBA
14310Sstevel@tonic-gate  *		as a slice in the used list.
14320Sstevel@tonic-gate  *
14330Sstevel@tonic-gate  *		Also checks to see if the input slice is connected thru any
14340Sstevel@tonic-gate  *		HBA in the used_hbas list.
14350Sstevel@tonic-gate  *
14360Sstevel@tonic-gate  *		If the slice is found to be on a unique HBA, bool is set
14370Sstevel@tonic-gate  *		to B_TRUE, B_FALSE otherwise.
14380Sstevel@tonic-gate  */
14390Sstevel@tonic-gate static int
slice_on_unique_hba(dm_descriptor_t slice,dlist_t * used,dlist_t * used_hbas,boolean_t * unique)14400Sstevel@tonic-gate slice_on_unique_hba(
14410Sstevel@tonic-gate 	dm_descriptor_t	slice,
14420Sstevel@tonic-gate 	dlist_t		*used,
14430Sstevel@tonic-gate 	dlist_t		*used_hbas,
14440Sstevel@tonic-gate 	boolean_t	*unique)
14450Sstevel@tonic-gate {
14460Sstevel@tonic-gate 	dlist_t		*iter	= NULL;
14470Sstevel@tonic-gate 	dlist_t		*iter1	= NULL;
14480Sstevel@tonic-gate 
14490Sstevel@tonic-gate 	dlist_t		*hbas = NULL;
14500Sstevel@tonic-gate 
14510Sstevel@tonic-gate 	int		error	= 0;
14520Sstevel@tonic-gate 
14530Sstevel@tonic-gate 	*unique = B_TRUE;
14540Sstevel@tonic-gate 
14550Sstevel@tonic-gate 	if ((error = slice_get_hbas(slice, &hbas)) != 0) {
14560Sstevel@tonic-gate 	    return (error);
14570Sstevel@tonic-gate 	}
14580Sstevel@tonic-gate 
14590Sstevel@tonic-gate 	/*
14600Sstevel@tonic-gate 	 * check to see if any of slice's HBAs is the same
14610Sstevel@tonic-gate 	 * as the HBA for any of the used
14620Sstevel@tonic-gate 	 */
14630Sstevel@tonic-gate 	for (iter = used;
14640Sstevel@tonic-gate 	    (iter != NULL) && (*unique == B_TRUE) && (error == 0);
14650Sstevel@tonic-gate 	    iter = iter->next) {
14660Sstevel@tonic-gate 
14670Sstevel@tonic-gate 	    devconfig_t	*dev = (devconfig_t *)iter->obj;
14680Sstevel@tonic-gate 	    if (devconfig_isA(dev, TYPE_SLICE)) {
14690Sstevel@tonic-gate 
14700Sstevel@tonic-gate 		dm_descriptor_t	odisk = NULL;
14710Sstevel@tonic-gate 		char		*oname = NULL;
14720Sstevel@tonic-gate 		dlist_t		*ohbas = NULL;
14730Sstevel@tonic-gate 
14740Sstevel@tonic-gate 		/* get HBAs for other slice using its disk */
14750Sstevel@tonic-gate 		/* because the slice doesn't exist yet. */
14760Sstevel@tonic-gate 		((error = devconfig_get_name(dev, &oname)) != 0) ||
14770Sstevel@tonic-gate 		(error = get_disk_for_named_slice(oname, &odisk)) ||
14780Sstevel@tonic-gate 		(error = disk_get_hbas(odisk, &ohbas));
14790Sstevel@tonic-gate 
14800Sstevel@tonic-gate 		/* any HBA overlap? */
14810Sstevel@tonic-gate 		for (iter1 = hbas;
14820Sstevel@tonic-gate 		    (iter1 != NULL) && (*unique == B_TRUE) && (error == 0);
14830Sstevel@tonic-gate 		    iter1 = iter1->next) {
14840Sstevel@tonic-gate 
14850Sstevel@tonic-gate 		    if (dlist_contains(ohbas, iter1->obj,
14860Sstevel@tonic-gate 				compare_descriptor_names) == B_TRUE) {
14870Sstevel@tonic-gate 			*unique = B_FALSE;
14880Sstevel@tonic-gate 		    }
14890Sstevel@tonic-gate 		}
14900Sstevel@tonic-gate 		dlist_free_items(ohbas, NULL);
14910Sstevel@tonic-gate 	    }
14920Sstevel@tonic-gate 	}
14930Sstevel@tonic-gate 
14940Sstevel@tonic-gate 	/*
14950Sstevel@tonic-gate 	 * check to see if any of slice's HBAs is the contained
14960Sstevel@tonic-gate 	 * in the list of used hbas
14970Sstevel@tonic-gate 	 */
14980Sstevel@tonic-gate 	for (iter = hbas;
14990Sstevel@tonic-gate 	    (iter != NULL) && (*unique == B_TRUE) && (error == 0);
15000Sstevel@tonic-gate 	    iter = iter->next) {
15010Sstevel@tonic-gate 	    if (dlist_contains(used_hbas,
15020Sstevel@tonic-gate 		iter->obj, compare_descriptor_names) == B_TRUE) {
15030Sstevel@tonic-gate 		*unique = B_FALSE;
15040Sstevel@tonic-gate 	    }
15050Sstevel@tonic-gate 	}
15060Sstevel@tonic-gate 
15070Sstevel@tonic-gate 	dlist_free_items(hbas, NULL);
15080Sstevel@tonic-gate 
15090Sstevel@tonic-gate 	return (error);
15100Sstevel@tonic-gate }
15110Sstevel@tonic-gate 
15120Sstevel@tonic-gate /*
15130Sstevel@tonic-gate  * FUNCTION:	slice_on_unique_disk(dm_descriptor_t slice,
15140Sstevel@tonic-gate  *			dlist_t *used, dlist_t *used_disks,
15150Sstevel@tonic-gate  *			boolean_t *unique)
15160Sstevel@tonic-gate  *
15170Sstevel@tonic-gate  * INPUT:	slice	- a dm_descriptor_t handle for the slice of interest
15180Sstevel@tonic-gate  *		used	- a dlist_t pointer to a list of used slices
15190Sstevel@tonic-gate  *		othervols - a dlist_t pointer to a list of other volumes
15200Sstevel@tonic-gate  *		bool	- a boolean_t pointer to hold the result
15210Sstevel@tonic-gate  *
15220Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
15230Sstevel@tonic-gate  *			 !0 otherwise
15240Sstevel@tonic-gate  *
15250Sstevel@tonic-gate  * PURPOSE:	Determines if the input slice is on a drive that is not
15260Sstevel@tonic-gate  *		part of any volume in the othervols list, or on the same
15270Sstevel@tonic-gate  *		drive as any slice in the used list.
15280Sstevel@tonic-gate  *
15290Sstevel@tonic-gate  *		If the slice is found to be on a unique disk, bool is set
15300Sstevel@tonic-gate  *		to B_TRUE, B_FALSE otherwise.
15310Sstevel@tonic-gate  */
15320Sstevel@tonic-gate static int
slice_on_unique_disk(dm_descriptor_t slice,dlist_t * used,dlist_t * used_disks,boolean_t * unique)15330Sstevel@tonic-gate slice_on_unique_disk(
15340Sstevel@tonic-gate 	dm_descriptor_t	slice,
15350Sstevel@tonic-gate 	dlist_t		*used,
15360Sstevel@tonic-gate 	dlist_t		*used_disks,
15370Sstevel@tonic-gate 	boolean_t	*unique)
15380Sstevel@tonic-gate {
15390Sstevel@tonic-gate 	dm_descriptor_t	disk = NULL;
15400Sstevel@tonic-gate 	dlist_t		*iter = NULL;
15410Sstevel@tonic-gate 	int		error = 0;
15420Sstevel@tonic-gate 
15430Sstevel@tonic-gate 	*unique = B_TRUE;
15440Sstevel@tonic-gate 
15450Sstevel@tonic-gate 	if ((error = slice_get_disk(slice, &disk)) != 0) {
15460Sstevel@tonic-gate 	    return (error);
15470Sstevel@tonic-gate 	}
15480Sstevel@tonic-gate 
15490Sstevel@tonic-gate 	/*
15500Sstevel@tonic-gate 	 * check to see if this disk is the same as the
15510Sstevel@tonic-gate 	 * disk for any of the used
15520Sstevel@tonic-gate 	 */
15530Sstevel@tonic-gate 	for (iter = used;
15540Sstevel@tonic-gate 	    (iter != NULL) && (*unique == B_TRUE) && (error == 0);
15550Sstevel@tonic-gate 	    iter = iter->next) {
15560Sstevel@tonic-gate 
15570Sstevel@tonic-gate 	    devconfig_t	*dev = (devconfig_t *)iter->obj;
15580Sstevel@tonic-gate 
15590Sstevel@tonic-gate 	    if (devconfig_isA(dev, TYPE_SLICE)) {
15600Sstevel@tonic-gate 
15610Sstevel@tonic-gate 		/* get disk for otherslice */
15620Sstevel@tonic-gate 		dm_descriptor_t	odisk = NULL;
15630Sstevel@tonic-gate 		char		*oname = NULL;
15640Sstevel@tonic-gate 
15650Sstevel@tonic-gate 		((error = devconfig_get_name(dev, &oname)) != 0) ||
15660Sstevel@tonic-gate 		(error = get_disk_for_named_slice(oname, &odisk));
15670Sstevel@tonic-gate 
15680Sstevel@tonic-gate 		if ((error == 0) &&
1569*62Sjeanm 			(compare_descriptor_names((void*)(uintptr_t)disk,
1570*62Sjeanm 			    (void*)(uintptr_t)odisk) == 0)) {
15710Sstevel@tonic-gate 		    /* origslice is on same disk, stop */
15720Sstevel@tonic-gate 		    *unique = B_FALSE;
15730Sstevel@tonic-gate 		}
15740Sstevel@tonic-gate 	    }
15750Sstevel@tonic-gate 	}
15760Sstevel@tonic-gate 
15770Sstevel@tonic-gate 	/* check disk against the used disks */
15780Sstevel@tonic-gate 	if ((error == 0) && (*unique == B_TRUE) &&
1579*62Sjeanm 		dlist_contains(used_disks, (void *)(uintptr_t)disk,
15800Sstevel@tonic-gate 			compare_descriptor_names) == B_TRUE) {
15810Sstevel@tonic-gate 		*unique = B_FALSE;
15820Sstevel@tonic-gate 	}
15830Sstevel@tonic-gate 
15840Sstevel@tonic-gate 	return (error);
15850Sstevel@tonic-gate }
15860Sstevel@tonic-gate 
15870Sstevel@tonic-gate /*
15880Sstevel@tonic-gate  * FUNCTION:	slice_has_same_disk_geom(dm_descriptor_t slice,
15890Sstevel@tonic-gate  *			dlist_t *used, boolean_t *has_same_geom)
15900Sstevel@tonic-gate  *
15910Sstevel@tonic-gate  * INPUT:	slice	- a dm_descriptor_t handle for the slice of interest
15920Sstevel@tonic-gate  *		used	- a dlist_t pointer to a list of used slices
15930Sstevel@tonic-gate  *		bool	- a boolean_t pointer to hold the result
15940Sstevel@tonic-gate  *
15950Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
15960Sstevel@tonic-gate  *			 !0 otherwise
15970Sstevel@tonic-gate  *
15980Sstevel@tonic-gate  * PURPOSE:	Determines if the input slice is on a drive with similar
15990Sstevel@tonic-gate  *		hardware geometry as the slices in the used list.
16000Sstevel@tonic-gate  *
16010Sstevel@tonic-gate  *		If the slice is found to be on a disk with similar geometry,
16020Sstevel@tonic-gate  *		bool is set to B_TRUE, B_FALSE otherwise.
16030Sstevel@tonic-gate  *
16040Sstevel@tonic-gate  *		The comparison is based on the available disk geometry
16050Sstevel@tonic-gate  *		information which may not be relevant or accurate for
16060Sstevel@tonic-gate  *		EFI labeled disks, so the disk drive type needs to be
16070Sstevel@tonic-gate  *		checked	as well.
16080Sstevel@tonic-gate  */
16090Sstevel@tonic-gate static int
slice_has_same_disk_geom(dm_descriptor_t slice,dlist_t * used,boolean_t * has_same_geom)16100Sstevel@tonic-gate slice_has_same_disk_geom(
16110Sstevel@tonic-gate 	dm_descriptor_t	slice,
16120Sstevel@tonic-gate 	dlist_t		*used,
16130Sstevel@tonic-gate 	boolean_t	*has_same_geom)
16140Sstevel@tonic-gate {
16150Sstevel@tonic-gate 	dm_descriptor_t	disk = NULL;
16160Sstevel@tonic-gate 	boolean_t	efi = B_FALSE;
16170Sstevel@tonic-gate 	uint64_t	bsize	= 0;
16180Sstevel@tonic-gate 	uint64_t	ncyls	= 0;
16190Sstevel@tonic-gate 	uint64_t	nsects	= 0;
16200Sstevel@tonic-gate 	uint64_t	nheads	= 0;
16210Sstevel@tonic-gate 	dlist_t		*iter	= NULL;
16220Sstevel@tonic-gate 	int		error	= 0;
16230Sstevel@tonic-gate 
16240Sstevel@tonic-gate 	*has_same_geom = B_TRUE;
16250Sstevel@tonic-gate 
16260Sstevel@tonic-gate 	((error = slice_get_disk(slice, &disk)) != 0) ||
16270Sstevel@tonic-gate 	(error = disk_get_is_efi(disk, &efi)) ||
16280Sstevel@tonic-gate 	(error = disk_get_blocksize(disk, &bsize));
16290Sstevel@tonic-gate 
16300Sstevel@tonic-gate 	if ((error == 0) && (efi == B_FALSE)) {
16310Sstevel@tonic-gate 	    ((error = disk_get_ncylinders(disk, &ncyls)) != 0) ||
16320Sstevel@tonic-gate 	    (error = disk_get_nheads(disk, &nheads)) ||
16330Sstevel@tonic-gate 	    (error = disk_get_nsectors(disk, &nsects));
16340Sstevel@tonic-gate 	}
16350Sstevel@tonic-gate 
16360Sstevel@tonic-gate 	if (error != 0) {
16370Sstevel@tonic-gate 	    return (error);
16380Sstevel@tonic-gate 	}
16390Sstevel@tonic-gate 
16400Sstevel@tonic-gate 	/*
16410Sstevel@tonic-gate 	 * check to see if slice's disk has the same geometry
16420Sstevel@tonic-gate 	 * as the disks for the slices in the used list
16430Sstevel@tonic-gate 	 */
16440Sstevel@tonic-gate 	for (iter = used;
16450Sstevel@tonic-gate 	    (iter != NULL) && (*has_same_geom == B_TRUE) && (error = 0);
16460Sstevel@tonic-gate 	    iter = iter->next) {
16470Sstevel@tonic-gate 
16480Sstevel@tonic-gate 	    devconfig_t	*dev = (devconfig_t *)iter->obj;
16490Sstevel@tonic-gate 
16500Sstevel@tonic-gate 	    if (devconfig_isA(dev, TYPE_SLICE)) {
16510Sstevel@tonic-gate 
16520Sstevel@tonic-gate 		/* get disk info for otherslice */
16530Sstevel@tonic-gate 		dm_descriptor_t	odisk	= NULL;
16540Sstevel@tonic-gate 		char		*oname	= NULL;
16550Sstevel@tonic-gate 		boolean_t	oefi = B_FALSE;
16560Sstevel@tonic-gate 		uint64_t	obsize	= 0;
16570Sstevel@tonic-gate 		uint64_t	oncyls	= 0;
16580Sstevel@tonic-gate 		uint64_t	onsects = 0;
16590Sstevel@tonic-gate 		uint64_t	onheads = 0;
16600Sstevel@tonic-gate 
16610Sstevel@tonic-gate 		((error = devconfig_get_name(dev, &oname)) != 0) ||
16620Sstevel@tonic-gate 		(error = get_disk_for_named_slice(oname, &odisk)) ||
16630Sstevel@tonic-gate 		(error = disk_get_is_efi(odisk, &oefi)) ||
16640Sstevel@tonic-gate 		(error = disk_get_blocksize(odisk, &obsize));
16650Sstevel@tonic-gate 
16660Sstevel@tonic-gate 		if ((error == 0) && (oefi == B_FALSE)) {
16670Sstevel@tonic-gate 		    ((error = disk_get_ncylinders(odisk, &oncyls)) != 0) ||
16680Sstevel@tonic-gate 		    (error = disk_get_nheads(odisk, &onheads)) ||
16690Sstevel@tonic-gate 		    (error = disk_get_nsectors(odisk, &onsects));
16700Sstevel@tonic-gate 		}
16710Sstevel@tonic-gate 
16720Sstevel@tonic-gate 		if (error == 0) {
16730Sstevel@tonic-gate 		    if ((bsize != obsize) || (ncyls != oncyls) ||
16740Sstevel@tonic-gate 			(nsects != onsects) || (nheads != onheads)) {
16750Sstevel@tonic-gate 			/* this disk has a different geometry */
16760Sstevel@tonic-gate 			*has_same_geom = B_FALSE;
16770Sstevel@tonic-gate 		    }
16780Sstevel@tonic-gate 		}
16790Sstevel@tonic-gate 	    }
16800Sstevel@tonic-gate 	}
16810Sstevel@tonic-gate 
16820Sstevel@tonic-gate 	return (error);
16830Sstevel@tonic-gate }
16840Sstevel@tonic-gate 
16850Sstevel@tonic-gate /*
16860Sstevel@tonic-gate  * FUNCTION:	slice_on_similar_bus(dm_descriptor_t slice,
16870Sstevel@tonic-gate  *			dlist_t *used, boolean_t *on_smlr_bus)
16880Sstevel@tonic-gate  *
16890Sstevel@tonic-gate  * INPUT:	slice	- a dm_descriptor_t handle for the slice of interest
16900Sstevel@tonic-gate  *		used	- a dlist_t pointer to a list of used slices
16910Sstevel@tonic-gate  *		bool	- a boolean_t pointer to hold the result
16920Sstevel@tonic-gate  *
16930Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
16940Sstevel@tonic-gate  *			 !0 otherwise
16950Sstevel@tonic-gate  *
16960Sstevel@tonic-gate  * PURPOSE:	Determines if the input slice is connected thru a bus with
16970Sstevel@tonic-gate  *		characteristics similar to the slices in the used list.
16980Sstevel@tonic-gate  *
16990Sstevel@tonic-gate  *		If the slice is found to be on a similar bus, bool is set
17000Sstevel@tonic-gate  *		to B_TRUE, B_FALSE otherwise.
17010Sstevel@tonic-gate  *
17020Sstevel@tonic-gate  *		The comparison is actually between any of the HBA/controllers
17030Sstevel@tonic-gate  *		thru which the slices are connected to the system.
17040Sstevel@tonic-gate  *		If any are of similar type (e.g., fibre, SCSI) and
17050Sstevel@tonic-gate  *		protocol (SCSI-2, -3, fast/wide), then the slices are
17060Sstevel@tonic-gate  *		considered to be on similar busses.
17070Sstevel@tonic-gate  */
17080Sstevel@tonic-gate static int
slice_on_similar_bus(dm_descriptor_t slice,dlist_t * used,boolean_t * on_smlr_bus)17090Sstevel@tonic-gate slice_on_similar_bus(
17100Sstevel@tonic-gate 	dm_descriptor_t	slice,
17110Sstevel@tonic-gate 	dlist_t		*used,
17120Sstevel@tonic-gate 	boolean_t	*on_smlr_bus)
17130Sstevel@tonic-gate {
17140Sstevel@tonic-gate 	dlist_t		*iter	= NULL;
17150Sstevel@tonic-gate 	dlist_t		*iter1	= NULL;
17160Sstevel@tonic-gate 	dlist_t		*hbas = NULL;
17170Sstevel@tonic-gate 	int		error	= 0;
17180Sstevel@tonic-gate 
17190Sstevel@tonic-gate 	/* if there are no used slices, then the bus is similar */
17200Sstevel@tonic-gate 	*on_smlr_bus = B_TRUE;
17210Sstevel@tonic-gate 	if (dlist_length(used) == 0) {
17220Sstevel@tonic-gate 	    return (0);
17230Sstevel@tonic-gate 	}
17240Sstevel@tonic-gate 
17250Sstevel@tonic-gate 	(error = slice_get_hbas(slice, &hbas));
17260Sstevel@tonic-gate 	if (error != 0) {
17270Sstevel@tonic-gate 	    return (error);
17280Sstevel@tonic-gate 	}
17290Sstevel@tonic-gate 
17300Sstevel@tonic-gate 	/* if there are used slices, then make sure the bus is similar */
17310Sstevel@tonic-gate 	*on_smlr_bus = B_FALSE;
17320Sstevel@tonic-gate 	for (iter = hbas;
17330Sstevel@tonic-gate 	    (iter != NULL) && (*on_smlr_bus == B_FALSE) && (error == 0);
17340Sstevel@tonic-gate 	    iter = iter->next) {
17350Sstevel@tonic-gate 
17360Sstevel@tonic-gate 	    dm_descriptor_t hba = (uintptr_t)iter->obj;
17370Sstevel@tonic-gate 	    char	*type	= NULL;
17380Sstevel@tonic-gate 	    boolean_t	fast80	= B_FALSE;
17390Sstevel@tonic-gate 	    boolean_t	fast40	= B_FALSE;
17400Sstevel@tonic-gate 	    boolean_t	fast20	= B_FALSE;
17410Sstevel@tonic-gate 	    boolean_t	wide	= B_FALSE;
17420Sstevel@tonic-gate 
17430Sstevel@tonic-gate 	    ((error = hba_get_type(hba, &type)) != 0) ||
17440Sstevel@tonic-gate 	    (error = hba_is_fast_80(hba, &fast80)) ||
17450Sstevel@tonic-gate 	    (error = hba_is_fast_40(hba, &fast40)) ||
17460Sstevel@tonic-gate 	    (error = hba_is_fast_20(hba, &fast20)) ||
17470Sstevel@tonic-gate 	    (error = hba_supports_wide(hba, &wide));
17480Sstevel@tonic-gate 	    if (error != 0) {
17490Sstevel@tonic-gate 		continue;
17500Sstevel@tonic-gate 	    }
17510Sstevel@tonic-gate 
17520Sstevel@tonic-gate 	    /* check against the HBAs for the used slices */
17530Sstevel@tonic-gate 	    for (iter1 = used;
17540Sstevel@tonic-gate 		(iter1 != NULL) && (*on_smlr_bus == B_FALSE) && (error == 0);
17550Sstevel@tonic-gate 		iter1 = iter1->next) {
17560Sstevel@tonic-gate 
17570Sstevel@tonic-gate 		devconfig_t *used = (devconfig_t *)iter1->obj;
17580Sstevel@tonic-gate 
17590Sstevel@tonic-gate 		/* get HBAs for otherslice */
17600Sstevel@tonic-gate 		dm_descriptor_t	udisk = NULL;
17610Sstevel@tonic-gate 		char		*uname = NULL;
17620Sstevel@tonic-gate 		dlist_t		*uhbas = NULL;
17630Sstevel@tonic-gate 		dlist_t		*iter2 = NULL;
17640Sstevel@tonic-gate 
17650Sstevel@tonic-gate 		((error = devconfig_get_name(used, &uname)) != 0) ||
17660Sstevel@tonic-gate 		(error = get_disk_for_named_slice(uname, &udisk)) ||
17670Sstevel@tonic-gate 		(error = disk_get_hbas(udisk, &uhbas));
17680Sstevel@tonic-gate 
17690Sstevel@tonic-gate 		for (iter2 = uhbas;
17700Sstevel@tonic-gate 		    (iter2 != NULL) && (*on_smlr_bus == B_FALSE) &&
17710Sstevel@tonic-gate 			(error == 0);
17720Sstevel@tonic-gate 		    iter2 = iter2 ->next) {
17730Sstevel@tonic-gate 
17740Sstevel@tonic-gate 		    dm_descriptor_t uhba = (uintptr_t)iter2->obj;
17750Sstevel@tonic-gate 		    char		*utype	= NULL;
17760Sstevel@tonic-gate 		    boolean_t	ufast80	= B_FALSE;
17770Sstevel@tonic-gate 		    boolean_t	ufast40	= B_FALSE;
17780Sstevel@tonic-gate 		    boolean_t	ufast20	= B_FALSE;
17790Sstevel@tonic-gate 		    boolean_t	uwide	= B_FALSE;
17800Sstevel@tonic-gate 
17810Sstevel@tonic-gate 		    ((error = hba_get_type(uhba, &utype)) != 0) ||
17820Sstevel@tonic-gate 		    (error = hba_is_fast_80(uhba, &ufast80)) ||
17830Sstevel@tonic-gate 		    (error = hba_is_fast_40(uhba, &ufast40)) ||
17840Sstevel@tonic-gate 		    (error = hba_is_fast_20(uhba, &ufast20)) ||
17850Sstevel@tonic-gate 		    (error = hba_supports_wide(uhba, &uwide));
17860Sstevel@tonic-gate 
17870Sstevel@tonic-gate 		    if (error == 0) {
17880Sstevel@tonic-gate 			/* check sync speed ? */
17890Sstevel@tonic-gate 			if ((fast80 == ufast80) && (fast40 == ufast40) &&
17900Sstevel@tonic-gate 			    (fast20 == ufast20) && (wide == uwide) &&
17910Sstevel@tonic-gate 			    (type == utype)) {
17920Sstevel@tonic-gate 			    *on_smlr_bus = B_TRUE;
17930Sstevel@tonic-gate 			}
17940Sstevel@tonic-gate 		    }
17950Sstevel@tonic-gate 		}
17960Sstevel@tonic-gate 		dlist_free_items(uhbas, NULL);
17970Sstevel@tonic-gate 	    }
17980Sstevel@tonic-gate 	}
17990Sstevel@tonic-gate 
18000Sstevel@tonic-gate 	dlist_free_items(hbas, NULL);
18010Sstevel@tonic-gate 
18020Sstevel@tonic-gate 	return (error);
18030Sstevel@tonic-gate }
18040Sstevel@tonic-gate 
18050Sstevel@tonic-gate /*
18060Sstevel@tonic-gate  * FUNCTION:	slice_has_n_paths(dm_descriptor_t slice,
18070Sstevel@tonic-gate  *			uint16_t npaths, boolean_t *has_n_paths)
18080Sstevel@tonic-gate  * INPUT:	slice	- a dm_descriptor_t handle for the slice of interest
18090Sstevel@tonic-gate  * 		npaths	- the number of paths desired
18100Sstevel@tonic-gate  *		has_n_paths - a boolean_t pointer to hold the result
18110Sstevel@tonic-gate  *
18120Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
18130Sstevel@tonic-gate  *			 !0 otherwise
18140Sstevel@tonic-gate  *
18150Sstevel@tonic-gate  * PURPOSE:	Determines if the input slice is connected via npaths.
18160Sstevel@tonic-gate  *		has_n_paths is set to B_TRUE if so, B_FALSE otherwise.
18170Sstevel@tonic-gate  *
18180Sstevel@tonic-gate  *		In order for a disk to have multiple paths, MPXIO must
18190Sstevel@tonic-gate  *		be enabled and these conditions should hold:
18200Sstevel@tonic-gate  *
18210Sstevel@tonic-gate  *			Slice will have one drive object.
18220Sstevel@tonic-gate  *			Drive will have one HBA (scsi_vhci)
18230Sstevel@tonic-gate  *			Drive will have one alias.
18240Sstevel@tonic-gate  *			Drive will have possibly > 1 paths.
18250Sstevel@tonic-gate  *
18260Sstevel@tonic-gate  *		Getting the HBAs and aliases for the disk is relatively
18270Sstevel@tonic-gate  *		expensive, so they aren't checked.  The actual number of
18280Sstevel@tonic-gate  *		paths is only checked if MPXIO is known to be enabled on
18290Sstevel@tonic-gate  *		the system and the input npaths is > 1.
18300Sstevel@tonic-gate  */
18310Sstevel@tonic-gate static int
slice_has_n_paths(dm_descriptor_t slice,uint16_t npaths,boolean_t * has_n_paths)18320Sstevel@tonic-gate slice_has_n_paths(
18330Sstevel@tonic-gate 	dm_descriptor_t	slice,
18340Sstevel@tonic-gate 	uint16_t	npaths,
18350Sstevel@tonic-gate 	boolean_t	*has_n_paths)
18360Sstevel@tonic-gate {
18370Sstevel@tonic-gate 	int		error	= 0;
18380Sstevel@tonic-gate 
18390Sstevel@tonic-gate 	*has_n_paths = B_FALSE;
18400Sstevel@tonic-gate 
18410Sstevel@tonic-gate 	if ((npaths > 1) && (is_mpxio_enabled() == B_TRUE)) {
18420Sstevel@tonic-gate 
18430Sstevel@tonic-gate 	    dm_descriptor_t	disk	= NULL;
18440Sstevel@tonic-gate 	    dlist_t		*paths	= NULL;
18450Sstevel@tonic-gate 
18460Sstevel@tonic-gate 	    ((error = slice_get_disk(slice, &disk)) != 0) ||
18470Sstevel@tonic-gate 	    (error = disk_get_paths(disk, &paths));
18480Sstevel@tonic-gate 
18490Sstevel@tonic-gate 	    if ((error == 0) && (dlist_length(paths) == npaths)) {
18500Sstevel@tonic-gate 		*has_n_paths = B_TRUE;
18510Sstevel@tonic-gate 	    }
18520Sstevel@tonic-gate 	    dlist_free_items(paths, NULL);
18530Sstevel@tonic-gate 	}
18540Sstevel@tonic-gate 
18550Sstevel@tonic-gate 	return (error);
18560Sstevel@tonic-gate }
18570Sstevel@tonic-gate 
18580Sstevel@tonic-gate /*
18590Sstevel@tonic-gate  * FUNCTION:	compare_string_to_modslice_name(void *str, void *modslice)
18600Sstevel@tonic-gate  *
18610Sstevel@tonic-gate  * INPUT:	str	- opaque char * pointer
18620Sstevel@tonic-gate  * 		modslice - opaque modslice_t pointer
18630Sstevel@tonic-gate  *
18640Sstevel@tonic-gate  * RETURNS:	int	- <0 - if str < modslice->slice_devcfg.name
18650Sstevel@tonic-gate  *			   0 - if str == modslice->slice_devcfg.name
18660Sstevel@tonic-gate  *			  >0 - if str > modslice->slice_devcfg.name
18670Sstevel@tonic-gate  *
18680Sstevel@tonic-gate  * PURPOSE:	dlist_t helper which compares the input string to
18690Sstevel@tonic-gate  *		the name of a slice represented as modslice_t struct.
18700Sstevel@tonic-gate  *
18710Sstevel@tonic-gate  *		Comparison is done via string_case_compare.
18720Sstevel@tonic-gate  */
18730Sstevel@tonic-gate static int
compare_string_to_modslice_name(void * str,void * modslice)18740Sstevel@tonic-gate compare_string_to_modslice_name(
18750Sstevel@tonic-gate 	void		*str,
18760Sstevel@tonic-gate 	void		*modslice)
18770Sstevel@tonic-gate {
18780Sstevel@tonic-gate 	char		*name = NULL;
18790Sstevel@tonic-gate 
18800Sstevel@tonic-gate 	assert(str != NULL);
18810Sstevel@tonic-gate 	assert(modslice != NULL);
18820Sstevel@tonic-gate 
18830Sstevel@tonic-gate 	(void) devconfig_get_name(
18840Sstevel@tonic-gate 		((modslice_t *)modslice)->slice_devcfg, &name);
18850Sstevel@tonic-gate 
18860Sstevel@tonic-gate 	return (string_case_compare((char *)str, name));
18870Sstevel@tonic-gate }
18880Sstevel@tonic-gate 
18890Sstevel@tonic-gate /*
18900Sstevel@tonic-gate  * FUNCTION:	compare_modslice_names(void *obj1, void *obj2)
18910Sstevel@tonic-gate  *
18920Sstevel@tonic-gate  * INPUT:	obj1	- opaque pointer
18930Sstevel@tonic-gate  * 		obj2	- opaque pointer
18940Sstevel@tonic-gate  *
18950Sstevel@tonic-gate  * RETURNS:	int	- <0 - if obj1 name < obj2 name
18960Sstevel@tonic-gate  *			   0 - if obj1 name == obj2 name
18970Sstevel@tonic-gate  *			  >0 - if obj1 name > obj2 name
18980Sstevel@tonic-gate  *
18990Sstevel@tonic-gate  * PURPOSE:	dlist_t helper which compares the names of two slices
19000Sstevel@tonic-gate  *		represented as modslice_t structs.
19010Sstevel@tonic-gate  *
19020Sstevel@tonic-gate  *		Comparison is done by string_case_compare
19030Sstevel@tonic-gate  */
19040Sstevel@tonic-gate static int
compare_modslice_names(void * obj1,void * obj2)19050Sstevel@tonic-gate compare_modslice_names(
19060Sstevel@tonic-gate 	void		*obj1,
19070Sstevel@tonic-gate 	void		*obj2)
19080Sstevel@tonic-gate {
19090Sstevel@tonic-gate 	char		*name1 = NULL;
19100Sstevel@tonic-gate 	char		*name2 = NULL;
19110Sstevel@tonic-gate 
19120Sstevel@tonic-gate 	assert(obj1 != NULL);
19130Sstevel@tonic-gate 	assert(obj2 != NULL);
19140Sstevel@tonic-gate 
19150Sstevel@tonic-gate 	(void) devconfig_get_name(
19160Sstevel@tonic-gate 		((modslice_t *)obj1)->slice_devcfg, &name1);
19170Sstevel@tonic-gate 	(void) devconfig_get_name(
19180Sstevel@tonic-gate 		((modslice_t *)obj2)->slice_devcfg, &name2);
19190Sstevel@tonic-gate 
19200Sstevel@tonic-gate 	return (string_case_compare(name1, name2));
19210Sstevel@tonic-gate }
19220Sstevel@tonic-gate 
19230Sstevel@tonic-gate /*
19240Sstevel@tonic-gate  * FUNCTION:	release_used_slices()
19250Sstevel@tonic-gate  *
19260Sstevel@tonic-gate  * PURPOSE:	Helper which cleans up the module private list of used
19270Sstevel@tonic-gate  *		slices.
19280Sstevel@tonic-gate  */
19290Sstevel@tonic-gate void
release_used_slices()19300Sstevel@tonic-gate release_used_slices()
19310Sstevel@tonic-gate {
19320Sstevel@tonic-gate 	dlist_free_items(_used_slices, free_used_slice);
19330Sstevel@tonic-gate 	_used_slices = NULL;
19340Sstevel@tonic-gate }
19350Sstevel@tonic-gate 
19360Sstevel@tonic-gate static void
free_used_slice(void * obj)19370Sstevel@tonic-gate free_used_slice(
19380Sstevel@tonic-gate 	void *obj)
19390Sstevel@tonic-gate {
19400Sstevel@tonic-gate 	if (obj != NULL) {
19410Sstevel@tonic-gate 	    usedslice_t *used = (usedslice_t *)obj;
19420Sstevel@tonic-gate 	    free(used->slicename);
19430Sstevel@tonic-gate 	    free(used);
19440Sstevel@tonic-gate 	}
19450Sstevel@tonic-gate }
19460Sstevel@tonic-gate 
19470Sstevel@tonic-gate /*
19480Sstevel@tonic-gate  * FUNCTION:	is_used_slice(dm_descriptor_t slice, boolean_t *is_used)
19490Sstevel@tonic-gate  *
19500Sstevel@tonic-gate  * INPUT:	slice	- a dm_descriptor_t slice handle
19510Sstevel@tonic-gate  *
19520Sstevel@tonic-gate  * OUTPUT:	is_reserved - pointer to a boolean_t to hold the
19530Sstevel@tonic-gate  *			return result.
19540Sstevel@tonic-gate  *
19550Sstevel@tonic-gate  * PURPOSE:	Helper which checks to see if the input slice
19560Sstevel@tonic-gate  *		is in the used_slice list.
19570Sstevel@tonic-gate  *
19580Sstevel@tonic-gate  *		Check the input name against any used slice name or alias.
19590Sstevel@tonic-gate  *		is_used is set to B_TRUE if the	input slice is already used,
19600Sstevel@tonic-gate  *		B_FALSE otherwise.
19610Sstevel@tonic-gate  */
19620Sstevel@tonic-gate int
is_used_slice(dm_descriptor_t slice,boolean_t * is_used)19630Sstevel@tonic-gate is_used_slice(
19640Sstevel@tonic-gate 	dm_descriptor_t	slice,
19650Sstevel@tonic-gate 	boolean_t	*is_used)
19660Sstevel@tonic-gate {
19670Sstevel@tonic-gate 	char	*name;
19680Sstevel@tonic-gate 	int	error = 0;
19690Sstevel@tonic-gate 
19700Sstevel@tonic-gate 	if ((error = get_display_name(slice, &name)) == 0) {
19710Sstevel@tonic-gate 	    *is_used = dlist_contains(_used_slices, (void *)name,
19720Sstevel@tonic-gate 		    compare_usedslice_name_to_string);
19730Sstevel@tonic-gate 	}
19740Sstevel@tonic-gate 
19750Sstevel@tonic-gate 	return (error);
19760Sstevel@tonic-gate }
19770Sstevel@tonic-gate 
19780Sstevel@tonic-gate /*
19790Sstevel@tonic-gate  * FUNCTIONS:	add_used_slice(dm_descriptor_t slice)
19800Sstevel@tonic-gate  *		add_used_slice_by_name(char *slicename)
19810Sstevel@tonic-gate  *		add_used_slice_list_entry(char *slice)
19820Sstevel@tonic-gate  *		remove_used_slice_by_name(char *slicename)
19830Sstevel@tonic-gate  *
19840Sstevel@tonic-gate  * INPUT:	diskset	- a char * diskset name.
19850Sstevel@tonic-gate  *		slice	- a dm_descriptor_t slice handle
19860Sstevel@tonic-gate  *
19870Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
19880Sstevel@tonic-gate  *			 !0 otherwise
19890Sstevel@tonic-gate  *
19900Sstevel@tonic-gate  * PURPOSE:	Access or maintain the list of used slices.
19910Sstevel@tonic-gate  */
19920Sstevel@tonic-gate int
add_used_slice(dm_descriptor_t slice)19930Sstevel@tonic-gate add_used_slice(
19940Sstevel@tonic-gate 	dm_descriptor_t	slice)
19950Sstevel@tonic-gate {
19960Sstevel@tonic-gate 	dm_descriptor_t disk;
19970Sstevel@tonic-gate 	char	*name;
19980Sstevel@tonic-gate 	int	error = 0;
19990Sstevel@tonic-gate 
20000Sstevel@tonic-gate 	assert(slice != (dm_descriptor_t)0);
20010Sstevel@tonic-gate 
20020Sstevel@tonic-gate 	((error = get_display_name(slice, &name)) != 0) ||
20030Sstevel@tonic-gate 	(error = slice_get_disk(slice, &disk)) ||
20040Sstevel@tonic-gate 	(error = add_used_slice_list_entry(name, disk));
20050Sstevel@tonic-gate 
20060Sstevel@tonic-gate 	return (error);
20070Sstevel@tonic-gate }
20080Sstevel@tonic-gate 
20090Sstevel@tonic-gate int
add_used_slice_by_name(char * slicename)20100Sstevel@tonic-gate add_used_slice_by_name(
20110Sstevel@tonic-gate 	char	*slicename)
20120Sstevel@tonic-gate {
20130Sstevel@tonic-gate 	dm_descriptor_t disk = (dm_descriptor_t)0;
20140Sstevel@tonic-gate 	int	error = 0;
20150Sstevel@tonic-gate 
20160Sstevel@tonic-gate 	assert(slicename != NULL);
20170Sstevel@tonic-gate 
20180Sstevel@tonic-gate 	/* find disk for slice */
20190Sstevel@tonic-gate 	error = get_disk_for_named_slice(slicename, &disk);
20200Sstevel@tonic-gate 	if (error == 0) {
20210Sstevel@tonic-gate 	    error = add_used_slice_list_entry(slicename, disk);
20220Sstevel@tonic-gate 	}
20230Sstevel@tonic-gate 
20240Sstevel@tonic-gate 	return (error);
20250Sstevel@tonic-gate }
20260Sstevel@tonic-gate 
20270Sstevel@tonic-gate static int
add_used_slice_list_entry(char * slicename,dm_descriptor_t disk)20280Sstevel@tonic-gate add_used_slice_list_entry(
20290Sstevel@tonic-gate 	char	*slicename,
20300Sstevel@tonic-gate 	dm_descriptor_t	disk)
20310Sstevel@tonic-gate {
20320Sstevel@tonic-gate 	usedslice_t *used = NULL;
20330Sstevel@tonic-gate 	int	error = 0;
20340Sstevel@tonic-gate 
20350Sstevel@tonic-gate 	assert(slicename != NULL);
20360Sstevel@tonic-gate 	assert(disk != (dm_descriptor_t)0);
20370Sstevel@tonic-gate 
20380Sstevel@tonic-gate 	used = (usedslice_t *)calloc(1, sizeof (usedslice_t));
20390Sstevel@tonic-gate 	if (used == NULL) {
20400Sstevel@tonic-gate 	    error = ENOMEM;
20410Sstevel@tonic-gate 	} else {
20420Sstevel@tonic-gate 
20430Sstevel@tonic-gate 	    used->disk = disk;
20440Sstevel@tonic-gate 	    if ((used->slicename = strdup(slicename)) == NULL) {
20450Sstevel@tonic-gate 		free(used);
20460Sstevel@tonic-gate 		error = ENOMEM;
20470Sstevel@tonic-gate 	    } else {
20480Sstevel@tonic-gate 		dlist_t *item = dlist_new_item((void *) used);
20490Sstevel@tonic-gate 		if (item == NULL) {
20500Sstevel@tonic-gate 		    free(used->slicename);
20510Sstevel@tonic-gate 		    free(used);
20520Sstevel@tonic-gate 		    error = ENOMEM;
20530Sstevel@tonic-gate 		} else {
20540Sstevel@tonic-gate 		    _used_slices =
20550Sstevel@tonic-gate 			dlist_append(item, _used_slices, AT_HEAD);
20560Sstevel@tonic-gate 		}
20570Sstevel@tonic-gate 	    }
20580Sstevel@tonic-gate 	}
20590Sstevel@tonic-gate 	return (error);
20600Sstevel@tonic-gate }
20610Sstevel@tonic-gate 
20620Sstevel@tonic-gate int
remove_used_slice_by_name(char * slice)20630Sstevel@tonic-gate remove_used_slice_by_name(
20640Sstevel@tonic-gate 	char	*slice)
20650Sstevel@tonic-gate {
20660Sstevel@tonic-gate 	dlist_t *removed = NULL;
20670Sstevel@tonic-gate 
20680Sstevel@tonic-gate 	_used_slices =
20690Sstevel@tonic-gate 	    dlist_remove_equivalent_item(_used_slices, (void *)slice,
20700Sstevel@tonic-gate 		    compare_usedslice_name_to_string, &removed);
20710Sstevel@tonic-gate 
20720Sstevel@tonic-gate 	if (removed != NULL) {
20730Sstevel@tonic-gate 	    free_used_slice(removed->obj);
20740Sstevel@tonic-gate 	    removed->obj = NULL;
20750Sstevel@tonic-gate 	    free(removed);
20760Sstevel@tonic-gate 	}
20770Sstevel@tonic-gate 
20780Sstevel@tonic-gate 	return (0);
20790Sstevel@tonic-gate }
20800Sstevel@tonic-gate 
20810Sstevel@tonic-gate /*
20820Sstevel@tonic-gate  * FUNCTION:	compare_usedslice_name_to_string(void *obj1, void *obj2)
20830Sstevel@tonic-gate  * INPUT:	obj1	- opaque pointer
20840Sstevel@tonic-gate  * 		obj2	- opaque pointer
20850Sstevel@tonic-gate  *
20860Sstevel@tonic-gate  * RETURNS:	int	- <0 - if obj1 name < obj2 name
20870Sstevel@tonic-gate  *			   0 - if obj1 name == obj2 name
20880Sstevel@tonic-gate  *			  >0 - if obj1 name > obj2 name
20890Sstevel@tonic-gate  *
20900Sstevel@tonic-gate  * PURPOSE:	dlist_t helper which compares the names of a slice
20910Sstevel@tonic-gate  *		represented as modslice_t struct to a string.
20920Sstevel@tonic-gate  *
20930Sstevel@tonic-gate  *		obj1 is assumed to be a char *
20940Sstevel@tonic-gate  *		obj2 is assumed to be a usedslice_t *
20950Sstevel@tonic-gate  *
20960Sstevel@tonic-gate  *		Comparison is done via string_case_compare.
20970Sstevel@tonic-gate  */
20980Sstevel@tonic-gate static int
compare_usedslice_name_to_string(void * obj1,void * obj2)20990Sstevel@tonic-gate compare_usedslice_name_to_string(
21000Sstevel@tonic-gate 	void		*obj1,
21010Sstevel@tonic-gate 	void		*obj2)
21020Sstevel@tonic-gate {
21030Sstevel@tonic-gate 	assert(obj1 != NULL);
21040Sstevel@tonic-gate 	assert(obj2 != NULL);
21050Sstevel@tonic-gate 
21060Sstevel@tonic-gate 	return (string_case_compare((char *)obj1,
21070Sstevel@tonic-gate 			((usedslice_t *)obj2)->slicename));
21080Sstevel@tonic-gate }
21090Sstevel@tonic-gate 
21100Sstevel@tonic-gate /*
21110Sstevel@tonic-gate  * FUNCTION:	disk_has_used_slice(dm_descriptor_t disk, boolean_t *hasused)
21120Sstevel@tonic-gate  *
21130Sstevel@tonic-gate  * INPUT:	disk	- a dm_descriptor_t disk handle.
21140Sstevel@tonic-gate  *		inuse	- a boolean_t pointer to hold the result
21150Sstevel@tonic-gate  *
21160Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
21170Sstevel@tonic-gate  *			 !0 othersize.
21180Sstevel@tonic-gate  *
21190Sstevel@tonic-gate  * PURPOSE:	Determines if any of the known used slices is on the
21200Sstevel@tonic-gate  *		input disk.
21210Sstevel@tonic-gate  */
21220Sstevel@tonic-gate int
disk_has_used_slice(dm_descriptor_t disk,boolean_t * hasused)21230Sstevel@tonic-gate disk_has_used_slice(
21240Sstevel@tonic-gate 	dm_descriptor_t disk,
21250Sstevel@tonic-gate 	boolean_t	*hasused)
21260Sstevel@tonic-gate {
21270Sstevel@tonic-gate 	dlist_t		*iter;
21280Sstevel@tonic-gate 	int		error = 0;
21290Sstevel@tonic-gate 
21300Sstevel@tonic-gate 	*hasused = B_FALSE;
21310Sstevel@tonic-gate 	for (iter = _used_slices;
21320Sstevel@tonic-gate 	    (iter != NULL) && (*hasused == B_FALSE);
21330Sstevel@tonic-gate 	    iter = iter->next) {
21340Sstevel@tonic-gate 
21350Sstevel@tonic-gate 	    usedslice_t *used = (usedslice_t *)iter->obj;
21360Sstevel@tonic-gate 
21370Sstevel@tonic-gate 	    /* compare used slice's disk to disk */
2138*62Sjeanm 	    if (compare_descriptors((void *)(uintptr_t)disk,
2139*62Sjeanm 		(void *)(uintptr_t)used->disk) == 0) {
21400Sstevel@tonic-gate 		*hasused = B_TRUE;
21410Sstevel@tonic-gate 	    }
21420Sstevel@tonic-gate 	}
21430Sstevel@tonic-gate 
21440Sstevel@tonic-gate 	return (error);
21450Sstevel@tonic-gate }
21460Sstevel@tonic-gate 
21470Sstevel@tonic-gate /*
21480Sstevel@tonic-gate  * FUNCTION:	add_reserved_slice(dm_descriptor_t slice)
21490Sstevel@tonic-gate  *
21500Sstevel@tonic-gate  * INPUT:	slice	- a dm_descriptor_t slice handle
21510Sstevel@tonic-gate  *
21520Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
21530Sstevel@tonic-gate  *			 !0 otherwise.
21540Sstevel@tonic-gate  *
21550Sstevel@tonic-gate  * PURPOSE:	Helper which remembers specfically requested slices
21560Sstevel@tonic-gate  *		in a private list to ensure that the same slice isn't
21570Sstevel@tonic-gate  *		requested more than once.
21580Sstevel@tonic-gate  *
21590Sstevel@tonic-gate  *		Does not check to see if the slice already exists
21600Sstevel@tonic-gate  *		in the list of reserved slices. Assumes that the
21610Sstevel@tonic-gate  *		caller has checked using is_reserved_slice().
21620Sstevel@tonic-gate  *
21630Sstevel@tonic-gate  *		The reserved slice list is used by several functions:
21640Sstevel@tonic-gate  *
21650Sstevel@tonic-gate  *		1. layout_validate.validate_slice_components() adds user
21660Sstevel@tonic-gate  *		   requested slices to the list.
21670Sstevel@tonic-gate  *
21680Sstevel@tonic-gate  *		2. After all potentially usable slices have been scanned,
21690Sstevel@tonic-gate  *		   layout_validate.validate_reserved_slices() checks the
21700Sstevel@tonic-gate  *		   slices in the reserved and ensures that each slice is
21710Sstevel@tonic-gate  *		   actually usable as a volume component.
21720Sstevel@tonic-gate  *
21730Sstevel@tonic-gate  *		3. layout.disk_get_avail_space(), layout.disk_get_avail_slices()
21740Sstevel@tonic-gate  *		   exclude slices in the reserved list from being considered
21750Sstevel@tonic-gate  *		   available for general layout use.
21760Sstevel@tonic-gate  */
21770Sstevel@tonic-gate int
add_reserved_slice(dm_descriptor_t slice)21780Sstevel@tonic-gate add_reserved_slice(
21790Sstevel@tonic-gate 	dm_descriptor_t	slice)
21800Sstevel@tonic-gate {
21810Sstevel@tonic-gate 	dlist_t	*item = NULL;
21820Sstevel@tonic-gate 
2183*62Sjeanm 	if ((item = dlist_new_item((void *)(uintptr_t)slice)) == NULL) {
21840Sstevel@tonic-gate 	    return (ENOMEM);
21850Sstevel@tonic-gate 	}
21860Sstevel@tonic-gate 
21870Sstevel@tonic-gate 	_rsvd_slices = dlist_append(item, _rsvd_slices, AT_HEAD);
21880Sstevel@tonic-gate 
21890Sstevel@tonic-gate 	return (0);
21900Sstevel@tonic-gate }
21910Sstevel@tonic-gate 
21920Sstevel@tonic-gate /*
21930Sstevel@tonic-gate  * FUNCTION:	is_reserved_slice(dm_descriptor_t slice,
21940Sstevel@tonic-gate  *			boolean_t *is_reserved)
21950Sstevel@tonic-gate  *
21960Sstevel@tonic-gate  * INPUT:	slice	- a dm_descriptor_t slice handle
21970Sstevel@tonic-gate  *
21980Sstevel@tonic-gate  * OUTPUT:	is_reserved - pointer to a boolean_t to hold the
21990Sstevel@tonic-gate  *			return result.
22000Sstevel@tonic-gate  *
22010Sstevel@tonic-gate  * PURPOSE:	Helper which checks to see if the input slice
22020Sstevel@tonic-gate  *		was previously reserved.
22030Sstevel@tonic-gate  *
22040Sstevel@tonic-gate  *		Check the input name against any reserved slice
22050Sstevel@tonic-gate  *		name or alias. is_reserved is set to B_TRUE if the
22060Sstevel@tonic-gate  *		input slice is already reserved, B_FALSE otherwise.
22070Sstevel@tonic-gate  */
22080Sstevel@tonic-gate int
is_reserved_slice(dm_descriptor_t slice,boolean_t * is_reserved)22090Sstevel@tonic-gate is_reserved_slice(
22100Sstevel@tonic-gate 	dm_descriptor_t	slice,
22110Sstevel@tonic-gate 	boolean_t	*is_reserved)
22120Sstevel@tonic-gate {
2213*62Sjeanm 	*is_reserved = dlist_contains(_rsvd_slices,
2214*62Sjeanm 	    (void *)(uintptr_t)slice, compare_descriptor_names);
22150Sstevel@tonic-gate 
22160Sstevel@tonic-gate 	return (0);
22170Sstevel@tonic-gate }
22180Sstevel@tonic-gate 
22190Sstevel@tonic-gate /*
22200Sstevel@tonic-gate  * FUNCTION:	release_reserved_slice()
22210Sstevel@tonic-gate  *
22220Sstevel@tonic-gate  * PURPOSE:	Helper which cleans up the module private list of reserved
22230Sstevel@tonic-gate  *		slices.
22240Sstevel@tonic-gate  */
22250Sstevel@tonic-gate void
release_reserved_slices()22260Sstevel@tonic-gate release_reserved_slices()
22270Sstevel@tonic-gate {
22280Sstevel@tonic-gate 	dlist_free_items(_rsvd_slices, free);
22290Sstevel@tonic-gate 	_rsvd_slices = NULL;
22300Sstevel@tonic-gate }
22310Sstevel@tonic-gate 
22320Sstevel@tonic-gate /*
22330Sstevel@tonic-gate  * FUNCTION:	get_reserved_slices(dlist_t **list)
22340Sstevel@tonic-gate  *
22350Sstevel@tonic-gate  * OUTPUT:	list	- a dlist_t pointer to hold the returned list of
22360Sstevel@tonic-gate  *			reserverd slices.
22370Sstevel@tonic-gate  *
22380Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
22390Sstevel@tonic-gate  *			 !0 otherwise
22400Sstevel@tonic-gate  *
22410Sstevel@tonic-gate  * PURPOSE:	Accessor to retrieve the current list of reserved slice
22420Sstevel@tonic-gate  *		dm_descriptor_t handles.
22430Sstevel@tonic-gate  */
22440Sstevel@tonic-gate int
get_reserved_slices(dlist_t ** list)22450Sstevel@tonic-gate get_reserved_slices(
22460Sstevel@tonic-gate 	dlist_t **list)
22470Sstevel@tonic-gate {
22480Sstevel@tonic-gate 	*list = _rsvd_slices;
22490Sstevel@tonic-gate 
22500Sstevel@tonic-gate 	return (0);
22510Sstevel@tonic-gate }
22520Sstevel@tonic-gate 
22530Sstevel@tonic-gate /*
22540Sstevel@tonic-gate  * FUNCTION:	add_slice_to_remove(char *name, uint32_t index)
22550Sstevel@tonic-gate  *
22560Sstevel@tonic-gate  * INPUT:	name	-	name of a slice
22570Sstevel@tonic-gate  *		index	-	index for the slice
22580Sstevel@tonic-gate  *
22590Sstevel@tonic-gate  * RETURNS:	int	- 0 on success
22600Sstevel@tonic-gate  *			 !0 otherwise
22610Sstevel@tonic-gate  *
22620Sstevel@tonic-gate  * PURPOSE:	Utility function to add the named slice to the list of
22630Sstevel@tonic-gate  *		those that need to be "removed" by having their sizes
22640Sstevel@tonic-gate  *		set to 0.
22650Sstevel@tonic-gate  */
22660Sstevel@tonic-gate int
add_slice_to_remove(char * name,uint32_t index)22670Sstevel@tonic-gate add_slice_to_remove(
22680Sstevel@tonic-gate 	char		*name,
22690Sstevel@tonic-gate 	uint32_t	index)
22700Sstevel@tonic-gate {
22710Sstevel@tonic-gate 	rmvdslice_t *rmvd = NULL;
22720Sstevel@tonic-gate 	int	error = 0;
22730Sstevel@tonic-gate 
22740Sstevel@tonic-gate 	assert(name != NULL);
22750Sstevel@tonic-gate 
22760Sstevel@tonic-gate 	rmvd = (rmvdslice_t *)calloc(1, sizeof (rmvdslice_t));
22770Sstevel@tonic-gate 	if (rmvd == NULL) {
22780Sstevel@tonic-gate 	    error = ENOMEM;
22790Sstevel@tonic-gate 	} else {
22800Sstevel@tonic-gate 	    rmvd->slice_index = index;
22810Sstevel@tonic-gate 	    if ((rmvd->slice_name = strdup(name)) == NULL) {
22820Sstevel@tonic-gate 		free(rmvd);
22830Sstevel@tonic-gate 		error = ENOMEM;
22840Sstevel@tonic-gate 	    } else {
22850Sstevel@tonic-gate 		dlist_t *item = dlist_new_item((void *) rmvd);
22860Sstevel@tonic-gate 		if (item == NULL) {
22870Sstevel@tonic-gate 		    free(rmvd->slice_name);
22880Sstevel@tonic-gate 		    free(rmvd);
22890Sstevel@tonic-gate 		    error = ENOMEM;
22900Sstevel@tonic-gate 		} else {
22910Sstevel@tonic-gate 		    _rmvd_slices =
22920Sstevel@tonic-gate 			dlist_append(item, _rmvd_slices, AT_HEAD);
22930Sstevel@tonic-gate 		}
22940Sstevel@tonic-gate 	    }
22950Sstevel@tonic-gate 	}
22960Sstevel@tonic-gate 	return (error);
22970Sstevel@tonic-gate }
22980Sstevel@tonic-gate 
22990Sstevel@tonic-gate /*
23000Sstevel@tonic-gate  * FUNCTION:	get_removed_slices()
23010Sstevel@tonic-gate  *
23020Sstevel@tonic-gate  * RETURNS:	dlist_t * - pointer to a list of rmvdslice_t structs
23030Sstevel@tonic-gate  *
23040Sstevel@tonic-gate  * PURPOSE:	Accessor to retrieve the current list of names of slices
23050Sstevel@tonic-gate  *		to be removed.
23060Sstevel@tonic-gate  */
23070Sstevel@tonic-gate dlist_t *
get_slices_to_remove(dlist_t ** list)23080Sstevel@tonic-gate get_slices_to_remove(
23090Sstevel@tonic-gate 	dlist_t **list)
23100Sstevel@tonic-gate {
23110Sstevel@tonic-gate 	return (_rmvd_slices);
23120Sstevel@tonic-gate }
23130Sstevel@tonic-gate 
23140Sstevel@tonic-gate static void
free_rmvd_slice(void * obj)23150Sstevel@tonic-gate free_rmvd_slice(
23160Sstevel@tonic-gate 	void *obj)
23170Sstevel@tonic-gate {
23180Sstevel@tonic-gate 	if (obj != NULL) {
23190Sstevel@tonic-gate 	    rmvdslice_t *rmvd = (rmvdslice_t *)obj;
23200Sstevel@tonic-gate 	    free(rmvd->slice_name);
23210Sstevel@tonic-gate 	    free(rmvd);
23220Sstevel@tonic-gate 	}
23230Sstevel@tonic-gate }
23240Sstevel@tonic-gate 
23250Sstevel@tonic-gate /*
23260Sstevel@tonic-gate  * FUNCTION:	release_removed_slices()
23270Sstevel@tonic-gate  *
23280Sstevel@tonic-gate  * PURPOSE:	Helper which cleans up the module private list of removed
23290Sstevel@tonic-gate  *		slices.
23300Sstevel@tonic-gate  */
23310Sstevel@tonic-gate void
release_slices_to_remove()23320Sstevel@tonic-gate release_slices_to_remove()
23330Sstevel@tonic-gate {
23340Sstevel@tonic-gate 	dlist_free_items(_rmvd_slices, free_rmvd_slice);
23350Sstevel@tonic-gate 	_rmvd_slices = NULL;
23360Sstevel@tonic-gate }
2337