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