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 * clear metadevices 31 */ 32 33 #include <meta.h> 34 #include <sdssc.h> 35 36 37 /* 38 * clear metadevice or hotspare pool 39 */ 40 static int 41 clear_name( 42 mdsetname_t **spp, 43 char *uname, 44 mdcmdopts_t options, 45 md_error_t *ep 46 ) 47 { 48 49 /* clear hotspare pool */ 50 if (is_hspname(uname)) { 51 mdhspname_t *hspnp; 52 53 /* get hotspare pool name */ 54 if ((hspnp = metahspname(spp, uname, ep)) == NULL) 55 return (-1); 56 assert(*spp != NULL); 57 58 /* grab set lock */ 59 if (meta_lock(*spp, TRUE, ep)) 60 return (-1); 61 62 /* check for ownership */ 63 if (meta_check_ownership(*spp, ep) != 0) 64 return (-1); 65 66 /* clear hotspare pool */ 67 return (meta_hsp_reset(*spp, hspnp, options, ep)); 68 } 69 70 /* clear metadevice */ 71 else { 72 mdname_t *np; 73 74 /* get metadevice name */ 75 if (((np = metaname(spp, uname, ep)) == NULL) || 76 (metachkmeta(np, ep) != 0)) { 77 return (-1); 78 } 79 assert(*spp != NULL); 80 81 /* grab set lock */ 82 if (meta_lock(*spp, TRUE, ep)) 83 return (-1); 84 85 /* check for ownership */ 86 if (meta_check_ownership(*spp, ep) != 0) 87 return (-1); 88 89 /* clear metadevice */ 90 return (meta_reset_by_name(*spp, np, options, ep)); 91 } 92 } 93 94 /* 95 * print usage message 96 */ 97 static void 98 usage( 99 mdsetname_t *sp, 100 int eval 101 ) 102 { 103 (void) fprintf(stderr, gettext("\ 104 usage: %s [-s setname] -a\n\ 105 %s [-s setname] [options] metadevice...\n\ 106 options:\n\ 107 -f force clear\n\ 108 -r recursive clear\n\ 109 -p clear all soft partitions on metadevice/component\n"), myname, myname); 110 md_exit(sp, eval); 111 } 112 113 /* 114 * mainline. crack command line arguments. 115 */ 116 int 117 main( 118 int argc, 119 char *argv[] 120 ) 121 { 122 char *sname = NULL; 123 mdsetname_t *sp = NULL; 124 int aflag = 0; 125 int pflag = 0; 126 mdcmdopts_t options = (MDCMD_PRINT|MDCMD_DOIT); 127 int c; 128 md_error_t status = mdnullerror; 129 md_error_t *ep = &status; 130 int eval = 1; 131 int error; 132 bool_t called_thru_rpc = FALSE; 133 char *cp; 134 int mnset = FALSE; 135 136 /* 137 * Get the locale set up before calling any other routines 138 * with messages to ouput. Just in case we're not in a build 139 * environment, make sure that TEXT_DOMAIN gets set to 140 * something. 141 */ 142 #if !defined(TEXT_DOMAIN) 143 #define TEXT_DOMAIN "SYS_TEST" 144 #endif 145 (void) setlocale(LC_ALL, ""); 146 (void) textdomain(TEXT_DOMAIN); 147 148 if ((cp = strstr(argv[0], ".rpc_call")) == NULL) { 149 if (sdssc_bind_library() == SDSSC_OKAY) 150 if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY, 151 &error) == SDSSC_PROXY_DONE) 152 exit(error); 153 } else { 154 *cp = '\0'; /* cut off ".rpc_call" */ 155 called_thru_rpc = TRUE; 156 } 157 158 159 /* initialize */ 160 if (md_init(argc, argv, 0, 1, ep) != 0 || 161 meta_check_root(ep) != 0) 162 goto errout; 163 164 /* parse args */ 165 optind = 1; 166 opterr = 1; 167 while ((c = getopt(argc, argv, "hs:afrp?")) != -1) { 168 switch (c) { 169 case 'h': 170 usage(sp, 0); 171 break; 172 173 case 's': 174 sname = optarg; 175 break; 176 177 case 'a': 178 ++aflag; 179 options |= MDCMD_FORCE; 180 break; 181 182 case 'f': 183 options |= MDCMD_FORCE; 184 break; 185 186 case 'r': 187 options |= MDCMD_RECURSE | MDCMD_FORCE; 188 break; 189 case 'p': 190 ++pflag; 191 break; 192 case '?': 193 if (optopt == '?') 194 usage(sp, 0); 195 /*FALLTHROUGH*/ 196 default: 197 usage(sp, 1); 198 break; 199 } 200 } 201 argc -= optind; 202 argv += optind; 203 204 if (sname != NULL && (sp = metasetname(sname, ep)) == NULL) { 205 goto errout; 206 } 207 208 if (called_thru_rpc) { 209 210 if (aflag) { 211 /* if -a, set name must have been specified by -s */ 212 if ((sp == NULL) || 213 (metaget_setdesc(sp, ep) == NULL)) 214 goto errout; 215 } else { 216 /* 217 * setname may be defined by setname in first arg 218 * if sp is NULL, meta_is_mn_name() derives sp from 219 * argv[0], eg from set/d10 220 */ 221 if (meta_is_mn_name(&sp, argv[0], ep)) { 222 if (metaget_setdesc(sp, ep) == NULL) 223 goto errout; 224 } else 225 goto errout; 226 } 227 228 /* Check if the device is open on all nodes */ 229 options |= MDCMD_MN_OPEN_CHECK; 230 } 231 232 if (aflag) { /* clear all devices */ 233 if (argc != 0) 234 usage(sp, 1); 235 236 if (sp == NULL) { 237 /* Get sp for local set */ 238 if ((sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) 239 goto errout; 240 } 241 242 /* 243 * If a MN set, we will generate a series of individual 244 * metaclear commands which will each grab the set lock. 245 * Therefore do not grab the set lock now. 246 */ 247 248 if (!meta_is_mn_set(sp, ep)) { 249 /* grab set lock */ 250 if (meta_lock(sp, TRUE, ep)) 251 goto errout; 252 253 /* check for ownership */ 254 if (meta_check_ownership(sp, ep) != 0) 255 goto errout; 256 } else { 257 mnset = TRUE; 258 } 259 260 /* reset all devices in set */ 261 if (meta_reset_all(sp, options, ep) != 0) { 262 if (!mnset) 263 mde_perror(ep, ""); 264 } else 265 eval = 0; 266 } else { 267 /* 268 * We are dealing with either a single or multiple names. 269 * The set for the command is either denoted by the -s option 270 * or the set of the first name. 271 */ 272 if (argc <= 0) 273 usage(sp, 1); 274 if (meta_is_mn_name(&sp, argv[0], ep)) 275 mnset = TRUE; 276 eval = 0; 277 278 for (; (argc > 0); --argc, ++argv) { 279 mdhspname_t *hspnp; 280 mdname_t *np; 281 char *cname; 282 283 /* 284 * If we are dealing with a MN set and we were not 285 * called thru an rpc call, we are just to send this 286 * command string to the master of the set and let it 287 * deal with it. 288 */ 289 if (!called_thru_rpc && mnset) { 290 if (pflag) { 291 /* 292 * If -p, set cname to the device 293 * argument. 294 */ 295 cname = argv[0]; 296 } else { 297 /* 298 * For hotspares and metadevices, set 299 * cname to the full name, 300 * setname/hspxxx or setname/dxxx 301 */ 302 if (is_hspname(argv[0])) { 303 /* get hotspare pool name */ 304 if ((hspnp = metahspname(&sp, 305 argv[0], ep)) == NULL) { 306 mde_perror(ep, ""); 307 eval = 1; 308 continue; 309 } 310 cname = hspnp->hspname; 311 } else { 312 /* get metadevice name */ 313 if (((np = metaname(&sp, 314 argv[0], ep)) == NULL) || 315 (metachkmeta(np, ep) 316 != 0)) { 317 mde_perror(ep, ""); 318 eval = 1; 319 continue; 320 } 321 cname = np->cname; 322 } 323 } 324 if (meta_mn_send_metaclear_command(sp, 325 cname, options, pflag, ep) != 0) { 326 eval = 1; 327 continue; 328 } 329 } else { 330 if (pflag) { 331 /* 332 * clear all soft partitions on named 333 * devices 334 */ 335 if (meta_sp_reset_component(sp, argv[0], 336 options, ep) != 0) { 337 mde_perror(ep, ""); 338 eval = 1; 339 continue; 340 } 341 } else { 342 /* clear named devices */ 343 if (clear_name(&sp, argv[0], 344 options, ep) != 0) { 345 mde_perror(ep, ""); 346 eval = 1; 347 continue; 348 } 349 } 350 } 351 } 352 } 353 /* update md.cf */ 354 if (sp == NULL) { 355 /* Get sp for local set */ 356 if ((sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) 357 goto errout; 358 } 359 360 if (meta_update_md_cf(sp, ep) != 0) { 361 mde_perror(ep, ""); 362 eval = 1; 363 } 364 md_exit(sp, eval); 365 366 errout: 367 mde_perror(ep, ""); 368 md_exit(sp, eval); 369 /*NOTREACHED*/ 370 return (eval); 371 } 372