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 * clear metadevices 30 */ 31 32 #include <meta.h> 33 #include <sdssc.h> 34 35 36 /* 37 * clear metadevice or hotspare pool 38 */ 39 static int 40 clear_name( 41 mdsetname_t **spp, 42 char *uname, 43 mdcmdopts_t options, 44 md_error_t *ep 45 ) 46 { 47 48 /* clear hotspare pool */ 49 if (is_existing_hsp(*spp, uname)) { 50 mdhspname_t *hspnp; 51 52 /* get hotspare pool name */ 53 if ((hspnp = metahspname(spp, uname, ep)) == NULL) 54 return (-1); 55 assert(*spp != NULL); 56 57 /* grab set lock */ 58 if (meta_lock(*spp, TRUE, ep)) 59 return (-1); 60 61 /* check for ownership */ 62 if (meta_check_ownership(*spp, ep) != 0) 63 return (-1); 64 65 /* clear hotspare pool */ 66 return (meta_hsp_reset(*spp, hspnp, options, ep)); 67 } 68 69 /* clear metadevice */ 70 else { 71 mdname_t *np; 72 73 /* check for ownership */ 74 if (meta_check_ownership(*spp, ep) != 0) 75 return (-1); 76 77 /* get metadevice name */ 78 if (((np = metaname(spp, uname, META_DEVICE, ep)) == NULL) || 79 (metachkmeta(np, ep) != 0)) { 80 return (-1); 81 } 82 assert(*spp != NULL); 83 84 /* grab set lock */ 85 if (meta_lock(*spp, TRUE, ep)) 86 return (-1); 87 88 /* clear metadevice */ 89 return (meta_reset_by_name(*spp, np, options, ep)); 90 } 91 } 92 93 /* 94 * print usage message 95 */ 96 static void 97 usage( 98 mdsetname_t *sp, 99 int eval 100 ) 101 { 102 (void) fprintf(stderr, gettext("\ 103 usage: %s [-s setname] -a\n\ 104 %s [-s setname] [options] metadevice...\n\ 105 options:\n\ 106 -f force clear\n\ 107 -r recursive clear\n\ 108 -p clear all soft partitions on metadevice/component\n"), myname, myname); 109 md_exit(sp, eval); 110 } 111 112 /* 113 * mainline. crack command line arguments. 114 */ 115 int 116 main( 117 int argc, 118 char *argv[] 119 ) 120 { 121 char *sname = MD_LOCAL_NAME; 122 mdsetname_t *sp = NULL; 123 int aflag = 0; 124 int pflag = 0; 125 int set_flag = 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 set_flag++; 176 break; 177 178 case 'a': 179 ++aflag; 180 options |= MDCMD_FORCE; 181 break; 182 183 case 'f': 184 options |= MDCMD_FORCE; 185 break; 186 187 case 'r': 188 options |= MDCMD_RECURSE | MDCMD_FORCE; 189 break; 190 case 'p': 191 ++pflag; 192 break; 193 case '?': 194 if (optopt == '?') 195 usage(sp, 0); 196 /*FALLTHROUGH*/ 197 default: 198 usage(sp, 1); 199 break; 200 } 201 } 202 argc -= optind; 203 argv += optind; 204 205 /* with mn sets if -a, set name must have been specified by -s */ 206 if (called_thru_rpc && aflag && !set_flag) { 207 md_eprintf(gettext( 208 "-a parameter requires the use of -s in multi-node sets")); 209 md_exit(sp, 1); 210 } 211 212 /* get set context */ 213 if ((sp = metasetname(sname, ep)) == NULL) { 214 mde_perror(ep, ""); 215 md_exit(sp, 1); 216 } 217 218 if (called_thru_rpc) { 219 /* Check if the device is open on all nodes */ 220 options |= MDCMD_MN_OPEN_CHECK; 221 } 222 223 if (aflag) { /* clear all devices */ 224 if (argc != 0) 225 usage(sp, 1); 226 227 /* 228 * If a MN set, we will generate a series of individual 229 * metaclear commands which will each grab the set lock. 230 * Therefore do not grab the set lock now. 231 */ 232 233 if (!meta_is_mn_set(sp, ep)) { 234 /* grab set lock */ 235 if (meta_lock(sp, TRUE, ep)) 236 goto errout; 237 238 /* check for ownership */ 239 if (meta_check_ownership(sp, ep) != 0) 240 goto errout; 241 } else { 242 mnset = TRUE; 243 } 244 245 /* reset all devices in set */ 246 if (meta_reset_all(sp, options, ep) != 0) { 247 if (!mnset) 248 mde_perror(ep, ""); 249 } else 250 eval = 0; 251 } else { 252 /* 253 * We are dealing with either a single or multiple names. 254 * The set for the command is either denoted by the -s option 255 * or the set of the first name. 256 */ 257 if (argc <= 0) 258 usage(sp, 1); 259 260 if (meta_is_mn_name(&sp, argv[0], ep)) 261 mnset = TRUE; 262 eval = 0; 263 264 for (; (argc > 0); --argc, ++argv) { 265 char *cname; 266 267 /* 268 * If we are dealing with a MN set and we were not 269 * called thru an rpc call, we are just to send this 270 * command string to the master of the set and let it 271 * deal with it. 272 */ 273 if (!called_thru_rpc && mnset) { 274 /* get the canonical name */ 275 if (pflag) { 276 /* 277 * If -p, set cname to the device 278 * argument. 279 */ 280 cname = Strdup(argv[0]); 281 } else { 282 /* 283 * For hotspares and metadevices, set 284 * cname to the full name, 285 * setname/hspxxx or setname/dxxx 286 */ 287 cname = meta_name_getname(&sp, 288 argv[0], META_DEVICE, ep); 289 if (cname == NULL) { 290 mde_perror(ep, ""); 291 eval = 1; 292 continue; 293 } 294 } 295 if (meta_mn_send_metaclear_command(sp, 296 cname, options, pflag, ep) != 0) { 297 eval = 1; 298 } 299 Free(cname); 300 } else { 301 if (pflag) { 302 /* 303 * clear all soft partitions on named 304 * devices 305 */ 306 if (meta_sp_reset_component(sp, argv[0], 307 options, ep) != 0) { 308 mde_perror(ep, ""); 309 eval = 1; 310 continue; 311 } 312 } else { 313 /* 314 * get the canonical name and 315 * setup sp if it has been 316 * specified as part of the 317 * metadevice/hsp name param 318 */ 319 cname = meta_name_getname(&sp, 320 argv[0], META_DEVICE, ep); 321 if (cname == NULL) { 322 mde_perror(ep, ""); 323 eval = 1; 324 continue; 325 } 326 327 /* clear named devices */ 328 if (clear_name(&sp, cname, 329 options, ep) != 0) { 330 mde_perror(ep, ""); 331 eval = 1; 332 Free(cname); 333 continue; 334 } 335 Free(cname); 336 } 337 } 338 } 339 } 340 /* update md.cf */ 341 if (meta_update_md_cf(sp, ep) != 0) { 342 mde_perror(ep, ""); 343 eval = 1; 344 } 345 md_exit(sp, eval); 346 347 errout: 348 mde_perror(ep, ""); 349 md_exit(sp, eval); 350 /*NOTREACHED*/ 351 return (eval); 352 } 353