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
clear_name(mdsetname_t ** spp,char * uname,mdcmdopts_t options,md_error_t * ep)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
usage(mdsetname_t * sp,int eval)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
main(int argc,char * argv[])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