xref: /titanic_41/usr/src/cmd/lvm/util/metaclear.c (revision de5d74c22760a6d2cefd94d0e7f0fd87214fb71f)
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