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