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 /* 30*0Sstevel@tonic-gate * hotspare maintenance 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <meta.h> 34*0Sstevel@tonic-gate #include <sdssc.h> 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate /* 37*0Sstevel@tonic-gate * possible actions 38*0Sstevel@tonic-gate */ 39*0Sstevel@tonic-gate enum metahs_op { 40*0Sstevel@tonic-gate NONE, 41*0Sstevel@tonic-gate ADD_A_HS, 42*0Sstevel@tonic-gate DELETE_A_HS, 43*0Sstevel@tonic-gate ENABLE_A_HS, 44*0Sstevel@tonic-gate REPLACE_A_HS, 45*0Sstevel@tonic-gate STATUS_A_HSP 46*0Sstevel@tonic-gate }; 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate /* 49*0Sstevel@tonic-gate * report status of a hotspare pool 50*0Sstevel@tonic-gate */ 51*0Sstevel@tonic-gate static int 52*0Sstevel@tonic-gate status_hsp( 53*0Sstevel@tonic-gate mdsetname_t *sp, 54*0Sstevel@tonic-gate mdhspname_t *hspnp, 55*0Sstevel@tonic-gate md_error_t *ep 56*0Sstevel@tonic-gate ) 57*0Sstevel@tonic-gate { 58*0Sstevel@tonic-gate mdprtopts_t options = (PRINT_HEADER | PRINT_SUBDEVS | PRINT_DEVID); 59*0Sstevel@tonic-gate mdnamelist_t *nlp = NULL; 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate /* must have set */ 62*0Sstevel@tonic-gate assert(sp != NULL); 63*0Sstevel@tonic-gate assert(sp->setno == HSP_SET(hspnp->hsp)); 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate /* print status */ 66*0Sstevel@tonic-gate if (meta_hsp_print(sp, hspnp, &nlp, NULL, stdout, options, ep) != 0) 67*0Sstevel@tonic-gate return (-1); 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate /* return success */ 70*0Sstevel@tonic-gate return (0); 71*0Sstevel@tonic-gate } 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate /* 74*0Sstevel@tonic-gate * print usage message 75*0Sstevel@tonic-gate */ 76*0Sstevel@tonic-gate static void 77*0Sstevel@tonic-gate usage( 78*0Sstevel@tonic-gate mdsetname_t *sp, 79*0Sstevel@tonic-gate int eval 80*0Sstevel@tonic-gate ) 81*0Sstevel@tonic-gate { 82*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("\ 83*0Sstevel@tonic-gate usage: %s [-s setname] -a hot_spare_pool [component...]\n\ 84*0Sstevel@tonic-gate %s [-s setname] -a \"all\" component...\n\ 85*0Sstevel@tonic-gate %s [-s setname] -d hot_spare_pool [component...]\n\ 86*0Sstevel@tonic-gate %s [-s setname] -d \"all\" component...\n\ 87*0Sstevel@tonic-gate %s [-s setname] -e component...\n\ 88*0Sstevel@tonic-gate %s [-s setname] -r hot_spare_pool component_old component_new\n\ 89*0Sstevel@tonic-gate %s [-s setname] -r \"all\" component_old component_new\n\ 90*0Sstevel@tonic-gate %s [-s setname] -i [hot_spare_pool...]\n"), 91*0Sstevel@tonic-gate myname, myname, myname, myname, myname, myname, myname, myname); 92*0Sstevel@tonic-gate md_exit(sp, eval); 93*0Sstevel@tonic-gate } 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate /* 96*0Sstevel@tonic-gate * check for "all" 97*0Sstevel@tonic-gate */ 98*0Sstevel@tonic-gate static int 99*0Sstevel@tonic-gate is_all(char *s) 100*0Sstevel@tonic-gate { 101*0Sstevel@tonic-gate if ((strcoll(s, gettext("all")) == 0) || 102*0Sstevel@tonic-gate (strcoll(s, gettext("ALL")) == 0)) 103*0Sstevel@tonic-gate return (1); 104*0Sstevel@tonic-gate return (0); 105*0Sstevel@tonic-gate } 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate /* 108*0Sstevel@tonic-gate * parse args and add hotspares 109*0Sstevel@tonic-gate */ 110*0Sstevel@tonic-gate static int 111*0Sstevel@tonic-gate add_hotspares( 112*0Sstevel@tonic-gate mdsetname_t **spp, 113*0Sstevel@tonic-gate int argc, 114*0Sstevel@tonic-gate char *argv[], 115*0Sstevel@tonic-gate mdcmdopts_t options, 116*0Sstevel@tonic-gate md_error_t *ep 117*0Sstevel@tonic-gate ) 118*0Sstevel@tonic-gate { 119*0Sstevel@tonic-gate mdhspnamelist_t *hspnlp = NULL; 120*0Sstevel@tonic-gate mdnamelist_t *nlp = NULL; 121*0Sstevel@tonic-gate int cnt; 122*0Sstevel@tonic-gate mdhspnamelist_t *p; 123*0Sstevel@tonic-gate int rval = -1; 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate /* get hotspare pool name(s) */ 126*0Sstevel@tonic-gate if (argc < 1) 127*0Sstevel@tonic-gate usage(*spp, 1); 128*0Sstevel@tonic-gate if ((argc > 1) && is_all(argv[0])) { 129*0Sstevel@tonic-gate if ((*spp == NULL) && 130*0Sstevel@tonic-gate ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)) { 131*0Sstevel@tonic-gate return (-1); 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate /* check for ownership */ 134*0Sstevel@tonic-gate assert(*spp != NULL); 135*0Sstevel@tonic-gate if (meta_check_ownership(*spp, ep) != 0) 136*0Sstevel@tonic-gate return (-1); 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate if ((cnt = meta_get_hsp_names(*spp, &hspnlp, 0, ep)) < 0) { 139*0Sstevel@tonic-gate return (-1); 140*0Sstevel@tonic-gate } else if (cnt == 0) { 141*0Sstevel@tonic-gate return (mderror(ep, MDE_NO_HSPS, NULL)); 142*0Sstevel@tonic-gate } 143*0Sstevel@tonic-gate } else if ((cnt = metahspnamelist(spp, &hspnlp, 1, &argv[0], 144*0Sstevel@tonic-gate ep)) < 0) { 145*0Sstevel@tonic-gate return (-1); 146*0Sstevel@tonic-gate } 147*0Sstevel@tonic-gate assert(cnt > 0); 148*0Sstevel@tonic-gate --argc, ++argv; 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate assert(*spp != NULL); 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate /* grab set lock */ 153*0Sstevel@tonic-gate if (meta_lock(*spp, TRUE, ep)) 154*0Sstevel@tonic-gate return (-1); 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate /* check for ownership */ 157*0Sstevel@tonic-gate if (meta_check_ownership(*spp, ep) != 0) 158*0Sstevel@tonic-gate return (-1); 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* get hotspares */ 161*0Sstevel@tonic-gate if (metanamelist(spp, &nlp, argc, argv, ep) < 0) { 162*0Sstevel@tonic-gate goto out; 163*0Sstevel@tonic-gate } 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate /* add hotspares */ 166*0Sstevel@tonic-gate for (p = hspnlp; (p != NULL); p = p->next) { 167*0Sstevel@tonic-gate mdhspname_t *hspnp = p->hspnamep; 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate if (meta_hs_add(*spp, hspnp, nlp, options, ep) != 0) 170*0Sstevel@tonic-gate goto out; 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate rval = 0; 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate /* cleanup, return success */ 175*0Sstevel@tonic-gate out: 176*0Sstevel@tonic-gate if (hspnlp != NULL) 177*0Sstevel@tonic-gate metafreehspnamelist(hspnlp); 178*0Sstevel@tonic-gate if (nlp != NULL) 179*0Sstevel@tonic-gate metafreenamelist(nlp); 180*0Sstevel@tonic-gate return (rval); 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate /* 184*0Sstevel@tonic-gate * parse args and delete hotspares 185*0Sstevel@tonic-gate */ 186*0Sstevel@tonic-gate static int 187*0Sstevel@tonic-gate delete_hotspares( 188*0Sstevel@tonic-gate mdsetname_t **spp, 189*0Sstevel@tonic-gate int argc, 190*0Sstevel@tonic-gate char *argv[], 191*0Sstevel@tonic-gate mdcmdopts_t options, 192*0Sstevel@tonic-gate md_error_t *ep 193*0Sstevel@tonic-gate ) 194*0Sstevel@tonic-gate { 195*0Sstevel@tonic-gate mdhspnamelist_t *hspnlp = NULL; 196*0Sstevel@tonic-gate mdnamelist_t *nlp = NULL; 197*0Sstevel@tonic-gate int cnt; 198*0Sstevel@tonic-gate mdhspnamelist_t *p; 199*0Sstevel@tonic-gate int rval = -1; 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate /* get hotspare pool name(s) */ 202*0Sstevel@tonic-gate if (argc < 1) 203*0Sstevel@tonic-gate usage(*spp, 1); 204*0Sstevel@tonic-gate if ((argc > 1) && is_all(argv[0])) { 205*0Sstevel@tonic-gate if ((*spp == NULL) && 206*0Sstevel@tonic-gate ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)) { 207*0Sstevel@tonic-gate return (-1); 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate /* check for ownership */ 210*0Sstevel@tonic-gate assert(*spp != NULL); 211*0Sstevel@tonic-gate if (meta_check_ownership(*spp, ep) != 0) 212*0Sstevel@tonic-gate return (-1); 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate if ((cnt = meta_get_hsp_names(*spp, &hspnlp, 0, ep)) < 0) { 215*0Sstevel@tonic-gate return (-1); 216*0Sstevel@tonic-gate } else if (cnt == 0) { 217*0Sstevel@tonic-gate return (mderror(ep, MDE_NO_HSPS, NULL)); 218*0Sstevel@tonic-gate } 219*0Sstevel@tonic-gate } else if ((cnt = metahspnamelist(spp, &hspnlp, 1, &argv[0], 220*0Sstevel@tonic-gate ep)) < 0) { 221*0Sstevel@tonic-gate return (-1); 222*0Sstevel@tonic-gate } 223*0Sstevel@tonic-gate assert(cnt > 0); 224*0Sstevel@tonic-gate --argc, ++argv; 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate assert(*spp != NULL); 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate /* grab set lock */ 229*0Sstevel@tonic-gate if (meta_lock(*spp, TRUE, ep)) 230*0Sstevel@tonic-gate return (-1); 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate /* check for ownership */ 233*0Sstevel@tonic-gate if (meta_check_ownership(*spp, ep) != 0) 234*0Sstevel@tonic-gate return (-1); 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate /* get hotspares */ 237*0Sstevel@tonic-gate if (metanamelist(spp, &nlp, argc, argv, ep) < 0) { 238*0Sstevel@tonic-gate goto out; 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate /* delete hotspares */ 242*0Sstevel@tonic-gate cnt = 0; 243*0Sstevel@tonic-gate for (p = hspnlp; (p != NULL); p = p->next) { 244*0Sstevel@tonic-gate mdhspname_t *hspnp = p->hspnamep; 245*0Sstevel@tonic-gate 246*0Sstevel@tonic-gate if (meta_hs_delete(*spp, hspnp, nlp, options, ep) != 0) { 247*0Sstevel@tonic-gate if (mdisdeverror(ep, MDE_INVAL_HS)) 248*0Sstevel@tonic-gate mdclrerror(ep); 249*0Sstevel@tonic-gate else 250*0Sstevel@tonic-gate goto out; 251*0Sstevel@tonic-gate } else { 252*0Sstevel@tonic-gate ++cnt; 253*0Sstevel@tonic-gate } 254*0Sstevel@tonic-gate } 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate /* make sure we got some */ 257*0Sstevel@tonic-gate if ((nlp != NULL) && (cnt == 0)) { 258*0Sstevel@tonic-gate (void) mddeverror(ep, MDE_INVAL_HS, nlp->namep->dev, 259*0Sstevel@tonic-gate nlp->namep->cname); 260*0Sstevel@tonic-gate goto out; 261*0Sstevel@tonic-gate } 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate /* success */ 264*0Sstevel@tonic-gate rval = 0; 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate /* cleanup, return success */ 267*0Sstevel@tonic-gate out: 268*0Sstevel@tonic-gate if (hspnlp != NULL) 269*0Sstevel@tonic-gate metafreehspnamelist(hspnlp); 270*0Sstevel@tonic-gate if (nlp != NULL) 271*0Sstevel@tonic-gate metafreenamelist(nlp); 272*0Sstevel@tonic-gate return (rval); 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate /* 276*0Sstevel@tonic-gate * parse args and enable hotspares 277*0Sstevel@tonic-gate */ 278*0Sstevel@tonic-gate static int 279*0Sstevel@tonic-gate enable_hotspares( 280*0Sstevel@tonic-gate mdsetname_t **spp, 281*0Sstevel@tonic-gate int argc, 282*0Sstevel@tonic-gate char *argv[], 283*0Sstevel@tonic-gate mdcmdopts_t options, 284*0Sstevel@tonic-gate md_error_t *ep 285*0Sstevel@tonic-gate ) 286*0Sstevel@tonic-gate { 287*0Sstevel@tonic-gate mdnamelist_t *nlp = NULL; 288*0Sstevel@tonic-gate int rval = -1; 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gate /* enable hotspares */ 291*0Sstevel@tonic-gate if (argc < 1) 292*0Sstevel@tonic-gate usage(*spp, 1); 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate /* get list of hotspares */ 295*0Sstevel@tonic-gate if (metanamelist(spp, &nlp, argc, argv, ep) < 0) 296*0Sstevel@tonic-gate goto out; 297*0Sstevel@tonic-gate assert(nlp != NULL); 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate assert(*spp != NULL); 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate /* grab set lock */ 302*0Sstevel@tonic-gate if (meta_lock(*spp, TRUE, ep)) 303*0Sstevel@tonic-gate return (-1); 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate /* check for ownership */ 306*0Sstevel@tonic-gate if (meta_check_ownership(*spp, ep) != 0) 307*0Sstevel@tonic-gate return (-1); 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate /* enable hotspares */ 310*0Sstevel@tonic-gate rval = meta_hs_enable(*spp, nlp, options, ep); 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate /* cleanup, return success */ 313*0Sstevel@tonic-gate out: 314*0Sstevel@tonic-gate metafreenamelist(nlp); 315*0Sstevel@tonic-gate return (rval); 316*0Sstevel@tonic-gate } 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate /* 319*0Sstevel@tonic-gate * parse args and replace hotspares 320*0Sstevel@tonic-gate */ 321*0Sstevel@tonic-gate static int 322*0Sstevel@tonic-gate replace_hotspares( 323*0Sstevel@tonic-gate mdsetname_t **spp, 324*0Sstevel@tonic-gate int argc, 325*0Sstevel@tonic-gate char *argv[], 326*0Sstevel@tonic-gate mdcmdopts_t options, 327*0Sstevel@tonic-gate md_error_t *ep 328*0Sstevel@tonic-gate ) 329*0Sstevel@tonic-gate { 330*0Sstevel@tonic-gate mdhspnamelist_t *hspnlp = NULL; 331*0Sstevel@tonic-gate int cnt; 332*0Sstevel@tonic-gate mdname_t *oldnp; 333*0Sstevel@tonic-gate mdname_t *newnp; 334*0Sstevel@tonic-gate mdhspnamelist_t *p; 335*0Sstevel@tonic-gate int rval = -1; 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate /* get hotspare pool name(s) */ 338*0Sstevel@tonic-gate if (argc != 3) 339*0Sstevel@tonic-gate usage(*spp, 1); 340*0Sstevel@tonic-gate if (is_all(argv[0])) { 341*0Sstevel@tonic-gate if ((*spp == NULL) && 342*0Sstevel@tonic-gate ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)) { 343*0Sstevel@tonic-gate return (-1); 344*0Sstevel@tonic-gate } 345*0Sstevel@tonic-gate /* check for ownership */ 346*0Sstevel@tonic-gate assert(*spp != NULL); 347*0Sstevel@tonic-gate if (meta_check_ownership(*spp, ep) != 0) 348*0Sstevel@tonic-gate return (-1); 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate if ((cnt = meta_get_hsp_names(*spp, &hspnlp, 0, ep)) < 0) { 351*0Sstevel@tonic-gate return (-1); 352*0Sstevel@tonic-gate } else if (cnt == 0) { 353*0Sstevel@tonic-gate return (mderror(ep, MDE_NO_HSPS, NULL)); 354*0Sstevel@tonic-gate } 355*0Sstevel@tonic-gate } else if ((cnt = metahspnamelist(spp, &hspnlp, 1, &argv[0], 356*0Sstevel@tonic-gate ep)) < 0) { 357*0Sstevel@tonic-gate return (-1); 358*0Sstevel@tonic-gate } 359*0Sstevel@tonic-gate assert(cnt > 0); 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate assert(*spp != NULL); 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate /* grab set lock */ 364*0Sstevel@tonic-gate if (meta_lock(*spp, TRUE, ep)) 365*0Sstevel@tonic-gate return (-1); 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate /* check for ownership */ 368*0Sstevel@tonic-gate if (meta_check_ownership(*spp, ep) != 0) 369*0Sstevel@tonic-gate return (-1); 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate /* get old component */ 372*0Sstevel@tonic-gate if ((oldnp = metaname(spp, argv[1], ep)) == NULL) 373*0Sstevel@tonic-gate goto out; 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate /* get new component */ 376*0Sstevel@tonic-gate if ((newnp = metaname(spp, argv[2], ep)) == NULL) 377*0Sstevel@tonic-gate goto out; 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate /* replace hotspares */ 380*0Sstevel@tonic-gate cnt = 0; 381*0Sstevel@tonic-gate for (p = hspnlp; (p != NULL); p = p->next) { 382*0Sstevel@tonic-gate mdhspname_t *hspnp = p->hspnamep; 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate if (meta_hs_replace(*spp, hspnp, oldnp, newnp, options, ep) 385*0Sstevel@tonic-gate != 0) { 386*0Sstevel@tonic-gate if (mdisdeverror(ep, MDE_INVAL_HS)) 387*0Sstevel@tonic-gate mdclrerror(ep); 388*0Sstevel@tonic-gate else 389*0Sstevel@tonic-gate goto out; 390*0Sstevel@tonic-gate } else { 391*0Sstevel@tonic-gate ++cnt; 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate } 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate /* make sure we got some */ 396*0Sstevel@tonic-gate if (cnt == 0) { 397*0Sstevel@tonic-gate (void) mddeverror(ep, MDE_INVAL_HS, oldnp->dev, oldnp->cname); 398*0Sstevel@tonic-gate goto out; 399*0Sstevel@tonic-gate } 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gate /* success */ 402*0Sstevel@tonic-gate rval = 0; 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate /* cleanup, return success */ 405*0Sstevel@tonic-gate out: 406*0Sstevel@tonic-gate if (hspnlp != NULL) 407*0Sstevel@tonic-gate metafreehspnamelist(hspnlp); 408*0Sstevel@tonic-gate return (rval); 409*0Sstevel@tonic-gate } 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate /* 412*0Sstevel@tonic-gate * print_hsp_devid will collect the information for each underlying 413*0Sstevel@tonic-gate * physical device for all the hotspare pools and print out the 414*0Sstevel@tonic-gate * device relocation information 415*0Sstevel@tonic-gate * INPUT: 416*0Sstevel@tonic-gate * mdsetname_t *sp set the hsp is in 417*0Sstevel@tonic-gate * mdhspnamelist_t *hspnlp list of hsp 418*0Sstevel@tonic-gate * FILE *fp where to print to 419*0Sstevel@tonic-gate * md_error_t *ep errors 420*0Sstevel@tonic-gate * RETURN: 421*0Sstevel@tonic-gate * 0 SUCCESS 422*0Sstevel@tonic-gate * -1 ERROR 423*0Sstevel@tonic-gate */ 424*0Sstevel@tonic-gate static int 425*0Sstevel@tonic-gate print_hsp_devid( 426*0Sstevel@tonic-gate mdsetname_t *sp, 427*0Sstevel@tonic-gate mdhspnamelist_t *hspnlp, 428*0Sstevel@tonic-gate FILE *fp, 429*0Sstevel@tonic-gate md_error_t *ep 430*0Sstevel@tonic-gate ) 431*0Sstevel@tonic-gate { 432*0Sstevel@tonic-gate mddevid_t *ldevidp = NULL; 433*0Sstevel@tonic-gate int retval = 0; 434*0Sstevel@tonic-gate mdhspnamelist_t *p; 435*0Sstevel@tonic-gate mddevid_t *nextp; 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate /* for all hotspare pools */ 438*0Sstevel@tonic-gate for (p = hspnlp; (p != NULL); p = p->next) { 439*0Sstevel@tonic-gate mdhspname_t *hspnp = p->hspnamep; 440*0Sstevel@tonic-gate uint_t hsi; 441*0Sstevel@tonic-gate 442*0Sstevel@tonic-gate /* for all hotspares within a pool */ 443*0Sstevel@tonic-gate for (hsi = 0; 444*0Sstevel@tonic-gate hsi < hspnp->unitp->hotspares.hotspares_len; hsi++) { 445*0Sstevel@tonic-gate mdname_t *hsname; 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate hsname = 448*0Sstevel@tonic-gate hspnp->unitp->hotspares.hotspares_val[hsi].hsnamep; 449*0Sstevel@tonic-gate 450*0Sstevel@tonic-gate meta_create_non_dup_list(hsname, &ldevidp); 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate } 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate retval = meta_print_devid(sp, fp, ldevidp, ep); 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate /* cleanup */ 457*0Sstevel@tonic-gate for (nextp = ldevidp; nextp != NULL; ldevidp = nextp) { 458*0Sstevel@tonic-gate Free(ldevidp->ctdname); 459*0Sstevel@tonic-gate nextp = ldevidp->next; 460*0Sstevel@tonic-gate Free(ldevidp); 461*0Sstevel@tonic-gate } 462*0Sstevel@tonic-gate return (retval); 463*0Sstevel@tonic-gate } 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate /* 466*0Sstevel@tonic-gate * parse args and status hotspares 467*0Sstevel@tonic-gate */ 468*0Sstevel@tonic-gate static int 469*0Sstevel@tonic-gate status_hotspares( 470*0Sstevel@tonic-gate mdsetname_t **spp, 471*0Sstevel@tonic-gate int argc, 472*0Sstevel@tonic-gate char *argv[], 473*0Sstevel@tonic-gate md_error_t *ep 474*0Sstevel@tonic-gate ) 475*0Sstevel@tonic-gate { 476*0Sstevel@tonic-gate mdhspnamelist_t *hspnlp = NULL; 477*0Sstevel@tonic-gate int cnt; 478*0Sstevel@tonic-gate mdhspnamelist_t *p; 479*0Sstevel@tonic-gate int rval = -1; 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate /* get hotspare pool name(s) */ 482*0Sstevel@tonic-gate if (argc == 0) { 483*0Sstevel@tonic-gate if ((*spp == NULL) && 484*0Sstevel@tonic-gate ((*spp = metasetname(MD_LOCAL_NAME, ep)) == NULL)) { 485*0Sstevel@tonic-gate return (-1); 486*0Sstevel@tonic-gate } 487*0Sstevel@tonic-gate /* check for ownership */ 488*0Sstevel@tonic-gate assert(*spp != NULL); 489*0Sstevel@tonic-gate if (meta_check_ownership(*spp, ep) != 0) 490*0Sstevel@tonic-gate return (-1); 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate if ((cnt = meta_get_hsp_names(*spp, &hspnlp, 0, ep)) < 0) { 493*0Sstevel@tonic-gate return (-1); 494*0Sstevel@tonic-gate } else if (cnt == 0) { 495*0Sstevel@tonic-gate return (mderror(ep, MDE_NO_HSPS, NULL)); 496*0Sstevel@tonic-gate } 497*0Sstevel@tonic-gate } else if ((cnt = metahspnamelist(spp, &hspnlp, argc, argv, ep)) < 0) { 498*0Sstevel@tonic-gate return (-1); 499*0Sstevel@tonic-gate } 500*0Sstevel@tonic-gate assert(cnt > 0); 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate /* check for ownership */ 503*0Sstevel@tonic-gate assert(*spp != NULL); 504*0Sstevel@tonic-gate if (meta_check_ownership(*spp, ep) != 0) 505*0Sstevel@tonic-gate return (-1); 506*0Sstevel@tonic-gate 507*0Sstevel@tonic-gate /* status hotspare pools */ 508*0Sstevel@tonic-gate for (p = hspnlp; (p != NULL); p = p->next) { 509*0Sstevel@tonic-gate mdhspname_t *hspnp = p->hspnamep; 510*0Sstevel@tonic-gate 511*0Sstevel@tonic-gate if (status_hsp(*spp, hspnp, ep) != 0) 512*0Sstevel@tonic-gate goto out; 513*0Sstevel@tonic-gate } 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate if (print_hsp_devid(*spp, hspnlp, stdout, ep) == 0) { 516*0Sstevel@tonic-gate rval = 0; 517*0Sstevel@tonic-gate } 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate /* cleanup, return success */ 520*0Sstevel@tonic-gate out: 521*0Sstevel@tonic-gate if (hspnlp != NULL) 522*0Sstevel@tonic-gate metafreehspnamelist(hspnlp); 523*0Sstevel@tonic-gate return (rval); 524*0Sstevel@tonic-gate } 525*0Sstevel@tonic-gate 526*0Sstevel@tonic-gate /* 527*0Sstevel@tonic-gate * parse args and doit 528*0Sstevel@tonic-gate */ 529*0Sstevel@tonic-gate int 530*0Sstevel@tonic-gate main( 531*0Sstevel@tonic-gate int argc, 532*0Sstevel@tonic-gate char **argv 533*0Sstevel@tonic-gate ) 534*0Sstevel@tonic-gate { 535*0Sstevel@tonic-gate char *sname = MD_LOCAL_NAME; 536*0Sstevel@tonic-gate mdsetname_t *sp = NULL; 537*0Sstevel@tonic-gate enum metahs_op which_op = NONE; 538*0Sstevel@tonic-gate mdcmdopts_t options = (MDCMD_PRINT | MDCMD_DOIT); 539*0Sstevel@tonic-gate int c; 540*0Sstevel@tonic-gate md_error_t status = mdnullerror; 541*0Sstevel@tonic-gate md_error_t *ep = &status; 542*0Sstevel@tonic-gate int error; 543*0Sstevel@tonic-gate bool_t called_thru_rpc = FALSE; 544*0Sstevel@tonic-gate char *cp; 545*0Sstevel@tonic-gate 546*0Sstevel@tonic-gate /* 547*0Sstevel@tonic-gate * Get the locale set up before calling any other routines 548*0Sstevel@tonic-gate * with messages to ouput. Just in case we're not in a build 549*0Sstevel@tonic-gate * environment, make sure that TEXT_DOMAIN gets set to 550*0Sstevel@tonic-gate * something. 551*0Sstevel@tonic-gate */ 552*0Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 553*0Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 554*0Sstevel@tonic-gate #endif 555*0Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 556*0Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 557*0Sstevel@tonic-gate 558*0Sstevel@tonic-gate 559*0Sstevel@tonic-gate if ((cp = strstr(argv[0], ".rpc_call")) == NULL) { 560*0Sstevel@tonic-gate if (sdssc_bind_library() == SDSSC_OKAY) 561*0Sstevel@tonic-gate if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY, 562*0Sstevel@tonic-gate &error) == SDSSC_PROXY_DONE) 563*0Sstevel@tonic-gate exit(error); 564*0Sstevel@tonic-gate } else { 565*0Sstevel@tonic-gate *cp = '\0'; /* cut off ".rpc_call" */ 566*0Sstevel@tonic-gate called_thru_rpc = TRUE; 567*0Sstevel@tonic-gate } 568*0Sstevel@tonic-gate 569*0Sstevel@tonic-gate /* initialize */ 570*0Sstevel@tonic-gate if (md_init(argc, argv, 0, 1, ep) != 0) { 571*0Sstevel@tonic-gate mde_perror(ep, ""); 572*0Sstevel@tonic-gate md_exit(sp, 1); 573*0Sstevel@tonic-gate } 574*0Sstevel@tonic-gate 575*0Sstevel@tonic-gate /* parse args */ 576*0Sstevel@tonic-gate optind = 1; 577*0Sstevel@tonic-gate opterr = 1; 578*0Sstevel@tonic-gate while ((c = getopt(argc, argv, "hs:aderin?")) != -1) { 579*0Sstevel@tonic-gate switch (c) { 580*0Sstevel@tonic-gate case 'h': 581*0Sstevel@tonic-gate usage(sp, 0); 582*0Sstevel@tonic-gate break; 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate case 's': 585*0Sstevel@tonic-gate sname = optarg; 586*0Sstevel@tonic-gate break; 587*0Sstevel@tonic-gate 588*0Sstevel@tonic-gate case 'a': 589*0Sstevel@tonic-gate if (which_op != NONE) 590*0Sstevel@tonic-gate usage(sp, 1); 591*0Sstevel@tonic-gate which_op = ADD_A_HS; 592*0Sstevel@tonic-gate break; 593*0Sstevel@tonic-gate 594*0Sstevel@tonic-gate case 'd': 595*0Sstevel@tonic-gate if (which_op != NONE) 596*0Sstevel@tonic-gate usage(sp, 1); 597*0Sstevel@tonic-gate which_op = DELETE_A_HS; 598*0Sstevel@tonic-gate break; 599*0Sstevel@tonic-gate 600*0Sstevel@tonic-gate case 'e': 601*0Sstevel@tonic-gate if (which_op != NONE) 602*0Sstevel@tonic-gate usage(sp, 1); 603*0Sstevel@tonic-gate which_op = ENABLE_A_HS; 604*0Sstevel@tonic-gate break; 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate case 'r': 607*0Sstevel@tonic-gate if (which_op != NONE) 608*0Sstevel@tonic-gate usage(sp, 1); 609*0Sstevel@tonic-gate which_op = REPLACE_A_HS; 610*0Sstevel@tonic-gate break; 611*0Sstevel@tonic-gate 612*0Sstevel@tonic-gate case 'i': 613*0Sstevel@tonic-gate if (which_op != NONE) 614*0Sstevel@tonic-gate usage(sp, 1); 615*0Sstevel@tonic-gate which_op = STATUS_A_HSP; 616*0Sstevel@tonic-gate break; 617*0Sstevel@tonic-gate 618*0Sstevel@tonic-gate case 'n': 619*0Sstevel@tonic-gate if (called_thru_rpc == TRUE) { 620*0Sstevel@tonic-gate options &= ~MDCMD_DOIT; 621*0Sstevel@tonic-gate } else { 622*0Sstevel@tonic-gate usage(sp, 1); 623*0Sstevel@tonic-gate } 624*0Sstevel@tonic-gate break; 625*0Sstevel@tonic-gate 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate case '?': 628*0Sstevel@tonic-gate if (optopt == '?') 629*0Sstevel@tonic-gate usage(sp, 0); 630*0Sstevel@tonic-gate /*FALLTHROUGH*/ 631*0Sstevel@tonic-gate default: 632*0Sstevel@tonic-gate usage(sp, 1); 633*0Sstevel@tonic-gate break; 634*0Sstevel@tonic-gate } 635*0Sstevel@tonic-gate } 636*0Sstevel@tonic-gate 637*0Sstevel@tonic-gate /* get set context */ 638*0Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) { 639*0Sstevel@tonic-gate mde_perror(ep, ""); 640*0Sstevel@tonic-gate md_exit(sp, 1); 641*0Sstevel@tonic-gate } 642*0Sstevel@tonic-gate 643*0Sstevel@tonic-gate /* 644*0Sstevel@tonic-gate * Send the command to all nodes if the -s argument refers to a MN 645*0Sstevel@tonic-gate * set or the next argument refers to MN set hotspare name ( argc 646*0Sstevel@tonic-gate * greater than optind if there is a next argument) 647*0Sstevel@tonic-gate */ 648*0Sstevel@tonic-gate if ((called_thru_rpc == FALSE) && 649*0Sstevel@tonic-gate (meta_is_mn_set(sp, ep) || ((argc > optind) && 650*0Sstevel@tonic-gate meta_is_mn_name(&sp, argv[optind], ep)))) { 651*0Sstevel@tonic-gate int i; 652*0Sstevel@tonic-gate int newargc; 653*0Sstevel@tonic-gate int result; 654*0Sstevel@tonic-gate char **newargv; 655*0Sstevel@tonic-gate 656*0Sstevel@tonic-gate /* 657*0Sstevel@tonic-gate * If we are dealing with a MN set and we were not 658*0Sstevel@tonic-gate * called thru an rpc call, we are just to send this 659*0Sstevel@tonic-gate * command string to the master of the set and let it 660*0Sstevel@tonic-gate * deal with it. 661*0Sstevel@tonic-gate * First we send out a dryrun version of this command. 662*0Sstevel@tonic-gate * If that returns success, we know it succeeded on all 663*0Sstevel@tonic-gate * nodes and it is safe to do the real command now. 664*0Sstevel@tonic-gate */ 665*0Sstevel@tonic-gate newargv = calloc(argc+1, sizeof (char *)); 666*0Sstevel@tonic-gate newargv[0] = "metahs"; 667*0Sstevel@tonic-gate newargv[1] = "-n"; /* always do "-n" first */ 668*0Sstevel@tonic-gate newargc = 2; 669*0Sstevel@tonic-gate for (i = 1; i < argc; i++, newargc++) 670*0Sstevel@tonic-gate newargv[newargc] = argv[i]; 671*0Sstevel@tonic-gate result = meta_mn_send_command(sp, newargc, newargv, 672*0Sstevel@tonic-gate MD_DISP_STDERR | MD_DRYRUN, NO_CONTEXT_STRING, ep); 673*0Sstevel@tonic-gate 674*0Sstevel@tonic-gate /* If we found a problem don't do it for real */ 675*0Sstevel@tonic-gate if (result != 0) { 676*0Sstevel@tonic-gate md_exit(sp, result); 677*0Sstevel@tonic-gate } 678*0Sstevel@tonic-gate 679*0Sstevel@tonic-gate /* 680*0Sstevel@tonic-gate * Do it for real now. Remove "-n" from the arguments and 681*0Sstevel@tonic-gate * MD_DRYRUN from the flags. If this fails the master must panic 682*0Sstevel@tonic-gate * as the mddbs may be inconsistent. 683*0Sstevel@tonic-gate */ 684*0Sstevel@tonic-gate newargv[1] = ""; /* this was "-n" before */ 685*0Sstevel@tonic-gate result = meta_mn_send_command(sp, newargc, newargv, 686*0Sstevel@tonic-gate MD_DISP_STDERR | MD_RETRY_BUSY | MD_PANIC_WHEN_INCONSISTENT, 687*0Sstevel@tonic-gate NO_CONTEXT_STRING, ep); 688*0Sstevel@tonic-gate free(newargv); 689*0Sstevel@tonic-gate 690*0Sstevel@tonic-gate /* No further action required */ 691*0Sstevel@tonic-gate md_exit(sp, result); 692*0Sstevel@tonic-gate } 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate argc -= optind; 695*0Sstevel@tonic-gate argv += optind; 696*0Sstevel@tonic-gate if (which_op == NONE) 697*0Sstevel@tonic-gate usage(sp, 1); 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate if (which_op == STATUS_A_HSP) { 700*0Sstevel@tonic-gate if (status_hotspares(&sp, argc, argv, ep) != 0) { 701*0Sstevel@tonic-gate mde_perror(ep, ""); 702*0Sstevel@tonic-gate md_exit(sp, 1); 703*0Sstevel@tonic-gate } 704*0Sstevel@tonic-gate md_exit(sp, 0); 705*0Sstevel@tonic-gate } 706*0Sstevel@tonic-gate 707*0Sstevel@tonic-gate if (meta_check_root(ep) != 0) { 708*0Sstevel@tonic-gate mde_perror(ep, ""); 709*0Sstevel@tonic-gate md_exit(sp, 1); 710*0Sstevel@tonic-gate } 711*0Sstevel@tonic-gate 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate /* dispatch */ 714*0Sstevel@tonic-gate switch (which_op) { 715*0Sstevel@tonic-gate 716*0Sstevel@tonic-gate case ADD_A_HS: 717*0Sstevel@tonic-gate if (add_hotspares(&sp, argc, argv, options, ep) != 0) { 718*0Sstevel@tonic-gate mde_perror(ep, ""); 719*0Sstevel@tonic-gate md_exit(sp, 1); 720*0Sstevel@tonic-gate } 721*0Sstevel@tonic-gate break; 722*0Sstevel@tonic-gate 723*0Sstevel@tonic-gate case DELETE_A_HS: 724*0Sstevel@tonic-gate if (delete_hotspares(&sp, argc, argv, options, ep) != 0) { 725*0Sstevel@tonic-gate mde_perror(ep, ""); 726*0Sstevel@tonic-gate md_exit(sp, 1); 727*0Sstevel@tonic-gate } 728*0Sstevel@tonic-gate break; 729*0Sstevel@tonic-gate 730*0Sstevel@tonic-gate case ENABLE_A_HS: 731*0Sstevel@tonic-gate if (enable_hotspares(&sp, argc, argv, options, ep) != 0) { 732*0Sstevel@tonic-gate mde_perror(ep, ""); 733*0Sstevel@tonic-gate md_exit(sp, 1); 734*0Sstevel@tonic-gate } 735*0Sstevel@tonic-gate break; 736*0Sstevel@tonic-gate 737*0Sstevel@tonic-gate case REPLACE_A_HS: 738*0Sstevel@tonic-gate if (replace_hotspares(&sp, argc, argv, options, ep) != 0) { 739*0Sstevel@tonic-gate mde_perror(ep, ""); 740*0Sstevel@tonic-gate md_exit(sp, 1); 741*0Sstevel@tonic-gate } 742*0Sstevel@tonic-gate break; 743*0Sstevel@tonic-gate 744*0Sstevel@tonic-gate default: 745*0Sstevel@tonic-gate assert(0); 746*0Sstevel@tonic-gate break; 747*0Sstevel@tonic-gate } 748*0Sstevel@tonic-gate 749*0Sstevel@tonic-gate /* update md.cf */ 750*0Sstevel@tonic-gate out: 751*0Sstevel@tonic-gate if (meta_update_md_cf(sp, ep) != 0) { 752*0Sstevel@tonic-gate mde_perror(ep, ""); 753*0Sstevel@tonic-gate md_exit(sp, 1); 754*0Sstevel@tonic-gate } 755*0Sstevel@tonic-gate md_exit(sp, 0); 756*0Sstevel@tonic-gate /*NOTREACHED*/ 757*0Sstevel@tonic-gate return (0); 758*0Sstevel@tonic-gate } 759