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 * detach submirrors 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] mirror submirror\n\ 48 %s [-s setname] [-f] trans\n"), 49 myname, myname); 50 md_exit(sp, eval); 51 } 52 53 /* 54 * detach submirror from mirror 55 */ 56 static int 57 mirror_detach( 58 mdsetname_t **spp, 59 mdname_t *mirnp, 60 int argc, 61 char *argv[], 62 mdcmdopts_t options, 63 md_error_t *ep 64 ) 65 { 66 mdname_t *submirnp; 67 int c; 68 69 /* reset and parse args */ 70 optind = 1; 71 opterr = 1; 72 while ((c = getopt(argc, argv, "s:f")) != -1) { 73 switch (c) { 74 case 's': 75 break; 76 77 case 'f': 78 options |= MDCMD_FORCE; 79 break; 80 81 default: 82 usage(*spp, 1); 83 /*NOTREACHED*/ 84 break; 85 } 86 } 87 argc -= optind; 88 argv += optind; 89 if (argc != 2) 90 usage(*spp, 1); 91 92 /* get submirror */ 93 if ((submirnp = metaname(spp, argv[1], ep)) == NULL) 94 return (-1); 95 96 /* detach submirror */ 97 if (meta_mirror_detach(*spp, mirnp, submirnp, options, ep) != 0) 98 return (-1); 99 100 /* update md.cf */ 101 if (meta_update_md_cf(*spp, ep) != 0) 102 return (-1); 103 104 /* return success */ 105 return (0); 106 } 107 108 /* 109 * detach log from trans 110 */ 111 static int 112 trans_detach( 113 mdsetname_t *sp, 114 mdname_t *transnp, 115 int argc, 116 char *argv[], 117 mdcmdopts_t options, 118 md_error_t *ep 119 ) 120 { 121 int delayed; 122 int c; 123 124 /* reset and parse args */ 125 optind = 1; 126 opterr = 1; 127 while ((c = getopt(argc, argv, "s:f")) != -1) { 128 switch (c) { 129 case 's': 130 break; 131 132 case 'f': 133 options |= MDCMD_FORCE; 134 break; 135 136 default: 137 usage(sp, 1); 138 /*NOTREACHED*/ 139 break; 140 } 141 } 142 argc -= optind; 143 argv += optind; 144 if (argc != 1) 145 usage(sp, 1); 146 147 /* detach log */ 148 if (meta_trans_detach(sp, transnp, options, &delayed, ep) != 0) 149 return (-1); 150 151 /* update md.cf */ 152 if (meta_update_md_cf(sp, ep) != 0) 153 return (-1); 154 155 /* return success */ 156 return (0); 157 } 158 159 /* 160 * parse args and doit 161 */ 162 int 163 main( 164 int argc, 165 char *argv[] 166 ) 167 { 168 char *sname = NULL; 169 mdsetname_t *sp = NULL; 170 mdcmdopts_t options = (MDCMD_PRINT); 171 mdname_t *np; 172 char *miscname; 173 int c; 174 md_error_t status = mdnullerror; 175 md_error_t *ep = &status; 176 int error; 177 bool_t called_thru_rpc = FALSE; 178 char *cp; 179 180 181 /* 182 * Get the locale set up before calling any other routines 183 * with messages to ouput. Just in case we're not in a build 184 * environment, make sure that TEXT_DOMAIN gets set to 185 * something. 186 */ 187 #if !defined(TEXT_DOMAIN) 188 #define TEXT_DOMAIN "SYS_TEST" 189 #endif 190 (void) setlocale(LC_ALL, ""); 191 (void) textdomain(TEXT_DOMAIN); 192 193 if ((cp = strstr(argv[0], ".rpc_call")) == NULL) { 194 if (sdssc_bind_library() == SDSSC_OKAY) 195 if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY, 196 &error) == SDSSC_PROXY_DONE) 197 exit(error); 198 } else { 199 *cp = '\0'; /* cut off ".rpc_call" */ 200 called_thru_rpc = TRUE; 201 } 202 203 204 /* initialize */ 205 if (md_init(argc, argv, 0, 1, ep) != 0 || 206 meta_check_root(ep) != 0) { 207 mde_perror(ep, ""); 208 md_exit(sp, 1); 209 } 210 211 /* find set and metadevice first */ 212 optind = 1; 213 opterr = 1; 214 while ((c = getopt(argc, argv, "hs:f?")) != -1) { 215 switch (c) { 216 case 'h': 217 usage(sp, 0); 218 break; 219 220 case 's': 221 sname = optarg; 222 break; 223 224 case '?': 225 if (optopt == '?') 226 usage(sp, 0); 227 break; 228 } 229 } 230 if ((argc - optind) <= 0) 231 usage(sp, 1); 232 233 if (sname != NULL) { 234 if ((sp = metasetname(sname, ep)) == NULL) { 235 mde_perror(ep, ""); 236 md_exit(sp, 1); 237 } 238 } 239 240 /* Get metadevice name */ 241 if (((np = metaname(&sp, argv[optind], ep)) == NULL) || 242 (metachkmeta(np, ep) != 0)) { 243 mde_perror(ep, ""); 244 md_exit(sp, 1); 245 } 246 assert(sp != NULL); 247 248 if ((called_thru_rpc == FALSE) && 249 meta_is_mn_name(&sp, argv[optind], ep)) { 250 /* 251 * If we are dealing with a MN set and we were not 252 * called thru an rpc call, we are just to send this 253 * command string to the master of the set and let it 254 * deal with it. 255 * Note that if sp is NULL, meta_is_mn_name() derives sp 256 * from argv[optind] which is the metadevice arg 257 * If this fails, the master must panic as the mddb may be 258 * inconsistent 259 */ 260 int result; 261 result = meta_mn_send_command(sp, argc, argv, MD_DISP_STDERR | 262 MD_PANIC_WHEN_INCONSISTENT, NO_CONTEXT_STRING, ep); 263 /* 264 * The error message has been already been displayed 265 * just exit 266 */ 267 md_exit(sp, result); 268 } 269 270 /* grab set lock */ 271 if (meta_lock(sp, TRUE, ep)) { 272 mde_perror(ep, ""); 273 md_exit(sp, 1); 274 } 275 276 /* check ownership */ 277 if (meta_check_ownership(sp, ep) != 0) { 278 mde_perror(ep, ""); 279 md_exit(sp, 1); 280 } 281 if ((miscname = metagetmiscname(np, ep)) == NULL) { 282 mde_perror(ep, ""); 283 md_exit(sp, 1); 284 } 285 286 /* dispatch based on device type */ 287 if (strcmp(miscname, MD_MIRROR) == 0) { 288 if (mirror_detach(&sp, np, argc, argv, options, ep) != 0) { 289 mde_perror(ep, ""); 290 md_exit(sp, 1); 291 } 292 } else if (strcmp(miscname, MD_TRANS) == 0) { 293 if (trans_detach(sp, np, argc, argv, options, ep) != 0) { 294 mde_perror(ep, ""); 295 md_exit(sp, 1); 296 } 297 } else { 298 md_eprintf(gettext( 299 "%s: invalid metadevice type %s\n"), 300 np->cname, miscname); 301 md_exit(sp, 1); 302 } 303 304 /* return success */ 305 md_exit(sp, 0); 306 /*NOTREACHED*/ 307 return (0); 308 } 309