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 * rename or exchange metadevice identity 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <meta.h> 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate #include <sdssc.h> 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate /* 38*0Sstevel@tonic-gate * print usage message 39*0Sstevel@tonic-gate */ 40*0Sstevel@tonic-gate static void 41*0Sstevel@tonic-gate usage( 42*0Sstevel@tonic-gate mdsetname_t *sp, 43*0Sstevel@tonic-gate int eval 44*0Sstevel@tonic-gate ) 45*0Sstevel@tonic-gate { 46*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("\ 47*0Sstevel@tonic-gate usage: %s [-s setname] [-f] [-x] metadevice1 metadevice2\n\ 48*0Sstevel@tonic-gate %s -h\n\ 49*0Sstevel@tonic-gate options:\n\ 50*0Sstevel@tonic-gate -s operations are done on the set setname, rather than the local set\n\ 51*0Sstevel@tonic-gate -f force exchange or rename\n\ 52*0Sstevel@tonic-gate -x exchange the identities of metadevice1 and metadevice2\n\ 53*0Sstevel@tonic-gate -h help: print this message\n"), myname, myname); 54*0Sstevel@tonic-gate md_exit(sp, eval); 55*0Sstevel@tonic-gate } 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate /* 58*0Sstevel@tonic-gate * mainline. crack command line arguments. 59*0Sstevel@tonic-gate */ 60*0Sstevel@tonic-gate int 61*0Sstevel@tonic-gate main( 62*0Sstevel@tonic-gate int argc, 63*0Sstevel@tonic-gate char *argv[] 64*0Sstevel@tonic-gate ) 65*0Sstevel@tonic-gate { 66*0Sstevel@tonic-gate char *sname = NULL; 67*0Sstevel@tonic-gate mdsetname_t *sp = NULL; 68*0Sstevel@tonic-gate int xflag = 0; 69*0Sstevel@tonic-gate mdcmdopts_t options = (MDCMD_PRINT | MDCMD_DOIT); 70*0Sstevel@tonic-gate md_error_t status = mdnullerror; 71*0Sstevel@tonic-gate md_error_t *ep = &status; 72*0Sstevel@tonic-gate int rc = 0; 73*0Sstevel@tonic-gate mdname_t *mdnms[2]; 74*0Sstevel@tonic-gate int c, i; 75*0Sstevel@tonic-gate int error; 76*0Sstevel@tonic-gate bool_t called_thru_rpc = FALSE; 77*0Sstevel@tonic-gate char *cp; 78*0Sstevel@tonic-gate int origargc = argc; 79*0Sstevel@tonic-gate char **origargv = argv; 80*0Sstevel@tonic-gate char *miscname; 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate /* 83*0Sstevel@tonic-gate * Get the locale set up before calling any other routines 84*0Sstevel@tonic-gate * with messages to ouput. Just in case we're not in a build 85*0Sstevel@tonic-gate * environment, make sure that TEXT_DOMAIN gets set to 86*0Sstevel@tonic-gate * something. 87*0Sstevel@tonic-gate */ 88*0Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 89*0Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 90*0Sstevel@tonic-gate #endif 91*0Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 92*0Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate if ((cp = strstr(argv[0], ".rpc_call")) == NULL) { 96*0Sstevel@tonic-gate if (sdssc_bind_library() == SDSSC_OKAY) 97*0Sstevel@tonic-gate if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY, 98*0Sstevel@tonic-gate &error) == SDSSC_PROXY_DONE) 99*0Sstevel@tonic-gate exit(error); 100*0Sstevel@tonic-gate } else { 101*0Sstevel@tonic-gate *cp = '\0'; /* cut off ".rpc_call" */ 102*0Sstevel@tonic-gate called_thru_rpc = TRUE; 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate /* initialize */ 106*0Sstevel@tonic-gate if (md_init(argc, argv, 0, 1, ep) != 0 || 107*0Sstevel@tonic-gate meta_check_root(ep) != 0) { 108*0Sstevel@tonic-gate mde_perror(ep, ""); 109*0Sstevel@tonic-gate md_exit(sp, 1); 110*0Sstevel@tonic-gate } 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate /* parse args */ 113*0Sstevel@tonic-gate optind = 1; 114*0Sstevel@tonic-gate opterr = 1; 115*0Sstevel@tonic-gate while ((c = getopt(argc, argv, "fns:xh?")) != -1) { 116*0Sstevel@tonic-gate switch (c) { 117*0Sstevel@tonic-gate case 'h': 118*0Sstevel@tonic-gate usage(sp, 0); 119*0Sstevel@tonic-gate break; 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate case 's': 122*0Sstevel@tonic-gate sname = optarg; 123*0Sstevel@tonic-gate break; 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate case 'x': 126*0Sstevel@tonic-gate ++xflag; 127*0Sstevel@tonic-gate break; 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate case 'f': 130*0Sstevel@tonic-gate options |= MDCMD_FORCE; 131*0Sstevel@tonic-gate break; 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate case 'n': 134*0Sstevel@tonic-gate if (called_thru_rpc == TRUE) { 135*0Sstevel@tonic-gate options &= ~MDCMD_DOIT; 136*0Sstevel@tonic-gate } else { 137*0Sstevel@tonic-gate usage(sp, 1); 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate break; 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate case '?': 142*0Sstevel@tonic-gate if (optopt == '?') 143*0Sstevel@tonic-gate usage(sp, 0); 144*0Sstevel@tonic-gate /*FALLTHROUGH*/ 145*0Sstevel@tonic-gate default: 146*0Sstevel@tonic-gate usage(sp, 1); 147*0Sstevel@tonic-gate break; 148*0Sstevel@tonic-gate } 149*0Sstevel@tonic-gate } 150*0Sstevel@tonic-gate argc -= optind; 151*0Sstevel@tonic-gate argv += optind; 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate if (sname != NULL) { 154*0Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) { 155*0Sstevel@tonic-gate mde_perror(ep, ""); 156*0Sstevel@tonic-gate md_exit(sp, 1); 157*0Sstevel@tonic-gate } 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate if (argc != 2) { 161*0Sstevel@tonic-gate usage(sp, 1); 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate if ((called_thru_rpc == FALSE) && 165*0Sstevel@tonic-gate meta_is_mn_name(&sp, argv[0], ep)) { 166*0Sstevel@tonic-gate /* 167*0Sstevel@tonic-gate * If we are dealing with a MN set and we were not 168*0Sstevel@tonic-gate * called thru an rpc call, we are just to send this 169*0Sstevel@tonic-gate * command string to the master of the set and let it 170*0Sstevel@tonic-gate * deal with it. 171*0Sstevel@tonic-gate * Note that if sp is NULL, meta_is_mn_name() derives sp 172*0Sstevel@tonic-gate * from argv[0] which is the metadevice arg 173*0Sstevel@tonic-gate */ 174*0Sstevel@tonic-gate int result; 175*0Sstevel@tonic-gate int i; 176*0Sstevel@tonic-gate int newargc; 177*0Sstevel@tonic-gate char **newargv; 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate /* 180*0Sstevel@tonic-gate * For MN sets we start a dryrun version of this command 181*0Sstevel@tonic-gate * before sending out the real version. 182*0Sstevel@tonic-gate * Thus we need a new array for the arguments as the first 183*0Sstevel@tonic-gate * one will be -n to indicate the dryrun 184*0Sstevel@tonic-gate */ 185*0Sstevel@tonic-gate newargv = calloc(origargc+1, sizeof (char *)); 186*0Sstevel@tonic-gate newargv[0] = "metarename"; 187*0Sstevel@tonic-gate newargv[1] = "-n"; /* always do "-n" first */ 188*0Sstevel@tonic-gate newargc = 2; 189*0Sstevel@tonic-gate for (i = 1; i < origargc; i++, newargc++) 190*0Sstevel@tonic-gate newargv[newargc] = origargv[i]; 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate result = meta_mn_send_command(sp, newargc, newargv, 193*0Sstevel@tonic-gate MD_DISP_STDERR | MD_DRYRUN, NO_CONTEXT_STRING, ep); 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate /* If we found a problem don't do it for real */ 196*0Sstevel@tonic-gate if (result != 0) { 197*0Sstevel@tonic-gate md_exit(sp, result); 198*0Sstevel@tonic-gate } 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate /* 201*0Sstevel@tonic-gate * Do it for real now. Remove "-n" from the arguments and 202*0Sstevel@tonic-gate * MD_DRYRUN from the flags. If this fails, the master must 203*0Sstevel@tonic-gate * panic as the mddb may be inconsistent. 204*0Sstevel@tonic-gate */ 205*0Sstevel@tonic-gate newargv[1] = ""; /* this was "-n" before */ 206*0Sstevel@tonic-gate result = meta_mn_send_command(sp, newargc, newargv, 207*0Sstevel@tonic-gate MD_DISP_STDERR | MD_RETRY_BUSY | MD_PANIC_WHEN_INCONSISTENT, 208*0Sstevel@tonic-gate NO_CONTEXT_STRING, ep); 209*0Sstevel@tonic-gate free(newargv); 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate md_exit(sp, result); 212*0Sstevel@tonic-gate } 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate for (i = 0; i < 2; i++) { 215*0Sstevel@tonic-gate if (!is_metaname(argv[i])) { 216*0Sstevel@tonic-gate /* 217*0Sstevel@tonic-gate * one of the input devices is not a valid 218*0Sstevel@tonic-gate * metadevice name 219*0Sstevel@tonic-gate */ 220*0Sstevel@tonic-gate usage(sp, 1); 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate if (i == 1 && !xflag) { 223*0Sstevel@tonic-gate /* rename, create dest metadevice name */ 224*0Sstevel@tonic-gate if (meta_init_make_device(&sp, argv[i], ep) != 0) { 225*0Sstevel@tonic-gate mde_perror(ep, argv[i]); 226*0Sstevel@tonic-gate md_exit(sp, 1); 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate } 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate if (NULL == (mdnms[i] = metaname(&sp, argv[i], ep))) { 231*0Sstevel@tonic-gate mde_perror(ep, argv[i]); 232*0Sstevel@tonic-gate md_exit(sp, 1); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate /* 237*0Sstevel@tonic-gate * The FORCE option is only valid for a trans metadevice, clear it if 238*0Sstevel@tonic-gate * it is not trans 239*0Sstevel@tonic-gate */ 240*0Sstevel@tonic-gate if ((miscname = metagetmiscname(mdnms[0], ep)) == NULL) { 241*0Sstevel@tonic-gate mde_perror(ep, ""); 242*0Sstevel@tonic-gate md_exit(sp, 1); 243*0Sstevel@tonic-gate } 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate if (strcmp(miscname, MD_TRANS) != 0) { 246*0Sstevel@tonic-gate options &= ~MDCMD_FORCE; 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate if (meta_lock(sp, TRUE, ep)) { 250*0Sstevel@tonic-gate mde_perror(ep, ""); 251*0Sstevel@tonic-gate md_exit(sp, 1); 252*0Sstevel@tonic-gate } 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate if (meta_check_ownership(sp, ep) != 0) { 255*0Sstevel@tonic-gate mde_perror(ep, ""); 256*0Sstevel@tonic-gate md_exit(sp, 1); 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate if (xflag) { 260*0Sstevel@tonic-gate rc = meta_exchange(sp, mdnms[0], mdnms[1], options, ep); 261*0Sstevel@tonic-gate } else { 262*0Sstevel@tonic-gate rc = meta_rename(sp, mdnms[0], mdnms[1], options, ep); 263*0Sstevel@tonic-gate } 264*0Sstevel@tonic-gate out: 265*0Sstevel@tonic-gate if (rc != 0 || !mdisok(ep)) { 266*0Sstevel@tonic-gate mde_perror(ep, ""); 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate md_exit(sp, rc); 269*0Sstevel@tonic-gate /*NOTREACHED*/ 270*0Sstevel@tonic-gate return (rc); 271*0Sstevel@tonic-gate } 272