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