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 2003 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 "volume_devconfig.h" 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #include <string.h> 32*0Sstevel@tonic-gate #include <ctype.h> 33*0Sstevel@tonic-gate #include <meta.h> 34*0Sstevel@tonic-gate #include "volume_nvpair.h" 35*0Sstevel@tonic-gate #include "volume_error.h" 36*0Sstevel@tonic-gate #include "volume_output.h" 37*0Sstevel@tonic-gate #include "volume_string.h" 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate /* 40*0Sstevel@tonic-gate * Methods which manipulate a devconfig_t struct 41*0Sstevel@tonic-gate */ 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate /* 44*0Sstevel@tonic-gate * Constructor: Create a devconfig_t struct. This devconfig_t must be 45*0Sstevel@tonic-gate * freed with free_devconfig(). 46*0Sstevel@tonic-gate * 47*0Sstevel@tonic-gate * @param devconfig 48*0Sstevel@tonic-gate * RETURN: a new devconfig_t 49*0Sstevel@tonic-gate * 50*0Sstevel@tonic-gate * @param type 51*0Sstevel@tonic-gate * the type of devconfig_t to create 52*0Sstevel@tonic-gate * 53*0Sstevel@tonic-gate * @return 0 54*0Sstevel@tonic-gate * if successful 55*0Sstevel@tonic-gate * 56*0Sstevel@tonic-gate * @return non-zero 57*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 58*0Sstevel@tonic-gate * retrieve the associated error message. 59*0Sstevel@tonic-gate */ 60*0Sstevel@tonic-gate int 61*0Sstevel@tonic-gate new_devconfig( 62*0Sstevel@tonic-gate devconfig_t **devconfig, 63*0Sstevel@tonic-gate component_type_t type) 64*0Sstevel@tonic-gate { 65*0Sstevel@tonic-gate int error; 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate *devconfig = (devconfig_t *)calloc(1, sizeof (devconfig_t)); 68*0Sstevel@tonic-gate if (*devconfig == NULL) { 69*0Sstevel@tonic-gate volume_set_error(gettext("new_devconfig() calloc() failed\n")); 70*0Sstevel@tonic-gate return (-1); 71*0Sstevel@tonic-gate } 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate /* Create attribute list */ 74*0Sstevel@tonic-gate if ((error = nvlist_alloc(&((*devconfig)->attributes), 75*0Sstevel@tonic-gate NV_UNIQUE_NAME_TYPE, 0)) != 0) { 76*0Sstevel@tonic-gate volume_set_error(gettext("devconfig_t nvlist_alloc() failed\n")); 77*0Sstevel@tonic-gate free_devconfig(*devconfig); 78*0Sstevel@tonic-gate return (error); 79*0Sstevel@tonic-gate } 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate if ((error = devconfig_set_type(*devconfig, type)) != 0) { 82*0Sstevel@tonic-gate free_devconfig(*devconfig); 83*0Sstevel@tonic-gate return (error); 84*0Sstevel@tonic-gate } 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate return (0); 87*0Sstevel@tonic-gate } 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate /* 90*0Sstevel@tonic-gate * Free memory (recursively) allocated to a devconfig_t struct 91*0Sstevel@tonic-gate * 92*0Sstevel@tonic-gate * @param arg 93*0Sstevel@tonic-gate * pointer to the devconfig_t to be freed 94*0Sstevel@tonic-gate */ 95*0Sstevel@tonic-gate void 96*0Sstevel@tonic-gate free_devconfig( 97*0Sstevel@tonic-gate void *arg) 98*0Sstevel@tonic-gate { 99*0Sstevel@tonic-gate devconfig_t *devconfig = (devconfig_t *)arg; 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate if (devconfig == NULL) { 102*0Sstevel@tonic-gate return; 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate /* Free the attributes nvlist */ 106*0Sstevel@tonic-gate if (devconfig->attributes != NULL) { 107*0Sstevel@tonic-gate nvlist_free(devconfig->attributes); 108*0Sstevel@tonic-gate } 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate /* Free available devices */ 111*0Sstevel@tonic-gate if (devconfig->available != NULL) { 112*0Sstevel@tonic-gate free_string_array(devconfig->available); 113*0Sstevel@tonic-gate } 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate /* Free unavailable devices */ 116*0Sstevel@tonic-gate if (devconfig->unavailable != NULL) { 117*0Sstevel@tonic-gate free_string_array(devconfig->unavailable); 118*0Sstevel@tonic-gate } 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate /* Free the components */ 121*0Sstevel@tonic-gate if (devconfig->components != NULL) { 122*0Sstevel@tonic-gate dlist_free_items(devconfig->components, free_devconfig); 123*0Sstevel@tonic-gate } 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate /* Free the devconfig itself */ 126*0Sstevel@tonic-gate free(devconfig); 127*0Sstevel@tonic-gate } 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate /* 130*0Sstevel@tonic-gate * Check the type of the given device. 131*0Sstevel@tonic-gate * 132*0Sstevel@tonic-gate * @param device 133*0Sstevel@tonic-gate * the device whose type to check 134*0Sstevel@tonic-gate * 135*0Sstevel@tonic-gate * @param type 136*0Sstevel@tonic-gate * the type of the device against which to compare 137*0Sstevel@tonic-gate * 138*0Sstevel@tonic-gate * @return B_TRUE if the device is of the given type, B_FALSE 139*0Sstevel@tonic-gate * otherwise 140*0Sstevel@tonic-gate */ 141*0Sstevel@tonic-gate boolean_t 142*0Sstevel@tonic-gate devconfig_isA( 143*0Sstevel@tonic-gate devconfig_t *device, 144*0Sstevel@tonic-gate component_type_t type) 145*0Sstevel@tonic-gate { 146*0Sstevel@tonic-gate component_type_t curtype; 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate if (device == NULL) { 149*0Sstevel@tonic-gate return (B_FALSE); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate if (devconfig_get_type(device, &curtype) != 0) { 153*0Sstevel@tonic-gate return (B_FALSE); 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate if (curtype != type) { 157*0Sstevel@tonic-gate return (B_FALSE); 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate return (B_TRUE); 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate /* 164*0Sstevel@tonic-gate * Get the first component of the given type from the given 165*0Sstevel@tonic-gate * devconfig_t. Create the component if create is B_TRUE. 166*0Sstevel@tonic-gate * 167*0Sstevel@tonic-gate * @return ENOENT 168*0Sstevel@tonic-gate * if the requested component does not exist and its 169*0Sstevel@tonic-gate * creation was not requested 170*0Sstevel@tonic-gate * 171*0Sstevel@tonic-gate * @return 0 172*0Sstevel@tonic-gate * if the requested component exists or was created 173*0Sstevel@tonic-gate * 174*0Sstevel@tonic-gate * @return non-zero 175*0Sstevel@tonic-gate * if the requested component did not exist and could not 176*0Sstevel@tonic-gate * be created 177*0Sstevel@tonic-gate */ 178*0Sstevel@tonic-gate int 179*0Sstevel@tonic-gate devconfig_get_component( 180*0Sstevel@tonic-gate devconfig_t *device, 181*0Sstevel@tonic-gate component_type_t type, 182*0Sstevel@tonic-gate devconfig_t **component, 183*0Sstevel@tonic-gate boolean_t create) 184*0Sstevel@tonic-gate { 185*0Sstevel@tonic-gate dlist_t *list; 186*0Sstevel@tonic-gate int error = 0; 187*0Sstevel@tonic-gate char *typestr = devconfig_type_to_str(type); 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate oprintf(OUTPUT_DEBUG, gettext("Searching for singleton %s\n"), typestr); 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate /* For each component of this device... */ 192*0Sstevel@tonic-gate for (list = devconfig_get_components(device); 193*0Sstevel@tonic-gate list != NULL; list = list->next) { 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate *component = (devconfig_t *)list->obj; 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate /* Is this subcomponent an instance of the given type? */ 198*0Sstevel@tonic-gate if (*component != NULL && devconfig_isA(*component, type)) { 199*0Sstevel@tonic-gate oprintf(OUTPUT_DEBUG, gettext("Found %s\n"), typestr); 200*0Sstevel@tonic-gate return (0); 201*0Sstevel@tonic-gate } 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate /* No component found */ 205*0Sstevel@tonic-gate error = ENOENT; 206*0Sstevel@tonic-gate *component = NULL; 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate oprintf(OUTPUT_DEBUG, gettext("%s not found\n"), typestr); 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate if (create == B_TRUE) { 211*0Sstevel@tonic-gate oprintf(OUTPUT_DEBUG, gettext("Creating %s\n"), typestr); 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate /* 214*0Sstevel@tonic-gate * An existing singleton component of the given type was 215*0Sstevel@tonic-gate * not found under the given disk set. So, create one. 216*0Sstevel@tonic-gate */ 217*0Sstevel@tonic-gate if ((error = new_devconfig(component, type)) == 0) { 218*0Sstevel@tonic-gate /* Attach new component to given device */ 219*0Sstevel@tonic-gate devconfig_set_components( 220*0Sstevel@tonic-gate device, dlist_append(dlist_new_item(*component), 221*0Sstevel@tonic-gate devconfig_get_components(device), AT_TAIL)); 222*0Sstevel@tonic-gate } 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate return (error); 226*0Sstevel@tonic-gate } 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate /* 229*0Sstevel@tonic-gate * Set the available devices for use in creating this device 230*0Sstevel@tonic-gate * 231*0Sstevel@tonic-gate * @param device 232*0Sstevel@tonic-gate * a devconfig_t representing the device to modify 233*0Sstevel@tonic-gate * 234*0Sstevel@tonic-gate * @param available 235*0Sstevel@tonic-gate * A NULL-terminated array of device names 236*0Sstevel@tonic-gate */ 237*0Sstevel@tonic-gate void 238*0Sstevel@tonic-gate devconfig_set_available( 239*0Sstevel@tonic-gate devconfig_t *device, 240*0Sstevel@tonic-gate char **available) 241*0Sstevel@tonic-gate { 242*0Sstevel@tonic-gate device->available = available; 243*0Sstevel@tonic-gate } 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate /* 246*0Sstevel@tonic-gate * Get the available devices for use in creating this device 247*0Sstevel@tonic-gate * 248*0Sstevel@tonic-gate * @param device 249*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 250*0Sstevel@tonic-gate * 251*0Sstevel@tonic-gate * @return available 252*0Sstevel@tonic-gate * A NULL-terminated array of device names 253*0Sstevel@tonic-gate */ 254*0Sstevel@tonic-gate char ** 255*0Sstevel@tonic-gate devconfig_get_available( 256*0Sstevel@tonic-gate devconfig_t *device) 257*0Sstevel@tonic-gate { 258*0Sstevel@tonic-gate return (device->available); 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate /* 262*0Sstevel@tonic-gate * Set the unavailable devices which may not be used in creating this 263*0Sstevel@tonic-gate * device 264*0Sstevel@tonic-gate * 265*0Sstevel@tonic-gate * @param device 266*0Sstevel@tonic-gate * a devconfig_t representing the device to modify 267*0Sstevel@tonic-gate * 268*0Sstevel@tonic-gate * @param available 269*0Sstevel@tonic-gate * A NULL-terminated array of device names 270*0Sstevel@tonic-gate */ 271*0Sstevel@tonic-gate void 272*0Sstevel@tonic-gate devconfig_set_unavailable( 273*0Sstevel@tonic-gate devconfig_t *device, 274*0Sstevel@tonic-gate char **unavailable) 275*0Sstevel@tonic-gate { 276*0Sstevel@tonic-gate device->unavailable = unavailable; 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate /* 280*0Sstevel@tonic-gate * Get the unavailable devices for use in creating this device 281*0Sstevel@tonic-gate * 282*0Sstevel@tonic-gate * @param device 283*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 284*0Sstevel@tonic-gate * 285*0Sstevel@tonic-gate * @return unavailable 286*0Sstevel@tonic-gate * A NULL-terminated array of device names 287*0Sstevel@tonic-gate */ 288*0Sstevel@tonic-gate char ** 289*0Sstevel@tonic-gate devconfig_get_unavailable( 290*0Sstevel@tonic-gate devconfig_t *device) 291*0Sstevel@tonic-gate { 292*0Sstevel@tonic-gate return (device->unavailable); 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate 295*0Sstevel@tonic-gate /* 296*0Sstevel@tonic-gate * Set the subcomponent devices of a given device 297*0Sstevel@tonic-gate * 298*0Sstevel@tonic-gate * @param device 299*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 300*0Sstevel@tonic-gate * 301*0Sstevel@tonic-gate * @param components 302*0Sstevel@tonic-gate * A dlist_t containing devconfig_t devices 303*0Sstevel@tonic-gate */ 304*0Sstevel@tonic-gate void 305*0Sstevel@tonic-gate devconfig_set_components( 306*0Sstevel@tonic-gate devconfig_t *device, 307*0Sstevel@tonic-gate dlist_t *components) 308*0Sstevel@tonic-gate { 309*0Sstevel@tonic-gate device->components = components; 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate /* 313*0Sstevel@tonic-gate * Get the subcomponent devices of a given device 314*0Sstevel@tonic-gate * 315*0Sstevel@tonic-gate * @param device 316*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 317*0Sstevel@tonic-gate * 318*0Sstevel@tonic-gate * @return A dlist_t containing devconfig_t devices 319*0Sstevel@tonic-gate */ 320*0Sstevel@tonic-gate dlist_t * 321*0Sstevel@tonic-gate devconfig_get_components( 322*0Sstevel@tonic-gate devconfig_t *device) 323*0Sstevel@tonic-gate { 324*0Sstevel@tonic-gate return (device->components); 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate /* 328*0Sstevel@tonic-gate * Set the device name 329*0Sstevel@tonic-gate * 330*0Sstevel@tonic-gate * @param device 331*0Sstevel@tonic-gate * a devconfig_t representing the device to modify 332*0Sstevel@tonic-gate * 333*0Sstevel@tonic-gate * @param name 334*0Sstevel@tonic-gate * the value to set as the device name 335*0Sstevel@tonic-gate * 336*0Sstevel@tonic-gate * @return 0 337*0Sstevel@tonic-gate * if successful 338*0Sstevel@tonic-gate * 339*0Sstevel@tonic-gate * @return non-zero 340*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 341*0Sstevel@tonic-gate * retrieve the associated error message. 342*0Sstevel@tonic-gate */ 343*0Sstevel@tonic-gate int 344*0Sstevel@tonic-gate devconfig_set_name( 345*0Sstevel@tonic-gate devconfig_t *device, 346*0Sstevel@tonic-gate char *name) 347*0Sstevel@tonic-gate { 348*0Sstevel@tonic-gate return (set_string(device->attributes, ATTR_NAME, name)); 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate /* 352*0Sstevel@tonic-gate * Set the disk set name 353*0Sstevel@tonic-gate * 354*0Sstevel@tonic-gate * @param diskset 355*0Sstevel@tonic-gate * a devconfig_t representing the diskset to modify 356*0Sstevel@tonic-gate * 357*0Sstevel@tonic-gate * @param name 358*0Sstevel@tonic-gate * the value to set as the device name 359*0Sstevel@tonic-gate * 360*0Sstevel@tonic-gate * @return 0 361*0Sstevel@tonic-gate * if successful 362*0Sstevel@tonic-gate * 363*0Sstevel@tonic-gate * @return non-zero 364*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 365*0Sstevel@tonic-gate * retrieve the associated error message. 366*0Sstevel@tonic-gate */ 367*0Sstevel@tonic-gate int 368*0Sstevel@tonic-gate devconfig_set_diskset_name( 369*0Sstevel@tonic-gate devconfig_t *diskset, 370*0Sstevel@tonic-gate char *name) 371*0Sstevel@tonic-gate { 372*0Sstevel@tonic-gate md_error_t error = mdnullerror; 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gate /* Verify syntax of disk set name */ 375*0Sstevel@tonic-gate if (meta_set_checkname(name, &error)) { 376*0Sstevel@tonic-gate volume_set_error(gettext("invalid disk set name: %s"), name); 377*0Sstevel@tonic-gate return (-1); 378*0Sstevel@tonic-gate } 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate return (devconfig_set_name(diskset, name)); 381*0Sstevel@tonic-gate } 382*0Sstevel@tonic-gate 383*0Sstevel@tonic-gate /* 384*0Sstevel@tonic-gate * Set the device name 385*0Sstevel@tonic-gate * 386*0Sstevel@tonic-gate * @param hsp 387*0Sstevel@tonic-gate * a devconfig_t representing the hsp to modify 388*0Sstevel@tonic-gate * 389*0Sstevel@tonic-gate * @param name 390*0Sstevel@tonic-gate * the value to set as the device name 391*0Sstevel@tonic-gate * 392*0Sstevel@tonic-gate * @return 0 393*0Sstevel@tonic-gate * if successful 394*0Sstevel@tonic-gate * 395*0Sstevel@tonic-gate * @return non-zero 396*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 397*0Sstevel@tonic-gate * retrieve the associated error message. 398*0Sstevel@tonic-gate */ 399*0Sstevel@tonic-gate int 400*0Sstevel@tonic-gate devconfig_set_hsp_name( 401*0Sstevel@tonic-gate devconfig_t *hsp, 402*0Sstevel@tonic-gate char *name) 403*0Sstevel@tonic-gate { 404*0Sstevel@tonic-gate /* Validate name */ 405*0Sstevel@tonic-gate if (!is_hspname(name)) { 406*0Sstevel@tonic-gate volume_set_error(gettext("invalid hot spare pool name: %s"), name); 407*0Sstevel@tonic-gate return (-1); 408*0Sstevel@tonic-gate } 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate return (devconfig_set_name(hsp, name)); 411*0Sstevel@tonic-gate } 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate /* 414*0Sstevel@tonic-gate * Set the device name 415*0Sstevel@tonic-gate * 416*0Sstevel@tonic-gate * @param volume 417*0Sstevel@tonic-gate * a devconfig_t representing the volume to modify 418*0Sstevel@tonic-gate * 419*0Sstevel@tonic-gate * @param name 420*0Sstevel@tonic-gate * the value to set as the device name 421*0Sstevel@tonic-gate * 422*0Sstevel@tonic-gate * @return 0 423*0Sstevel@tonic-gate * if successful 424*0Sstevel@tonic-gate * 425*0Sstevel@tonic-gate * @return non-zero 426*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 427*0Sstevel@tonic-gate * retrieve the associated error message. 428*0Sstevel@tonic-gate */ 429*0Sstevel@tonic-gate int 430*0Sstevel@tonic-gate devconfig_set_volume_name( 431*0Sstevel@tonic-gate devconfig_t *volume, 432*0Sstevel@tonic-gate char *name) 433*0Sstevel@tonic-gate { 434*0Sstevel@tonic-gate /* Validate name */ 435*0Sstevel@tonic-gate if (!is_metaname(name)) { 436*0Sstevel@tonic-gate volume_set_error(gettext("invalid volume name: %s"), name); 437*0Sstevel@tonic-gate return (-1); 438*0Sstevel@tonic-gate } 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate return (devconfig_set_name(volume, name)); 441*0Sstevel@tonic-gate } 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate /* 444*0Sstevel@tonic-gate * Get the device name 445*0Sstevel@tonic-gate * 446*0Sstevel@tonic-gate * @param volume 447*0Sstevel@tonic-gate * a devconfig_t representing the volume to examine 448*0Sstevel@tonic-gate * 449*0Sstevel@tonic-gate * @param name 450*0Sstevel@tonic-gate * RETURN: the device name 451*0Sstevel@tonic-gate * 452*0Sstevel@tonic-gate * @return 0 453*0Sstevel@tonic-gate * if successful 454*0Sstevel@tonic-gate * 455*0Sstevel@tonic-gate * @return non-zero 456*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 457*0Sstevel@tonic-gate * retrieve the associated error message. 458*0Sstevel@tonic-gate */ 459*0Sstevel@tonic-gate int 460*0Sstevel@tonic-gate devconfig_get_name( 461*0Sstevel@tonic-gate devconfig_t *device, 462*0Sstevel@tonic-gate char **name) 463*0Sstevel@tonic-gate { 464*0Sstevel@tonic-gate int error = get_string(device->attributes, ATTR_NAME, name); 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 467*0Sstevel@tonic-gate if (error == ENOENT) { 468*0Sstevel@tonic-gate volume_set_error(gettext("device name not set")); 469*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 470*0Sstevel@tonic-gate } 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate return (error); 473*0Sstevel@tonic-gate } 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate /* 476*0Sstevel@tonic-gate * Set the device type 477*0Sstevel@tonic-gate * 478*0Sstevel@tonic-gate * @param device 479*0Sstevel@tonic-gate * a devconfig_t representing the device to modify 480*0Sstevel@tonic-gate * 481*0Sstevel@tonic-gate * @param type 482*0Sstevel@tonic-gate * the value to set as the device type 483*0Sstevel@tonic-gate * 484*0Sstevel@tonic-gate * @return 0 485*0Sstevel@tonic-gate * if successful 486*0Sstevel@tonic-gate * 487*0Sstevel@tonic-gate * @return non-zero 488*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 489*0Sstevel@tonic-gate * retrieve the associated error message. 490*0Sstevel@tonic-gate */ 491*0Sstevel@tonic-gate int 492*0Sstevel@tonic-gate devconfig_set_type( 493*0Sstevel@tonic-gate devconfig_t *device, 494*0Sstevel@tonic-gate component_type_t type) 495*0Sstevel@tonic-gate { 496*0Sstevel@tonic-gate return (set_uint16(device->attributes, ATTR_TYPE, (uint16_t)type)); 497*0Sstevel@tonic-gate } 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate /* 500*0Sstevel@tonic-gate * Get the device type 501*0Sstevel@tonic-gate * 502*0Sstevel@tonic-gate * @param device 503*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 504*0Sstevel@tonic-gate * 505*0Sstevel@tonic-gate * @param type 506*0Sstevel@tonic-gate * RETURN: the device type 507*0Sstevel@tonic-gate * 508*0Sstevel@tonic-gate * @return 0 509*0Sstevel@tonic-gate * if successful 510*0Sstevel@tonic-gate * 511*0Sstevel@tonic-gate * @return non-zero 512*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 513*0Sstevel@tonic-gate * retrieve the associated error message. 514*0Sstevel@tonic-gate */ 515*0Sstevel@tonic-gate int 516*0Sstevel@tonic-gate devconfig_get_type( 517*0Sstevel@tonic-gate devconfig_t *device, 518*0Sstevel@tonic-gate component_type_t *type) 519*0Sstevel@tonic-gate { 520*0Sstevel@tonic-gate uint16_t val; 521*0Sstevel@tonic-gate int error = get_uint16(device->attributes, ATTR_TYPE, &val); 522*0Sstevel@tonic-gate 523*0Sstevel@tonic-gate switch (error) { 524*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 525*0Sstevel@tonic-gate case ENOENT: 526*0Sstevel@tonic-gate volume_set_error(gettext("device type not set")); 527*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 528*0Sstevel@tonic-gate break; 529*0Sstevel@tonic-gate 530*0Sstevel@tonic-gate /* Success */ 531*0Sstevel@tonic-gate case 0: 532*0Sstevel@tonic-gate *type = (component_type_t)val; 533*0Sstevel@tonic-gate } 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate return (error); 536*0Sstevel@tonic-gate } 537*0Sstevel@tonic-gate 538*0Sstevel@tonic-gate /* 539*0Sstevel@tonic-gate * Set the device size (for volume, mirror, stripe, concat) in bytes 540*0Sstevel@tonic-gate * 541*0Sstevel@tonic-gate * Note that size in bytes in a 64-bit field cannot hold the size that 542*0Sstevel@tonic-gate * can be accessed in a 16 byte CDB. Since CDBs operate on blocks, 543*0Sstevel@tonic-gate * the max capacity is 2^73 bytes with 512 byte blocks. 544*0Sstevel@tonic-gate * 545*0Sstevel@tonic-gate * @param device 546*0Sstevel@tonic-gate * a devconfig_t representing the device to modify 547*0Sstevel@tonic-gate * 548*0Sstevel@tonic-gate * @param size_in_bytes 549*0Sstevel@tonic-gate * the value to set as the device size in bytes 550*0Sstevel@tonic-gate * 551*0Sstevel@tonic-gate * @return 0 552*0Sstevel@tonic-gate * if successful 553*0Sstevel@tonic-gate * 554*0Sstevel@tonic-gate * @return non-zero 555*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 556*0Sstevel@tonic-gate * retrieve the associated error message. 557*0Sstevel@tonic-gate */ 558*0Sstevel@tonic-gate int 559*0Sstevel@tonic-gate devconfig_set_size( 560*0Sstevel@tonic-gate devconfig_t *device, 561*0Sstevel@tonic-gate uint64_t size_in_bytes) 562*0Sstevel@tonic-gate { 563*0Sstevel@tonic-gate 564*0Sstevel@tonic-gate /* Validate against limits */ 565*0Sstevel@tonic-gate /* LINTED -- MIN_SIZE may be 0 */ 566*0Sstevel@tonic-gate if (size_in_bytes < MIN_SIZE) { 567*0Sstevel@tonic-gate volume_set_error(gettext("size (in bytes) too small: %llu"), 568*0Sstevel@tonic-gate (unsigned long long)size_in_bytes); 569*0Sstevel@tonic-gate return (-1); 570*0Sstevel@tonic-gate } 571*0Sstevel@tonic-gate 572*0Sstevel@tonic-gate return (set_uint64(device->attributes, 573*0Sstevel@tonic-gate ATTR_SIZEINBYTES, size_in_bytes)); 574*0Sstevel@tonic-gate } 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate /* 577*0Sstevel@tonic-gate * Get the device size (for volume, mirror, stripe, concat) in bytes 578*0Sstevel@tonic-gate * 579*0Sstevel@tonic-gate * Note that size in bytes in a 64-bit field cannot hold the size that 580*0Sstevel@tonic-gate * can be accessed in a 16 byte CDB. Since CDBs operate on blocks, 581*0Sstevel@tonic-gate * the max capacity is 2^73 bytes with 512 byte blocks. 582*0Sstevel@tonic-gate * 583*0Sstevel@tonic-gate * @param device 584*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 585*0Sstevel@tonic-gate * 586*0Sstevel@tonic-gate * @param size_in_bytes 587*0Sstevel@tonic-gate * RETURN: the device size in bytes 588*0Sstevel@tonic-gate * 589*0Sstevel@tonic-gate * @return 0 590*0Sstevel@tonic-gate * if successful 591*0Sstevel@tonic-gate * 592*0Sstevel@tonic-gate * @return non-zero 593*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 594*0Sstevel@tonic-gate * retrieve the associated error message. 595*0Sstevel@tonic-gate */ 596*0Sstevel@tonic-gate int 597*0Sstevel@tonic-gate devconfig_get_size( 598*0Sstevel@tonic-gate devconfig_t *device, 599*0Sstevel@tonic-gate uint64_t *size_in_bytes) 600*0Sstevel@tonic-gate { 601*0Sstevel@tonic-gate int error = get_uint64( 602*0Sstevel@tonic-gate device->attributes, ATTR_SIZEINBYTES, size_in_bytes); 603*0Sstevel@tonic-gate 604*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 605*0Sstevel@tonic-gate if (error == ENOENT) { 606*0Sstevel@tonic-gate volume_set_error(gettext("size (in bytes) not set")); 607*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 608*0Sstevel@tonic-gate } 609*0Sstevel@tonic-gate 610*0Sstevel@tonic-gate return (error); 611*0Sstevel@tonic-gate } 612*0Sstevel@tonic-gate 613*0Sstevel@tonic-gate /* 614*0Sstevel@tonic-gate * Set the device size in blocks 615*0Sstevel@tonic-gate * 616*0Sstevel@tonic-gate * @param device 617*0Sstevel@tonic-gate * a devconfig_t representing the device to modify 618*0Sstevel@tonic-gate * 619*0Sstevel@tonic-gate * @param type 620*0Sstevel@tonic-gate * the value to set as the device size in blocks 621*0Sstevel@tonic-gate * 622*0Sstevel@tonic-gate * @return 0 623*0Sstevel@tonic-gate * if successful 624*0Sstevel@tonic-gate * 625*0Sstevel@tonic-gate * @return non-zero 626*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 627*0Sstevel@tonic-gate * retrieve the associated error message. 628*0Sstevel@tonic-gate */ 629*0Sstevel@tonic-gate int 630*0Sstevel@tonic-gate devconfig_set_size_in_blocks( 631*0Sstevel@tonic-gate devconfig_t *device, 632*0Sstevel@tonic-gate uint64_t size_in_blocks) 633*0Sstevel@tonic-gate { 634*0Sstevel@tonic-gate /* Validate against limits */ 635*0Sstevel@tonic-gate /* LINTED -- MIN_SIZE_IN_BLOCKS may be 0 */ 636*0Sstevel@tonic-gate if (size_in_blocks < MIN_SIZE_IN_BLOCKS) { 637*0Sstevel@tonic-gate volume_set_error(gettext("size (in blocks) too small: %llu"), 638*0Sstevel@tonic-gate (unsigned long long)size_in_blocks); 639*0Sstevel@tonic-gate return (-1); 640*0Sstevel@tonic-gate } 641*0Sstevel@tonic-gate 642*0Sstevel@tonic-gate return (set_uint64(device->attributes, 643*0Sstevel@tonic-gate ATTR_SIZEINBLOCKS, size_in_blocks)); 644*0Sstevel@tonic-gate } 645*0Sstevel@tonic-gate 646*0Sstevel@tonic-gate /* 647*0Sstevel@tonic-gate * Get the device size in blocks 648*0Sstevel@tonic-gate * 649*0Sstevel@tonic-gate * @param device 650*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 651*0Sstevel@tonic-gate * 652*0Sstevel@tonic-gate * @param size_in_blocks 653*0Sstevel@tonic-gate * RETURN: the device size in blocks 654*0Sstevel@tonic-gate * 655*0Sstevel@tonic-gate * @return 0 656*0Sstevel@tonic-gate * if successful 657*0Sstevel@tonic-gate * 658*0Sstevel@tonic-gate * @return non-zero 659*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 660*0Sstevel@tonic-gate * retrieve the associated error message. 661*0Sstevel@tonic-gate */ 662*0Sstevel@tonic-gate int 663*0Sstevel@tonic-gate devconfig_get_size_in_blocks( 664*0Sstevel@tonic-gate devconfig_t *device, 665*0Sstevel@tonic-gate uint64_t *size_in_blocks) 666*0Sstevel@tonic-gate { 667*0Sstevel@tonic-gate int error = get_uint64( 668*0Sstevel@tonic-gate device->attributes, ATTR_SIZEINBLOCKS, size_in_blocks); 669*0Sstevel@tonic-gate 670*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 671*0Sstevel@tonic-gate if (error == ENOENT) { 672*0Sstevel@tonic-gate volume_set_error(gettext("size (in blocks) not set")); 673*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 674*0Sstevel@tonic-gate } 675*0Sstevel@tonic-gate 676*0Sstevel@tonic-gate return (error); 677*0Sstevel@tonic-gate } 678*0Sstevel@tonic-gate 679*0Sstevel@tonic-gate /* 680*0Sstevel@tonic-gate * Set the the slice index 681*0Sstevel@tonic-gate * 682*0Sstevel@tonic-gate * @param slice 683*0Sstevel@tonic-gate * a devconfig_t representing the slice to modify 684*0Sstevel@tonic-gate * 685*0Sstevel@tonic-gate * @param index 686*0Sstevel@tonic-gate * the value to set as the the slice index 687*0Sstevel@tonic-gate * 688*0Sstevel@tonic-gate * @return 0 689*0Sstevel@tonic-gate * if successful 690*0Sstevel@tonic-gate * 691*0Sstevel@tonic-gate * @return non-zero 692*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 693*0Sstevel@tonic-gate * retrieve the associated error message. 694*0Sstevel@tonic-gate */ 695*0Sstevel@tonic-gate int 696*0Sstevel@tonic-gate devconfig_set_slice_index( 697*0Sstevel@tonic-gate devconfig_t *slice, 698*0Sstevel@tonic-gate uint16_t index) 699*0Sstevel@tonic-gate { 700*0Sstevel@tonic-gate return (set_uint16(slice->attributes, ATTR_SLICE_INDEX, index)); 701*0Sstevel@tonic-gate } 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gate /* 704*0Sstevel@tonic-gate * Get the slice index 705*0Sstevel@tonic-gate * 706*0Sstevel@tonic-gate * @param device 707*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 708*0Sstevel@tonic-gate * 709*0Sstevel@tonic-gate * @param index 710*0Sstevel@tonic-gate * RETURN: the slice index 711*0Sstevel@tonic-gate * 712*0Sstevel@tonic-gate * @return 0 713*0Sstevel@tonic-gate * if successful 714*0Sstevel@tonic-gate * 715*0Sstevel@tonic-gate * @return non-zero 716*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 717*0Sstevel@tonic-gate * retrieve the associated error message. 718*0Sstevel@tonic-gate */ 719*0Sstevel@tonic-gate int 720*0Sstevel@tonic-gate devconfig_get_slice_index( 721*0Sstevel@tonic-gate devconfig_t *slice, 722*0Sstevel@tonic-gate uint16_t *index) 723*0Sstevel@tonic-gate { 724*0Sstevel@tonic-gate int error = get_uint16(slice->attributes, ATTR_SLICE_INDEX, index); 725*0Sstevel@tonic-gate 726*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 727*0Sstevel@tonic-gate if (error == ENOENT) { 728*0Sstevel@tonic-gate volume_set_error(gettext("slice index not set")); 729*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 730*0Sstevel@tonic-gate } 731*0Sstevel@tonic-gate 732*0Sstevel@tonic-gate return (error); 733*0Sstevel@tonic-gate } 734*0Sstevel@tonic-gate 735*0Sstevel@tonic-gate /* 736*0Sstevel@tonic-gate * Set the the slice start block 737*0Sstevel@tonic-gate * 738*0Sstevel@tonic-gate * @param slice 739*0Sstevel@tonic-gate * a devconfig_t representing the slice to modify 740*0Sstevel@tonic-gate * 741*0Sstevel@tonic-gate * @param start_block 742*0Sstevel@tonic-gate * the value to set as the the slice start block 743*0Sstevel@tonic-gate * 744*0Sstevel@tonic-gate * @return 0 745*0Sstevel@tonic-gate * if successful 746*0Sstevel@tonic-gate * 747*0Sstevel@tonic-gate * @return non-zero 748*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 749*0Sstevel@tonic-gate * retrieve the associated error message. 750*0Sstevel@tonic-gate */ 751*0Sstevel@tonic-gate int 752*0Sstevel@tonic-gate devconfig_set_slice_start_block( 753*0Sstevel@tonic-gate devconfig_t *slice, 754*0Sstevel@tonic-gate uint64_t start_block) 755*0Sstevel@tonic-gate { 756*0Sstevel@tonic-gate return (set_uint64(slice->attributes, 757*0Sstevel@tonic-gate ATTR_SLICE_STARTSECTOR, start_block)); 758*0Sstevel@tonic-gate } 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate /* 761*0Sstevel@tonic-gate * Get the slice start block 762*0Sstevel@tonic-gate * 763*0Sstevel@tonic-gate * @param device 764*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 765*0Sstevel@tonic-gate * 766*0Sstevel@tonic-gate * @param start_block 767*0Sstevel@tonic-gate * RETURN: the slice start block 768*0Sstevel@tonic-gate * 769*0Sstevel@tonic-gate * @return 0 770*0Sstevel@tonic-gate * if successful 771*0Sstevel@tonic-gate * 772*0Sstevel@tonic-gate * @return non-zero 773*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 774*0Sstevel@tonic-gate * retrieve the associated error message. 775*0Sstevel@tonic-gate */ 776*0Sstevel@tonic-gate int 777*0Sstevel@tonic-gate devconfig_get_slice_start_block( 778*0Sstevel@tonic-gate devconfig_t *slice, 779*0Sstevel@tonic-gate uint64_t *start_block) 780*0Sstevel@tonic-gate { 781*0Sstevel@tonic-gate int error = get_uint64( 782*0Sstevel@tonic-gate slice->attributes, ATTR_SLICE_STARTSECTOR, start_block); 783*0Sstevel@tonic-gate 784*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 785*0Sstevel@tonic-gate if (error == ENOENT) { 786*0Sstevel@tonic-gate volume_set_error(gettext("slice start block not set")); 787*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 788*0Sstevel@tonic-gate } 789*0Sstevel@tonic-gate 790*0Sstevel@tonic-gate return (error); 791*0Sstevel@tonic-gate } 792*0Sstevel@tonic-gate 793*0Sstevel@tonic-gate /* 794*0Sstevel@tonic-gate * Set the number of subcomponents in mirror 795*0Sstevel@tonic-gate * 796*0Sstevel@tonic-gate * @param mirror 797*0Sstevel@tonic-gate * a devconfig_t representing the mirror to modify 798*0Sstevel@tonic-gate * 799*0Sstevel@tonic-gate * @param nsubs 800*0Sstevel@tonic-gate * the value to set as the number of subcomponents in 801*0Sstevel@tonic-gate * mirror 802*0Sstevel@tonic-gate * 803*0Sstevel@tonic-gate * @return 0 804*0Sstevel@tonic-gate * if successful 805*0Sstevel@tonic-gate * 806*0Sstevel@tonic-gate * @return non-zero 807*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 808*0Sstevel@tonic-gate * retrieve the associated error message. 809*0Sstevel@tonic-gate */ 810*0Sstevel@tonic-gate int 811*0Sstevel@tonic-gate devconfig_set_mirror_nsubs( 812*0Sstevel@tonic-gate devconfig_t *mirror, 813*0Sstevel@tonic-gate uint16_t nsubs) 814*0Sstevel@tonic-gate { 815*0Sstevel@tonic-gate /* Validate against limits */ 816*0Sstevel@tonic-gate if (nsubs < 1 || nsubs > NMIRROR) { 817*0Sstevel@tonic-gate volume_set_error( 818*0Sstevel@tonic-gate gettext("number of submirrors (%d) out of valid range (%d-%d)"), 819*0Sstevel@tonic-gate nsubs, 1, NMIRROR); 820*0Sstevel@tonic-gate return (-1); 821*0Sstevel@tonic-gate } 822*0Sstevel@tonic-gate 823*0Sstevel@tonic-gate return (set_uint16(mirror->attributes, ATTR_MIRROR_NSUBMIRRORS, nsubs)); 824*0Sstevel@tonic-gate } 825*0Sstevel@tonic-gate 826*0Sstevel@tonic-gate /* 827*0Sstevel@tonic-gate * Get number of subcomponents in mirror 828*0Sstevel@tonic-gate * 829*0Sstevel@tonic-gate * @param device 830*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 831*0Sstevel@tonic-gate * 832*0Sstevel@tonic-gate * @param nsubs 833*0Sstevel@tonic-gate * RETURN: number of subcomponents in mirror 834*0Sstevel@tonic-gate * 835*0Sstevel@tonic-gate * @return 0 836*0Sstevel@tonic-gate * if successful 837*0Sstevel@tonic-gate * 838*0Sstevel@tonic-gate * @return non-zero 839*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 840*0Sstevel@tonic-gate * retrieve the associated error message. 841*0Sstevel@tonic-gate */ 842*0Sstevel@tonic-gate int 843*0Sstevel@tonic-gate devconfig_get_mirror_nsubs( 844*0Sstevel@tonic-gate devconfig_t *mirror, 845*0Sstevel@tonic-gate uint16_t *nsubs) 846*0Sstevel@tonic-gate { 847*0Sstevel@tonic-gate int error = get_uint16( 848*0Sstevel@tonic-gate mirror->attributes, ATTR_MIRROR_NSUBMIRRORS, nsubs); 849*0Sstevel@tonic-gate 850*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 851*0Sstevel@tonic-gate if (error == ENOENT) { 852*0Sstevel@tonic-gate volume_set_error(gettext("number or submirrors not set")); 853*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 854*0Sstevel@tonic-gate } 855*0Sstevel@tonic-gate 856*0Sstevel@tonic-gate return (error); 857*0Sstevel@tonic-gate } 858*0Sstevel@tonic-gate 859*0Sstevel@tonic-gate /* 860*0Sstevel@tonic-gate * Set the read strategy for mirror 861*0Sstevel@tonic-gate * 862*0Sstevel@tonic-gate * @param mirror 863*0Sstevel@tonic-gate * a devconfig_t representing the mirror to modify 864*0Sstevel@tonic-gate * 865*0Sstevel@tonic-gate * @param read 866*0Sstevel@tonic-gate * the value to set as the read strategy for mirror 867*0Sstevel@tonic-gate * 868*0Sstevel@tonic-gate * @return 0 869*0Sstevel@tonic-gate * if successful 870*0Sstevel@tonic-gate * 871*0Sstevel@tonic-gate * @return non-zero 872*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 873*0Sstevel@tonic-gate * retrieve the associated error message. 874*0Sstevel@tonic-gate */ 875*0Sstevel@tonic-gate int 876*0Sstevel@tonic-gate devconfig_set_mirror_read( 877*0Sstevel@tonic-gate devconfig_t *mirror, 878*0Sstevel@tonic-gate mirror_read_strategy_t read) 879*0Sstevel@tonic-gate { 880*0Sstevel@tonic-gate return (set_uint16(mirror->attributes, 881*0Sstevel@tonic-gate ATTR_MIRROR_READ, (uint16_t)read)); 882*0Sstevel@tonic-gate } 883*0Sstevel@tonic-gate 884*0Sstevel@tonic-gate /* 885*0Sstevel@tonic-gate * Get read strategy for mirror 886*0Sstevel@tonic-gate * 887*0Sstevel@tonic-gate * @param device 888*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 889*0Sstevel@tonic-gate * 890*0Sstevel@tonic-gate * @param read 891*0Sstevel@tonic-gate * RETURN: read strategy for mirror 892*0Sstevel@tonic-gate * 893*0Sstevel@tonic-gate * @return 0 894*0Sstevel@tonic-gate * if successful 895*0Sstevel@tonic-gate * 896*0Sstevel@tonic-gate * @return non-zero 897*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 898*0Sstevel@tonic-gate * retrieve the associated error message. 899*0Sstevel@tonic-gate */ 900*0Sstevel@tonic-gate int 901*0Sstevel@tonic-gate devconfig_get_mirror_read( 902*0Sstevel@tonic-gate devconfig_t *mirror, 903*0Sstevel@tonic-gate mirror_read_strategy_t *read) 904*0Sstevel@tonic-gate { 905*0Sstevel@tonic-gate uint16_t val; 906*0Sstevel@tonic-gate int error = get_uint16(mirror->attributes, ATTR_MIRROR_READ, &val); 907*0Sstevel@tonic-gate 908*0Sstevel@tonic-gate switch (error) { 909*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 910*0Sstevel@tonic-gate case ENOENT: 911*0Sstevel@tonic-gate volume_set_error(gettext("mirror read strategy not set")); 912*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 913*0Sstevel@tonic-gate break; 914*0Sstevel@tonic-gate 915*0Sstevel@tonic-gate /* Success */ 916*0Sstevel@tonic-gate case 0: 917*0Sstevel@tonic-gate *read = (mirror_read_strategy_t)val; 918*0Sstevel@tonic-gate } 919*0Sstevel@tonic-gate 920*0Sstevel@tonic-gate return (error); 921*0Sstevel@tonic-gate } 922*0Sstevel@tonic-gate 923*0Sstevel@tonic-gate /* 924*0Sstevel@tonic-gate * Set the write strategy for mirror 925*0Sstevel@tonic-gate * 926*0Sstevel@tonic-gate * @param mirror 927*0Sstevel@tonic-gate * a devconfig_t representing the mirror to modify 928*0Sstevel@tonic-gate * 929*0Sstevel@tonic-gate * @param write 930*0Sstevel@tonic-gate * the value to set as the write strategy for mirror 931*0Sstevel@tonic-gate * 932*0Sstevel@tonic-gate * @return 0 933*0Sstevel@tonic-gate * if successful 934*0Sstevel@tonic-gate * 935*0Sstevel@tonic-gate * @return non-zero 936*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 937*0Sstevel@tonic-gate * retrieve the associated error message. 938*0Sstevel@tonic-gate */ 939*0Sstevel@tonic-gate int 940*0Sstevel@tonic-gate devconfig_set_mirror_write( 941*0Sstevel@tonic-gate devconfig_t *mirror, 942*0Sstevel@tonic-gate mirror_write_strategy_t write) 943*0Sstevel@tonic-gate { 944*0Sstevel@tonic-gate return (set_uint16(mirror->attributes, 945*0Sstevel@tonic-gate ATTR_MIRROR_WRITE, (uint16_t)write)); 946*0Sstevel@tonic-gate } 947*0Sstevel@tonic-gate 948*0Sstevel@tonic-gate /* 949*0Sstevel@tonic-gate * Get write strategy for mirror 950*0Sstevel@tonic-gate * 951*0Sstevel@tonic-gate * @param device 952*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 953*0Sstevel@tonic-gate * 954*0Sstevel@tonic-gate * @param write 955*0Sstevel@tonic-gate * RETURN: write strategy for mirror 956*0Sstevel@tonic-gate * 957*0Sstevel@tonic-gate * @return 0 958*0Sstevel@tonic-gate * if successful 959*0Sstevel@tonic-gate * 960*0Sstevel@tonic-gate * @return non-zero 961*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 962*0Sstevel@tonic-gate * retrieve the associated error message. 963*0Sstevel@tonic-gate */ 964*0Sstevel@tonic-gate int 965*0Sstevel@tonic-gate devconfig_get_mirror_write( 966*0Sstevel@tonic-gate devconfig_t *mirror, 967*0Sstevel@tonic-gate mirror_write_strategy_t *write) 968*0Sstevel@tonic-gate { 969*0Sstevel@tonic-gate uint16_t val; 970*0Sstevel@tonic-gate int error = get_uint16(mirror->attributes, ATTR_MIRROR_WRITE, &val); 971*0Sstevel@tonic-gate 972*0Sstevel@tonic-gate switch (error) { 973*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 974*0Sstevel@tonic-gate case ENOENT: 975*0Sstevel@tonic-gate volume_set_error(gettext("mirror write strategy not set")); 976*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 977*0Sstevel@tonic-gate break; 978*0Sstevel@tonic-gate 979*0Sstevel@tonic-gate /* Success */ 980*0Sstevel@tonic-gate case 0: 981*0Sstevel@tonic-gate *write = (mirror_write_strategy_t)val; 982*0Sstevel@tonic-gate } 983*0Sstevel@tonic-gate 984*0Sstevel@tonic-gate return (error); 985*0Sstevel@tonic-gate } 986*0Sstevel@tonic-gate 987*0Sstevel@tonic-gate /* 988*0Sstevel@tonic-gate * Set the resync pass for mirror 989*0Sstevel@tonic-gate * 990*0Sstevel@tonic-gate * @param mirror 991*0Sstevel@tonic-gate * a devconfig_t representing the mirror to modify 992*0Sstevel@tonic-gate * 993*0Sstevel@tonic-gate * @param pass 994*0Sstevel@tonic-gate * the value to set as the resync pass for mirror 995*0Sstevel@tonic-gate * 996*0Sstevel@tonic-gate * @return 0 997*0Sstevel@tonic-gate * if successful 998*0Sstevel@tonic-gate * 999*0Sstevel@tonic-gate * @return non-zero 1000*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 1001*0Sstevel@tonic-gate * retrieve the associated error message. 1002*0Sstevel@tonic-gate */ 1003*0Sstevel@tonic-gate int 1004*0Sstevel@tonic-gate devconfig_set_mirror_pass( 1005*0Sstevel@tonic-gate devconfig_t *mirror, 1006*0Sstevel@tonic-gate uint16_t pass) 1007*0Sstevel@tonic-gate { 1008*0Sstevel@tonic-gate /* Validate against max value */ 1009*0Sstevel@tonic-gate if (pass > MD_PASS_MAX) { 1010*0Sstevel@tonic-gate volume_set_error( 1011*0Sstevel@tonic-gate gettext("mirror pass number (%d) out of valid range (0-%d)"), 1012*0Sstevel@tonic-gate pass, MD_PASS_MAX); 1013*0Sstevel@tonic-gate return (-1); 1014*0Sstevel@tonic-gate } 1015*0Sstevel@tonic-gate 1016*0Sstevel@tonic-gate return (set_uint16(mirror->attributes, ATTR_MIRROR_PASSNUM, pass)); 1017*0Sstevel@tonic-gate } 1018*0Sstevel@tonic-gate 1019*0Sstevel@tonic-gate /* 1020*0Sstevel@tonic-gate * Get resync pass for mirror 1021*0Sstevel@tonic-gate * 1022*0Sstevel@tonic-gate * @param device 1023*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 1024*0Sstevel@tonic-gate * 1025*0Sstevel@tonic-gate * @param pass 1026*0Sstevel@tonic-gate * RETURN: resync pass for mirror 1027*0Sstevel@tonic-gate * 1028*0Sstevel@tonic-gate * @return 0 1029*0Sstevel@tonic-gate * if successful 1030*0Sstevel@tonic-gate * 1031*0Sstevel@tonic-gate * @return non-zero 1032*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 1033*0Sstevel@tonic-gate * retrieve the associated error message. 1034*0Sstevel@tonic-gate */ 1035*0Sstevel@tonic-gate int 1036*0Sstevel@tonic-gate devconfig_get_mirror_pass( 1037*0Sstevel@tonic-gate devconfig_t *mirror, 1038*0Sstevel@tonic-gate uint16_t *pass) 1039*0Sstevel@tonic-gate { 1040*0Sstevel@tonic-gate int error = get_uint16(mirror->attributes, ATTR_MIRROR_PASSNUM, pass); 1041*0Sstevel@tonic-gate 1042*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 1043*0Sstevel@tonic-gate if (error == ENOENT) { 1044*0Sstevel@tonic-gate volume_set_error(gettext("mirror pass number not set")); 1045*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 1046*0Sstevel@tonic-gate } 1047*0Sstevel@tonic-gate 1048*0Sstevel@tonic-gate return (error); 1049*0Sstevel@tonic-gate } 1050*0Sstevel@tonic-gate 1051*0Sstevel@tonic-gate /* 1052*0Sstevel@tonic-gate * Set the minimum number of components in stripe 1053*0Sstevel@tonic-gate * 1054*0Sstevel@tonic-gate * @param stripe 1055*0Sstevel@tonic-gate * a devconfig_t representing the stripe to modify 1056*0Sstevel@tonic-gate * 1057*0Sstevel@tonic-gate * @param mincomp 1058*0Sstevel@tonic-gate * the value to set as the minimum number of components 1059*0Sstevel@tonic-gate * in stripe 1060*0Sstevel@tonic-gate * 1061*0Sstevel@tonic-gate * @return 0 1062*0Sstevel@tonic-gate * if successful 1063*0Sstevel@tonic-gate * 1064*0Sstevel@tonic-gate * @return non-zero 1065*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 1066*0Sstevel@tonic-gate * retrieve the associated error message. 1067*0Sstevel@tonic-gate */ 1068*0Sstevel@tonic-gate int 1069*0Sstevel@tonic-gate devconfig_set_stripe_mincomp( 1070*0Sstevel@tonic-gate devconfig_t *stripe, 1071*0Sstevel@tonic-gate uint16_t mincomp) 1072*0Sstevel@tonic-gate { 1073*0Sstevel@tonic-gate /* Validate against minimum value */ 1074*0Sstevel@tonic-gate if (mincomp < MIN_NSTRIPE_COMP) { 1075*0Sstevel@tonic-gate volume_set_error(gettext( 1076*0Sstevel@tonic-gate "minimum stripe components (%d) below minimum allowable (%d)"), 1077*0Sstevel@tonic-gate mincomp, MIN_NSTRIPE_COMP); 1078*0Sstevel@tonic-gate return (-1); 1079*0Sstevel@tonic-gate } 1080*0Sstevel@tonic-gate 1081*0Sstevel@tonic-gate return (set_uint16(stripe->attributes, ATTR_STRIPE_MINCOMP, mincomp)); 1082*0Sstevel@tonic-gate } 1083*0Sstevel@tonic-gate 1084*0Sstevel@tonic-gate /* 1085*0Sstevel@tonic-gate * Get minimum number of components in stripe 1086*0Sstevel@tonic-gate * 1087*0Sstevel@tonic-gate * @param device 1088*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 1089*0Sstevel@tonic-gate * 1090*0Sstevel@tonic-gate * @param mincomp 1091*0Sstevel@tonic-gate * RETURN: minimum number of components in stripe 1092*0Sstevel@tonic-gate * 1093*0Sstevel@tonic-gate * @return 0 1094*0Sstevel@tonic-gate * if successful 1095*0Sstevel@tonic-gate * 1096*0Sstevel@tonic-gate * @return non-zero 1097*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 1098*0Sstevel@tonic-gate * retrieve the associated error message. 1099*0Sstevel@tonic-gate */ 1100*0Sstevel@tonic-gate int 1101*0Sstevel@tonic-gate devconfig_get_stripe_mincomp( 1102*0Sstevel@tonic-gate devconfig_t *stripe, 1103*0Sstevel@tonic-gate uint16_t *mincomp) 1104*0Sstevel@tonic-gate { 1105*0Sstevel@tonic-gate int error = get_uint16( 1106*0Sstevel@tonic-gate stripe->attributes, ATTR_STRIPE_MINCOMP, mincomp); 1107*0Sstevel@tonic-gate 1108*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 1109*0Sstevel@tonic-gate if (error == ENOENT) { 1110*0Sstevel@tonic-gate volume_set_error( 1111*0Sstevel@tonic-gate gettext("minimum number of stripe components not set")); 1112*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 1113*0Sstevel@tonic-gate } 1114*0Sstevel@tonic-gate 1115*0Sstevel@tonic-gate return (error); 1116*0Sstevel@tonic-gate } 1117*0Sstevel@tonic-gate 1118*0Sstevel@tonic-gate /* 1119*0Sstevel@tonic-gate * Set the maximum number of components in stripe 1120*0Sstevel@tonic-gate * 1121*0Sstevel@tonic-gate * @param stripe 1122*0Sstevel@tonic-gate * a devconfig_t representing the stripe to modify 1123*0Sstevel@tonic-gate * 1124*0Sstevel@tonic-gate * @param maxcomp 1125*0Sstevel@tonic-gate * the value to set as the maximum number of components 1126*0Sstevel@tonic-gate * in stripe 1127*0Sstevel@tonic-gate * 1128*0Sstevel@tonic-gate * @return 0 1129*0Sstevel@tonic-gate * if successful 1130*0Sstevel@tonic-gate * 1131*0Sstevel@tonic-gate * @return non-zero 1132*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 1133*0Sstevel@tonic-gate * retrieve the associated error message. 1134*0Sstevel@tonic-gate */ 1135*0Sstevel@tonic-gate int 1136*0Sstevel@tonic-gate devconfig_set_stripe_maxcomp( 1137*0Sstevel@tonic-gate devconfig_t *stripe, 1138*0Sstevel@tonic-gate uint16_t maxcomp) 1139*0Sstevel@tonic-gate { 1140*0Sstevel@tonic-gate /* Validate against minimum value */ 1141*0Sstevel@tonic-gate if (maxcomp < MIN_NSTRIPE_COMP) { 1142*0Sstevel@tonic-gate volume_set_error(gettext( 1143*0Sstevel@tonic-gate "maximum stripe components (%d) below minimum allowable (%d)"), 1144*0Sstevel@tonic-gate maxcomp, MIN_NSTRIPE_COMP); 1145*0Sstevel@tonic-gate return (-1); 1146*0Sstevel@tonic-gate } 1147*0Sstevel@tonic-gate 1148*0Sstevel@tonic-gate return (set_uint16(stripe->attributes, ATTR_STRIPE_MAXCOMP, maxcomp)); 1149*0Sstevel@tonic-gate } 1150*0Sstevel@tonic-gate 1151*0Sstevel@tonic-gate /* 1152*0Sstevel@tonic-gate * Get maximum number of components in stripe 1153*0Sstevel@tonic-gate * 1154*0Sstevel@tonic-gate * @param device 1155*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 1156*0Sstevel@tonic-gate * 1157*0Sstevel@tonic-gate * @param maxcomp 1158*0Sstevel@tonic-gate * RETURN: maximum number of components in stripe 1159*0Sstevel@tonic-gate * 1160*0Sstevel@tonic-gate * @return 0 1161*0Sstevel@tonic-gate * if successful 1162*0Sstevel@tonic-gate * 1163*0Sstevel@tonic-gate * @return non-zero 1164*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 1165*0Sstevel@tonic-gate * retrieve the associated error message. 1166*0Sstevel@tonic-gate */ 1167*0Sstevel@tonic-gate int 1168*0Sstevel@tonic-gate devconfig_get_stripe_maxcomp( 1169*0Sstevel@tonic-gate devconfig_t *stripe, 1170*0Sstevel@tonic-gate uint16_t *maxcomp) 1171*0Sstevel@tonic-gate { 1172*0Sstevel@tonic-gate int error = get_uint16( 1173*0Sstevel@tonic-gate stripe->attributes, ATTR_STRIPE_MAXCOMP, maxcomp); 1174*0Sstevel@tonic-gate 1175*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 1176*0Sstevel@tonic-gate if (error == ENOENT) { 1177*0Sstevel@tonic-gate volume_set_error( 1178*0Sstevel@tonic-gate gettext("maximum number of stripe components not set")); 1179*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 1180*0Sstevel@tonic-gate } 1181*0Sstevel@tonic-gate 1182*0Sstevel@tonic-gate return (error); 1183*0Sstevel@tonic-gate } 1184*0Sstevel@tonic-gate 1185*0Sstevel@tonic-gate /* 1186*0Sstevel@tonic-gate * Set the stripe interlace 1187*0Sstevel@tonic-gate * 1188*0Sstevel@tonic-gate * @param stripe 1189*0Sstevel@tonic-gate * a devconfig_t representing the stripe to modify 1190*0Sstevel@tonic-gate * 1191*0Sstevel@tonic-gate * @param interlace 1192*0Sstevel@tonic-gate * the value to set as the stripe interlace 1193*0Sstevel@tonic-gate * 1194*0Sstevel@tonic-gate * @return 0 1195*0Sstevel@tonic-gate * if successful 1196*0Sstevel@tonic-gate * 1197*0Sstevel@tonic-gate * @return non-zero 1198*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 1199*0Sstevel@tonic-gate * retrieve the associated error message. 1200*0Sstevel@tonic-gate */ 1201*0Sstevel@tonic-gate int 1202*0Sstevel@tonic-gate devconfig_set_stripe_interlace( 1203*0Sstevel@tonic-gate devconfig_t *stripe, 1204*0Sstevel@tonic-gate uint64_t interlace) 1205*0Sstevel@tonic-gate { 1206*0Sstevel@tonic-gate if (interlace < MININTERLACE || interlace > MAXINTERLACE) { 1207*0Sstevel@tonic-gate char *intstr = NULL; 1208*0Sstevel@tonic-gate char *minstr = NULL; 1209*0Sstevel@tonic-gate char *maxstr = NULL; 1210*0Sstevel@tonic-gate 1211*0Sstevel@tonic-gate /* Get string representations of interlaces */ 1212*0Sstevel@tonic-gate bytes_to_sizestr(interlace, &intstr, universal_units, B_FALSE); 1213*0Sstevel@tonic-gate bytes_to_sizestr(MININTERLACE, &minstr, universal_units, B_FALSE); 1214*0Sstevel@tonic-gate bytes_to_sizestr(MAXINTERLACE, &maxstr, universal_units, B_FALSE); 1215*0Sstevel@tonic-gate 1216*0Sstevel@tonic-gate volume_set_error( 1217*0Sstevel@tonic-gate gettext("interlace (%s) out of valid range (%s - %s)"), 1218*0Sstevel@tonic-gate intstr, minstr, maxstr); 1219*0Sstevel@tonic-gate 1220*0Sstevel@tonic-gate free(intstr); 1221*0Sstevel@tonic-gate free(minstr); 1222*0Sstevel@tonic-gate free(maxstr); 1223*0Sstevel@tonic-gate 1224*0Sstevel@tonic-gate return (-1); 1225*0Sstevel@tonic-gate } 1226*0Sstevel@tonic-gate 1227*0Sstevel@tonic-gate return (set_uint64(stripe->attributes, 1228*0Sstevel@tonic-gate ATTR_STRIPE_INTERLACE, interlace)); 1229*0Sstevel@tonic-gate } 1230*0Sstevel@tonic-gate 1231*0Sstevel@tonic-gate /* 1232*0Sstevel@tonic-gate * Get stripe interlace 1233*0Sstevel@tonic-gate * 1234*0Sstevel@tonic-gate * @param device 1235*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 1236*0Sstevel@tonic-gate * 1237*0Sstevel@tonic-gate * @param interlace 1238*0Sstevel@tonic-gate * RETURN: stripe interlace 1239*0Sstevel@tonic-gate * 1240*0Sstevel@tonic-gate * @return 0 1241*0Sstevel@tonic-gate * if successful 1242*0Sstevel@tonic-gate * 1243*0Sstevel@tonic-gate * @return non-zero 1244*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 1245*0Sstevel@tonic-gate * retrieve the associated error message. 1246*0Sstevel@tonic-gate */ 1247*0Sstevel@tonic-gate int 1248*0Sstevel@tonic-gate devconfig_get_stripe_interlace( 1249*0Sstevel@tonic-gate devconfig_t *stripe, 1250*0Sstevel@tonic-gate uint64_t *interlace) 1251*0Sstevel@tonic-gate { 1252*0Sstevel@tonic-gate int error = get_uint64( 1253*0Sstevel@tonic-gate stripe->attributes, ATTR_STRIPE_INTERLACE, interlace); 1254*0Sstevel@tonic-gate 1255*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 1256*0Sstevel@tonic-gate if (error == ENOENT) { 1257*0Sstevel@tonic-gate volume_set_error(gettext("stripe interlace not set")); 1258*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 1259*0Sstevel@tonic-gate } 1260*0Sstevel@tonic-gate 1261*0Sstevel@tonic-gate return (error); 1262*0Sstevel@tonic-gate } 1263*0Sstevel@tonic-gate 1264*0Sstevel@tonic-gate /* 1265*0Sstevel@tonic-gate * Set the redundancy level for a volume. 1266*0Sstevel@tonic-gate * 1267*0Sstevel@tonic-gate * @param volume 1268*0Sstevel@tonic-gate * a devconfig_t representing the volume to modify 1269*0Sstevel@tonic-gate * 1270*0Sstevel@tonic-gate * @param rlevel 1271*0Sstevel@tonic-gate * If 0, a stripe will be created. If > 0, a mirror with 1272*0Sstevel@tonic-gate * this number of submirrors will be created. 1273*0Sstevel@tonic-gate * 1274*0Sstevel@tonic-gate * @return 0 1275*0Sstevel@tonic-gate * if successful 1276*0Sstevel@tonic-gate * 1277*0Sstevel@tonic-gate * @return non-zero 1278*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 1279*0Sstevel@tonic-gate * retrieve the associated error message. 1280*0Sstevel@tonic-gate */ 1281*0Sstevel@tonic-gate int 1282*0Sstevel@tonic-gate devconfig_set_volume_redundancy_level( 1283*0Sstevel@tonic-gate devconfig_t *volume, 1284*0Sstevel@tonic-gate uint16_t rlevel) 1285*0Sstevel@tonic-gate { 1286*0Sstevel@tonic-gate /* Validate against limits */ 1287*0Sstevel@tonic-gate if (rlevel > NMIRROR) { 1288*0Sstevel@tonic-gate volume_set_error(gettext( 1289*0Sstevel@tonic-gate "volume redundancy level (%d) out of valid range (%d-%d)"), 1290*0Sstevel@tonic-gate rlevel, 0, NMIRROR); 1291*0Sstevel@tonic-gate return (-1); 1292*0Sstevel@tonic-gate } 1293*0Sstevel@tonic-gate 1294*0Sstevel@tonic-gate return (set_uint16(volume->attributes, ATTR_VOLUME_REDUNDANCY, rlevel)); 1295*0Sstevel@tonic-gate } 1296*0Sstevel@tonic-gate 1297*0Sstevel@tonic-gate /* 1298*0Sstevel@tonic-gate * Get the redundancy level for a volume. 1299*0Sstevel@tonic-gate * 1300*0Sstevel@tonic-gate * @param device 1301*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 1302*0Sstevel@tonic-gate * 1303*0Sstevel@tonic-gate * @param rlevel 1304*0Sstevel@tonic-gate * RETURN: the redundancy level for a volume 1305*0Sstevel@tonic-gate * 1306*0Sstevel@tonic-gate * @return 0 1307*0Sstevel@tonic-gate * if successful 1308*0Sstevel@tonic-gate * 1309*0Sstevel@tonic-gate * @return non-zero 1310*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 1311*0Sstevel@tonic-gate * retrieve the associated error message. 1312*0Sstevel@tonic-gate */ 1313*0Sstevel@tonic-gate int 1314*0Sstevel@tonic-gate devconfig_get_volume_redundancy_level( 1315*0Sstevel@tonic-gate devconfig_t *volume, 1316*0Sstevel@tonic-gate uint16_t *rlevel) 1317*0Sstevel@tonic-gate { 1318*0Sstevel@tonic-gate int error = get_uint16( 1319*0Sstevel@tonic-gate volume->attributes, ATTR_VOLUME_REDUNDANCY, rlevel); 1320*0Sstevel@tonic-gate 1321*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 1322*0Sstevel@tonic-gate if (error == ENOENT) { 1323*0Sstevel@tonic-gate volume_set_error(gettext("volume redundancy level not set")); 1324*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 1325*0Sstevel@tonic-gate } 1326*0Sstevel@tonic-gate 1327*0Sstevel@tonic-gate return (error); 1328*0Sstevel@tonic-gate } 1329*0Sstevel@tonic-gate 1330*0Sstevel@tonic-gate /* 1331*0Sstevel@tonic-gate * Set the number of paths in volume 1332*0Sstevel@tonic-gate * 1333*0Sstevel@tonic-gate * @param volume 1334*0Sstevel@tonic-gate * a devconfig_t representing the volume to modify 1335*0Sstevel@tonic-gate * 1336*0Sstevel@tonic-gate * @param npaths 1337*0Sstevel@tonic-gate * the value to set as the number of paths in volume 1338*0Sstevel@tonic-gate * 1339*0Sstevel@tonic-gate * @return 0 1340*0Sstevel@tonic-gate * if successful 1341*0Sstevel@tonic-gate * 1342*0Sstevel@tonic-gate * @return non-zero 1343*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 1344*0Sstevel@tonic-gate * retrieve the associated error message. 1345*0Sstevel@tonic-gate */ 1346*0Sstevel@tonic-gate int 1347*0Sstevel@tonic-gate devconfig_set_volume_npaths( 1348*0Sstevel@tonic-gate devconfig_t *volume, 1349*0Sstevel@tonic-gate uint16_t npaths) 1350*0Sstevel@tonic-gate { 1351*0Sstevel@tonic-gate /* Validate against limits */ 1352*0Sstevel@tonic-gate if (npaths < MIN_NDATAPATHS || npaths > MAX_NDATAPATHS) { 1353*0Sstevel@tonic-gate volume_set_error( 1354*0Sstevel@tonic-gate gettext("number of data paths (%d) out of valid range (%d-%d)"), 1355*0Sstevel@tonic-gate npaths, MIN_NDATAPATHS, MAX_NDATAPATHS); 1356*0Sstevel@tonic-gate return (-1); 1357*0Sstevel@tonic-gate } 1358*0Sstevel@tonic-gate 1359*0Sstevel@tonic-gate return (set_uint16(volume->attributes, ATTR_VOLUME_DATAPATHS, npaths)); 1360*0Sstevel@tonic-gate } 1361*0Sstevel@tonic-gate 1362*0Sstevel@tonic-gate /* 1363*0Sstevel@tonic-gate * Get number of paths in volume 1364*0Sstevel@tonic-gate * 1365*0Sstevel@tonic-gate * @param device 1366*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 1367*0Sstevel@tonic-gate * 1368*0Sstevel@tonic-gate * @param npaths 1369*0Sstevel@tonic-gate * RETURN: number of paths in volume 1370*0Sstevel@tonic-gate * 1371*0Sstevel@tonic-gate * @return 0 1372*0Sstevel@tonic-gate * if successful 1373*0Sstevel@tonic-gate * 1374*0Sstevel@tonic-gate * @return non-zero 1375*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 1376*0Sstevel@tonic-gate * retrieve the associated error message. 1377*0Sstevel@tonic-gate */ 1378*0Sstevel@tonic-gate int 1379*0Sstevel@tonic-gate devconfig_get_volume_npaths( 1380*0Sstevel@tonic-gate devconfig_t *volume, 1381*0Sstevel@tonic-gate uint16_t *npaths) 1382*0Sstevel@tonic-gate { 1383*0Sstevel@tonic-gate int error = get_uint16( 1384*0Sstevel@tonic-gate volume->attributes, ATTR_VOLUME_DATAPATHS, npaths); 1385*0Sstevel@tonic-gate 1386*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 1387*0Sstevel@tonic-gate if (error == ENOENT) { 1388*0Sstevel@tonic-gate volume_set_error(gettext("number of data paths not set")); 1389*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 1390*0Sstevel@tonic-gate } 1391*0Sstevel@tonic-gate 1392*0Sstevel@tonic-gate return (error); 1393*0Sstevel@tonic-gate } 1394*0Sstevel@tonic-gate 1395*0Sstevel@tonic-gate /* 1396*0Sstevel@tonic-gate * Set the HSP creation option (for volume, stripe, concat, mirror) 1397*0Sstevel@tonic-gate * 1398*0Sstevel@tonic-gate * @param volume 1399*0Sstevel@tonic-gate * a devconfig_t representing the volume to modify 1400*0Sstevel@tonic-gate * 1401*0Sstevel@tonic-gate * @param usehsp 1402*0Sstevel@tonic-gate * the value to set as the HSP creation option 1403*0Sstevel@tonic-gate * 1404*0Sstevel@tonic-gate * @return 0 1405*0Sstevel@tonic-gate * if successful 1406*0Sstevel@tonic-gate * 1407*0Sstevel@tonic-gate * @return non-zero 1408*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 1409*0Sstevel@tonic-gate * retrieve the associated error message. 1410*0Sstevel@tonic-gate */ 1411*0Sstevel@tonic-gate int 1412*0Sstevel@tonic-gate devconfig_set_volume_usehsp( 1413*0Sstevel@tonic-gate devconfig_t *volume, 1414*0Sstevel@tonic-gate boolean_t usehsp) 1415*0Sstevel@tonic-gate { 1416*0Sstevel@tonic-gate return (set_boolean(volume->attributes, ATTR_VOLUME_USEHSP, usehsp)); 1417*0Sstevel@tonic-gate } 1418*0Sstevel@tonic-gate 1419*0Sstevel@tonic-gate /* 1420*0Sstevel@tonic-gate * Get HSP creation option (for volume, stripe, concat, mirror) 1421*0Sstevel@tonic-gate * 1422*0Sstevel@tonic-gate * @param device 1423*0Sstevel@tonic-gate * a devconfig_t representing the device to examine 1424*0Sstevel@tonic-gate * 1425*0Sstevel@tonic-gate * @param usehsp 1426*0Sstevel@tonic-gate * RETURN: HSP creation option (for volume, stripe, 1427*0Sstevel@tonic-gate * concat, mirror) 1428*0Sstevel@tonic-gate * 1429*0Sstevel@tonic-gate * @return 0 1430*0Sstevel@tonic-gate * if successful 1431*0Sstevel@tonic-gate * 1432*0Sstevel@tonic-gate * @return non-zero 1433*0Sstevel@tonic-gate * if an error occurred. Use get_error_string() to 1434*0Sstevel@tonic-gate * retrieve the associated error message. 1435*0Sstevel@tonic-gate */ 1436*0Sstevel@tonic-gate int 1437*0Sstevel@tonic-gate devconfig_get_volume_usehsp( 1438*0Sstevel@tonic-gate devconfig_t *volume, 1439*0Sstevel@tonic-gate boolean_t *usehsp) 1440*0Sstevel@tonic-gate { 1441*0Sstevel@tonic-gate int error = get_boolean( 1442*0Sstevel@tonic-gate volume->attributes, ATTR_VOLUME_USEHSP, usehsp); 1443*0Sstevel@tonic-gate 1444*0Sstevel@tonic-gate /* Convert ENOENT to ERR_ATTR_UNSET for a custom error message */ 1445*0Sstevel@tonic-gate if (error == ENOENT) { 1446*0Sstevel@tonic-gate volume_set_error(gettext("volume usehsp not set")); 1447*0Sstevel@tonic-gate error = ERR_ATTR_UNSET; 1448*0Sstevel@tonic-gate } 1449*0Sstevel@tonic-gate 1450*0Sstevel@tonic-gate return (error); 1451*0Sstevel@tonic-gate } 1452*0Sstevel@tonic-gate 1453*0Sstevel@tonic-gate /* 1454*0Sstevel@tonic-gate * Get the string representation of the volume's type 1455*0Sstevel@tonic-gate * 1456*0Sstevel@tonic-gate * @param type 1457*0Sstevel@tonic-gate * a valid component_type_t 1458*0Sstevel@tonic-gate * 1459*0Sstevel@tonic-gate * @return an internationalized string representing the given 1460*0Sstevel@tonic-gate * type 1461*0Sstevel@tonic-gate */ 1462*0Sstevel@tonic-gate char * 1463*0Sstevel@tonic-gate devconfig_type_to_str( 1464*0Sstevel@tonic-gate component_type_t type) 1465*0Sstevel@tonic-gate { 1466*0Sstevel@tonic-gate char *str; 1467*0Sstevel@tonic-gate 1468*0Sstevel@tonic-gate switch (type) { 1469*0Sstevel@tonic-gate case TYPE_CONCAT: str = gettext("Concat"); break; 1470*0Sstevel@tonic-gate case TYPE_CONTROLLER: str = gettext("Controller"); break; 1471*0Sstevel@tonic-gate case TYPE_DISKSET: str = gettext("Diskset"); break; 1472*0Sstevel@tonic-gate case TYPE_DRIVE: str = gettext("Disk"); break; 1473*0Sstevel@tonic-gate case TYPE_EXTENT: str = gettext("Extent"); break; 1474*0Sstevel@tonic-gate case TYPE_HOST: str = gettext("Host"); break; 1475*0Sstevel@tonic-gate case TYPE_HSP: str = gettext("Hot Spare Pool"); break; 1476*0Sstevel@tonic-gate case TYPE_MIRROR: str = gettext("Mirror"); break; 1477*0Sstevel@tonic-gate case TYPE_RAID5: str = gettext("Raid5"); break; 1478*0Sstevel@tonic-gate case TYPE_SLICE: str = gettext("Slice"); break; 1479*0Sstevel@tonic-gate case TYPE_SOFTPART: str = gettext("Soft Partition"); break; 1480*0Sstevel@tonic-gate case TYPE_STRIPE: str = gettext("Stripe"); break; 1481*0Sstevel@tonic-gate case TYPE_TRANS: str = gettext("Trans"); break; 1482*0Sstevel@tonic-gate case TYPE_VOLUME: str = gettext("Volume"); break; 1483*0Sstevel@tonic-gate default: 1484*0Sstevel@tonic-gate case TYPE_UNKNOWN: str = gettext("Unknown"); break; 1485*0Sstevel@tonic-gate } 1486*0Sstevel@tonic-gate 1487*0Sstevel@tonic-gate return (str); 1488*0Sstevel@tonic-gate } 1489*0Sstevel@tonic-gate 1490*0Sstevel@tonic-gate /* 1491*0Sstevel@tonic-gate * Get the string representation of the mirror's read strategy 1492*0Sstevel@tonic-gate * 1493*0Sstevel@tonic-gate * @param read 1494*0Sstevel@tonic-gate * a valid mirror_read_strategy_t 1495*0Sstevel@tonic-gate * 1496*0Sstevel@tonic-gate * @return an internationalized string representing the given 1497*0Sstevel@tonic-gate * read strategy 1498*0Sstevel@tonic-gate */ 1499*0Sstevel@tonic-gate char * 1500*0Sstevel@tonic-gate devconfig_read_strategy_to_str( 1501*0Sstevel@tonic-gate mirror_read_strategy_t read) 1502*0Sstevel@tonic-gate { 1503*0Sstevel@tonic-gate char *str; 1504*0Sstevel@tonic-gate 1505*0Sstevel@tonic-gate switch (read) { 1506*0Sstevel@tonic-gate case MIRROR_READ_ROUNDROBIN: str = gettext("ROUNDROBIN"); break; 1507*0Sstevel@tonic-gate case MIRROR_READ_GEOMETRIC: str = gettext("GEOMETRIC"); break; 1508*0Sstevel@tonic-gate case MIRROR_READ_FIRST: str = gettext("FIRST"); break; 1509*0Sstevel@tonic-gate default: str = ""; 1510*0Sstevel@tonic-gate } 1511*0Sstevel@tonic-gate 1512*0Sstevel@tonic-gate return (str); 1513*0Sstevel@tonic-gate } 1514*0Sstevel@tonic-gate 1515*0Sstevel@tonic-gate /* 1516*0Sstevel@tonic-gate * Get the string representation of the mirror's write strategy 1517*0Sstevel@tonic-gate * 1518*0Sstevel@tonic-gate * @param write 1519*0Sstevel@tonic-gate * a valid mirror_write_strategy_t 1520*0Sstevel@tonic-gate * 1521*0Sstevel@tonic-gate * @return an internationalized string representing the given 1522*0Sstevel@tonic-gate * write strategy 1523*0Sstevel@tonic-gate */ 1524*0Sstevel@tonic-gate char * 1525*0Sstevel@tonic-gate devconfig_write_strategy_to_str( 1526*0Sstevel@tonic-gate mirror_write_strategy_t write) 1527*0Sstevel@tonic-gate { 1528*0Sstevel@tonic-gate char *str; 1529*0Sstevel@tonic-gate 1530*0Sstevel@tonic-gate switch (write) { 1531*0Sstevel@tonic-gate case MIRROR_WRITE_PARALLEL: str = gettext("PARALLEL"); break; 1532*0Sstevel@tonic-gate case MIRROR_WRITE_SERIAL: str = gettext("SERIAL"); break; 1533*0Sstevel@tonic-gate default: str = ""; 1534*0Sstevel@tonic-gate } 1535*0Sstevel@tonic-gate 1536*0Sstevel@tonic-gate return (str); 1537*0Sstevel@tonic-gate } 1538*0Sstevel@tonic-gate 1539*0Sstevel@tonic-gate #ifdef DEBUG 1540*0Sstevel@tonic-gate /* 1541*0Sstevel@tonic-gate * Dump the contents of a devconfig_t struct to stdout. 1542*0Sstevel@tonic-gate * 1543*0Sstevel@tonic-gate * @param device 1544*0Sstevel@tonic-gate * the devconfig_t to examine 1545*0Sstevel@tonic-gate * 1546*0Sstevel@tonic-gate * @param prefix 1547*0Sstevel@tonic-gate * a prefix string to print before each line 1548*0Sstevel@tonic-gate */ 1549*0Sstevel@tonic-gate void 1550*0Sstevel@tonic-gate devconfig_dump( 1551*0Sstevel@tonic-gate devconfig_t *device, 1552*0Sstevel@tonic-gate char *prefix) 1553*0Sstevel@tonic-gate { 1554*0Sstevel@tonic-gate dlist_t *comps = NULL; 1555*0Sstevel@tonic-gate char **array = NULL; 1556*0Sstevel@tonic-gate char *str = NULL; 1557*0Sstevel@tonic-gate int i = 0; 1558*0Sstevel@tonic-gate 1559*0Sstevel@tonic-gate component_type_t type = TYPE_UNKNOWN; 1560*0Sstevel@tonic-gate boolean_t bool = B_FALSE; 1561*0Sstevel@tonic-gate uint16_t val16 = 0; 1562*0Sstevel@tonic-gate uint64_t val64 = 0; 1563*0Sstevel@tonic-gate mirror_read_strategy_t read; 1564*0Sstevel@tonic-gate mirror_write_strategy_t write; 1565*0Sstevel@tonic-gate 1566*0Sstevel@tonic-gate if (device == NULL) { 1567*0Sstevel@tonic-gate return; 1568*0Sstevel@tonic-gate } 1569*0Sstevel@tonic-gate 1570*0Sstevel@tonic-gate /* Type */ 1571*0Sstevel@tonic-gate if (devconfig_get_type(device, &type) == 0) { 1572*0Sstevel@tonic-gate printf("%s%s\n", prefix, devconfig_type_to_str(type)); 1573*0Sstevel@tonic-gate } 1574*0Sstevel@tonic-gate 1575*0Sstevel@tonic-gate /* Name */ 1576*0Sstevel@tonic-gate if (devconfig_get_name(device, &str) == 0) { 1577*0Sstevel@tonic-gate printf("%s name: %s\n", prefix, str); 1578*0Sstevel@tonic-gate } 1579*0Sstevel@tonic-gate 1580*0Sstevel@tonic-gate /* Size in bytes */ 1581*0Sstevel@tonic-gate if (devconfig_get_size(device, &val64) == 0) { 1582*0Sstevel@tonic-gate printf("%s size in bytes: %llu\n", prefix, val64); 1583*0Sstevel@tonic-gate } 1584*0Sstevel@tonic-gate 1585*0Sstevel@tonic-gate /* Size in blocks */ 1586*0Sstevel@tonic-gate if (devconfig_get_size_in_blocks(device, &val64) == 0) { 1587*0Sstevel@tonic-gate printf("%s size in blocks: %llu\n", prefix, val64); 1588*0Sstevel@tonic-gate } 1589*0Sstevel@tonic-gate 1590*0Sstevel@tonic-gate /* Use HSP */ 1591*0Sstevel@tonic-gate if (devconfig_get_volume_usehsp(device, &bool) == 0) { 1592*0Sstevel@tonic-gate printf("%s usehsp: %s\n", prefix, bool? "TRUE" : "FALSE"); 1593*0Sstevel@tonic-gate } 1594*0Sstevel@tonic-gate 1595*0Sstevel@tonic-gate switch (type) { 1596*0Sstevel@tonic-gate case TYPE_VOLUME: 1597*0Sstevel@tonic-gate /* Volume rlevel */ 1598*0Sstevel@tonic-gate if (devconfig_get_volume_redundancy_level( 1599*0Sstevel@tonic-gate device, &val16) == 0) { 1600*0Sstevel@tonic-gate printf("%s volume redundancy level: %d\n", prefix, val16); 1601*0Sstevel@tonic-gate } 1602*0Sstevel@tonic-gate 1603*0Sstevel@tonic-gate /* Volume npaths */ 1604*0Sstevel@tonic-gate if (devconfig_get_volume_npaths(device, &val16) == 0) { 1605*0Sstevel@tonic-gate printf("%s volume npaths: %d\n", prefix, val16); 1606*0Sstevel@tonic-gate } 1607*0Sstevel@tonic-gate break; 1608*0Sstevel@tonic-gate 1609*0Sstevel@tonic-gate case TYPE_MIRROR: 1610*0Sstevel@tonic-gate 1611*0Sstevel@tonic-gate /* Mirror nsubs */ 1612*0Sstevel@tonic-gate if (devconfig_get_mirror_nsubs(device, &val16) == 0) { 1613*0Sstevel@tonic-gate printf("%s mirror nsubs: %d\n", prefix, val16); 1614*0Sstevel@tonic-gate } 1615*0Sstevel@tonic-gate 1616*0Sstevel@tonic-gate /* Mirror read */ 1617*0Sstevel@tonic-gate if (devconfig_get_mirror_read(device, &read) == 0) { 1618*0Sstevel@tonic-gate printf("%s mirror read: %s\n", prefix, 1619*0Sstevel@tonic-gate devconfig_read_strategy_to_str(read)); 1620*0Sstevel@tonic-gate } 1621*0Sstevel@tonic-gate 1622*0Sstevel@tonic-gate /* Mirror write */ 1623*0Sstevel@tonic-gate if (devconfig_get_mirror_write(device, &write) == 0) { 1624*0Sstevel@tonic-gate printf("%s mirror write: %s\n", prefix, 1625*0Sstevel@tonic-gate devconfig_write_strategy_to_str(write)); 1626*0Sstevel@tonic-gate } 1627*0Sstevel@tonic-gate 1628*0Sstevel@tonic-gate /* Mirror pass */ 1629*0Sstevel@tonic-gate if (devconfig_get_mirror_pass(device, &val16) == 0) { 1630*0Sstevel@tonic-gate printf("%s mirror pass: %d\n", prefix, val16); 1631*0Sstevel@tonic-gate } 1632*0Sstevel@tonic-gate break; 1633*0Sstevel@tonic-gate 1634*0Sstevel@tonic-gate case TYPE_STRIPE: 1635*0Sstevel@tonic-gate /* Stripe mincomp */ 1636*0Sstevel@tonic-gate if (devconfig_get_stripe_mincomp(device, &val16) == 0) { 1637*0Sstevel@tonic-gate printf("%s stripe mincomp: %d\n", prefix, val16); 1638*0Sstevel@tonic-gate } 1639*0Sstevel@tonic-gate 1640*0Sstevel@tonic-gate /* Stripe maxcomp */ 1641*0Sstevel@tonic-gate if (devconfig_get_stripe_maxcomp(device, &val16) == 0) { 1642*0Sstevel@tonic-gate printf("%s stripe maxcomp: %d\n", prefix, val16); 1643*0Sstevel@tonic-gate } 1644*0Sstevel@tonic-gate 1645*0Sstevel@tonic-gate /* Stripe interlace */ 1646*0Sstevel@tonic-gate if (devconfig_get_stripe_interlace(device, &val64) == 0) { 1647*0Sstevel@tonic-gate printf("%s stripe interlace: %lld\n", prefix, val64); 1648*0Sstevel@tonic-gate } 1649*0Sstevel@tonic-gate break; 1650*0Sstevel@tonic-gate 1651*0Sstevel@tonic-gate case TYPE_SLICE: 1652*0Sstevel@tonic-gate /* Slice index */ 1653*0Sstevel@tonic-gate if (devconfig_get_slice_index(device, &val16) == 0) { 1654*0Sstevel@tonic-gate printf("%s slice index: %d\n", prefix, val16); 1655*0Sstevel@tonic-gate } 1656*0Sstevel@tonic-gate 1657*0Sstevel@tonic-gate /* Slice start block */ 1658*0Sstevel@tonic-gate if (devconfig_get_slice_start_block(device, &val64) == 0) { 1659*0Sstevel@tonic-gate printf("%s slice start block: %llu\n", prefix, val64); 1660*0Sstevel@tonic-gate } 1661*0Sstevel@tonic-gate break; 1662*0Sstevel@tonic-gate } 1663*0Sstevel@tonic-gate 1664*0Sstevel@tonic-gate array = devconfig_get_available(device); 1665*0Sstevel@tonic-gate if (array != NULL) { 1666*0Sstevel@tonic-gate printf("%s available:\n", prefix); 1667*0Sstevel@tonic-gate for (i = 0; array[i] != NULL; i++) { 1668*0Sstevel@tonic-gate printf("%s %s\n", prefix, array[i]); 1669*0Sstevel@tonic-gate } 1670*0Sstevel@tonic-gate } 1671*0Sstevel@tonic-gate 1672*0Sstevel@tonic-gate array = devconfig_get_unavailable(device); 1673*0Sstevel@tonic-gate if (array != NULL) { 1674*0Sstevel@tonic-gate printf("%s unavailable:\n", prefix); 1675*0Sstevel@tonic-gate for (i = 0; array[i] != NULL; i++) { 1676*0Sstevel@tonic-gate printf("%s %s\n", prefix, array[i]); 1677*0Sstevel@tonic-gate } 1678*0Sstevel@tonic-gate } 1679*0Sstevel@tonic-gate 1680*0Sstevel@tonic-gate printf("\n"); 1681*0Sstevel@tonic-gate 1682*0Sstevel@tonic-gate comps = devconfig_get_components(device); 1683*0Sstevel@tonic-gate if (comps != NULL) { 1684*0Sstevel@tonic-gate char buf[128]; 1685*0Sstevel@tonic-gate snprintf(buf, 128, "%s%s", prefix, " "); 1686*0Sstevel@tonic-gate for (; comps != NULL; comps = comps->next) { 1687*0Sstevel@tonic-gate devconfig_dump((devconfig_t *)comps->obj, buf); 1688*0Sstevel@tonic-gate } 1689*0Sstevel@tonic-gate } 1690*0Sstevel@tonic-gate } 1691*0Sstevel@tonic-gate #endif /* DEBUG */ 1692