1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * change metadevice parameters 30 */ 31 32 #include <meta.h> 33 34 #include <sdssc.h> 35 36 /* 37 * print usage message 38 */ 39 static void 40 usage( 41 mdsetname_t *sp, 42 int eval 43 ) 44 { 45 (void) fprintf(stderr, gettext("\ 46 usage: %s [-s setname] [options] concat/stripe | RAID\n\ 47 %s [-s setname] [options] mirror\n\ 48 \n\ 49 Concat/Stripe or RAID options:\n\ 50 -h hotspare_pool | \"none\"\n\ 51 \n\ 52 Mirror options:\n\ 53 -r roundrobin | geometric | first\n\ 54 -w parallel | serial\n\ 55 -p 0-%d\n"), myname, myname, MD_PASS_MAX); 56 57 md_exit(sp, eval); 58 } 59 60 /* 61 * do mirror parameters 62 */ 63 static int 64 mirror_params( 65 mdsetname_t *sp, 66 mdname_t *mirnp, 67 int argc, 68 char *argv[], 69 md_error_t *ep 70 ) 71 { 72 mm_params_t mmp; 73 int modified = 0; 74 int c; 75 76 /* we must have a set */ 77 assert(sp != NULL); 78 assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev))); 79 80 /* initialize */ 81 (void) memset(&mmp, '\0', sizeof (mmp)); 82 83 /* reset and parse args */ 84 optind = 1; 85 opterr = 1; 86 while ((c = getopt(argc, argv, "s:r:w:p:")) != -1) { 87 switch (c) { 88 case 's': 89 break; 90 91 case 'r': 92 if (name_to_rd_opt(mirnp->cname, optarg, 93 &mmp.read_option, ep) != 0) { 94 return (-1); 95 } 96 mmp.change_read_option = 1; 97 modified = 1; 98 break; 99 100 case 'w': 101 if (name_to_wr_opt(mirnp->cname, optarg, 102 &mmp.write_option, ep) != 0) { 103 return (-1); 104 } 105 mmp.change_write_option = 1; 106 modified = 1; 107 break; 108 109 case 'p': 110 if (name_to_pass_num(mirnp->cname, optarg, 111 &mmp.pass_num, ep) != 0) { 112 return (-1); 113 } 114 mmp.change_pass_num = 1; 115 modified = 1; 116 break; 117 118 default: 119 usage(sp, 1); 120 /*NOTREACHED*/ 121 break; 122 } 123 } 124 125 argc -= optind; 126 argv += optind; 127 if (argc != 1) 128 usage(sp, 1); 129 130 /* if just printing */ 131 if (! modified) { 132 if (meta_mirror_get_params(sp, mirnp, &mmp, ep) != 0) 133 return (-1); 134 (void) printf( 135 gettext( 136 "%s: Mirror current parameters are:\n"), 137 mirnp->cname); 138 if (meta_print_mirror_options(mmp.read_option, 139 mmp.write_option, mmp.pass_num, 0, NULL, 140 sp, stdout, ep) != 0) { 141 return (-1); 142 } 143 } 144 145 /* otherwise, change parameters */ 146 else { 147 if (meta_mirror_set_params(sp, mirnp, &mmp, ep) != 0) 148 return (-1); 149 150 /* update md.cf */ 151 if (meta_update_md_cf(sp, ep) != 0) 152 return (-1); 153 } 154 155 /* return success */ 156 return (0); 157 } 158 159 /* 160 * do stripe parameters 161 */ 162 static int 163 stripe_params( 164 mdsetname_t *sp, 165 mdname_t *stripenp, 166 int argc, 167 char *argv[], 168 md_error_t *ep 169 ) 170 { 171 ms_params_t msp; 172 int modified = 0; 173 mdhspname_t *hspnp; 174 int c; 175 176 /* we must have a set */ 177 assert(sp != NULL); 178 assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev))); 179 180 /* initialize */ 181 (void) memset(&msp, '\0', sizeof (msp)); 182 183 /* reset and parse args */ 184 optind = 1; 185 opterr = 1; 186 while ((c = getopt(argc, argv, "s:h:")) != -1) { 187 switch (c) { 188 case 's': 189 break; 190 191 case 'h': 192 if (meta_is_none(optarg)) { 193 msp.hsp_id = MD_HSP_NONE; 194 } else if ((hspnp = metahspname(&sp, optarg, 195 ep)) == NULL) { 196 return (-1); 197 } else if (metachkhsp(sp, hspnp, ep) != 0) { 198 return (-1); 199 } else { 200 msp.hsp_id = hspnp->hsp; 201 } 202 msp.change_hsp_id = 1; 203 modified = 1; 204 break; 205 206 default: 207 usage(sp, 1); 208 /*NOTREACHED*/ 209 break; 210 } 211 } 212 argc -= optind; 213 argv += optind; 214 if (argc != 1) 215 usage(sp, 1); 216 217 /* if just printing */ 218 if (! modified) { 219 if (meta_stripe_get_params(sp, stripenp, &msp, ep) != 0) 220 return (-1); 221 if (msp.hsp_id == MD_HSP_NONE) 222 hspnp = NULL; 223 else if ((hspnp = metahsphspname(&sp, msp.hsp_id, ep)) == NULL) 224 return (-1); 225 (void) printf(gettext( 226 "%s: Concat/Stripe current parameters are:\n"), 227 stripenp->cname); 228 if (meta_print_stripe_options(hspnp, NULL, stdout, ep) != 0) 229 return (-1); 230 } 231 232 /* otherwise, change parameters */ 233 else { 234 if (meta_stripe_set_params(sp, stripenp, &msp, ep) != 0) 235 return (-1); 236 237 /* update md.cf */ 238 if (meta_update_md_cf(sp, ep) != 0) 239 return (-1); 240 } 241 242 /* return success */ 243 return (0); 244 } 245 246 /* 247 * do raid parameters 248 */ 249 static int 250 raid_params( 251 mdsetname_t *sp, 252 mdname_t *raidnp, 253 int argc, 254 char *argv[], 255 md_error_t *ep 256 ) 257 { 258 mr_params_t msp; 259 int modified = 0; 260 mdhspname_t *hspnp; 261 int c; 262 263 /* we must have a set */ 264 assert(sp != NULL); 265 assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev))); 266 267 /* initialize */ 268 (void) memset(&msp, '\0', sizeof (msp)); 269 270 /* reset and parse args */ 271 optind = 1; 272 opterr = 1; 273 while ((c = getopt(argc, argv, "s:h:")) != -1) { 274 switch (c) { 275 case 's': 276 break; 277 278 case 'h': 279 if (meta_is_none(optarg)) { 280 msp.hsp_id = MD_HSP_NONE; 281 } else if ((hspnp = metahspname(&sp, optarg, 282 ep)) == NULL) { 283 return (-1); 284 } else if (metachkhsp(sp, hspnp, ep) != 0) { 285 return (-1); 286 } else { 287 msp.hsp_id = hspnp->hsp; 288 } 289 msp.change_hsp_id = 1; 290 modified = 1; 291 break; 292 293 default: 294 usage(sp, 1); 295 /*NOTREACHED*/ 296 break; 297 } 298 } 299 argc -= optind; 300 argv += optind; 301 if (argc != 1) 302 usage(sp, 1); 303 304 /* if just printing */ 305 if (! modified) { 306 if (meta_raid_get_params(sp, raidnp, &msp, ep) != 0) 307 return (-1); 308 if (msp.hsp_id == MD_HSP_NONE) 309 hspnp = NULL; 310 else if ((hspnp = metahsphspname(&sp, msp.hsp_id, ep)) == NULL) 311 return (-1); 312 (void) printf(gettext( 313 "%s: RAID current parameters are:\n"), 314 raidnp->cname); 315 if (meta_print_raid_options(hspnp, NULL, stdout, ep) != 0) 316 return (-1); 317 } 318 319 /* otherwise, change parameters */ 320 else { 321 if (meta_raid_set_params(sp, raidnp, &msp, ep) != 0) 322 return (-1); 323 324 /* update md.cf */ 325 if (meta_update_md_cf(sp, ep) != 0) 326 return (-1); 327 } 328 329 /* return success */ 330 return (0); 331 } 332 333 /* 334 * parse args and doit 335 */ 336 int 337 main( 338 int argc, 339 char **argv 340 ) 341 { 342 char *sname = NULL; 343 mdsetname_t *sp = NULL; 344 mdname_t *np; 345 char *miscname; 346 int c; 347 md_error_t status = mdnullerror; 348 md_error_t *ep = &status; 349 int error; 350 bool_t called_thru_rpc = FALSE; 351 char *cp; 352 char *firstarg = NULL; 353 354 355 /* 356 * Get the locale set up before calling any other routines 357 * with messages to ouput. Just in case we're not in a build 358 * environment, make sure that TEXT_DOMAIN gets set to 359 * something. 360 */ 361 #if !defined(TEXT_DOMAIN) 362 #define TEXT_DOMAIN "SYS_TEST" 363 #endif 364 (void) setlocale(LC_ALL, ""); 365 (void) textdomain(TEXT_DOMAIN); 366 367 if ((cp = strstr(argv[0], ".rpc_call")) == NULL) { 368 if (sdssc_bind_library() == SDSSC_OKAY) 369 if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY, 370 &error) == SDSSC_PROXY_DONE) 371 exit(error); 372 } else { 373 *cp = '\0'; /* cut off ".rpc_call" */ 374 called_thru_rpc = TRUE; 375 } 376 377 378 /* initialize */ 379 if (md_init(argc, argv, 0, 1, ep) != 0 || 380 meta_check_root(ep) != 0) { 381 mde_perror(ep, ""); 382 md_exit(sp, 1); 383 } 384 385 /* find set and metadevice first */ 386 optind = 1; 387 opterr = 1; 388 while ((c = getopt(argc, argv, "s:h:p:r:w:o:?")) != -1) { 389 switch (c) { 390 case 's': 391 sname = optarg; 392 break; 393 case 'h': 394 firstarg = optarg; 395 break; 396 case '?': 397 if (optopt == '?') 398 usage(sp, 0); 399 break; 400 } 401 } 402 if ((argc - optind) <= 0) 403 usage(sp, 1); 404 405 if (sname != NULL) { 406 if ((sp = metasetname(sname, ep)) == NULL) { 407 mde_perror(ep, ""); 408 md_exit(sp, 1); 409 } 410 } 411 if (firstarg == NULL) 412 firstarg = argv[optind]; 413 if ((called_thru_rpc == FALSE) && 414 meta_is_mn_name(&sp, firstarg, ep)) { 415 /* 416 * If we are dealing with a MN set and we were not 417 * called thru an rpc call, we are just to send this 418 * command string to the master of the set and let it 419 * deal with it. 420 * Note that if sp is NULL, meta_is_mn_name() derives sp 421 * from firstarg which is the metadevice arg 422 * If this fails, the master must panic as the mddb may be 423 * inconsistent 424 */ 425 int result; 426 result = meta_mn_send_command(sp, argc, argv, MD_DISP_STDERR | 427 MD_PANIC_WHEN_INCONSISTENT, NO_CONTEXT_STRING, ep); 428 /* No further action required */ 429 md_exit(sp, result); 430 } 431 432 if ((np = metaname(&sp, argv[optind], META_DEVICE, ep)) == NULL) { 433 mde_perror(ep, ""); 434 md_exit(sp, 1); 435 } 436 assert(sp != NULL); 437 /* grab set lock */ 438 if (meta_lock(sp, TRUE, ep)) { 439 mde_perror(ep, ""); 440 md_exit(sp, 1); 441 } 442 443 if (meta_check_ownership(sp, ep) != 0) { 444 mde_perror(ep, ""); 445 md_exit(sp, 1); 446 } 447 if ((miscname = metagetmiscname(np, ep)) == NULL) { 448 mde_perror(ep, ""); 449 md_exit(sp, 1); 450 } 451 452 /* dispatch based on device type */ 453 if (strcmp(miscname, MD_STRIPE) == 0) { 454 if (stripe_params(sp, np, argc, argv, ep) != 0) { 455 mde_perror(ep, ""); 456 md_exit(sp, 1); 457 } 458 } else if (strcmp(miscname, MD_MIRROR) == 0) { 459 if (mirror_params(sp, np, argc, argv, ep) != 0) { 460 mde_perror(ep, ""); 461 md_exit(sp, 1); 462 } 463 } else if (strcmp(miscname, MD_RAID) == 0) { 464 if (raid_params(sp, np, argc, argv, ep) != 0) { 465 mde_perror(ep, ""); 466 md_exit(sp, 1); 467 } 468 } else { 469 md_eprintf(gettext( 470 "%s: invalid metadevice type %s\n"), 471 np->cname, miscname); 472 md_exit(sp, 1); 473 } 474 475 /* return success */ 476 md_exit(sp, 0); 477 /*NOTREACHED*/ 478 return (0); 479 } 480