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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * rename or exchange metadevice identity 31 */ 32 33 #include <meta.h> 34 35 #include <sdssc.h> 36 37 /* 38 * print usage message 39 */ 40 static void 41 usage( 42 mdsetname_t *sp, 43 int eval 44 ) 45 { 46 (void) fprintf(stderr, gettext("\ 47 usage: %s [-s setname] [-f] [-x] metadevice1 metadevice2\n\ 48 %s -h\n\ 49 options:\n\ 50 -s operations are done on the set setname, rather than the local set\n\ 51 -f force exchange or rename\n\ 52 -x exchange the identities of metadevice1 and metadevice2\n\ 53 -h help: print this message\n"), myname, myname); 54 md_exit(sp, eval); 55 } 56 57 /* 58 * mainline. crack command line arguments. 59 */ 60 int 61 main( 62 int argc, 63 char *argv[] 64 ) 65 { 66 char *sname = NULL; 67 mdsetname_t *sp = NULL; 68 int xflag = 0; 69 mdcmdopts_t options = (MDCMD_PRINT | MDCMD_DOIT); 70 md_error_t status = mdnullerror; 71 md_error_t *ep = &status; 72 int rc = 0; 73 mdname_t *mdnms[2]; 74 int c, i; 75 int error; 76 bool_t called_thru_rpc = FALSE; 77 char *cp; 78 int origargc = argc; 79 char **origargv = argv; 80 char *miscname; 81 82 /* 83 * Get the locale set up before calling any other routines 84 * with messages to ouput. Just in case we're not in a build 85 * environment, make sure that TEXT_DOMAIN gets set to 86 * something. 87 */ 88 #if !defined(TEXT_DOMAIN) 89 #define TEXT_DOMAIN "SYS_TEST" 90 #endif 91 (void) setlocale(LC_ALL, ""); 92 (void) textdomain(TEXT_DOMAIN); 93 94 95 if ((cp = strstr(argv[0], ".rpc_call")) == NULL) { 96 if (sdssc_bind_library() == SDSSC_OKAY) 97 if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY, 98 &error) == SDSSC_PROXY_DONE) 99 exit(error); 100 } else { 101 *cp = '\0'; /* cut off ".rpc_call" */ 102 called_thru_rpc = TRUE; 103 } 104 105 /* initialize */ 106 if (md_init(argc, argv, 0, 1, ep) != 0 || 107 meta_check_root(ep) != 0) { 108 mde_perror(ep, ""); 109 md_exit(sp, 1); 110 } 111 112 /* parse args */ 113 optind = 1; 114 opterr = 1; 115 while ((c = getopt(argc, argv, "fns:xh?")) != -1) { 116 switch (c) { 117 case 'h': 118 usage(sp, 0); 119 break; 120 121 case 's': 122 sname = optarg; 123 break; 124 125 case 'x': 126 ++xflag; 127 break; 128 129 case 'f': 130 options |= MDCMD_FORCE; 131 break; 132 133 case 'n': 134 if (called_thru_rpc == TRUE) { 135 options &= ~MDCMD_DOIT; 136 } else { 137 usage(sp, 1); 138 } 139 break; 140 141 case '?': 142 if (optopt == '?') 143 usage(sp, 0); 144 /*FALLTHROUGH*/ 145 default: 146 usage(sp, 1); 147 break; 148 } 149 } 150 argc -= optind; 151 argv += optind; 152 153 if (sname != NULL) { 154 if ((sp = metasetname(sname, ep)) == NULL) { 155 mde_perror(ep, ""); 156 md_exit(sp, 1); 157 } 158 } 159 160 if (argc != 2) { 161 usage(sp, 1); 162 } 163 164 if ((called_thru_rpc == FALSE) && 165 meta_is_mn_name(&sp, argv[0], ep)) { 166 /* 167 * If we are dealing with a MN set and we were not 168 * called thru an rpc call, we are just to send this 169 * command string to the master of the set and let it 170 * deal with it. 171 * Note that if sp is NULL, meta_is_mn_name() derives sp 172 * from argv[0] which is the metadevice arg 173 */ 174 int result; 175 int i; 176 int newargc; 177 char **newargv; 178 179 /* 180 * For MN sets we start a dryrun version of this command 181 * before sending out the real version. 182 * Thus we need a new array for the arguments as the first 183 * one will be -n to indicate the dryrun 184 */ 185 newargv = calloc(origargc+1, sizeof (char *)); 186 newargv[0] = "metarename"; 187 newargv[1] = "-n"; /* always do "-n" first */ 188 newargc = 2; 189 for (i = 1; i < origargc; i++, newargc++) 190 newargv[newargc] = origargv[i]; 191 192 result = meta_mn_send_command(sp, newargc, newargv, 193 MD_DISP_STDERR | MD_DRYRUN, NO_CONTEXT_STRING, ep); 194 195 /* If we found a problem don't do it for real */ 196 if (result != 0) { 197 md_exit(sp, result); 198 } 199 200 /* 201 * Do it for real now. Remove "-n" from the arguments and 202 * MD_DRYRUN from the flags. If this fails, the master must 203 * panic as the mddb may be inconsistent. 204 */ 205 newargv[1] = ""; /* this was "-n" before */ 206 result = meta_mn_send_command(sp, newargc, newargv, 207 MD_DISP_STDERR | MD_RETRY_BUSY | MD_PANIC_WHEN_INCONSISTENT, 208 NO_CONTEXT_STRING, ep); 209 free(newargv); 210 211 md_exit(sp, result); 212 } 213 214 for (i = 0; i < 2; i++) { 215 if (!is_metaname(argv[i])) { 216 /* 217 * one of the input devices is not a valid 218 * metadevice name 219 */ 220 usage(sp, 1); 221 } 222 if (i == 1 && !xflag) { 223 /* rename, create dest metadevice name */ 224 if (meta_init_make_device(&sp, argv[i], ep) != 0) { 225 mde_perror(ep, argv[i]); 226 md_exit(sp, 1); 227 } 228 } 229 230 if (NULL == (mdnms[i] = metaname(&sp, argv[i], ep))) { 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