1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/param.h> 30*0Sstevel@tonic-gate #include <meta.h> 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate #include "volume_string.h" 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate #include "volume_devconfig.h" 35*0Sstevel@tonic-gate #include "volume_error.h" 36*0Sstevel@tonic-gate #include "volume_dlist.h" 37*0Sstevel@tonic-gate #include "volume_output.h" 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate #include "layout_device_cache.h" 40*0Sstevel@tonic-gate #include "layout_device_util.h" 41*0Sstevel@tonic-gate #include "layout_discovery.h" 42*0Sstevel@tonic-gate #include "layout_dlist_util.h" 43*0Sstevel@tonic-gate #include "layout_messages.h" 44*0Sstevel@tonic-gate #include "layout_request.h" 45*0Sstevel@tonic-gate #include "layout_slice.h" 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate #define _LAYOUT_SLICE_C 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate static int pick_from_best_hba_and_disk( 50*0Sstevel@tonic-gate dlist_t *list, 51*0Sstevel@tonic-gate dlist_t *used, 52*0Sstevel@tonic-gate dm_descriptor_t *chosen); 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate static int slice_has_same_disk_geom( 55*0Sstevel@tonic-gate dm_descriptor_t slice, 56*0Sstevel@tonic-gate dlist_t *used, 57*0Sstevel@tonic-gate boolean_t *bool); 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate static int slice_on_unique_disk( 60*0Sstevel@tonic-gate dm_descriptor_t slice, 61*0Sstevel@tonic-gate dlist_t *used, 62*0Sstevel@tonic-gate dlist_t *othervols, 63*0Sstevel@tonic-gate boolean_t *bool); 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate static int slice_on_unique_hba( 66*0Sstevel@tonic-gate dm_descriptor_t slice, 67*0Sstevel@tonic-gate dlist_t *used, 68*0Sstevel@tonic-gate dlist_t *othervols, 69*0Sstevel@tonic-gate boolean_t *bool); 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate static int slice_on_similar_bus( 72*0Sstevel@tonic-gate dm_descriptor_t slice, 73*0Sstevel@tonic-gate dlist_t *used, 74*0Sstevel@tonic-gate boolean_t *bool); 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate static int slice_has_n_paths( 77*0Sstevel@tonic-gate dm_descriptor_t slice, 78*0Sstevel@tonic-gate uint16_t npaths, 79*0Sstevel@tonic-gate boolean_t *bool); 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate static int compare_modslice_names( 82*0Sstevel@tonic-gate void *obj1, 83*0Sstevel@tonic-gate void *obj2); 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate static int compare_string_to_modslice_name( 86*0Sstevel@tonic-gate void *str, 87*0Sstevel@tonic-gate void *modslice); 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate static int create_new_slice( 90*0Sstevel@tonic-gate dm_descriptor_t oslice, 91*0Sstevel@tonic-gate uint64_t nbytes, 92*0Sstevel@tonic-gate boolean_t add_extra_cyl, 93*0Sstevel@tonic-gate devconfig_t **nslice); 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate static int create_modified_slice( 96*0Sstevel@tonic-gate dm_descriptor_t oslice, 97*0Sstevel@tonic-gate char *oname, 98*0Sstevel@tonic-gate uint32_t oindex, 99*0Sstevel@tonic-gate uint64_t ostart, 100*0Sstevel@tonic-gate uint64_t osize, 101*0Sstevel@tonic-gate uint64_t bps, 102*0Sstevel@tonic-gate char *nname, 103*0Sstevel@tonic-gate uint32_t nindex, 104*0Sstevel@tonic-gate uint64_t nsize, 105*0Sstevel@tonic-gate devconfig_t **nslice); 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate /* 108*0Sstevel@tonic-gate * list to track resized slices 109*0Sstevel@tonic-gate */ 110*0Sstevel@tonic-gate static dlist_t *_modified_slices = NULL; 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate /* 113*0Sstevel@tonic-gate * struct to track used slices and their disks... 114*0Sstevel@tonic-gate */ 115*0Sstevel@tonic-gate typedef struct { 116*0Sstevel@tonic-gate char *slicename; 117*0Sstevel@tonic-gate dm_descriptor_t disk; 118*0Sstevel@tonic-gate } usedslice_t; 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate /* 121*0Sstevel@tonic-gate * list to of usedslice_t to track slices that have been 122*0Sstevel@tonic-gate * used for any reason. 123*0Sstevel@tonic-gate */ 124*0Sstevel@tonic-gate static dlist_t *_used_slices = NULL; 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate static int add_used_slice_list_entry(char *slicename, dm_descriptor_t disk); 127*0Sstevel@tonic-gate static int compare_usedslice_name_to_string(void *obj1, void *obj2); 128*0Sstevel@tonic-gate static void free_used_slice(void *obj); 129*0Sstevel@tonic-gate 130*0Sstevel@tonic-gate /* 131*0Sstevel@tonic-gate * list of slices reserved to be used for explicit 132*0Sstevel@tonic-gate * volume requests 133*0Sstevel@tonic-gate */ 134*0Sstevel@tonic-gate static dlist_t *_rsvd_slices = NULL; 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate /* 137*0Sstevel@tonic-gate * list of slices needing to be removed (zeroed out) prior to 138*0Sstevel@tonic-gate * applying any metassist modifications to the system. 139*0Sstevel@tonic-gate */ 140*0Sstevel@tonic-gate static dlist_t *_rmvd_slices = NULL; 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate /* 143*0Sstevel@tonic-gate * FUNCTION: choose_slice( 144*0Sstevel@tonic-gate * uint64_t nbytes, 145*0Sstevel@tonic-gate * uint16_t npaths, 146*0Sstevel@tonic-gate * dlist_t *slices, 147*0Sstevel@tonic-gate * dlist_t *used, 148*0Sstevel@tonic-gate * dlist_t *used_hbas, 149*0Sstevel@tonic-gate * dlist_t *used_disks, 150*0Sstevel@tonic-gate * boolean_t unused_disk, 151*0Sstevel@tonic-gate * boolean_t nbytes_is_min, 152*0Sstevel@tonic-gate * boolean_t add_extra_cyl, 153*0Sstevel@tonic-gate * devconfig_t **chosen) 154*0Sstevel@tonic-gate * 155*0Sstevel@tonic-gate * INPUT: nbytes - required size 156*0Sstevel@tonic-gate * npaths - minimum required data paths 157*0Sstevel@tonic-gate * *slices - slices from which to choose 158*0Sstevel@tonic-gate * *used - slices used by the volume under construction 159*0Sstevel@tonic-gate * *used_hbas - hbas used by other volumes relevant to 160*0Sstevel@tonic-gate * the volume under construction 161*0Sstevel@tonic-gate * *used_disks - disks used by other volumes relevant to 162*0Sstevel@tonic-gate * the volume under construction 163*0Sstevel@tonic-gate * unused_disk - if true, the chosen slice must be from an 164*0Sstevel@tonic-gate * unused disk 165*0Sstevel@tonic-gate * nbytes_is_min - if true, the chosen slice may be larger than 166*0Sstevel@tonic-gate * nbytes. 167*0Sstevel@tonic-gate * add_extra_cyl - passed to create_new_slice, see comment there. 168*0Sstevel@tonic-gate * **chosen - pointer to hold the chosen slice 169*0Sstevel@tonic-gate * 170*0Sstevel@tonic-gate * RETURNS: int - 0 on success 171*0Sstevel@tonic-gate * !0 otherwise 172*0Sstevel@tonic-gate * 173*0Sstevel@tonic-gate * PURPOSE: Choosen a slice from the list of those available. 174*0Sstevel@tonic-gate * 175*0Sstevel@tonic-gate * Of those available, choose in order of preference: 176*0Sstevel@tonic-gate * 177*0Sstevel@tonic-gate * - one on a unique HBA and disk that is of the exact size 178*0Sstevel@tonic-gate * - one on a unique HBA and disk that is of sufficient size 179*0Sstevel@tonic-gate * - one on unique HBA that is of the exact size 180*0Sstevel@tonic-gate * - one on unique HBA that is of sufficient size 181*0Sstevel@tonic-gate * - one on unique disk that is of the exact size 182*0Sstevel@tonic-gate * - one on unique disk that is of sufficient size 183*0Sstevel@tonic-gate * - one on any HBA that is of exact size 184*0Sstevel@tonic-gate * - one on any HBA that is of sufficient size 185*0Sstevel@tonic-gate * - one on a unique HBA that is the largest size 186*0Sstevel@tonic-gate * - one on a unique disk that is the largest size 187*0Sstevel@tonic-gate * - one on any HBA that is the largest size 188*0Sstevel@tonic-gate * 189*0Sstevel@tonic-gate * The function scans the available slices and builds lists of 190*0Sstevel@tonic-gate * those meeting the criteria above. After the scan is complete, 191*0Sstevel@tonic-gate * the lists are examined in order, the first non-empty list is 192*0Sstevel@tonic-gate * chosen. If there are several possibilities in the chosen list, 193*0Sstevel@tonic-gate * see if it is possible select the slice from the least used HBA 194*0Sstevel@tonic-gate * and/or disk. 195*0Sstevel@tonic-gate * 196*0Sstevel@tonic-gate * If nbytes_is_min is true, the returned slice will be 197*0Sstevel@tonic-gate * at least nbytes in capacity. 198*0Sstevel@tonic-gate * 199*0Sstevel@tonic-gate * If unused_disk is true, the returned slice will be from 200*0Sstevel@tonic-gate * a disk with no other known uses. 201*0Sstevel@tonic-gate */ 202*0Sstevel@tonic-gate int 203*0Sstevel@tonic-gate choose_slice( 204*0Sstevel@tonic-gate uint64_t nbytes, 205*0Sstevel@tonic-gate uint16_t npaths, 206*0Sstevel@tonic-gate dlist_t *slices, 207*0Sstevel@tonic-gate dlist_t *used, 208*0Sstevel@tonic-gate dlist_t *used_hbas, 209*0Sstevel@tonic-gate dlist_t *used_disks, 210*0Sstevel@tonic-gate boolean_t unused_disk, 211*0Sstevel@tonic-gate boolean_t nbytes_is_min, 212*0Sstevel@tonic-gate boolean_t add_extra_cyl, 213*0Sstevel@tonic-gate devconfig_t **chosen) 214*0Sstevel@tonic-gate { 215*0Sstevel@tonic-gate dlist_t *iter = NULL; 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate dm_descriptor_t slice = NULL; 218*0Sstevel@tonic-gate boolean_t resize = B_FALSE; 219*0Sstevel@tonic-gate boolean_t verbose = (get_max_verbosity() == OUTPUT_VERBOSE); 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate int error = 0; 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate /* 224*0Sstevel@tonic-gate * indexes into the list array: 225*0Sstevel@tonic-gate * i -> unique controller 0 = yes, 1 = no 226*0Sstevel@tonic-gate * j -> same bus type 0 = yes, 1 = no 227*0Sstevel@tonic-gate * k -> unique disk 0 = yes, 1 = no 228*0Sstevel@tonic-gate * l -> same disk geom 0 = yes, 1 = no 229*0Sstevel@tonic-gate * m -> size 0 == exact, 1 = larger, 2 = any 230*0Sstevel@tonic-gate */ 231*0Sstevel@tonic-gate int i, j, k, l, m; 232*0Sstevel@tonic-gate dlist_t *list[2][2][2][2][3]; 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate /* output string arrays for each array dimension and index */ 235*0Sstevel@tonic-gate char *uniqhba[2]; 236*0Sstevel@tonic-gate char *samebus[2]; 237*0Sstevel@tonic-gate char *uniqdisk[2]; 238*0Sstevel@tonic-gate char *samegeom[2]; 239*0Sstevel@tonic-gate char *sizes[3]; 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate /* other output strings */ 242*0Sstevel@tonic-gate char *look_msg = NULL; 243*0Sstevel@tonic-gate char *npaths_msg = NULL; 244*0Sstevel@tonic-gate char *samegeom_msg = NULL; 245*0Sstevel@tonic-gate char *samebus_msg = NULL; 246*0Sstevel@tonic-gate char *uniqhba_msg = NULL; 247*0Sstevel@tonic-gate char *uniqdisk_msg = NULL; 248*0Sstevel@tonic-gate char *exact_msg = NULL; 249*0Sstevel@tonic-gate char *larger_msg = NULL; 250*0Sstevel@tonic-gate char *smaller_msg = NULL; 251*0Sstevel@tonic-gate char *insuff_paths = NULL; 252*0Sstevel@tonic-gate char *too_small = NULL; 253*0Sstevel@tonic-gate char *useddisk_msg = NULL; 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate if (verbose == B_TRUE) { 256*0Sstevel@tonic-gate /* only initialize the output strings if needed */ 257*0Sstevel@tonic-gate 258*0Sstevel@tonic-gate /* BEGIN CSTYLED */ 259*0Sstevel@tonic-gate look_msg = gettext( 260*0Sstevel@tonic-gate "\tlooking at slice: %s (%s)\n"); 261*0Sstevel@tonic-gate npaths_msg = gettext( 262*0Sstevel@tonic-gate "\t has the requested number of data paths (%d)\n"); 263*0Sstevel@tonic-gate samegeom_msg = gettext( 264*0Sstevel@tonic-gate "\t has the same disk geometry relative to used slices\n"); 265*0Sstevel@tonic-gate samebus_msg = gettext( 266*0Sstevel@tonic-gate "\t on a similar I/O bus/HBA relative to used slices\n"); 267*0Sstevel@tonic-gate uniqhba_msg = gettext( 268*0Sstevel@tonic-gate "\t on a unique HBA relative to used slices\n"); 269*0Sstevel@tonic-gate uniqdisk_msg = gettext( 270*0Sstevel@tonic-gate "\t on a unique disk relative to used slices\n"); 271*0Sstevel@tonic-gate exact_msg = gettext( 272*0Sstevel@tonic-gate "\t the exact size necessary\n"); 273*0Sstevel@tonic-gate larger_msg = gettext( 274*0Sstevel@tonic-gate "\t larger than necessary\n"); 275*0Sstevel@tonic-gate smaller_msg = gettext( 276*0Sstevel@tonic-gate "\t smaller than necessary\n"); 277*0Sstevel@tonic-gate insuff_paths = gettext( 278*0Sstevel@tonic-gate "\t rejected: not enough paths (%d requested)\n"); 279*0Sstevel@tonic-gate too_small = gettext( 280*0Sstevel@tonic-gate "\t rejected: too small\n"); 281*0Sstevel@tonic-gate useddisk_msg = gettext( 282*0Sstevel@tonic-gate "\t rejected: on a disk with other volume component(s)\n"); 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gate uniqhba[0] = gettext("unique HBA"); 285*0Sstevel@tonic-gate uniqhba[1] = gettext("non unique HBA"); 286*0Sstevel@tonic-gate samebus[0] = gettext("same bus type"); 287*0Sstevel@tonic-gate samebus[1] = gettext("different bus type"); 288*0Sstevel@tonic-gate uniqdisk[0] = gettext("unique disk"); 289*0Sstevel@tonic-gate uniqdisk[1] = gettext("non unique disk"); 290*0Sstevel@tonic-gate samegeom[0] = gettext("same geometry"); 291*0Sstevel@tonic-gate samegeom[1] = gettext("different geometry"); 292*0Sstevel@tonic-gate sizes[0] = gettext("an exact size slice"); 293*0Sstevel@tonic-gate sizes[1] = gettext("a larger slice"); 294*0Sstevel@tonic-gate sizes[2] = gettext("a smaller slice"); 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate /* END CSTYLED */ 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate /* init list array pointers */ 300*0Sstevel@tonic-gate (void) memset(list, 0, 2*2*2*2*3 * sizeof (dlist_t *)); 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate for (iter = slices; 303*0Sstevel@tonic-gate (iter != NULL) && (error == 0); iter = iter->next) { 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate dm_descriptor_t slice = (uintptr_t)iter->obj; 306*0Sstevel@tonic-gate uint64_t snbytes = 0; 307*0Sstevel@tonic-gate boolean_t uniqdisk = B_FALSE; 308*0Sstevel@tonic-gate boolean_t uniqhba = B_FALSE; 309*0Sstevel@tonic-gate boolean_t samegeom = B_FALSE; 310*0Sstevel@tonic-gate boolean_t samebus = B_FALSE; 311*0Sstevel@tonic-gate boolean_t paths = B_FALSE; 312*0Sstevel@tonic-gate dlist_t *item = NULL; 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate ((error = slice_get_size(slice, &snbytes)) != 0) || 315*0Sstevel@tonic-gate (error = slice_has_n_paths(slice, npaths, &paths)) || 316*0Sstevel@tonic-gate (error = slice_on_unique_hba(slice, used, used_hbas, &uniqhba)) || 317*0Sstevel@tonic-gate (error = slice_on_unique_disk(slice, used, used_disks, 318*0Sstevel@tonic-gate &uniqdisk)) || 319*0Sstevel@tonic-gate (error = slice_on_similar_bus(slice, used, &samebus)) || 320*0Sstevel@tonic-gate (error = slice_has_same_disk_geom(slice, used, &samegeom)); 321*0Sstevel@tonic-gate if (error != 0) { 322*0Sstevel@tonic-gate continue; 323*0Sstevel@tonic-gate } 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate if (verbose == B_TRUE) { 326*0Sstevel@tonic-gate char *sname = NULL; 327*0Sstevel@tonic-gate char *sizestr = NULL; 328*0Sstevel@tonic-gate (void) get_display_name(slice, &sname); 329*0Sstevel@tonic-gate if (bytes_to_sizestr(snbytes, &sizestr, 330*0Sstevel@tonic-gate universal_units, B_FALSE) == 0) { 331*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, look_msg, sname, sizestr); 332*0Sstevel@tonic-gate free(sizestr); 333*0Sstevel@tonic-gate } 334*0Sstevel@tonic-gate } 335*0Sstevel@tonic-gate 336*0Sstevel@tonic-gate if (npaths > 1) { 337*0Sstevel@tonic-gate if (paths && verbose) { 338*0Sstevel@tonic-gate /* specifically asked for more paths, ... */ 339*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, npaths_msg); 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate } else if (npaths == 1) { 342*0Sstevel@tonic-gate /* every disk has at least 1 path */ 343*0Sstevel@tonic-gate paths = B_TRUE; 344*0Sstevel@tonic-gate } 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate if (verbose == B_TRUE) { 347*0Sstevel@tonic-gate if (uniqhba) { 348*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, uniqhba_msg); 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate if (uniqdisk) { 351*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, uniqdisk_msg); 352*0Sstevel@tonic-gate } 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate if (used != NULL) { 355*0Sstevel@tonic-gate if (samebus) { 356*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, samebus_msg); 357*0Sstevel@tonic-gate } 358*0Sstevel@tonic-gate if (samegeom) { 359*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, samegeom_msg); 360*0Sstevel@tonic-gate } 361*0Sstevel@tonic-gate } 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate if (snbytes > nbytes) { 364*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, larger_msg); 365*0Sstevel@tonic-gate } else if (snbytes == nbytes) { 366*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, exact_msg); 367*0Sstevel@tonic-gate } else { 368*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, smaller_msg); 369*0Sstevel@tonic-gate } 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate /* filter slices not meeting minimum criteria */ 373*0Sstevel@tonic-gate if (nbytes_is_min && (snbytes < nbytes)) { 374*0Sstevel@tonic-gate /* not large enough */ 375*0Sstevel@tonic-gate if (verbose == B_TRUE) { 376*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, too_small); 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate continue; 379*0Sstevel@tonic-gate } 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate if (paths == B_FALSE) { 382*0Sstevel@tonic-gate /* not connected thru enough paths */ 383*0Sstevel@tonic-gate if (verbose == B_TRUE) { 384*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, insuff_paths, npaths); 385*0Sstevel@tonic-gate } 386*0Sstevel@tonic-gate continue; 387*0Sstevel@tonic-gate } 388*0Sstevel@tonic-gate 389*0Sstevel@tonic-gate if (uniqdisk != B_TRUE && unused_disk == TRUE) { 390*0Sstevel@tonic-gate /* not on a unique disk */ 391*0Sstevel@tonic-gate if (verbose == B_TRUE) { 392*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, useddisk_msg); 393*0Sstevel@tonic-gate } 394*0Sstevel@tonic-gate continue; 395*0Sstevel@tonic-gate } 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate /* map slice properties into array indices */ 398*0Sstevel@tonic-gate i = (uniqhba ? 0 : 1); 399*0Sstevel@tonic-gate j = (samebus ? 0 : 1); 400*0Sstevel@tonic-gate k = (uniqdisk ? 0 : 1); 401*0Sstevel@tonic-gate l = (samegeom ? 0 : 1); 402*0Sstevel@tonic-gate m = (snbytes == nbytes ? 0 : (snbytes > nbytes ? 1 : 2)); 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate /* 405*0Sstevel@tonic-gate * insert slice into the list array using derived indices. 406*0Sstevel@tonic-gate * NB: lists of slices larger than necessary are kept in 407*0Sstevel@tonic-gate * ascending order (results in best fit, not worst fit) 408*0Sstevel@tonic-gate */ 409*0Sstevel@tonic-gate if ((item = dlist_new_item((void*)slice)) == NULL) { 410*0Sstevel@tonic-gate error = ENOMEM; 411*0Sstevel@tonic-gate } else { 412*0Sstevel@tonic-gate list[i][j][k][l][m] = 413*0Sstevel@tonic-gate dlist_insert_ordered( 414*0Sstevel@tonic-gate item, 415*0Sstevel@tonic-gate list[i][j][k][l][m], 416*0Sstevel@tonic-gate (m == 1 ? ASCENDING : DESCENDING), 417*0Sstevel@tonic-gate compare_slice_sizes); 418*0Sstevel@tonic-gate } 419*0Sstevel@tonic-gate } 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gate /* 422*0Sstevel@tonic-gate * Select a slice from one of the lists. 423*0Sstevel@tonic-gate * 424*0Sstevel@tonic-gate * The list with the combination of lowest indices 425*0Sstevel@tonic-gate * is the most preferred list... in rough order: 426*0Sstevel@tonic-gate * 427*0Sstevel@tonic-gate * one on a unique HBA and disk that is of the exact size 428*0Sstevel@tonic-gate * one on a unique HBA and disk that is of sufficient size (resize) 429*0Sstevel@tonic-gate * one on unique HBA that is of the exact size 430*0Sstevel@tonic-gate * one on unique HBA that is of sufficient size (resize) 431*0Sstevel@tonic-gate * one on unique disk that is of the exact size 432*0Sstevel@tonic-gate * one on unique disk that is of sufficient size (resize) 433*0Sstevel@tonic-gate * one on any HBA that is of exact size 434*0Sstevel@tonic-gate * one on any HBA that is of sufficient size (resize) 435*0Sstevel@tonic-gate * one on a unique HBA that is the largest size 436*0Sstevel@tonic-gate * one on a unique disk that is the largest size 437*0Sstevel@tonic-gate * one on any HBA that is the largest size 438*0Sstevel@tonic-gate */ 439*0Sstevel@tonic-gate slice = NULL; 440*0Sstevel@tonic-gate 441*0Sstevel@tonic-gate for (i = 0; i < 2; i++) { 442*0Sstevel@tonic-gate for (j = 0; j < 2; j++) { 443*0Sstevel@tonic-gate for (k = 0; k < 2; k++) { 444*0Sstevel@tonic-gate for (l = 0; l < 2; l++) { 445*0Sstevel@tonic-gate for (m = 0; m < 3; m++) { 446*0Sstevel@tonic-gate if (list[i][j][k][l][m] != NULL) { 447*0Sstevel@tonic-gate 448*0Sstevel@tonic-gate /* pick least used slice from this list */ 449*0Sstevel@tonic-gate error = pick_from_best_hba_and_disk( 450*0Sstevel@tonic-gate list[i][j][k][l][m], 451*0Sstevel@tonic-gate used, &slice); 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate resize = (m == 1); 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate /* terminate all loops */ 456*0Sstevel@tonic-gate goto stop; 457*0Sstevel@tonic-gate } 458*0Sstevel@tonic-gate } 459*0Sstevel@tonic-gate } 460*0Sstevel@tonic-gate } 461*0Sstevel@tonic-gate } 462*0Sstevel@tonic-gate } 463*0Sstevel@tonic-gate stop: 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate /* 466*0Sstevel@tonic-gate * Slice chosen, is a resize necessary? 467*0Sstevel@tonic-gate */ 468*0Sstevel@tonic-gate if ((error == 0) && (slice != NULL)) { 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate if (error == 0) { 471*0Sstevel@tonic-gate if (verbose == B_TRUE) { 472*0Sstevel@tonic-gate uint64_t snbytes = 0; 473*0Sstevel@tonic-gate char *sname = NULL; 474*0Sstevel@tonic-gate char *sizestr = NULL; 475*0Sstevel@tonic-gate 476*0Sstevel@tonic-gate (void) get_display_name(slice, &sname); 477*0Sstevel@tonic-gate (void) slice_get_size(slice, &snbytes); 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gate if (bytes_to_sizestr(snbytes, &sizestr, 480*0Sstevel@tonic-gate universal_units, B_FALSE) == 0) { 481*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, 482*0Sstevel@tonic-gate gettext(" selected %s (%s)\n" 483*0Sstevel@tonic-gate " it is %s on a\n" 484*0Sstevel@tonic-gate " %s (%s) and a\n" 485*0Sstevel@tonic-gate " %s (%s)\n"), 486*0Sstevel@tonic-gate sname, sizestr, 487*0Sstevel@tonic-gate sizes[m], 488*0Sstevel@tonic-gate uniqhba[i], samebus[j], 489*0Sstevel@tonic-gate uniqdisk[k], samegeom[l]); 490*0Sstevel@tonic-gate free(sizestr); 491*0Sstevel@tonic-gate } 492*0Sstevel@tonic-gate } 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gate if (resize) { 495*0Sstevel@tonic-gate if (verbose == B_TRUE) { 496*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, 497*0Sstevel@tonic-gate gettext(" it has excess space, " 498*0Sstevel@tonic-gate "resizing...\n")); 499*0Sstevel@tonic-gate } 500*0Sstevel@tonic-gate 501*0Sstevel@tonic-gate error = create_new_slice(slice, nbytes, add_extra_cyl, 502*0Sstevel@tonic-gate chosen); 503*0Sstevel@tonic-gate if ((error == 0) && (*chosen != NULL) && verbose) { 504*0Sstevel@tonic-gate oprintf(OUTPUT_VERBOSE, 505*0Sstevel@tonic-gate gettext(" exactly resized\n")); 506*0Sstevel@tonic-gate } 507*0Sstevel@tonic-gate } 508*0Sstevel@tonic-gate 509*0Sstevel@tonic-gate if (error == 0) { 510*0Sstevel@tonic-gate /* either no resize was necessary or the resize failed */ 511*0Sstevel@tonic-gate if (*chosen == NULL) { 512*0Sstevel@tonic-gate /* 513*0Sstevel@tonic-gate * use the original slice as it is. 514*0Sstevel@tonic-gate * Make a devconfig_t for it. 515*0Sstevel@tonic-gate */ 516*0Sstevel@tonic-gate error = create_devconfig_for_slice(slice, chosen); 517*0Sstevel@tonic-gate } 518*0Sstevel@tonic-gate } 519*0Sstevel@tonic-gate } 520*0Sstevel@tonic-gate } else if (slice == NULL) { 521*0Sstevel@tonic-gate oprintf(OUTPUT_DEBUG, 522*0Sstevel@tonic-gate gettext(" no possible slice\n")); 523*0Sstevel@tonic-gate } 524*0Sstevel@tonic-gate 525*0Sstevel@tonic-gate for (i = 0; i < 2; i++) { 526*0Sstevel@tonic-gate for (j = 0; j < 2; j++) { 527*0Sstevel@tonic-gate for (k = 0; k < 2; k++) { 528*0Sstevel@tonic-gate for (l = 0; l < 2; l++) { 529*0Sstevel@tonic-gate for (m = 0; m < 3; m++) { 530*0Sstevel@tonic-gate if (list[i][j][k][l][m] != NULL) { 531*0Sstevel@tonic-gate dlist_free_items(list[i][j][k][l][m], NULL); 532*0Sstevel@tonic-gate } 533*0Sstevel@tonic-gate } 534*0Sstevel@tonic-gate } 535*0Sstevel@tonic-gate } 536*0Sstevel@tonic-gate } 537*0Sstevel@tonic-gate } 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate return (error); 540*0Sstevel@tonic-gate } 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate /* 543*0Sstevel@tonic-gate * FUNCTION: create_devconfig_for_slice(dm_descriptor_t slice, 544*0Sstevel@tonic-gate * devconfig_t **nslice) 545*0Sstevel@tonic-gate * 546*0Sstevel@tonic-gate * INPUT: slice - dm_descriptor_t handle to an existing slice 547*0Sstevel@tonic-gate * nslice - devconfig_t pointer to hold the new slice 548*0Sstevel@tonic-gate * 549*0Sstevel@tonic-gate * RETURNS: int - 0 on success 550*0Sstevel@tonic-gate * !0 otherwise 551*0Sstevel@tonic-gate * 552*0Sstevel@tonic-gate * PURPOSE: Creates a devconfig_t struct representation of the input 553*0Sstevel@tonic-gate * slice dm_descriptor. 554*0Sstevel@tonic-gate */ 555*0Sstevel@tonic-gate int 556*0Sstevel@tonic-gate create_devconfig_for_slice( 557*0Sstevel@tonic-gate dm_descriptor_t slice, 558*0Sstevel@tonic-gate devconfig_t **nslice) 559*0Sstevel@tonic-gate { 560*0Sstevel@tonic-gate uint64_t nbytes = 0; 561*0Sstevel@tonic-gate uint64_t nblks = 0; 562*0Sstevel@tonic-gate uint64_t stblk = 0; 563*0Sstevel@tonic-gate uint32_t index = 0; 564*0Sstevel@tonic-gate char *name = NULL; 565*0Sstevel@tonic-gate int error = 0; 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate ((error = get_display_name(slice, &name)) != 0) || 568*0Sstevel@tonic-gate (error = slice_get_size(slice, &nbytes)) || 569*0Sstevel@tonic-gate (error = slice_get_size_in_blocks(slice, &nblks)) || 570*0Sstevel@tonic-gate (error = slice_get_start_block(slice, &stblk)) || 571*0Sstevel@tonic-gate (error = slice_get_index(slice, &index)); 572*0Sstevel@tonic-gate if (error != 0) { 573*0Sstevel@tonic-gate return (error); 574*0Sstevel@tonic-gate } 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate ((error = new_devconfig(nslice, TYPE_SLICE)) != 0) || 577*0Sstevel@tonic-gate (error = devconfig_set_name(*nslice, name)) || 578*0Sstevel@tonic-gate (error = devconfig_set_slice_index(*nslice, index)) || 579*0Sstevel@tonic-gate (error = devconfig_set_slice_start_block(*nslice, stblk)) || 580*0Sstevel@tonic-gate (error = devconfig_set_size_in_blocks(*nslice, nblks)) || 581*0Sstevel@tonic-gate (error = devconfig_set_size(*nslice, nbytes)); 582*0Sstevel@tonic-gate if (error != 0) { 583*0Sstevel@tonic-gate free_devconfig(*nslice); 584*0Sstevel@tonic-gate } 585*0Sstevel@tonic-gate 586*0Sstevel@tonic-gate return (error); 587*0Sstevel@tonic-gate } 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate /* 590*0Sstevel@tonic-gate * FUNCTION: make_slicename_for_disk_and_index(dm_descriptor_t disk, 591*0Sstevel@tonic-gate * uint32_t index, char **slicename) 592*0Sstevel@tonic-gate * 593*0Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t disk handle 594*0Sstevel@tonic-gate * index - a slice index 595*0Sstevel@tonic-gate * 596*0Sstevel@tonic-gate * OUTPUT slicename - a char * pointer to hold the resulting slicename 597*0Sstevel@tonic-gate * 598*0Sstevel@tonic-gate * RETURNS: int - 0 on success 599*0Sstevel@tonic-gate * !0 otherwise 600*0Sstevel@tonic-gate * 601*0Sstevel@tonic-gate * PURPOSE: Utility function to manufacture a new slice name given the 602*0Sstevel@tonic-gate * "parent" disk and an available slice index. 603*0Sstevel@tonic-gate * 604*0Sstevel@tonic-gate * The caller should free the returned name when done with it. 605*0Sstevel@tonic-gate */ 606*0Sstevel@tonic-gate static int 607*0Sstevel@tonic-gate make_slicename_for_disk_and_index( 608*0Sstevel@tonic-gate dm_descriptor_t disk, 609*0Sstevel@tonic-gate uint16_t index, 610*0Sstevel@tonic-gate char **slicename) 611*0Sstevel@tonic-gate { 612*0Sstevel@tonic-gate char *dname; 613*0Sstevel@tonic-gate int error = 0; 614*0Sstevel@tonic-gate 615*0Sstevel@tonic-gate if ((error = get_display_name(disk, &dname)) == 0) { 616*0Sstevel@tonic-gate error = make_slicename_for_diskname_and_index(dname, 617*0Sstevel@tonic-gate index, slicename); 618*0Sstevel@tonic-gate } 619*0Sstevel@tonic-gate 620*0Sstevel@tonic-gate return (error); 621*0Sstevel@tonic-gate } 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gate /* 624*0Sstevel@tonic-gate * FUNCTION: make_slicename_for_diskname_and_index(char *diskname, 625*0Sstevel@tonic-gate * uint32_t index, char **slicename) 626*0Sstevel@tonic-gate * 627*0Sstevel@tonic-gate * INPUT: diskname - a char * disk name 628*0Sstevel@tonic-gate * index - a slice index 629*0Sstevel@tonic-gate * 630*0Sstevel@tonic-gate * OUTPUT slicename - a char * pointer to hold the resulting slicename 631*0Sstevel@tonic-gate * 632*0Sstevel@tonic-gate * RETURNS: int - 0 on success 633*0Sstevel@tonic-gate * !0 otherwise 634*0Sstevel@tonic-gate * 635*0Sstevel@tonic-gate * PURPOSE: Utility function to manufacture a new slice name given the 636*0Sstevel@tonic-gate * name of a disk and an available slice index. 637*0Sstevel@tonic-gate * 638*0Sstevel@tonic-gate * The caller should free the returned name when done with it. 639*0Sstevel@tonic-gate */ 640*0Sstevel@tonic-gate int 641*0Sstevel@tonic-gate make_slicename_for_diskname_and_index( 642*0Sstevel@tonic-gate char *diskname, 643*0Sstevel@tonic-gate uint16_t index, 644*0Sstevel@tonic-gate char **slicename) 645*0Sstevel@tonic-gate { 646*0Sstevel@tonic-gate int error = 0; 647*0Sstevel@tonic-gate char buf[MAXNAMELEN+1]; 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%ss%u", diskname, index); 650*0Sstevel@tonic-gate if ((*slicename = strdup(buf)) == NULL) { 651*0Sstevel@tonic-gate *slicename = NULL; 652*0Sstevel@tonic-gate error = ENOMEM; 653*0Sstevel@tonic-gate } 654*0Sstevel@tonic-gate 655*0Sstevel@tonic-gate return (error); 656*0Sstevel@tonic-gate } 657*0Sstevel@tonic-gate 658*0Sstevel@tonic-gate /* 659*0Sstevel@tonic-gate * FUNCTION: create_new_slice(dm_descriptor_t oslice, uint64_t nbytes, 660*0Sstevel@tonic-gate * boolean_t add_extra_cyl, devconfig_t **nslice) 661*0Sstevel@tonic-gate * 662*0Sstevel@tonic-gate * INPUT: oslice - dm_descriptor_t handle to an existing slice 663*0Sstevel@tonic-gate * nbytes - desired minimum size of the new slice 664*0Sstevel@tonic-gate * add_extra_cyl - boolean indicating whether the resized slice 665*0Sstevel@tonic-gate * needs to be oversized by 1 cylinder to account for 666*0Sstevel@tonic-gate * interlace rounding done for stripe components. 667*0Sstevel@tonic-gate * nslice - devconfig_t pointer to hold the new slice 668*0Sstevel@tonic-gate * 669*0Sstevel@tonic-gate * RETURNS: int - 0 on success 670*0Sstevel@tonic-gate * !0 otherwise 671*0Sstevel@tonic-gate * 672*0Sstevel@tonic-gate * PURPOSE: Creates a new slice object using space from the input slice. 673*0Sstevel@tonic-gate * 674*0Sstevel@tonic-gate * If there is an open slice slot in the disk VTOC, it will be 675*0Sstevel@tonic-gate * reserved for the new slice. Space for the new slice will be 676*0Sstevel@tonic-gate * taken from the original slice. 677*0Sstevel@tonic-gate * 678*0Sstevel@tonic-gate * If there is no open slice slot, the original slice will be 679*0Sstevel@tonic-gate * returned as the usable new slice. 680*0Sstevel@tonic-gate * 681*0Sstevel@tonic-gate * The new slice will be of at least 'nbytes' bytes and possibly 682*0Sstevel@tonic-gate * larger due to sector and cylinder boundary alignment. 683*0Sstevel@tonic-gate * 684*0Sstevel@tonic-gate * For EFI labeled disks, nbytes is rounded up to the next block 685*0Sstevel@tonic-gate * boundary. 686*0Sstevel@tonic-gate * 687*0Sstevel@tonic-gate * For VTOC labeled disks, nbytes is rounded up to the next 688*0Sstevel@tonic-gate * cylinder boundary. 689*0Sstevel@tonic-gate * 690*0Sstevel@tonic-gate * Additionally, if add_extra_cyl is true, the new slice will be 691*0Sstevel@tonic-gate * made 1 cylinder larger than necessary. This accounts for the 692*0Sstevel@tonic-gate * interlace rounding done within libmeta when computing the 693*0Sstevel@tonic-gate * usable size of stripe components on disks with VTOC labels. 694*0Sstevel@tonic-gate * Rounding the size up to the next cylinder boundary is not 695*0Sstevel@tonic-gate * sufficient because libmeta will round this size down to an 696*0Sstevel@tonic-gate * integral multiple of the stripe interlace and then round that 697*0Sstevel@tonic-gate * result down to a cylinder boundary. This makes the usable 698*0Sstevel@tonic-gate * size of the slice one cylinder smaller and possibly less than 699*0Sstevel@tonic-gate * nbytes. Adding an extra cylinder ensures the usable size is 700*0Sstevel@tonic-gate * greater than nbytes despite the rounding. 701*0Sstevel@tonic-gate * 702*0Sstevel@tonic-gate * If the resize is successful a pointer to the devconfig_t 703*0Sstevel@tonic-gate * representing the new slice will be returned in "newslice". 704*0Sstevel@tonic-gate * 705*0Sstevel@tonic-gate * If the resize cannot be done, the newslice pointer will 706*0Sstevel@tonic-gate * be NULL. 707*0Sstevel@tonic-gate */ 708*0Sstevel@tonic-gate static int 709*0Sstevel@tonic-gate create_new_slice( 710*0Sstevel@tonic-gate dm_descriptor_t oslice, 711*0Sstevel@tonic-gate uint64_t nbytes, 712*0Sstevel@tonic-gate boolean_t add_extra_cyl, 713*0Sstevel@tonic-gate devconfig_t **nslice) 714*0Sstevel@tonic-gate { 715*0Sstevel@tonic-gate dm_descriptor_t odisk = NULL; 716*0Sstevel@tonic-gate boolean_t efi = B_FALSE; 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate char *oname = NULL; 719*0Sstevel@tonic-gate uint64_t osize = 0; /* orig size (bytes) */ 720*0Sstevel@tonic-gate uint64_t ostart = 0; /* orig start (byte) */ 721*0Sstevel@tonic-gate uint64_t ostblk = 0; /* orig start (blk) */ 722*0Sstevel@tonic-gate uint64_t nsize = 0; /* new size (bytes) */ 723*0Sstevel@tonic-gate uint64_t bytes_per_sect = 0; 724*0Sstevel@tonic-gate 725*0Sstevel@tonic-gate uint32_t oindex = 0; 726*0Sstevel@tonic-gate uint32_t nindex = oindex; 727*0Sstevel@tonic-gate 728*0Sstevel@tonic-gate int error = 0; 729*0Sstevel@tonic-gate 730*0Sstevel@tonic-gate *nslice = NULL; 731*0Sstevel@tonic-gate 732*0Sstevel@tonic-gate ((error = slice_get_disk(oslice, &odisk)) != 0) || 733*0Sstevel@tonic-gate (error = slice_get_index(oslice, &oindex)); 734*0Sstevel@tonic-gate if (error != 0) { 735*0Sstevel@tonic-gate return (error); 736*0Sstevel@tonic-gate } 737*0Sstevel@tonic-gate 738*0Sstevel@tonic-gate /* find an unused slice number, default to oindex */ 739*0Sstevel@tonic-gate nindex = oindex; 740*0Sstevel@tonic-gate if ((error = disk_get_available_slice_index(odisk, &nindex)) != 0) { 741*0Sstevel@tonic-gate return (error); 742*0Sstevel@tonic-gate } 743*0Sstevel@tonic-gate 744*0Sstevel@tonic-gate ((error = get_display_name(oslice, &oname)) != 0) || 745*0Sstevel@tonic-gate (error = slice_get_size(oslice, &osize)) || 746*0Sstevel@tonic-gate (error = slice_get_start(oslice, &ostart)) || 747*0Sstevel@tonic-gate (error = slice_get_start_block(oslice, &ostblk)) || 748*0Sstevel@tonic-gate (error = disk_get_is_efi(odisk, &efi)) || 749*0Sstevel@tonic-gate (error = disk_get_blocksize(odisk, &bytes_per_sect)); 750*0Sstevel@tonic-gate if (error != 0) { 751*0Sstevel@tonic-gate return (error); 752*0Sstevel@tonic-gate } 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate if (efi) { 755*0Sstevel@tonic-gate 756*0Sstevel@tonic-gate /* EFI: round size to an integral number of blocks (sectors) */ 757*0Sstevel@tonic-gate nsize = bytes_per_sect * 758*0Sstevel@tonic-gate ((nbytes + (bytes_per_sect - 1)) / bytes_per_sect); 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate oprintf(OUTPUT_DEBUG, 761*0Sstevel@tonic-gate gettext(" " 762*0Sstevel@tonic-gate "rounded up to %10.2f blocks\n"), 763*0Sstevel@tonic-gate (double)(nsize/bytes_per_sect)); 764*0Sstevel@tonic-gate 765*0Sstevel@tonic-gate } else { 766*0Sstevel@tonic-gate 767*0Sstevel@tonic-gate /* VTOC: round size to an integral number of cylinders */ 768*0Sstevel@tonic-gate uint64_t nhead = 0; 769*0Sstevel@tonic-gate uint64_t nsect = 0; 770*0Sstevel@tonic-gate uint64_t ncyls = 0; 771*0Sstevel@tonic-gate 772*0Sstevel@tonic-gate ((error = disk_get_ncylinders(odisk, &ncyls)) != 0) || 773*0Sstevel@tonic-gate (error = disk_get_nheads(odisk, &nhead)) || 774*0Sstevel@tonic-gate (error = disk_get_nsectors(odisk, &nsect)); 775*0Sstevel@tonic-gate if (error == 0) { 776*0Sstevel@tonic-gate uint64_t bytes_per_cyl = nhead * nsect * bytes_per_sect; 777*0Sstevel@tonic-gate nsize = bytes_per_cyl * 778*0Sstevel@tonic-gate ((nbytes + (bytes_per_cyl - 1)) / bytes_per_cyl); 779*0Sstevel@tonic-gate 780*0Sstevel@tonic-gate if (add_extra_cyl == TRUE) { 781*0Sstevel@tonic-gate nsize += bytes_per_cyl; 782*0Sstevel@tonic-gate } 783*0Sstevel@tonic-gate 784*0Sstevel@tonic-gate oprintf(OUTPUT_DEBUG, 785*0Sstevel@tonic-gate gettext(" " 786*0Sstevel@tonic-gate "rounded VTOC slice to %10.2f cylinders " 787*0Sstevel@tonic-gate "(out of %llu)\n"), 788*0Sstevel@tonic-gate (double)(nsize/bytes_per_cyl), ncyls); 789*0Sstevel@tonic-gate } 790*0Sstevel@tonic-gate } 791*0Sstevel@tonic-gate 792*0Sstevel@tonic-gate /* is sufficient space still available? */ 793*0Sstevel@tonic-gate if (error == 0) { 794*0Sstevel@tonic-gate if (osize == nsize) { 795*0Sstevel@tonic-gate /* use existing slice as is */ 796*0Sstevel@tonic-gate ((error = create_devconfig_for_slice(oslice, nslice)) != 0) || 797*0Sstevel@tonic-gate (error = disk_reserve_index(odisk, (uint16_t)nindex)); 798*0Sstevel@tonic-gate } else if (osize > nsize) { 799*0Sstevel@tonic-gate 800*0Sstevel@tonic-gate if (nindex == oindex) { 801*0Sstevel@tonic-gate /* no more slices, resize existing slice */ 802*0Sstevel@tonic-gate ((error = create_devconfig_for_slice(oslice, 803*0Sstevel@tonic-gate nslice)) != 0) || 804*0Sstevel@tonic-gate (error = devconfig_set_size(*nslice, nsize)) || 805*0Sstevel@tonic-gate (error = devconfig_set_size_in_blocks(*nslice, 806*0Sstevel@tonic-gate nsize/bytes_per_sect)); 807*0Sstevel@tonic-gate (error = disk_reserve_index(odisk, (uint16_t)nindex)); 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate } else { 810*0Sstevel@tonic-gate /* make a new slice */ 811*0Sstevel@tonic-gate char *nname = NULL; 812*0Sstevel@tonic-gate 813*0Sstevel@tonic-gate ((error = make_slicename_for_disk_and_index(odisk, 814*0Sstevel@tonic-gate nindex, &nname)) != 0) || 815*0Sstevel@tonic-gate (error = create_modified_slice(oslice, oname, oindex, 816*0Sstevel@tonic-gate ostart, osize, bytes_per_sect, nname, nindex, nsize, 817*0Sstevel@tonic-gate nslice)) || 818*0Sstevel@tonic-gate /* mark the new slice's index as used */ 819*0Sstevel@tonic-gate (error = disk_reserve_index(odisk, (uint16_t)nindex)); 820*0Sstevel@tonic-gate 821*0Sstevel@tonic-gate if ((error != 0) && (*nslice == NULL)) { 822*0Sstevel@tonic-gate free(nname); 823*0Sstevel@tonic-gate } 824*0Sstevel@tonic-gate } 825*0Sstevel@tonic-gate } 826*0Sstevel@tonic-gate } 827*0Sstevel@tonic-gate 828*0Sstevel@tonic-gate return (error); 829*0Sstevel@tonic-gate } 830*0Sstevel@tonic-gate 831*0Sstevel@tonic-gate /* 832*0Sstevel@tonic-gate * FUNCTION: create_modified_slice(dm_descriptor_t oslice, char *oname, 833*0Sstevel@tonic-gate * uint32_t oindex, uint64_t ostart, uint64_t osize, 834*0Sstevel@tonic-gate * uint64_t bytes_per_sect, uint64_t nsize, 835*0Sstevel@tonic-gate * char *nname, uint32_t nindex, devconfig_t **nslice) 836*0Sstevel@tonic-gate * 837*0Sstevel@tonic-gate * INPUT: oslice - dm_descriptor_t handle for the original slice 838*0Sstevel@tonic-gate * oname - existing source slice name 839*0Sstevel@tonic-gate * oindex - existing source slice VTOC index 840*0Sstevel@tonic-gate * ostart - existing source slice start byte 841*0Sstevel@tonic-gate * osize - existing source slice size in bytes 842*0Sstevel@tonic-gate * bytes_per_sect - bytes per block (sector) for the disk 843*0Sstevel@tonic-gate * nname - new slice name 844*0Sstevel@tonic-gate * nindex - new slice VTOC index 845*0Sstevel@tonic-gate * nsize - new slice size in bytes (cylinder and block aligned) 846*0Sstevel@tonic-gate * 847*0Sstevel@tonic-gate * SIDEEFFECTS: updates the module private list of modified slices 848*0Sstevel@tonic-gate * 849*0Sstevel@tonic-gate * OUTPUT: nslice - pointer to a devconfig_t to hold the new slice 850*0Sstevel@tonic-gate * 851*0Sstevel@tonic-gate * PURPOSE: create a new VTOC slice by taking space from an 852*0Sstevel@tonic-gate * existing slice. 853*0Sstevel@tonic-gate * 854*0Sstevel@tonic-gate * The input size for the new slice is expected to be 855*0Sstevel@tonic-gate * cylinder aligned. 856*0Sstevel@tonic-gate */ 857*0Sstevel@tonic-gate static int 858*0Sstevel@tonic-gate create_modified_slice( 859*0Sstevel@tonic-gate dm_descriptor_t oslice, 860*0Sstevel@tonic-gate char *oname, 861*0Sstevel@tonic-gate uint32_t oindex, 862*0Sstevel@tonic-gate uint64_t ostart, 863*0Sstevel@tonic-gate uint64_t osize, 864*0Sstevel@tonic-gate uint64_t bytes_per_sect, 865*0Sstevel@tonic-gate char *nname, 866*0Sstevel@tonic-gate uint32_t nindex, 867*0Sstevel@tonic-gate uint64_t nsize, 868*0Sstevel@tonic-gate devconfig_t **nslice) 869*0Sstevel@tonic-gate { 870*0Sstevel@tonic-gate int error = 0; 871*0Sstevel@tonic-gate 872*0Sstevel@tonic-gate /* compute start sector and size in sectors for the new slice */ 873*0Sstevel@tonic-gate 874*0Sstevel@tonic-gate /* subtract nsize from original slice to get starting byte */ 875*0Sstevel@tonic-gate uint64_t nstart = (ostart + osize) - nsize; 876*0Sstevel@tonic-gate 877*0Sstevel@tonic-gate /* convert starting byte to a sector */ 878*0Sstevel@tonic-gate uint64_t nstblk = (uint64_t)(nstart / bytes_per_sect); 879*0Sstevel@tonic-gate 880*0Sstevel@tonic-gate /* convert nsize to an integral number of blocks (sectors) */ 881*0Sstevel@tonic-gate uint64_t nblks = (uint64_t)(nsize / bytes_per_sect); 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate /* create a modified slice record for the new slice */ 884*0Sstevel@tonic-gate error = assemble_modified_slice(oslice, nname, nindex, 885*0Sstevel@tonic-gate nstblk, nblks, nsize, nslice); 886*0Sstevel@tonic-gate if (error != 0) { 887*0Sstevel@tonic-gate free(nname); 888*0Sstevel@tonic-gate return (error); 889*0Sstevel@tonic-gate } 890*0Sstevel@tonic-gate 891*0Sstevel@tonic-gate /* update the existing source slice's new size */ 892*0Sstevel@tonic-gate osize = osize - nsize; 893*0Sstevel@tonic-gate (void) slice_set_size(oslice, osize); 894*0Sstevel@tonic-gate 895*0Sstevel@tonic-gate /* update/create the modified slice record gfor the source slice */ 896*0Sstevel@tonic-gate error = assemble_modified_slice((dm_descriptor_t)0, 897*0Sstevel@tonic-gate oname, oindex, (uint64_t)(ostart / bytes_per_sect), 898*0Sstevel@tonic-gate (uint64_t)(osize / bytes_per_sect), 899*0Sstevel@tonic-gate osize, NULL); 900*0Sstevel@tonic-gate 901*0Sstevel@tonic-gate return (error); 902*0Sstevel@tonic-gate } 903*0Sstevel@tonic-gate 904*0Sstevel@tonic-gate /* 905*0Sstevel@tonic-gate * FUNCTION: assemble_modified_slice(dm_descriptor_t src_slice, 906*0Sstevel@tonic-gate * char *mod_name, uint32_t mod_index, 907*0Sstevel@tonic-gate * uint64_t mod_stblk, uint64_t mod_nblks, 908*0Sstevel@tonic-gate * uint64_t mod_size, devconfig_t **modslice) 909*0Sstevel@tonic-gate * 910*0Sstevel@tonic-gate * INPUT: src_slice - dm_descriptor_t handle of the slice space 911*0Sstevel@tonic-gate * was taken from to create the modified slice 912*0Sstevel@tonic-gate * mod_name - name of the modified slice 913*0Sstevel@tonic-gate * mod_index - name of the modified slice 914*0Sstevel@tonic-gate * mod_stblk - start block of the modified slice 915*0Sstevel@tonic-gate * mod_nblks - size in blocks of the modified slice 916*0Sstevel@tonic-gate * mod_size - size in bytes of the modified slice 917*0Sstevel@tonic-gate * 918*0Sstevel@tonic-gate * OUTPUT: mod_slice - if non-NULL, will be populated with a 919*0Sstevel@tonic-gate * devconfig_t representing the modified slice. 920*0Sstevel@tonic-gate * 921*0Sstevel@tonic-gate * SIDEEFFECTS: adds or updates an entry in the modified slice list 922*0Sstevel@tonic-gate * tracking the slices that have been explicitly modified 923*0Sstevel@tonic-gate * by the layout code. 924*0Sstevel@tonic-gate * 925*0Sstevel@tonic-gate * RETURNS: int - 0 on success 926*0Sstevel@tonic-gate * !0 otherwise 927*0Sstevel@tonic-gate * 928*0Sstevel@tonic-gate * PURPOSE: Utility function to which updates or creates a devconfig_t 929*0Sstevel@tonic-gate * representing a slice that needs to be modified. 930*0Sstevel@tonic-gate * 931*0Sstevel@tonic-gate * If a modified slice record does not exist for the named 932*0Sstevel@tonic-gate * slice, a new devconfig_t struct is allocated and added 933*0Sstevel@tonic-gate * to the modified slice list. 934*0Sstevel@tonic-gate * 935*0Sstevel@tonic-gate * The existing or created devconfig_t struct is updated with 936*0Sstevel@tonic-gate * the input values. 937*0Sstevel@tonic-gate * 938*0Sstevel@tonic-gate * The information about the slices in the modified slice list 939*0Sstevel@tonic-gate * will eventually be handed to fmthard. 940*0Sstevel@tonic-gate */ 941*0Sstevel@tonic-gate int 942*0Sstevel@tonic-gate assemble_modified_slice( 943*0Sstevel@tonic-gate dm_descriptor_t src_slice, 944*0Sstevel@tonic-gate char *mod_name, 945*0Sstevel@tonic-gate uint32_t mod_index, 946*0Sstevel@tonic-gate uint64_t mod_stblk, 947*0Sstevel@tonic-gate uint64_t mod_nblks, 948*0Sstevel@tonic-gate uint64_t mod_size, 949*0Sstevel@tonic-gate devconfig_t **mod_slice) 950*0Sstevel@tonic-gate { 951*0Sstevel@tonic-gate devconfig_t *slice = NULL; 952*0Sstevel@tonic-gate modslice_t *mstp = NULL; 953*0Sstevel@tonic-gate dlist_t *item = NULL; 954*0Sstevel@tonic-gate int error = 0; 955*0Sstevel@tonic-gate 956*0Sstevel@tonic-gate /* see if the slice has been modified before */ 957*0Sstevel@tonic-gate if ((item = dlist_find(_modified_slices, mod_name, 958*0Sstevel@tonic-gate compare_string_to_modslice_name)) != NULL) { 959*0Sstevel@tonic-gate 960*0Sstevel@tonic-gate /* yes, update the resize count and attributes */ 961*0Sstevel@tonic-gate mstp = (modslice_t *)item->obj; 962*0Sstevel@tonic-gate slice = mstp->slice_devcfg; 963*0Sstevel@tonic-gate 964*0Sstevel@tonic-gate mstp->times_modified += 1; 965*0Sstevel@tonic-gate mstp->src_slice_desc = src_slice; 966*0Sstevel@tonic-gate 967*0Sstevel@tonic-gate ((error = devconfig_set_slice_start_block(slice, 968*0Sstevel@tonic-gate mod_stblk)) != 0) || 969*0Sstevel@tonic-gate (error = devconfig_set_size(slice, mod_size)) || 970*0Sstevel@tonic-gate (error = devconfig_set_size_in_blocks(slice, mod_nblks)); 971*0Sstevel@tonic-gate 972*0Sstevel@tonic-gate } else { 973*0Sstevel@tonic-gate 974*0Sstevel@tonic-gate /* no, first modification... */ 975*0Sstevel@tonic-gate /* create a devconfig_t representing the new slice */ 976*0Sstevel@tonic-gate ((error = new_devconfig(&slice, TYPE_SLICE)) != 0) || 977*0Sstevel@tonic-gate (error = devconfig_set_name(slice, mod_name)) || 978*0Sstevel@tonic-gate (error = devconfig_set_slice_index(slice, mod_index)) || 979*0Sstevel@tonic-gate (error = devconfig_set_slice_start_block(slice, mod_stblk)) || 980*0Sstevel@tonic-gate (error = devconfig_set_size_in_blocks(slice, mod_nblks)) || 981*0Sstevel@tonic-gate (error = devconfig_set_size(slice, mod_size)); 982*0Sstevel@tonic-gate if (error == 0) { 983*0Sstevel@tonic-gate /* add to list of modified slices */ 984*0Sstevel@tonic-gate if ((mstp = (modslice_t *) 985*0Sstevel@tonic-gate calloc(1, sizeof (modslice_t))) != NULL) { 986*0Sstevel@tonic-gate 987*0Sstevel@tonic-gate /* count # of times source slice has been modified */ 988*0Sstevel@tonic-gate if (src_slice != (dm_descriptor_t)0) { 989*0Sstevel@tonic-gate mstp->times_modified = 0; 990*0Sstevel@tonic-gate } else { 991*0Sstevel@tonic-gate mstp->times_modified = 1; 992*0Sstevel@tonic-gate } 993*0Sstevel@tonic-gate mstp->src_slice_desc = src_slice; 994*0Sstevel@tonic-gate mstp->slice_devcfg = slice; 995*0Sstevel@tonic-gate 996*0Sstevel@tonic-gate if ((item = dlist_new_item(mstp)) != NULL) { 997*0Sstevel@tonic-gate _modified_slices = 998*0Sstevel@tonic-gate dlist_insert_ordered( 999*0Sstevel@tonic-gate item, 1000*0Sstevel@tonic-gate _modified_slices, 1001*0Sstevel@tonic-gate ASCENDING, 1002*0Sstevel@tonic-gate compare_modslice_names); 1003*0Sstevel@tonic-gate } else { 1004*0Sstevel@tonic-gate error = ENOMEM; 1005*0Sstevel@tonic-gate } 1006*0Sstevel@tonic-gate } else { 1007*0Sstevel@tonic-gate error = ENOMEM; 1008*0Sstevel@tonic-gate } 1009*0Sstevel@tonic-gate } 1010*0Sstevel@tonic-gate 1011*0Sstevel@tonic-gate if (error != 0) { 1012*0Sstevel@tonic-gate free_devconfig(mstp); 1013*0Sstevel@tonic-gate free_devconfig(slice); 1014*0Sstevel@tonic-gate } 1015*0Sstevel@tonic-gate } 1016*0Sstevel@tonic-gate 1017*0Sstevel@tonic-gate if (error == 0) { 1018*0Sstevel@tonic-gate oprintf(OUTPUT_DEBUG, 1019*0Sstevel@tonic-gate " " 1020*0Sstevel@tonic-gate "modified %s (start blk: %9llu, nblks: %9llu)\n", 1021*0Sstevel@tonic-gate mod_name, mod_stblk, mod_nblks); 1022*0Sstevel@tonic-gate 1023*0Sstevel@tonic-gate /* return devconfig_t for modified slice */ 1024*0Sstevel@tonic-gate if (mod_slice != NULL) { 1025*0Sstevel@tonic-gate *mod_slice = slice; 1026*0Sstevel@tonic-gate mstp->volume_component = B_TRUE; 1027*0Sstevel@tonic-gate } 1028*0Sstevel@tonic-gate } 1029*0Sstevel@tonic-gate 1030*0Sstevel@tonic-gate return (error); 1031*0Sstevel@tonic-gate } 1032*0Sstevel@tonic-gate 1033*0Sstevel@tonic-gate /* 1034*0Sstevel@tonic-gate * FUNCTION: dlist_t *get_modified_slices() 1035*0Sstevel@tonic-gate * 1036*0Sstevel@tonic-gate * RETURNS: pointer to the list of modslice_t structs representing 1037*0Sstevel@tonic-gate * modified slices 1038*0Sstevel@tonic-gate * 1039*0Sstevel@tonic-gate * PURPOSE: public accessor to the list of slices modified while 1040*0Sstevel@tonic-gate * processing a request. 1041*0Sstevel@tonic-gate */ 1042*0Sstevel@tonic-gate dlist_t * 1043*0Sstevel@tonic-gate get_modified_slices() 1044*0Sstevel@tonic-gate { 1045*0Sstevel@tonic-gate return (_modified_slices); 1046*0Sstevel@tonic-gate } 1047*0Sstevel@tonic-gate 1048*0Sstevel@tonic-gate /* 1049*0Sstevel@tonic-gate * FUNCTION: free_modslice_object(void *obj) 1050*0Sstevel@tonic-gate * 1051*0Sstevel@tonic-gate * INPUT: obj - opaque pointer 1052*0Sstevel@tonic-gate * 1053*0Sstevel@tonic-gate * PURPOSE: Frees memory associated with a modslice_t struct. 1054*0Sstevel@tonic-gate */ 1055*0Sstevel@tonic-gate static void 1056*0Sstevel@tonic-gate free_modslice_object( 1057*0Sstevel@tonic-gate void *obj) 1058*0Sstevel@tonic-gate { 1059*0Sstevel@tonic-gate assert(obj != (modslice_t *)NULL); 1060*0Sstevel@tonic-gate 1061*0Sstevel@tonic-gate if (((modslice_t *)obj)->slice_devcfg != NULL) { 1062*0Sstevel@tonic-gate if (((modslice_t *)obj)->volume_component != B_TRUE) { 1063*0Sstevel@tonic-gate free_devconfig(((modslice_t *)obj)->slice_devcfg); 1064*0Sstevel@tonic-gate } 1065*0Sstevel@tonic-gate } 1066*0Sstevel@tonic-gate 1067*0Sstevel@tonic-gate free(obj); 1068*0Sstevel@tonic-gate } 1069*0Sstevel@tonic-gate 1070*0Sstevel@tonic-gate /* 1071*0Sstevel@tonic-gate * FUNCTION: void release_modified_slices() 1072*0Sstevel@tonic-gate * 1073*0Sstevel@tonic-gate * INPUT: none - 1074*0Sstevel@tonic-gate * OUTPUT: none - 1075*0Sstevel@tonic-gate * 1076*0Sstevel@tonic-gate * PURPOSE: cleanup the module global list of slices modified 1077*0Sstevel@tonic-gate * while processing a request. 1078*0Sstevel@tonic-gate */ 1079*0Sstevel@tonic-gate int 1080*0Sstevel@tonic-gate release_modified_slices() 1081*0Sstevel@tonic-gate { 1082*0Sstevel@tonic-gate dlist_free_items(_modified_slices, free_modslice_object); 1083*0Sstevel@tonic-gate _modified_slices = NULL; 1084*0Sstevel@tonic-gate 1085*0Sstevel@tonic-gate return (0); 1086*0Sstevel@tonic-gate } 1087*0Sstevel@tonic-gate 1088*0Sstevel@tonic-gate /* 1089*0Sstevel@tonic-gate * FUNCTION: destroy_new_slice(devconfig_t *dev) 1090*0Sstevel@tonic-gate * 1091*0Sstevel@tonic-gate * INPUT: dev - a devconfig_t pointer to a slice object 1092*0Sstevel@tonic-gate * 1093*0Sstevel@tonic-gate * RETURNS: int - 0 on success 1094*0Sstevel@tonic-gate * !0 otherwise 1095*0Sstevel@tonic-gate * 1096*0Sstevel@tonic-gate * PURPOSE: Undoes slice creation done by create_new_slice(): 1097*0Sstevel@tonic-gate * 1098*0Sstevel@tonic-gate * release index 1099*0Sstevel@tonic-gate * remove from used_slices 1100*0Sstevel@tonic-gate * remove from modified_slices 1101*0Sstevel@tonic-gate * return space to source slice 1102*0Sstevel@tonic-gate * free memory 1103*0Sstevel@tonic-gate */ 1104*0Sstevel@tonic-gate int 1105*0Sstevel@tonic-gate destroy_new_slice( 1106*0Sstevel@tonic-gate devconfig_t *dev) 1107*0Sstevel@tonic-gate { 1108*0Sstevel@tonic-gate dm_descriptor_t disk = NULL; 1109*0Sstevel@tonic-gate uint64_t size = 0; 1110*0Sstevel@tonic-gate uint16_t index = 0; 1111*0Sstevel@tonic-gate modslice_t *modified = NULL; 1112*0Sstevel@tonic-gate dlist_t *item = NULL; 1113*0Sstevel@tonic-gate char *name = NULL; 1114*0Sstevel@tonic-gate int error = 0; 1115*0Sstevel@tonic-gate 1116*0Sstevel@tonic-gate ((error = devconfig_get_name(dev, &name)) != 0) || 1117*0Sstevel@tonic-gate (error = devconfig_get_slice_index(dev, &index)) || 1118*0Sstevel@tonic-gate (error = devconfig_get_size(dev, &size)) || 1119*0Sstevel@tonic-gate (error = get_disk_for_named_slice(name, &disk)) || 1120*0Sstevel@tonic-gate (error = disk_release_index(disk, index)) || 1121*0Sstevel@tonic-gate (error = remove_used_slice_by_name(name)); 1122*0Sstevel@tonic-gate if (error != 0) { 1123*0Sstevel@tonic-gate return (error); 1124*0Sstevel@tonic-gate } 1125*0Sstevel@tonic-gate 1126*0Sstevel@tonic-gate /* remove from the modified_slices list */ 1127*0Sstevel@tonic-gate _modified_slices = 1128*0Sstevel@tonic-gate dlist_remove_equivalent_item( 1129*0Sstevel@tonic-gate _modified_slices, name, 1130*0Sstevel@tonic-gate compare_string_to_modslice_name, &item); 1131*0Sstevel@tonic-gate 1132*0Sstevel@tonic-gate if (item != NULL) { 1133*0Sstevel@tonic-gate modified = (modslice_t *)item->obj; 1134*0Sstevel@tonic-gate free((void*) item); 1135*0Sstevel@tonic-gate } 1136*0Sstevel@tonic-gate 1137*0Sstevel@tonic-gate /* space from an existing slice? if so reclaim it. */ 1138*0Sstevel@tonic-gate if (modified != NULL) { 1139*0Sstevel@tonic-gate 1140*0Sstevel@tonic-gate dm_descriptor_t src = modified->src_slice_desc; 1141*0Sstevel@tonic-gate char *srcname = NULL; 1142*0Sstevel@tonic-gate dlist_t *srcitem = NULL; 1143*0Sstevel@tonic-gate 1144*0Sstevel@tonic-gate if (src != (dm_descriptor_t)0) { 1145*0Sstevel@tonic-gate if ((error = get_display_name(src, &srcname)) == 0) { 1146*0Sstevel@tonic-gate srcitem = 1147*0Sstevel@tonic-gate dlist_find( 1148*0Sstevel@tonic-gate _modified_slices, 1149*0Sstevel@tonic-gate srcname, 1150*0Sstevel@tonic-gate compare_string_to_modslice_name); 1151*0Sstevel@tonic-gate } 1152*0Sstevel@tonic-gate } 1153*0Sstevel@tonic-gate 1154*0Sstevel@tonic-gate if ((error == 0) && (srcitem != NULL)) { 1155*0Sstevel@tonic-gate 1156*0Sstevel@tonic-gate modslice_t *source = (modslice_t *)srcitem->obj; 1157*0Sstevel@tonic-gate devconfig_t *srcdevcfg = NULL; 1158*0Sstevel@tonic-gate uint64_t srcsize = NULL; 1159*0Sstevel@tonic-gate uint64_t srcsizeblks = NULL; 1160*0Sstevel@tonic-gate uint64_t inblks = NULL; 1161*0Sstevel@tonic-gate 1162*0Sstevel@tonic-gate srcdevcfg = source->slice_devcfg; 1163*0Sstevel@tonic-gate source->times_modified -= 1; 1164*0Sstevel@tonic-gate 1165*0Sstevel@tonic-gate ((error = devconfig_get_size(srcdevcfg, &srcsize)) != 0) || 1166*0Sstevel@tonic-gate (error = devconfig_set_size(srcdevcfg, srcsize + size)) || 1167*0Sstevel@tonic-gate (error = slice_set_size(src, srcsize + size)) || 1168*0Sstevel@tonic-gate (error = slice_get_size_in_blocks(src, &srcsizeblks)) || 1169*0Sstevel@tonic-gate (error = devconfig_get_size_in_blocks(srcdevcfg, &inblks)); 1170*0Sstevel@tonic-gate (error = devconfig_set_size_in_blocks(srcdevcfg, srcsizeblks)); 1171*0Sstevel@tonic-gate 1172*0Sstevel@tonic-gate if (error == 0) { 1173*0Sstevel@tonic-gate 1174*0Sstevel@tonic-gate /* was only modification undone? */ 1175*0Sstevel@tonic-gate if (source->times_modified == 0) { 1176*0Sstevel@tonic-gate 1177*0Sstevel@tonic-gate _modified_slices = 1178*0Sstevel@tonic-gate dlist_remove_equivalent_item( 1179*0Sstevel@tonic-gate _modified_slices, srcname, 1180*0Sstevel@tonic-gate compare_string_to_modslice_name, 1181*0Sstevel@tonic-gate &srcitem); 1182*0Sstevel@tonic-gate 1183*0Sstevel@tonic-gate free_modslice_object((modslice_t *)srcitem->obj); 1184*0Sstevel@tonic-gate free((void *)srcitem); 1185*0Sstevel@tonic-gate } 1186*0Sstevel@tonic-gate } 1187*0Sstevel@tonic-gate } 1188*0Sstevel@tonic-gate 1189*0Sstevel@tonic-gate free_modslice_object(modified); 1190*0Sstevel@tonic-gate } 1191*0Sstevel@tonic-gate 1192*0Sstevel@tonic-gate return (error); 1193*0Sstevel@tonic-gate } 1194*0Sstevel@tonic-gate 1195*0Sstevel@tonic-gate /* 1196*0Sstevel@tonic-gate * FUNCTION: pick_from_best_hba_and_disk(dlist_t *slices, 1197*0Sstevel@tonic-gate * dlist_t *used, dm_descriptor_t *chosen) 1198*0Sstevel@tonic-gate * 1199*0Sstevel@tonic-gate * INPUT: slices - a dlist_t poitner to a list of slices 1200*0Sstevel@tonic-gate * used - a dlist_t pointer to a list of used slices 1201*0Sstevel@tonic-gate * chosen - a dm_descriptor_t pointer to hold the result 1202*0Sstevel@tonic-gate * 1203*0Sstevel@tonic-gate * RETURNS: int - 0 on success 1204*0Sstevel@tonic-gate * !0 otherwise 1205*0Sstevel@tonic-gate * 1206*0Sstevel@tonic-gate * PURPOSE: Examines the input list of slices and chooses the one 1207*0Sstevel@tonic-gate * that is on the least used HBA and disk. 1208*0Sstevel@tonic-gate * 1209*0Sstevel@tonic-gate * HBA and disk usage is determined by examining the input 1210*0Sstevel@tonic-gate * list of used slices and counting the number of slices 1211*0Sstevel@tonic-gate * each HBA and disk contributes. 1212*0Sstevel@tonic-gate * 1213*0Sstevel@tonic-gate * The HBA which contributes the fewest is selected, and 1214*0Sstevel@tonic-gate * then the disk on that HBA which contributes the fewest 1215*0Sstevel@tonic-gate * is selected. 1216*0Sstevel@tonic-gate * 1217*0Sstevel@tonic-gate * The largest slice from that disk is then returned. 1218*0Sstevel@tonic-gate */ 1219*0Sstevel@tonic-gate static int 1220*0Sstevel@tonic-gate pick_from_best_hba_and_disk( 1221*0Sstevel@tonic-gate dlist_t *slices, 1222*0Sstevel@tonic-gate dlist_t *used, 1223*0Sstevel@tonic-gate dm_descriptor_t *chosen) 1224*0Sstevel@tonic-gate { 1225*0Sstevel@tonic-gate dlist_t *iter = NULL; 1226*0Sstevel@tonic-gate dlist_t *iter1 = NULL; 1227*0Sstevel@tonic-gate dlist_t *iter2 = NULL; 1228*0Sstevel@tonic-gate dlist_t *item = NULL; 1229*0Sstevel@tonic-gate 1230*0Sstevel@tonic-gate dlist_t *used_slice_hbas = NULL; 1231*0Sstevel@tonic-gate 1232*0Sstevel@tonic-gate int maxuses = 128; 1233*0Sstevel@tonic-gate int maxslices = VTOC_SIZE; /* meta.h */ 1234*0Sstevel@tonic-gate 1235*0Sstevel@tonic-gate int i = 0; 1236*0Sstevel@tonic-gate int error = 0; 1237*0Sstevel@tonic-gate 1238*0Sstevel@tonic-gate /* 1239*0Sstevel@tonic-gate * allocate an array to hold lists of slices grouped by 1240*0Sstevel@tonic-gate * HBA contribution... the list indexed by N is the list 1241*0Sstevel@tonic-gate * of slices that are on HBAs contributing N slices 1242*0Sstevel@tonic-gate */ 1243*0Sstevel@tonic-gate dlist_t **prefhbas = (dlist_t **)calloc(maxuses, sizeof (dlist_t *)); 1244*0Sstevel@tonic-gate 1245*0Sstevel@tonic-gate /* 1246*0Sstevel@tonic-gate * allocate an array to hold lists of slices grouped by 1247*0Sstevel@tonic-gate * disk contribution... the list indexed by N is the list 1248*0Sstevel@tonic-gate * of slices that are on disks contributing N slices 1249*0Sstevel@tonic-gate */ 1250*0Sstevel@tonic-gate dlist_t **prefdisks = (dlist_t **)calloc(maxslices, sizeof (dlist_t *)); 1251*0Sstevel@tonic-gate 1252*0Sstevel@tonic-gate *chosen = (dm_descriptor_t)0; 1253*0Sstevel@tonic-gate 1254*0Sstevel@tonic-gate if (prefhbas == NULL || prefdisks == NULL) { 1255*0Sstevel@tonic-gate free(prefhbas); 1256*0Sstevel@tonic-gate free(prefdisks); 1257*0Sstevel@tonic-gate return (ENOMEM); 1258*0Sstevel@tonic-gate } 1259*0Sstevel@tonic-gate 1260*0Sstevel@tonic-gate /* 1261*0Sstevel@tonic-gate * precompute the used slices' lists of HBAS: iterate the list 1262*0Sstevel@tonic-gate * of used slices and determine the HBA(s) each is connected thru. 1263*0Sstevel@tonic-gate * construct a list of lists containing the HBAs. 1264*0Sstevel@tonic-gate */ 1265*0Sstevel@tonic-gate for (iter = used; 1266*0Sstevel@tonic-gate (iter != NULL) && (error == 0); 1267*0Sstevel@tonic-gate iter = iter->next) { 1268*0Sstevel@tonic-gate 1269*0Sstevel@tonic-gate devconfig_t *uslice = (devconfig_t *)iter->obj; 1270*0Sstevel@tonic-gate dm_descriptor_t udisk = NULL; 1271*0Sstevel@tonic-gate char *uname = NULL; 1272*0Sstevel@tonic-gate dlist_t *uhbas = NULL; 1273*0Sstevel@tonic-gate 1274*0Sstevel@tonic-gate /* need to use disk to get to HBAs because */ 1275*0Sstevel@tonic-gate /* the slice doesn't exist yet */ 1276*0Sstevel@tonic-gate ((error = devconfig_get_name(uslice, &uname)) != 0) || 1277*0Sstevel@tonic-gate (error = get_disk_for_named_slice(uname, &udisk)) || 1278*0Sstevel@tonic-gate (error = disk_get_hbas(udisk, &uhbas)); 1279*0Sstevel@tonic-gate if (error == 0) { 1280*0Sstevel@tonic-gate if ((item = dlist_new_item((void *)uhbas)) == NULL) { 1281*0Sstevel@tonic-gate error = ENOMEM; 1282*0Sstevel@tonic-gate } else { 1283*0Sstevel@tonic-gate used_slice_hbas = dlist_append( 1284*0Sstevel@tonic-gate item, used_slice_hbas, AT_HEAD); 1285*0Sstevel@tonic-gate } 1286*0Sstevel@tonic-gate } 1287*0Sstevel@tonic-gate } 1288*0Sstevel@tonic-gate 1289*0Sstevel@tonic-gate /* 1290*0Sstevel@tonic-gate * iterate the list of chosen slices and for each, 1291*0Sstevel@tonic-gate * determine how many other slices from its HBA(s) 1292*0Sstevel@tonic-gate * are already being used... 1293*0Sstevel@tonic-gate * 1294*0Sstevel@tonic-gate * iter steps thru the list of slices 1295*0Sstevel@tonic-gate * iter1 steps thru each of the slice's HBAs 1296*0Sstevel@tonic-gate * iter2 steps thru the precomputed list of used slice's HBAs 1297*0Sstevel@tonic-gate * dlist_contains then searches each used slice's HBAs 1298*0Sstevel@tonic-gate * to see if it contains iter1's HBA 1299*0Sstevel@tonic-gate * 1300*0Sstevel@tonic-gate * If it does, increment the count for that HBA. 1301*0Sstevel@tonic-gate */ 1302*0Sstevel@tonic-gate for (iter = slices; 1303*0Sstevel@tonic-gate (iter != NULL) && (error == 0); 1304*0Sstevel@tonic-gate iter = iter->next) { 1305*0Sstevel@tonic-gate 1306*0Sstevel@tonic-gate dm_descriptor_t slice = (uintptr_t)iter->obj; 1307*0Sstevel@tonic-gate dlist_t *hbas = NULL; 1308*0Sstevel@tonic-gate int n = 0; /* # slices each HBA contributes */ 1309*0Sstevel@tonic-gate 1310*0Sstevel@tonic-gate if ((error = slice_get_hbas(slice, &hbas)) != 0) { 1311*0Sstevel@tonic-gate continue; 1312*0Sstevel@tonic-gate } 1313*0Sstevel@tonic-gate 1314*0Sstevel@tonic-gate for (iter1 = hbas; iter1 != NULL; iter1 = iter1->next) { 1315*0Sstevel@tonic-gate for (iter2 = used_slice_hbas; iter2 != NULL; 1316*0Sstevel@tonic-gate iter2 = iter2->next) { 1317*0Sstevel@tonic-gate 1318*0Sstevel@tonic-gate dlist_t *uhbas = (dlist_t *)iter2->obj; 1319*0Sstevel@tonic-gate if (dlist_contains(uhbas, iter1->obj, 1320*0Sstevel@tonic-gate compare_descriptor_names) == B_TRUE) { 1321*0Sstevel@tonic-gate n++; 1322*0Sstevel@tonic-gate } 1323*0Sstevel@tonic-gate } 1324*0Sstevel@tonic-gate } 1325*0Sstevel@tonic-gate 1326*0Sstevel@tonic-gate dlist_free_items(hbas, NULL); 1327*0Sstevel@tonic-gate 1328*0Sstevel@tonic-gate /* group slices from HBAs contributing more than maxuses */ 1329*0Sstevel@tonic-gate if (n >= maxuses) { 1330*0Sstevel@tonic-gate n = maxuses - 1; 1331*0Sstevel@tonic-gate } 1332*0Sstevel@tonic-gate 1333*0Sstevel@tonic-gate /* add slice to list in descending size order */ 1334*0Sstevel@tonic-gate if ((item = dlist_new_item((void*)slice)) == NULL) { 1335*0Sstevel@tonic-gate error = ENOMEM; 1336*0Sstevel@tonic-gate } else { 1337*0Sstevel@tonic-gate prefhbas[n] = 1338*0Sstevel@tonic-gate dlist_insert_ordered( 1339*0Sstevel@tonic-gate item, 1340*0Sstevel@tonic-gate prefhbas[n], 1341*0Sstevel@tonic-gate DESCENDING, 1342*0Sstevel@tonic-gate compare_slice_sizes); 1343*0Sstevel@tonic-gate } 1344*0Sstevel@tonic-gate } 1345*0Sstevel@tonic-gate 1346*0Sstevel@tonic-gate /* free list of lists of used slices HBAs */ 1347*0Sstevel@tonic-gate for (iter = used_slice_hbas; iter != NULL; iter = iter->next) { 1348*0Sstevel@tonic-gate dlist_free_items((dlist_t *)iter->obj, NULL); 1349*0Sstevel@tonic-gate } 1350*0Sstevel@tonic-gate dlist_free_items(used_slice_hbas, NULL); 1351*0Sstevel@tonic-gate 1352*0Sstevel@tonic-gate /* 1353*0Sstevel@tonic-gate * Select the list of slices that are on the HBA(s) contributing 1354*0Sstevel@tonic-gate * the fewest slices... iterate these slices and for each, detemmine 1355*0Sstevel@tonic-gate * how many other slices from its disk are already being used... 1356*0Sstevel@tonic-gate */ 1357*0Sstevel@tonic-gate for (i = 0; (i < maxuses) && (error == 0); i++) { 1358*0Sstevel@tonic-gate 1359*0Sstevel@tonic-gate for (iter = (dlist_t *)prefhbas[i]; 1360*0Sstevel@tonic-gate (iter != NULL) && (error == 0); 1361*0Sstevel@tonic-gate iter = iter->next) { 1362*0Sstevel@tonic-gate 1363*0Sstevel@tonic-gate dm_descriptor_t slice = (uintptr_t)iter->obj; 1364*0Sstevel@tonic-gate dm_descriptor_t disk; 1365*0Sstevel@tonic-gate int n = 0; 1366*0Sstevel@tonic-gate 1367*0Sstevel@tonic-gate (void) slice_get_disk(slice, &disk); 1368*0Sstevel@tonic-gate 1369*0Sstevel@tonic-gate /* 1370*0Sstevel@tonic-gate * count how many slices this slice's disk is contributing 1371*0Sstevel@tonic-gate * by comparing it to the list of used slices 1372*0Sstevel@tonic-gate */ 1373*0Sstevel@tonic-gate for (iter1 = _used_slices; iter1 != NULL; iter1 = iter1->next) { 1374*0Sstevel@tonic-gate usedslice_t *used = (usedslice_t *)iter1->obj; 1375*0Sstevel@tonic-gate if (compare_descriptors( 1376*0Sstevel@tonic-gate (void *)disk, (void *)used->disk) == 0) { 1377*0Sstevel@tonic-gate n++; 1378*0Sstevel@tonic-gate } 1379*0Sstevel@tonic-gate } 1380*0Sstevel@tonic-gate 1381*0Sstevel@tonic-gate /* add slice to list in descending size order */ 1382*0Sstevel@tonic-gate if ((item = dlist_new_item((void *)slice)) == NULL) { 1383*0Sstevel@tonic-gate error = ENOMEM; 1384*0Sstevel@tonic-gate } else { 1385*0Sstevel@tonic-gate prefdisks[n] = 1386*0Sstevel@tonic-gate dlist_insert_ordered( 1387*0Sstevel@tonic-gate item, 1388*0Sstevel@tonic-gate prefdisks[n], 1389*0Sstevel@tonic-gate DESCENDING, 1390*0Sstevel@tonic-gate compare_slice_sizes); 1391*0Sstevel@tonic-gate } 1392*0Sstevel@tonic-gate } 1393*0Sstevel@tonic-gate } 1394*0Sstevel@tonic-gate 1395*0Sstevel@tonic-gate if (error == 0) { 1396*0Sstevel@tonic-gate /* select largest slice from least used disk */ 1397*0Sstevel@tonic-gate for (i = 0; (i < maxslices) && (*chosen == NULL); i++) { 1398*0Sstevel@tonic-gate if (prefdisks[i] != NULL) { 1399*0Sstevel@tonic-gate *chosen = (uintptr_t)prefdisks[i]->obj; 1400*0Sstevel@tonic-gate } 1401*0Sstevel@tonic-gate } 1402*0Sstevel@tonic-gate } 1403*0Sstevel@tonic-gate 1404*0Sstevel@tonic-gate for (i = 0; i < maxuses; i++) { 1405*0Sstevel@tonic-gate dlist_free_items(prefhbas[i], NULL); 1406*0Sstevel@tonic-gate } 1407*0Sstevel@tonic-gate for (i = 0; i < maxslices; i++) { 1408*0Sstevel@tonic-gate dlist_free_items(prefdisks[i], NULL); 1409*0Sstevel@tonic-gate } 1410*0Sstevel@tonic-gate 1411*0Sstevel@tonic-gate free((void*)prefhbas); 1412*0Sstevel@tonic-gate free((void*)prefdisks); 1413*0Sstevel@tonic-gate 1414*0Sstevel@tonic-gate return (error); 1415*0Sstevel@tonic-gate } 1416*0Sstevel@tonic-gate 1417*0Sstevel@tonic-gate /* 1418*0Sstevel@tonic-gate * FUNCTION: slice_on_unique_hba(dm_descriptor_t slice, 1419*0Sstevel@tonic-gate * dlist_t *used, dlist_t *used_hbas, 1420*0Sstevel@tonic-gate * boolean_t *unique) 1421*0Sstevel@tonic-gate * 1422*0Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t handle for the slice of interest 1423*0Sstevel@tonic-gate * used - a dlist_t pointer to a list of used slices 1424*0Sstevel@tonic-gate * used_hbas - a dlist_t pointer to a list of used_hbas 1425*0Sstevel@tonic-gate * unique - a boolean_t pointer to hold the result 1426*0Sstevel@tonic-gate * 1427*0Sstevel@tonic-gate * RETURNS: int - 0 on success 1428*0Sstevel@tonic-gate * !0 otherwise 1429*0Sstevel@tonic-gate * 1430*0Sstevel@tonic-gate * PURPOSE: Determines if the input slice is connected thru the same HBA 1431*0Sstevel@tonic-gate * as a slice in the used list. 1432*0Sstevel@tonic-gate * 1433*0Sstevel@tonic-gate * Also checks to see if the input slice is connected thru any 1434*0Sstevel@tonic-gate * HBA in the used_hbas list. 1435*0Sstevel@tonic-gate * 1436*0Sstevel@tonic-gate * If the slice is found to be on a unique HBA, bool is set 1437*0Sstevel@tonic-gate * to B_TRUE, B_FALSE otherwise. 1438*0Sstevel@tonic-gate */ 1439*0Sstevel@tonic-gate static int 1440*0Sstevel@tonic-gate slice_on_unique_hba( 1441*0Sstevel@tonic-gate dm_descriptor_t slice, 1442*0Sstevel@tonic-gate dlist_t *used, 1443*0Sstevel@tonic-gate dlist_t *used_hbas, 1444*0Sstevel@tonic-gate boolean_t *unique) 1445*0Sstevel@tonic-gate { 1446*0Sstevel@tonic-gate dlist_t *iter = NULL; 1447*0Sstevel@tonic-gate dlist_t *iter1 = NULL; 1448*0Sstevel@tonic-gate 1449*0Sstevel@tonic-gate dlist_t *hbas = NULL; 1450*0Sstevel@tonic-gate 1451*0Sstevel@tonic-gate int error = 0; 1452*0Sstevel@tonic-gate 1453*0Sstevel@tonic-gate *unique = B_TRUE; 1454*0Sstevel@tonic-gate 1455*0Sstevel@tonic-gate if ((error = slice_get_hbas(slice, &hbas)) != 0) { 1456*0Sstevel@tonic-gate return (error); 1457*0Sstevel@tonic-gate } 1458*0Sstevel@tonic-gate 1459*0Sstevel@tonic-gate /* 1460*0Sstevel@tonic-gate * check to see if any of slice's HBAs is the same 1461*0Sstevel@tonic-gate * as the HBA for any of the used 1462*0Sstevel@tonic-gate */ 1463*0Sstevel@tonic-gate for (iter = used; 1464*0Sstevel@tonic-gate (iter != NULL) && (*unique == B_TRUE) && (error == 0); 1465*0Sstevel@tonic-gate iter = iter->next) { 1466*0Sstevel@tonic-gate 1467*0Sstevel@tonic-gate devconfig_t *dev = (devconfig_t *)iter->obj; 1468*0Sstevel@tonic-gate if (devconfig_isA(dev, TYPE_SLICE)) { 1469*0Sstevel@tonic-gate 1470*0Sstevel@tonic-gate dm_descriptor_t odisk = NULL; 1471*0Sstevel@tonic-gate char *oname = NULL; 1472*0Sstevel@tonic-gate dlist_t *ohbas = NULL; 1473*0Sstevel@tonic-gate 1474*0Sstevel@tonic-gate /* get HBAs for other slice using its disk */ 1475*0Sstevel@tonic-gate /* because the slice doesn't exist yet. */ 1476*0Sstevel@tonic-gate ((error = devconfig_get_name(dev, &oname)) != 0) || 1477*0Sstevel@tonic-gate (error = get_disk_for_named_slice(oname, &odisk)) || 1478*0Sstevel@tonic-gate (error = disk_get_hbas(odisk, &ohbas)); 1479*0Sstevel@tonic-gate 1480*0Sstevel@tonic-gate /* any HBA overlap? */ 1481*0Sstevel@tonic-gate for (iter1 = hbas; 1482*0Sstevel@tonic-gate (iter1 != NULL) && (*unique == B_TRUE) && (error == 0); 1483*0Sstevel@tonic-gate iter1 = iter1->next) { 1484*0Sstevel@tonic-gate 1485*0Sstevel@tonic-gate if (dlist_contains(ohbas, iter1->obj, 1486*0Sstevel@tonic-gate compare_descriptor_names) == B_TRUE) { 1487*0Sstevel@tonic-gate *unique = B_FALSE; 1488*0Sstevel@tonic-gate } 1489*0Sstevel@tonic-gate } 1490*0Sstevel@tonic-gate dlist_free_items(ohbas, NULL); 1491*0Sstevel@tonic-gate } 1492*0Sstevel@tonic-gate } 1493*0Sstevel@tonic-gate 1494*0Sstevel@tonic-gate /* 1495*0Sstevel@tonic-gate * check to see if any of slice's HBAs is the contained 1496*0Sstevel@tonic-gate * in the list of used hbas 1497*0Sstevel@tonic-gate */ 1498*0Sstevel@tonic-gate for (iter = hbas; 1499*0Sstevel@tonic-gate (iter != NULL) && (*unique == B_TRUE) && (error == 0); 1500*0Sstevel@tonic-gate iter = iter->next) { 1501*0Sstevel@tonic-gate if (dlist_contains(used_hbas, 1502*0Sstevel@tonic-gate iter->obj, compare_descriptor_names) == B_TRUE) { 1503*0Sstevel@tonic-gate *unique = B_FALSE; 1504*0Sstevel@tonic-gate } 1505*0Sstevel@tonic-gate } 1506*0Sstevel@tonic-gate 1507*0Sstevel@tonic-gate dlist_free_items(hbas, NULL); 1508*0Sstevel@tonic-gate 1509*0Sstevel@tonic-gate return (error); 1510*0Sstevel@tonic-gate } 1511*0Sstevel@tonic-gate 1512*0Sstevel@tonic-gate /* 1513*0Sstevel@tonic-gate * FUNCTION: slice_on_unique_disk(dm_descriptor_t slice, 1514*0Sstevel@tonic-gate * dlist_t *used, dlist_t *used_disks, 1515*0Sstevel@tonic-gate * boolean_t *unique) 1516*0Sstevel@tonic-gate * 1517*0Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t handle for the slice of interest 1518*0Sstevel@tonic-gate * used - a dlist_t pointer to a list of used slices 1519*0Sstevel@tonic-gate * othervols - a dlist_t pointer to a list of other volumes 1520*0Sstevel@tonic-gate * bool - a boolean_t pointer to hold the result 1521*0Sstevel@tonic-gate * 1522*0Sstevel@tonic-gate * RETURNS: int - 0 on success 1523*0Sstevel@tonic-gate * !0 otherwise 1524*0Sstevel@tonic-gate * 1525*0Sstevel@tonic-gate * PURPOSE: Determines if the input slice is on a drive that is not 1526*0Sstevel@tonic-gate * part of any volume in the othervols list, or on the same 1527*0Sstevel@tonic-gate * drive as any slice in the used list. 1528*0Sstevel@tonic-gate * 1529*0Sstevel@tonic-gate * If the slice is found to be on a unique disk, bool is set 1530*0Sstevel@tonic-gate * to B_TRUE, B_FALSE otherwise. 1531*0Sstevel@tonic-gate */ 1532*0Sstevel@tonic-gate static int 1533*0Sstevel@tonic-gate slice_on_unique_disk( 1534*0Sstevel@tonic-gate dm_descriptor_t slice, 1535*0Sstevel@tonic-gate dlist_t *used, 1536*0Sstevel@tonic-gate dlist_t *used_disks, 1537*0Sstevel@tonic-gate boolean_t *unique) 1538*0Sstevel@tonic-gate { 1539*0Sstevel@tonic-gate dm_descriptor_t disk = NULL; 1540*0Sstevel@tonic-gate dlist_t *iter = NULL; 1541*0Sstevel@tonic-gate int error = 0; 1542*0Sstevel@tonic-gate 1543*0Sstevel@tonic-gate *unique = B_TRUE; 1544*0Sstevel@tonic-gate 1545*0Sstevel@tonic-gate if ((error = slice_get_disk(slice, &disk)) != 0) { 1546*0Sstevel@tonic-gate return (error); 1547*0Sstevel@tonic-gate } 1548*0Sstevel@tonic-gate 1549*0Sstevel@tonic-gate /* 1550*0Sstevel@tonic-gate * check to see if this disk is the same as the 1551*0Sstevel@tonic-gate * disk for any of the used 1552*0Sstevel@tonic-gate */ 1553*0Sstevel@tonic-gate for (iter = used; 1554*0Sstevel@tonic-gate (iter != NULL) && (*unique == B_TRUE) && (error == 0); 1555*0Sstevel@tonic-gate iter = iter->next) { 1556*0Sstevel@tonic-gate 1557*0Sstevel@tonic-gate devconfig_t *dev = (devconfig_t *)iter->obj; 1558*0Sstevel@tonic-gate 1559*0Sstevel@tonic-gate if (devconfig_isA(dev, TYPE_SLICE)) { 1560*0Sstevel@tonic-gate 1561*0Sstevel@tonic-gate /* get disk for otherslice */ 1562*0Sstevel@tonic-gate dm_descriptor_t odisk = NULL; 1563*0Sstevel@tonic-gate char *oname = NULL; 1564*0Sstevel@tonic-gate 1565*0Sstevel@tonic-gate ((error = devconfig_get_name(dev, &oname)) != 0) || 1566*0Sstevel@tonic-gate (error = get_disk_for_named_slice(oname, &odisk)); 1567*0Sstevel@tonic-gate 1568*0Sstevel@tonic-gate if ((error == 0) && 1569*0Sstevel@tonic-gate (compare_descriptor_names( 1570*0Sstevel@tonic-gate (void*)disk, (void*)odisk) == 0)) { 1571*0Sstevel@tonic-gate /* origslice is on same disk, stop */ 1572*0Sstevel@tonic-gate *unique = B_FALSE; 1573*0Sstevel@tonic-gate } 1574*0Sstevel@tonic-gate } 1575*0Sstevel@tonic-gate } 1576*0Sstevel@tonic-gate 1577*0Sstevel@tonic-gate /* check disk against the used disks */ 1578*0Sstevel@tonic-gate if ((error == 0) && (*unique == B_TRUE) && 1579*0Sstevel@tonic-gate dlist_contains(used_disks, (void *)disk, 1580*0Sstevel@tonic-gate compare_descriptor_names) == B_TRUE) { 1581*0Sstevel@tonic-gate *unique = B_FALSE; 1582*0Sstevel@tonic-gate } 1583*0Sstevel@tonic-gate 1584*0Sstevel@tonic-gate return (error); 1585*0Sstevel@tonic-gate } 1586*0Sstevel@tonic-gate 1587*0Sstevel@tonic-gate /* 1588*0Sstevel@tonic-gate * FUNCTION: slice_has_same_disk_geom(dm_descriptor_t slice, 1589*0Sstevel@tonic-gate * dlist_t *used, boolean_t *has_same_geom) 1590*0Sstevel@tonic-gate * 1591*0Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t handle for the slice of interest 1592*0Sstevel@tonic-gate * used - a dlist_t pointer to a list of used slices 1593*0Sstevel@tonic-gate * bool - a boolean_t pointer to hold the result 1594*0Sstevel@tonic-gate * 1595*0Sstevel@tonic-gate * RETURNS: int - 0 on success 1596*0Sstevel@tonic-gate * !0 otherwise 1597*0Sstevel@tonic-gate * 1598*0Sstevel@tonic-gate * PURPOSE: Determines if the input slice is on a drive with similar 1599*0Sstevel@tonic-gate * hardware geometry as the slices in the used list. 1600*0Sstevel@tonic-gate * 1601*0Sstevel@tonic-gate * If the slice is found to be on a disk with similar geometry, 1602*0Sstevel@tonic-gate * bool is set to B_TRUE, B_FALSE otherwise. 1603*0Sstevel@tonic-gate * 1604*0Sstevel@tonic-gate * The comparison is based on the available disk geometry 1605*0Sstevel@tonic-gate * information which may not be relevant or accurate for 1606*0Sstevel@tonic-gate * EFI labeled disks, so the disk drive type needs to be 1607*0Sstevel@tonic-gate * checked as well. 1608*0Sstevel@tonic-gate */ 1609*0Sstevel@tonic-gate static int 1610*0Sstevel@tonic-gate slice_has_same_disk_geom( 1611*0Sstevel@tonic-gate dm_descriptor_t slice, 1612*0Sstevel@tonic-gate dlist_t *used, 1613*0Sstevel@tonic-gate boolean_t *has_same_geom) 1614*0Sstevel@tonic-gate { 1615*0Sstevel@tonic-gate dm_descriptor_t disk = NULL; 1616*0Sstevel@tonic-gate boolean_t efi = B_FALSE; 1617*0Sstevel@tonic-gate uint64_t bsize = 0; 1618*0Sstevel@tonic-gate uint64_t ncyls = 0; 1619*0Sstevel@tonic-gate uint64_t nsects = 0; 1620*0Sstevel@tonic-gate uint64_t nheads = 0; 1621*0Sstevel@tonic-gate dlist_t *iter = NULL; 1622*0Sstevel@tonic-gate int error = 0; 1623*0Sstevel@tonic-gate 1624*0Sstevel@tonic-gate *has_same_geom = B_TRUE; 1625*0Sstevel@tonic-gate 1626*0Sstevel@tonic-gate ((error = slice_get_disk(slice, &disk)) != 0) || 1627*0Sstevel@tonic-gate (error = disk_get_is_efi(disk, &efi)) || 1628*0Sstevel@tonic-gate (error = disk_get_blocksize(disk, &bsize)); 1629*0Sstevel@tonic-gate 1630*0Sstevel@tonic-gate if ((error == 0) && (efi == B_FALSE)) { 1631*0Sstevel@tonic-gate ((error = disk_get_ncylinders(disk, &ncyls)) != 0) || 1632*0Sstevel@tonic-gate (error = disk_get_nheads(disk, &nheads)) || 1633*0Sstevel@tonic-gate (error = disk_get_nsectors(disk, &nsects)); 1634*0Sstevel@tonic-gate } 1635*0Sstevel@tonic-gate 1636*0Sstevel@tonic-gate if (error != 0) { 1637*0Sstevel@tonic-gate return (error); 1638*0Sstevel@tonic-gate } 1639*0Sstevel@tonic-gate 1640*0Sstevel@tonic-gate /* 1641*0Sstevel@tonic-gate * check to see if slice's disk has the same geometry 1642*0Sstevel@tonic-gate * as the disks for the slices in the used list 1643*0Sstevel@tonic-gate */ 1644*0Sstevel@tonic-gate for (iter = used; 1645*0Sstevel@tonic-gate (iter != NULL) && (*has_same_geom == B_TRUE) && (error = 0); 1646*0Sstevel@tonic-gate iter = iter->next) { 1647*0Sstevel@tonic-gate 1648*0Sstevel@tonic-gate devconfig_t *dev = (devconfig_t *)iter->obj; 1649*0Sstevel@tonic-gate 1650*0Sstevel@tonic-gate if (devconfig_isA(dev, TYPE_SLICE)) { 1651*0Sstevel@tonic-gate 1652*0Sstevel@tonic-gate /* get disk info for otherslice */ 1653*0Sstevel@tonic-gate dm_descriptor_t odisk = NULL; 1654*0Sstevel@tonic-gate char *oname = NULL; 1655*0Sstevel@tonic-gate boolean_t oefi = B_FALSE; 1656*0Sstevel@tonic-gate uint64_t obsize = 0; 1657*0Sstevel@tonic-gate uint64_t oncyls = 0; 1658*0Sstevel@tonic-gate uint64_t onsects = 0; 1659*0Sstevel@tonic-gate uint64_t onheads = 0; 1660*0Sstevel@tonic-gate 1661*0Sstevel@tonic-gate ((error = devconfig_get_name(dev, &oname)) != 0) || 1662*0Sstevel@tonic-gate (error = get_disk_for_named_slice(oname, &odisk)) || 1663*0Sstevel@tonic-gate (error = disk_get_is_efi(odisk, &oefi)) || 1664*0Sstevel@tonic-gate (error = disk_get_blocksize(odisk, &obsize)); 1665*0Sstevel@tonic-gate 1666*0Sstevel@tonic-gate if ((error == 0) && (oefi == B_FALSE)) { 1667*0Sstevel@tonic-gate ((error = disk_get_ncylinders(odisk, &oncyls)) != 0) || 1668*0Sstevel@tonic-gate (error = disk_get_nheads(odisk, &onheads)) || 1669*0Sstevel@tonic-gate (error = disk_get_nsectors(odisk, &onsects)); 1670*0Sstevel@tonic-gate } 1671*0Sstevel@tonic-gate 1672*0Sstevel@tonic-gate if (error == 0) { 1673*0Sstevel@tonic-gate if ((bsize != obsize) || (ncyls != oncyls) || 1674*0Sstevel@tonic-gate (nsects != onsects) || (nheads != onheads)) { 1675*0Sstevel@tonic-gate /* this disk has a different geometry */ 1676*0Sstevel@tonic-gate *has_same_geom = B_FALSE; 1677*0Sstevel@tonic-gate } 1678*0Sstevel@tonic-gate } 1679*0Sstevel@tonic-gate } 1680*0Sstevel@tonic-gate } 1681*0Sstevel@tonic-gate 1682*0Sstevel@tonic-gate return (error); 1683*0Sstevel@tonic-gate } 1684*0Sstevel@tonic-gate 1685*0Sstevel@tonic-gate /* 1686*0Sstevel@tonic-gate * FUNCTION: slice_on_similar_bus(dm_descriptor_t slice, 1687*0Sstevel@tonic-gate * dlist_t *used, boolean_t *on_smlr_bus) 1688*0Sstevel@tonic-gate * 1689*0Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t handle for the slice of interest 1690*0Sstevel@tonic-gate * used - a dlist_t pointer to a list of used slices 1691*0Sstevel@tonic-gate * bool - a boolean_t pointer to hold the result 1692*0Sstevel@tonic-gate * 1693*0Sstevel@tonic-gate * RETURNS: int - 0 on success 1694*0Sstevel@tonic-gate * !0 otherwise 1695*0Sstevel@tonic-gate * 1696*0Sstevel@tonic-gate * PURPOSE: Determines if the input slice is connected thru a bus with 1697*0Sstevel@tonic-gate * characteristics similar to the slices in the used list. 1698*0Sstevel@tonic-gate * 1699*0Sstevel@tonic-gate * If the slice is found to be on a similar bus, bool is set 1700*0Sstevel@tonic-gate * to B_TRUE, B_FALSE otherwise. 1701*0Sstevel@tonic-gate * 1702*0Sstevel@tonic-gate * The comparison is actually between any of the HBA/controllers 1703*0Sstevel@tonic-gate * thru which the slices are connected to the system. 1704*0Sstevel@tonic-gate * If any are of similar type (e.g., fibre, SCSI) and 1705*0Sstevel@tonic-gate * protocol (SCSI-2, -3, fast/wide), then the slices are 1706*0Sstevel@tonic-gate * considered to be on similar busses. 1707*0Sstevel@tonic-gate */ 1708*0Sstevel@tonic-gate static int 1709*0Sstevel@tonic-gate slice_on_similar_bus( 1710*0Sstevel@tonic-gate dm_descriptor_t slice, 1711*0Sstevel@tonic-gate dlist_t *used, 1712*0Sstevel@tonic-gate boolean_t *on_smlr_bus) 1713*0Sstevel@tonic-gate { 1714*0Sstevel@tonic-gate dlist_t *iter = NULL; 1715*0Sstevel@tonic-gate dlist_t *iter1 = NULL; 1716*0Sstevel@tonic-gate dlist_t *hbas = NULL; 1717*0Sstevel@tonic-gate int error = 0; 1718*0Sstevel@tonic-gate 1719*0Sstevel@tonic-gate /* if there are no used slices, then the bus is similar */ 1720*0Sstevel@tonic-gate *on_smlr_bus = B_TRUE; 1721*0Sstevel@tonic-gate if (dlist_length(used) == 0) { 1722*0Sstevel@tonic-gate return (0); 1723*0Sstevel@tonic-gate } 1724*0Sstevel@tonic-gate 1725*0Sstevel@tonic-gate (error = slice_get_hbas(slice, &hbas)); 1726*0Sstevel@tonic-gate if (error != 0) { 1727*0Sstevel@tonic-gate return (error); 1728*0Sstevel@tonic-gate } 1729*0Sstevel@tonic-gate 1730*0Sstevel@tonic-gate /* if there are used slices, then make sure the bus is similar */ 1731*0Sstevel@tonic-gate *on_smlr_bus = B_FALSE; 1732*0Sstevel@tonic-gate for (iter = hbas; 1733*0Sstevel@tonic-gate (iter != NULL) && (*on_smlr_bus == B_FALSE) && (error == 0); 1734*0Sstevel@tonic-gate iter = iter->next) { 1735*0Sstevel@tonic-gate 1736*0Sstevel@tonic-gate dm_descriptor_t hba = (uintptr_t)iter->obj; 1737*0Sstevel@tonic-gate char *type = NULL; 1738*0Sstevel@tonic-gate boolean_t fast80 = B_FALSE; 1739*0Sstevel@tonic-gate boolean_t fast40 = B_FALSE; 1740*0Sstevel@tonic-gate boolean_t fast20 = B_FALSE; 1741*0Sstevel@tonic-gate boolean_t wide = B_FALSE; 1742*0Sstevel@tonic-gate 1743*0Sstevel@tonic-gate ((error = hba_get_type(hba, &type)) != 0) || 1744*0Sstevel@tonic-gate (error = hba_is_fast_80(hba, &fast80)) || 1745*0Sstevel@tonic-gate (error = hba_is_fast_40(hba, &fast40)) || 1746*0Sstevel@tonic-gate (error = hba_is_fast_20(hba, &fast20)) || 1747*0Sstevel@tonic-gate (error = hba_supports_wide(hba, &wide)); 1748*0Sstevel@tonic-gate if (error != 0) { 1749*0Sstevel@tonic-gate continue; 1750*0Sstevel@tonic-gate } 1751*0Sstevel@tonic-gate 1752*0Sstevel@tonic-gate /* check against the HBAs for the used slices */ 1753*0Sstevel@tonic-gate for (iter1 = used; 1754*0Sstevel@tonic-gate (iter1 != NULL) && (*on_smlr_bus == B_FALSE) && (error == 0); 1755*0Sstevel@tonic-gate iter1 = iter1->next) { 1756*0Sstevel@tonic-gate 1757*0Sstevel@tonic-gate devconfig_t *used = (devconfig_t *)iter1->obj; 1758*0Sstevel@tonic-gate 1759*0Sstevel@tonic-gate /* get HBAs for otherslice */ 1760*0Sstevel@tonic-gate dm_descriptor_t udisk = NULL; 1761*0Sstevel@tonic-gate char *uname = NULL; 1762*0Sstevel@tonic-gate dlist_t *uhbas = NULL; 1763*0Sstevel@tonic-gate dlist_t *iter2 = NULL; 1764*0Sstevel@tonic-gate 1765*0Sstevel@tonic-gate ((error = devconfig_get_name(used, &uname)) != 0) || 1766*0Sstevel@tonic-gate (error = get_disk_for_named_slice(uname, &udisk)) || 1767*0Sstevel@tonic-gate (error = disk_get_hbas(udisk, &uhbas)); 1768*0Sstevel@tonic-gate 1769*0Sstevel@tonic-gate for (iter2 = uhbas; 1770*0Sstevel@tonic-gate (iter2 != NULL) && (*on_smlr_bus == B_FALSE) && 1771*0Sstevel@tonic-gate (error == 0); 1772*0Sstevel@tonic-gate iter2 = iter2 ->next) { 1773*0Sstevel@tonic-gate 1774*0Sstevel@tonic-gate dm_descriptor_t uhba = (uintptr_t)iter2->obj; 1775*0Sstevel@tonic-gate char *utype = NULL; 1776*0Sstevel@tonic-gate boolean_t ufast80 = B_FALSE; 1777*0Sstevel@tonic-gate boolean_t ufast40 = B_FALSE; 1778*0Sstevel@tonic-gate boolean_t ufast20 = B_FALSE; 1779*0Sstevel@tonic-gate boolean_t uwide = B_FALSE; 1780*0Sstevel@tonic-gate 1781*0Sstevel@tonic-gate ((error = hba_get_type(uhba, &utype)) != 0) || 1782*0Sstevel@tonic-gate (error = hba_is_fast_80(uhba, &ufast80)) || 1783*0Sstevel@tonic-gate (error = hba_is_fast_40(uhba, &ufast40)) || 1784*0Sstevel@tonic-gate (error = hba_is_fast_20(uhba, &ufast20)) || 1785*0Sstevel@tonic-gate (error = hba_supports_wide(uhba, &uwide)); 1786*0Sstevel@tonic-gate 1787*0Sstevel@tonic-gate if (error == 0) { 1788*0Sstevel@tonic-gate /* check sync speed ? */ 1789*0Sstevel@tonic-gate if ((fast80 == ufast80) && (fast40 == ufast40) && 1790*0Sstevel@tonic-gate (fast20 == ufast20) && (wide == uwide) && 1791*0Sstevel@tonic-gate (type == utype)) { 1792*0Sstevel@tonic-gate *on_smlr_bus = B_TRUE; 1793*0Sstevel@tonic-gate } 1794*0Sstevel@tonic-gate } 1795*0Sstevel@tonic-gate } 1796*0Sstevel@tonic-gate dlist_free_items(uhbas, NULL); 1797*0Sstevel@tonic-gate } 1798*0Sstevel@tonic-gate } 1799*0Sstevel@tonic-gate 1800*0Sstevel@tonic-gate dlist_free_items(hbas, NULL); 1801*0Sstevel@tonic-gate 1802*0Sstevel@tonic-gate return (error); 1803*0Sstevel@tonic-gate } 1804*0Sstevel@tonic-gate 1805*0Sstevel@tonic-gate /* 1806*0Sstevel@tonic-gate * FUNCTION: slice_has_n_paths(dm_descriptor_t slice, 1807*0Sstevel@tonic-gate * uint16_t npaths, boolean_t *has_n_paths) 1808*0Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t handle for the slice of interest 1809*0Sstevel@tonic-gate * npaths - the number of paths desired 1810*0Sstevel@tonic-gate * has_n_paths - a boolean_t pointer to hold the result 1811*0Sstevel@tonic-gate * 1812*0Sstevel@tonic-gate * RETURNS: int - 0 on success 1813*0Sstevel@tonic-gate * !0 otherwise 1814*0Sstevel@tonic-gate * 1815*0Sstevel@tonic-gate * PURPOSE: Determines if the input slice is connected via npaths. 1816*0Sstevel@tonic-gate * has_n_paths is set to B_TRUE if so, B_FALSE otherwise. 1817*0Sstevel@tonic-gate * 1818*0Sstevel@tonic-gate * In order for a disk to have multiple paths, MPXIO must 1819*0Sstevel@tonic-gate * be enabled and these conditions should hold: 1820*0Sstevel@tonic-gate * 1821*0Sstevel@tonic-gate * Slice will have one drive object. 1822*0Sstevel@tonic-gate * Drive will have one HBA (scsi_vhci) 1823*0Sstevel@tonic-gate * Drive will have one alias. 1824*0Sstevel@tonic-gate * Drive will have possibly > 1 paths. 1825*0Sstevel@tonic-gate * 1826*0Sstevel@tonic-gate * Getting the HBAs and aliases for the disk is relatively 1827*0Sstevel@tonic-gate * expensive, so they aren't checked. The actual number of 1828*0Sstevel@tonic-gate * paths is only checked if MPXIO is known to be enabled on 1829*0Sstevel@tonic-gate * the system and the input npaths is > 1. 1830*0Sstevel@tonic-gate */ 1831*0Sstevel@tonic-gate static int 1832*0Sstevel@tonic-gate slice_has_n_paths( 1833*0Sstevel@tonic-gate dm_descriptor_t slice, 1834*0Sstevel@tonic-gate uint16_t npaths, 1835*0Sstevel@tonic-gate boolean_t *has_n_paths) 1836*0Sstevel@tonic-gate { 1837*0Sstevel@tonic-gate int error = 0; 1838*0Sstevel@tonic-gate 1839*0Sstevel@tonic-gate *has_n_paths = B_FALSE; 1840*0Sstevel@tonic-gate 1841*0Sstevel@tonic-gate if ((npaths > 1) && (is_mpxio_enabled() == B_TRUE)) { 1842*0Sstevel@tonic-gate 1843*0Sstevel@tonic-gate dm_descriptor_t disk = NULL; 1844*0Sstevel@tonic-gate dlist_t *paths = NULL; 1845*0Sstevel@tonic-gate 1846*0Sstevel@tonic-gate ((error = slice_get_disk(slice, &disk)) != 0) || 1847*0Sstevel@tonic-gate (error = disk_get_paths(disk, &paths)); 1848*0Sstevel@tonic-gate 1849*0Sstevel@tonic-gate if ((error == 0) && (dlist_length(paths) == npaths)) { 1850*0Sstevel@tonic-gate *has_n_paths = B_TRUE; 1851*0Sstevel@tonic-gate } 1852*0Sstevel@tonic-gate dlist_free_items(paths, NULL); 1853*0Sstevel@tonic-gate } 1854*0Sstevel@tonic-gate 1855*0Sstevel@tonic-gate return (error); 1856*0Sstevel@tonic-gate } 1857*0Sstevel@tonic-gate 1858*0Sstevel@tonic-gate /* 1859*0Sstevel@tonic-gate * FUNCTION: compare_string_to_modslice_name(void *str, void *modslice) 1860*0Sstevel@tonic-gate * 1861*0Sstevel@tonic-gate * INPUT: str - opaque char * pointer 1862*0Sstevel@tonic-gate * modslice - opaque modslice_t pointer 1863*0Sstevel@tonic-gate * 1864*0Sstevel@tonic-gate * RETURNS: int - <0 - if str < modslice->slice_devcfg.name 1865*0Sstevel@tonic-gate * 0 - if str == modslice->slice_devcfg.name 1866*0Sstevel@tonic-gate * >0 - if str > modslice->slice_devcfg.name 1867*0Sstevel@tonic-gate * 1868*0Sstevel@tonic-gate * PURPOSE: dlist_t helper which compares the input string to 1869*0Sstevel@tonic-gate * the name of a slice represented as modslice_t struct. 1870*0Sstevel@tonic-gate * 1871*0Sstevel@tonic-gate * Comparison is done via string_case_compare. 1872*0Sstevel@tonic-gate */ 1873*0Sstevel@tonic-gate static int 1874*0Sstevel@tonic-gate compare_string_to_modslice_name( 1875*0Sstevel@tonic-gate void *str, 1876*0Sstevel@tonic-gate void *modslice) 1877*0Sstevel@tonic-gate { 1878*0Sstevel@tonic-gate char *name = NULL; 1879*0Sstevel@tonic-gate 1880*0Sstevel@tonic-gate assert(str != NULL); 1881*0Sstevel@tonic-gate assert(modslice != NULL); 1882*0Sstevel@tonic-gate 1883*0Sstevel@tonic-gate (void) devconfig_get_name( 1884*0Sstevel@tonic-gate ((modslice_t *)modslice)->slice_devcfg, &name); 1885*0Sstevel@tonic-gate 1886*0Sstevel@tonic-gate return (string_case_compare((char *)str, name)); 1887*0Sstevel@tonic-gate } 1888*0Sstevel@tonic-gate 1889*0Sstevel@tonic-gate /* 1890*0Sstevel@tonic-gate * FUNCTION: compare_modslice_names(void *obj1, void *obj2) 1891*0Sstevel@tonic-gate * 1892*0Sstevel@tonic-gate * INPUT: obj1 - opaque pointer 1893*0Sstevel@tonic-gate * obj2 - opaque pointer 1894*0Sstevel@tonic-gate * 1895*0Sstevel@tonic-gate * RETURNS: int - <0 - if obj1 name < obj2 name 1896*0Sstevel@tonic-gate * 0 - if obj1 name == obj2 name 1897*0Sstevel@tonic-gate * >0 - if obj1 name > obj2 name 1898*0Sstevel@tonic-gate * 1899*0Sstevel@tonic-gate * PURPOSE: dlist_t helper which compares the names of two slices 1900*0Sstevel@tonic-gate * represented as modslice_t structs. 1901*0Sstevel@tonic-gate * 1902*0Sstevel@tonic-gate * Comparison is done by string_case_compare 1903*0Sstevel@tonic-gate */ 1904*0Sstevel@tonic-gate static int 1905*0Sstevel@tonic-gate compare_modslice_names( 1906*0Sstevel@tonic-gate void *obj1, 1907*0Sstevel@tonic-gate void *obj2) 1908*0Sstevel@tonic-gate { 1909*0Sstevel@tonic-gate char *name1 = NULL; 1910*0Sstevel@tonic-gate char *name2 = NULL; 1911*0Sstevel@tonic-gate 1912*0Sstevel@tonic-gate assert(obj1 != NULL); 1913*0Sstevel@tonic-gate assert(obj2 != NULL); 1914*0Sstevel@tonic-gate 1915*0Sstevel@tonic-gate (void) devconfig_get_name( 1916*0Sstevel@tonic-gate ((modslice_t *)obj1)->slice_devcfg, &name1); 1917*0Sstevel@tonic-gate (void) devconfig_get_name( 1918*0Sstevel@tonic-gate ((modslice_t *)obj2)->slice_devcfg, &name2); 1919*0Sstevel@tonic-gate 1920*0Sstevel@tonic-gate return (string_case_compare(name1, name2)); 1921*0Sstevel@tonic-gate } 1922*0Sstevel@tonic-gate 1923*0Sstevel@tonic-gate /* 1924*0Sstevel@tonic-gate * FUNCTION: release_used_slices() 1925*0Sstevel@tonic-gate * 1926*0Sstevel@tonic-gate * PURPOSE: Helper which cleans up the module private list of used 1927*0Sstevel@tonic-gate * slices. 1928*0Sstevel@tonic-gate */ 1929*0Sstevel@tonic-gate void 1930*0Sstevel@tonic-gate release_used_slices() 1931*0Sstevel@tonic-gate { 1932*0Sstevel@tonic-gate dlist_free_items(_used_slices, free_used_slice); 1933*0Sstevel@tonic-gate _used_slices = NULL; 1934*0Sstevel@tonic-gate } 1935*0Sstevel@tonic-gate 1936*0Sstevel@tonic-gate static void 1937*0Sstevel@tonic-gate free_used_slice( 1938*0Sstevel@tonic-gate void *obj) 1939*0Sstevel@tonic-gate { 1940*0Sstevel@tonic-gate if (obj != NULL) { 1941*0Sstevel@tonic-gate usedslice_t *used = (usedslice_t *)obj; 1942*0Sstevel@tonic-gate free(used->slicename); 1943*0Sstevel@tonic-gate free(used); 1944*0Sstevel@tonic-gate } 1945*0Sstevel@tonic-gate } 1946*0Sstevel@tonic-gate 1947*0Sstevel@tonic-gate /* 1948*0Sstevel@tonic-gate * FUNCTION: is_used_slice(dm_descriptor_t slice, boolean_t *is_used) 1949*0Sstevel@tonic-gate * 1950*0Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t slice handle 1951*0Sstevel@tonic-gate * 1952*0Sstevel@tonic-gate * OUTPUT: is_reserved - pointer to a boolean_t to hold the 1953*0Sstevel@tonic-gate * return result. 1954*0Sstevel@tonic-gate * 1955*0Sstevel@tonic-gate * PURPOSE: Helper which checks to see if the input slice 1956*0Sstevel@tonic-gate * is in the used_slice list. 1957*0Sstevel@tonic-gate * 1958*0Sstevel@tonic-gate * Check the input name against any used slice name or alias. 1959*0Sstevel@tonic-gate * is_used is set to B_TRUE if the input slice is already used, 1960*0Sstevel@tonic-gate * B_FALSE otherwise. 1961*0Sstevel@tonic-gate */ 1962*0Sstevel@tonic-gate int 1963*0Sstevel@tonic-gate is_used_slice( 1964*0Sstevel@tonic-gate dm_descriptor_t slice, 1965*0Sstevel@tonic-gate boolean_t *is_used) 1966*0Sstevel@tonic-gate { 1967*0Sstevel@tonic-gate char *name; 1968*0Sstevel@tonic-gate int error = 0; 1969*0Sstevel@tonic-gate 1970*0Sstevel@tonic-gate if ((error = get_display_name(slice, &name)) == 0) { 1971*0Sstevel@tonic-gate *is_used = dlist_contains(_used_slices, (void *)name, 1972*0Sstevel@tonic-gate compare_usedslice_name_to_string); 1973*0Sstevel@tonic-gate } 1974*0Sstevel@tonic-gate 1975*0Sstevel@tonic-gate return (error); 1976*0Sstevel@tonic-gate } 1977*0Sstevel@tonic-gate 1978*0Sstevel@tonic-gate /* 1979*0Sstevel@tonic-gate * FUNCTIONS: add_used_slice(dm_descriptor_t slice) 1980*0Sstevel@tonic-gate * add_used_slice_by_name(char *slicename) 1981*0Sstevel@tonic-gate * add_used_slice_list_entry(char *slice) 1982*0Sstevel@tonic-gate * remove_used_slice_by_name(char *slicename) 1983*0Sstevel@tonic-gate * 1984*0Sstevel@tonic-gate * INPUT: diskset - a char * diskset name. 1985*0Sstevel@tonic-gate * slice - a dm_descriptor_t slice handle 1986*0Sstevel@tonic-gate * 1987*0Sstevel@tonic-gate * RETURNS: int - 0 on success 1988*0Sstevel@tonic-gate * !0 otherwise 1989*0Sstevel@tonic-gate * 1990*0Sstevel@tonic-gate * PURPOSE: Access or maintain the list of used slices. 1991*0Sstevel@tonic-gate */ 1992*0Sstevel@tonic-gate int 1993*0Sstevel@tonic-gate add_used_slice( 1994*0Sstevel@tonic-gate dm_descriptor_t slice) 1995*0Sstevel@tonic-gate { 1996*0Sstevel@tonic-gate dm_descriptor_t disk; 1997*0Sstevel@tonic-gate char *name; 1998*0Sstevel@tonic-gate int error = 0; 1999*0Sstevel@tonic-gate 2000*0Sstevel@tonic-gate assert(slice != (dm_descriptor_t)0); 2001*0Sstevel@tonic-gate 2002*0Sstevel@tonic-gate ((error = get_display_name(slice, &name)) != 0) || 2003*0Sstevel@tonic-gate (error = slice_get_disk(slice, &disk)) || 2004*0Sstevel@tonic-gate (error = add_used_slice_list_entry(name, disk)); 2005*0Sstevel@tonic-gate 2006*0Sstevel@tonic-gate return (error); 2007*0Sstevel@tonic-gate } 2008*0Sstevel@tonic-gate 2009*0Sstevel@tonic-gate int 2010*0Sstevel@tonic-gate add_used_slice_by_name( 2011*0Sstevel@tonic-gate char *slicename) 2012*0Sstevel@tonic-gate { 2013*0Sstevel@tonic-gate dm_descriptor_t disk = (dm_descriptor_t)0; 2014*0Sstevel@tonic-gate int error = 0; 2015*0Sstevel@tonic-gate 2016*0Sstevel@tonic-gate assert(slicename != NULL); 2017*0Sstevel@tonic-gate 2018*0Sstevel@tonic-gate /* find disk for slice */ 2019*0Sstevel@tonic-gate error = get_disk_for_named_slice(slicename, &disk); 2020*0Sstevel@tonic-gate if (error == 0) { 2021*0Sstevel@tonic-gate error = add_used_slice_list_entry(slicename, disk); 2022*0Sstevel@tonic-gate } 2023*0Sstevel@tonic-gate 2024*0Sstevel@tonic-gate return (error); 2025*0Sstevel@tonic-gate } 2026*0Sstevel@tonic-gate 2027*0Sstevel@tonic-gate static int 2028*0Sstevel@tonic-gate add_used_slice_list_entry( 2029*0Sstevel@tonic-gate char *slicename, 2030*0Sstevel@tonic-gate dm_descriptor_t disk) 2031*0Sstevel@tonic-gate { 2032*0Sstevel@tonic-gate usedslice_t *used = NULL; 2033*0Sstevel@tonic-gate int error = 0; 2034*0Sstevel@tonic-gate 2035*0Sstevel@tonic-gate assert(slicename != NULL); 2036*0Sstevel@tonic-gate assert(disk != (dm_descriptor_t)0); 2037*0Sstevel@tonic-gate 2038*0Sstevel@tonic-gate used = (usedslice_t *)calloc(1, sizeof (usedslice_t)); 2039*0Sstevel@tonic-gate if (used == NULL) { 2040*0Sstevel@tonic-gate error = ENOMEM; 2041*0Sstevel@tonic-gate } else { 2042*0Sstevel@tonic-gate 2043*0Sstevel@tonic-gate used->disk = disk; 2044*0Sstevel@tonic-gate if ((used->slicename = strdup(slicename)) == NULL) { 2045*0Sstevel@tonic-gate free(used); 2046*0Sstevel@tonic-gate error = ENOMEM; 2047*0Sstevel@tonic-gate } else { 2048*0Sstevel@tonic-gate dlist_t *item = dlist_new_item((void *) used); 2049*0Sstevel@tonic-gate if (item == NULL) { 2050*0Sstevel@tonic-gate free(used->slicename); 2051*0Sstevel@tonic-gate free(used); 2052*0Sstevel@tonic-gate error = ENOMEM; 2053*0Sstevel@tonic-gate } else { 2054*0Sstevel@tonic-gate _used_slices = 2055*0Sstevel@tonic-gate dlist_append(item, _used_slices, AT_HEAD); 2056*0Sstevel@tonic-gate } 2057*0Sstevel@tonic-gate } 2058*0Sstevel@tonic-gate } 2059*0Sstevel@tonic-gate return (error); 2060*0Sstevel@tonic-gate } 2061*0Sstevel@tonic-gate 2062*0Sstevel@tonic-gate int 2063*0Sstevel@tonic-gate remove_used_slice_by_name( 2064*0Sstevel@tonic-gate char *slice) 2065*0Sstevel@tonic-gate { 2066*0Sstevel@tonic-gate dlist_t *removed = NULL; 2067*0Sstevel@tonic-gate 2068*0Sstevel@tonic-gate _used_slices = 2069*0Sstevel@tonic-gate dlist_remove_equivalent_item(_used_slices, (void *)slice, 2070*0Sstevel@tonic-gate compare_usedslice_name_to_string, &removed); 2071*0Sstevel@tonic-gate 2072*0Sstevel@tonic-gate if (removed != NULL) { 2073*0Sstevel@tonic-gate free_used_slice(removed->obj); 2074*0Sstevel@tonic-gate removed->obj = NULL; 2075*0Sstevel@tonic-gate free(removed); 2076*0Sstevel@tonic-gate } 2077*0Sstevel@tonic-gate 2078*0Sstevel@tonic-gate return (0); 2079*0Sstevel@tonic-gate } 2080*0Sstevel@tonic-gate 2081*0Sstevel@tonic-gate /* 2082*0Sstevel@tonic-gate * FUNCTION: compare_usedslice_name_to_string(void *obj1, void *obj2) 2083*0Sstevel@tonic-gate * INPUT: obj1 - opaque pointer 2084*0Sstevel@tonic-gate * obj2 - opaque pointer 2085*0Sstevel@tonic-gate * 2086*0Sstevel@tonic-gate * RETURNS: int - <0 - if obj1 name < obj2 name 2087*0Sstevel@tonic-gate * 0 - if obj1 name == obj2 name 2088*0Sstevel@tonic-gate * >0 - if obj1 name > obj2 name 2089*0Sstevel@tonic-gate * 2090*0Sstevel@tonic-gate * PURPOSE: dlist_t helper which compares the names of a slice 2091*0Sstevel@tonic-gate * represented as modslice_t struct to a string. 2092*0Sstevel@tonic-gate * 2093*0Sstevel@tonic-gate * obj1 is assumed to be a char * 2094*0Sstevel@tonic-gate * obj2 is assumed to be a usedslice_t * 2095*0Sstevel@tonic-gate * 2096*0Sstevel@tonic-gate * Comparison is done via string_case_compare. 2097*0Sstevel@tonic-gate */ 2098*0Sstevel@tonic-gate static int 2099*0Sstevel@tonic-gate compare_usedslice_name_to_string( 2100*0Sstevel@tonic-gate void *obj1, 2101*0Sstevel@tonic-gate void *obj2) 2102*0Sstevel@tonic-gate { 2103*0Sstevel@tonic-gate assert(obj1 != NULL); 2104*0Sstevel@tonic-gate assert(obj2 != NULL); 2105*0Sstevel@tonic-gate 2106*0Sstevel@tonic-gate return (string_case_compare((char *)obj1, 2107*0Sstevel@tonic-gate ((usedslice_t *)obj2)->slicename)); 2108*0Sstevel@tonic-gate } 2109*0Sstevel@tonic-gate 2110*0Sstevel@tonic-gate /* 2111*0Sstevel@tonic-gate * FUNCTION: disk_has_used_slice(dm_descriptor_t disk, boolean_t *hasused) 2112*0Sstevel@tonic-gate * 2113*0Sstevel@tonic-gate * INPUT: disk - a dm_descriptor_t disk handle. 2114*0Sstevel@tonic-gate * inuse - a boolean_t pointer to hold the result 2115*0Sstevel@tonic-gate * 2116*0Sstevel@tonic-gate * RETURNS: int - 0 on success 2117*0Sstevel@tonic-gate * !0 othersize. 2118*0Sstevel@tonic-gate * 2119*0Sstevel@tonic-gate * PURPOSE: Determines if any of the known used slices is on the 2120*0Sstevel@tonic-gate * input disk. 2121*0Sstevel@tonic-gate */ 2122*0Sstevel@tonic-gate int 2123*0Sstevel@tonic-gate disk_has_used_slice( 2124*0Sstevel@tonic-gate dm_descriptor_t disk, 2125*0Sstevel@tonic-gate boolean_t *hasused) 2126*0Sstevel@tonic-gate { 2127*0Sstevel@tonic-gate dlist_t *iter; 2128*0Sstevel@tonic-gate int error = 0; 2129*0Sstevel@tonic-gate 2130*0Sstevel@tonic-gate *hasused = B_FALSE; 2131*0Sstevel@tonic-gate for (iter = _used_slices; 2132*0Sstevel@tonic-gate (iter != NULL) && (*hasused == B_FALSE); 2133*0Sstevel@tonic-gate iter = iter->next) { 2134*0Sstevel@tonic-gate 2135*0Sstevel@tonic-gate usedslice_t *used = (usedslice_t *)iter->obj; 2136*0Sstevel@tonic-gate 2137*0Sstevel@tonic-gate /* compare used slice's disk to disk */ 2138*0Sstevel@tonic-gate if (compare_descriptors((void *)disk, (void *)used->disk) == 0) { 2139*0Sstevel@tonic-gate *hasused = B_TRUE; 2140*0Sstevel@tonic-gate } 2141*0Sstevel@tonic-gate } 2142*0Sstevel@tonic-gate 2143*0Sstevel@tonic-gate return (error); 2144*0Sstevel@tonic-gate } 2145*0Sstevel@tonic-gate 2146*0Sstevel@tonic-gate /* 2147*0Sstevel@tonic-gate * FUNCTION: add_reserved_slice(dm_descriptor_t slice) 2148*0Sstevel@tonic-gate * 2149*0Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t slice handle 2150*0Sstevel@tonic-gate * 2151*0Sstevel@tonic-gate * RETURNS: int - 0 on success 2152*0Sstevel@tonic-gate * !0 otherwise. 2153*0Sstevel@tonic-gate * 2154*0Sstevel@tonic-gate * PURPOSE: Helper which remembers specfically requested slices 2155*0Sstevel@tonic-gate * in a private list to ensure that the same slice isn't 2156*0Sstevel@tonic-gate * requested more than once. 2157*0Sstevel@tonic-gate * 2158*0Sstevel@tonic-gate * Does not check to see if the slice already exists 2159*0Sstevel@tonic-gate * in the list of reserved slices. Assumes that the 2160*0Sstevel@tonic-gate * caller has checked using is_reserved_slice(). 2161*0Sstevel@tonic-gate * 2162*0Sstevel@tonic-gate * The reserved slice list is used by several functions: 2163*0Sstevel@tonic-gate * 2164*0Sstevel@tonic-gate * 1. layout_validate.validate_slice_components() adds user 2165*0Sstevel@tonic-gate * requested slices to the list. 2166*0Sstevel@tonic-gate * 2167*0Sstevel@tonic-gate * 2. After all potentially usable slices have been scanned, 2168*0Sstevel@tonic-gate * layout_validate.validate_reserved_slices() checks the 2169*0Sstevel@tonic-gate * slices in the reserved and ensures that each slice is 2170*0Sstevel@tonic-gate * actually usable as a volume component. 2171*0Sstevel@tonic-gate * 2172*0Sstevel@tonic-gate * 3. layout.disk_get_avail_space(), layout.disk_get_avail_slices() 2173*0Sstevel@tonic-gate * exclude slices in the reserved list from being considered 2174*0Sstevel@tonic-gate * available for general layout use. 2175*0Sstevel@tonic-gate */ 2176*0Sstevel@tonic-gate int 2177*0Sstevel@tonic-gate add_reserved_slice( 2178*0Sstevel@tonic-gate dm_descriptor_t slice) 2179*0Sstevel@tonic-gate { 2180*0Sstevel@tonic-gate dlist_t *item = NULL; 2181*0Sstevel@tonic-gate 2182*0Sstevel@tonic-gate if ((item = dlist_new_item((void *)slice)) == NULL) { 2183*0Sstevel@tonic-gate return (ENOMEM); 2184*0Sstevel@tonic-gate } 2185*0Sstevel@tonic-gate 2186*0Sstevel@tonic-gate _rsvd_slices = dlist_append(item, _rsvd_slices, AT_HEAD); 2187*0Sstevel@tonic-gate 2188*0Sstevel@tonic-gate return (0); 2189*0Sstevel@tonic-gate } 2190*0Sstevel@tonic-gate 2191*0Sstevel@tonic-gate /* 2192*0Sstevel@tonic-gate * FUNCTION: is_reserved_slice(dm_descriptor_t slice, 2193*0Sstevel@tonic-gate * boolean_t *is_reserved) 2194*0Sstevel@tonic-gate * 2195*0Sstevel@tonic-gate * INPUT: slice - a dm_descriptor_t slice handle 2196*0Sstevel@tonic-gate * 2197*0Sstevel@tonic-gate * OUTPUT: is_reserved - pointer to a boolean_t to hold the 2198*0Sstevel@tonic-gate * return result. 2199*0Sstevel@tonic-gate * 2200*0Sstevel@tonic-gate * PURPOSE: Helper which checks to see if the input slice 2201*0Sstevel@tonic-gate * was previously reserved. 2202*0Sstevel@tonic-gate * 2203*0Sstevel@tonic-gate * Check the input name against any reserved slice 2204*0Sstevel@tonic-gate * name or alias. is_reserved is set to B_TRUE if the 2205*0Sstevel@tonic-gate * input slice is already reserved, B_FALSE otherwise. 2206*0Sstevel@tonic-gate */ 2207*0Sstevel@tonic-gate int 2208*0Sstevel@tonic-gate is_reserved_slice( 2209*0Sstevel@tonic-gate dm_descriptor_t slice, 2210*0Sstevel@tonic-gate boolean_t *is_reserved) 2211*0Sstevel@tonic-gate { 2212*0Sstevel@tonic-gate *is_reserved = dlist_contains( 2213*0Sstevel@tonic-gate _rsvd_slices, (void *)slice, compare_descriptor_names); 2214*0Sstevel@tonic-gate 2215*0Sstevel@tonic-gate return (0); 2216*0Sstevel@tonic-gate } 2217*0Sstevel@tonic-gate 2218*0Sstevel@tonic-gate /* 2219*0Sstevel@tonic-gate * FUNCTION: release_reserved_slice() 2220*0Sstevel@tonic-gate * 2221*0Sstevel@tonic-gate * PURPOSE: Helper which cleans up the module private list of reserved 2222*0Sstevel@tonic-gate * slices. 2223*0Sstevel@tonic-gate */ 2224*0Sstevel@tonic-gate void 2225*0Sstevel@tonic-gate release_reserved_slices() 2226*0Sstevel@tonic-gate { 2227*0Sstevel@tonic-gate dlist_free_items(_rsvd_slices, free); 2228*0Sstevel@tonic-gate _rsvd_slices = NULL; 2229*0Sstevel@tonic-gate } 2230*0Sstevel@tonic-gate 2231*0Sstevel@tonic-gate /* 2232*0Sstevel@tonic-gate * FUNCTION: get_reserved_slices(dlist_t **list) 2233*0Sstevel@tonic-gate * 2234*0Sstevel@tonic-gate * OUTPUT: list - a dlist_t pointer to hold the returned list of 2235*0Sstevel@tonic-gate * reserverd slices. 2236*0Sstevel@tonic-gate * 2237*0Sstevel@tonic-gate * RETURNS: int - 0 on success 2238*0Sstevel@tonic-gate * !0 otherwise 2239*0Sstevel@tonic-gate * 2240*0Sstevel@tonic-gate * PURPOSE: Accessor to retrieve the current list of reserved slice 2241*0Sstevel@tonic-gate * dm_descriptor_t handles. 2242*0Sstevel@tonic-gate */ 2243*0Sstevel@tonic-gate int 2244*0Sstevel@tonic-gate get_reserved_slices( 2245*0Sstevel@tonic-gate dlist_t **list) 2246*0Sstevel@tonic-gate { 2247*0Sstevel@tonic-gate *list = _rsvd_slices; 2248*0Sstevel@tonic-gate 2249*0Sstevel@tonic-gate return (0); 2250*0Sstevel@tonic-gate } 2251*0Sstevel@tonic-gate 2252*0Sstevel@tonic-gate /* 2253*0Sstevel@tonic-gate * FUNCTION: add_slice_to_remove(char *name, uint32_t index) 2254*0Sstevel@tonic-gate * 2255*0Sstevel@tonic-gate * INPUT: name - name of a slice 2256*0Sstevel@tonic-gate * index - index for the slice 2257*0Sstevel@tonic-gate * 2258*0Sstevel@tonic-gate * RETURNS: int - 0 on success 2259*0Sstevel@tonic-gate * !0 otherwise 2260*0Sstevel@tonic-gate * 2261*0Sstevel@tonic-gate * PURPOSE: Utility function to add the named slice to the list of 2262*0Sstevel@tonic-gate * those that need to be "removed" by having their sizes 2263*0Sstevel@tonic-gate * set to 0. 2264*0Sstevel@tonic-gate */ 2265*0Sstevel@tonic-gate int 2266*0Sstevel@tonic-gate add_slice_to_remove( 2267*0Sstevel@tonic-gate char *name, 2268*0Sstevel@tonic-gate uint32_t index) 2269*0Sstevel@tonic-gate { 2270*0Sstevel@tonic-gate rmvdslice_t *rmvd = NULL; 2271*0Sstevel@tonic-gate int error = 0; 2272*0Sstevel@tonic-gate 2273*0Sstevel@tonic-gate assert(name != NULL); 2274*0Sstevel@tonic-gate 2275*0Sstevel@tonic-gate rmvd = (rmvdslice_t *)calloc(1, sizeof (rmvdslice_t)); 2276*0Sstevel@tonic-gate if (rmvd == NULL) { 2277*0Sstevel@tonic-gate error = ENOMEM; 2278*0Sstevel@tonic-gate } else { 2279*0Sstevel@tonic-gate rmvd->slice_index = index; 2280*0Sstevel@tonic-gate if ((rmvd->slice_name = strdup(name)) == NULL) { 2281*0Sstevel@tonic-gate free(rmvd); 2282*0Sstevel@tonic-gate error = ENOMEM; 2283*0Sstevel@tonic-gate } else { 2284*0Sstevel@tonic-gate dlist_t *item = dlist_new_item((void *) rmvd); 2285*0Sstevel@tonic-gate if (item == NULL) { 2286*0Sstevel@tonic-gate free(rmvd->slice_name); 2287*0Sstevel@tonic-gate free(rmvd); 2288*0Sstevel@tonic-gate error = ENOMEM; 2289*0Sstevel@tonic-gate } else { 2290*0Sstevel@tonic-gate _rmvd_slices = 2291*0Sstevel@tonic-gate dlist_append(item, _rmvd_slices, AT_HEAD); 2292*0Sstevel@tonic-gate } 2293*0Sstevel@tonic-gate } 2294*0Sstevel@tonic-gate } 2295*0Sstevel@tonic-gate return (error); 2296*0Sstevel@tonic-gate } 2297*0Sstevel@tonic-gate 2298*0Sstevel@tonic-gate /* 2299*0Sstevel@tonic-gate * FUNCTION: get_removed_slices() 2300*0Sstevel@tonic-gate * 2301*0Sstevel@tonic-gate * RETURNS: dlist_t * - pointer to a list of rmvdslice_t structs 2302*0Sstevel@tonic-gate * 2303*0Sstevel@tonic-gate * PURPOSE: Accessor to retrieve the current list of names of slices 2304*0Sstevel@tonic-gate * to be removed. 2305*0Sstevel@tonic-gate */ 2306*0Sstevel@tonic-gate dlist_t * 2307*0Sstevel@tonic-gate get_slices_to_remove( 2308*0Sstevel@tonic-gate dlist_t **list) 2309*0Sstevel@tonic-gate { 2310*0Sstevel@tonic-gate return (_rmvd_slices); 2311*0Sstevel@tonic-gate } 2312*0Sstevel@tonic-gate 2313*0Sstevel@tonic-gate static void 2314*0Sstevel@tonic-gate free_rmvd_slice( 2315*0Sstevel@tonic-gate void *obj) 2316*0Sstevel@tonic-gate { 2317*0Sstevel@tonic-gate if (obj != NULL) { 2318*0Sstevel@tonic-gate rmvdslice_t *rmvd = (rmvdslice_t *)obj; 2319*0Sstevel@tonic-gate free(rmvd->slice_name); 2320*0Sstevel@tonic-gate free(rmvd); 2321*0Sstevel@tonic-gate } 2322*0Sstevel@tonic-gate } 2323*0Sstevel@tonic-gate 2324*0Sstevel@tonic-gate /* 2325*0Sstevel@tonic-gate * FUNCTION: release_removed_slices() 2326*0Sstevel@tonic-gate * 2327*0Sstevel@tonic-gate * PURPOSE: Helper which cleans up the module private list of removed 2328*0Sstevel@tonic-gate * slices. 2329*0Sstevel@tonic-gate */ 2330*0Sstevel@tonic-gate void 2331*0Sstevel@tonic-gate release_slices_to_remove() 2332*0Sstevel@tonic-gate { 2333*0Sstevel@tonic-gate dlist_free_items(_rmvd_slices, free_rmvd_slice); 2334*0Sstevel@tonic-gate _rmvd_slices = NULL; 2335*0Sstevel@tonic-gate } 2336