xref: /titanic_41/usr/src/cmd/lvm/util/metaparam.c (revision 70025d765b044c6d8594bb965a2247a61e991a99)
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  * change metadevice parameters
31  */
32 
33 #include <meta.h>
34 
35 #include <sdssc.h>
36 
37 /*
38  * check for "none"
39  */
40 static int
41 is_none(char *s)
42 {
43 	if ((strcoll(s, gettext("none")) == 0) ||
44 	    (strcoll(s, gettext("NONE")) == 0))
45 		return (1);
46 	return (0);
47 }
48 
49 /*
50  * print usage message
51  */
52 static void
53 usage(
54 	mdsetname_t	*sp,
55 	int		eval
56 )
57 {
58 	(void) fprintf(stderr, gettext("\
59 usage:	%s [-s setname] [options] concat/stripe | RAID\n\
60 	%s [-s setname] [options] mirror\n\
61 \n\
62 Concat/Stripe or RAID options:\n\
63 -h	hotspare_pool | \"none\"\n\
64 \n\
65 Mirror options:\n\
66 -r	roundrobin | geometric | first\n\
67 -w	parallel | serial\n\
68 -p	0-%d\n"), myname, myname, MD_PASS_MAX);
69 
70 	md_exit(sp, eval);
71 }
72 
73 /*
74  * do mirror parameters
75  */
76 static int
77 mirror_params(
78 	mdsetname_t	*sp,
79 	mdname_t	*mirnp,
80 	int		argc,
81 	char		*argv[],
82 	md_error_t	*ep
83 )
84 {
85 	mm_params_t	mmp;
86 	int		modified = 0;
87 	int		c;
88 
89 	/* we must have a set */
90 	assert(sp != NULL);
91 	assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev)));
92 
93 	/* initialize */
94 	(void) memset(&mmp, '\0', sizeof (mmp));
95 
96 	/* reset and parse args */
97 	optind = 1;
98 	opterr = 1;
99 	while ((c = getopt(argc, argv, "s:r:w:p:")) != -1) {
100 		switch (c) {
101 		case 's':
102 			break;
103 
104 		case 'r':
105 			if (name_to_rd_opt(mirnp->cname, optarg,
106 			    &mmp.read_option, ep) != 0) {
107 				return (-1);
108 			}
109 			mmp.change_read_option = 1;
110 			modified = 1;
111 			break;
112 
113 		case 'w':
114 			if (name_to_wr_opt(mirnp->cname, optarg,
115 			    &mmp.write_option, ep) != 0) {
116 				return (-1);
117 			}
118 			mmp.change_write_option = 1;
119 			modified = 1;
120 			break;
121 
122 		case 'p':
123 			if (name_to_pass_num(mirnp->cname, optarg,
124 			    &mmp.pass_num, ep) != 0) {
125 				return (-1);
126 			}
127 			mmp.change_pass_num = 1;
128 			modified = 1;
129 			break;
130 
131 		default:
132 			usage(sp, 1);
133 			/*NOTREACHED*/
134 			break;
135 		}
136 	}
137 
138 	argc -= optind;
139 	argv += optind;
140 	if (argc != 1)
141 		usage(sp, 1);
142 
143 	/* if just printing */
144 	if (! modified) {
145 		if (meta_mirror_get_params(sp, mirnp, &mmp, ep) != 0)
146 			return (-1);
147 		(void) printf(
148 		    gettext(
149 		    "%s: Mirror current parameters are:\n"),
150 		    mirnp->cname);
151 		if (meta_print_mirror_options(mmp.read_option,
152 		    mmp.write_option, mmp.pass_num, 0, NULL,
153 		    sp, stdout, ep) != 0) {
154 			return (-1);
155 		}
156 	}
157 
158 	/* otherwise, change parameters */
159 	else {
160 		if (meta_mirror_set_params(sp, mirnp, &mmp, ep) != 0)
161 			return (-1);
162 
163 		/* update md.cf */
164 		if (meta_update_md_cf(sp, ep) != 0)
165 			return (-1);
166 	}
167 
168 	/* return success */
169 	return (0);
170 }
171 
172 /*
173  * do stripe parameters
174  */
175 static int
176 stripe_params(
177 	mdsetname_t	*sp,
178 	mdname_t	*stripenp,
179 	int		argc,
180 	char		*argv[],
181 	md_error_t	*ep
182 )
183 {
184 	ms_params_t	msp;
185 	int		modified = 0;
186 	mdhspname_t	*hspnp;
187 	int		c;
188 
189 	/* we must have a set */
190 	assert(sp != NULL);
191 	assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev)));
192 
193 	/* initialize */
194 	(void) memset(&msp, '\0', sizeof (msp));
195 
196 	/* reset and parse args */
197 	optind = 1;
198 	opterr = 1;
199 	while ((c = getopt(argc, argv, "s:h:")) != -1) {
200 		switch (c) {
201 		case 's':
202 			break;
203 
204 		case 'h':
205 			if (is_none(optarg)) {
206 				msp.hsp_id = MD_HSP_NONE;
207 			} else if ((hspnp = metahspname(&sp, optarg,
208 			    ep)) == NULL) {
209 				return (-1);
210 			} else if (metachkhsp(sp, hspnp, ep) != 0) {
211 				return (-1);
212 			} else {
213 				msp.hsp_id = hspnp->hsp;
214 			}
215 			msp.change_hsp_id = 1;
216 			modified = 1;
217 			break;
218 
219 		default:
220 			usage(sp, 1);
221 			/*NOTREACHED*/
222 			break;
223 		}
224 	}
225 	argc -= optind;
226 	argv += optind;
227 	if (argc != 1)
228 		usage(sp, 1);
229 
230 	/* if just printing */
231 	if (! modified) {
232 		if (meta_stripe_get_params(sp, stripenp, &msp, ep) != 0)
233 			return (-1);
234 		if (msp.hsp_id == MD_HSP_NONE)
235 			hspnp = NULL;
236 		else if ((hspnp = metahsphspname(&sp, msp.hsp_id, ep)) == NULL)
237 			return (-1);
238 		(void) printf(gettext(
239 		    "%s: Concat/Stripe current parameters are:\n"),
240 		    stripenp->cname);
241 		if (meta_print_stripe_options(hspnp, NULL, stdout, ep) != 0)
242 			return (-1);
243 	}
244 
245 	/* otherwise, change parameters */
246 	else {
247 		if (meta_stripe_set_params(sp, stripenp, &msp, ep) != 0)
248 			return (-1);
249 
250 		/* update md.cf */
251 		if (meta_update_md_cf(sp, ep) != 0)
252 			return (-1);
253 	}
254 
255 	/* return success */
256 	return (0);
257 }
258 
259 /*
260  * do raid parameters
261  */
262 static int
263 raid_params(
264 	mdsetname_t	*sp,
265 	mdname_t	*raidnp,
266 	int		argc,
267 	char		*argv[],
268 	md_error_t	*ep
269 )
270 {
271 	mr_params_t	msp;
272 	int		modified = 0;
273 	mdhspname_t	*hspnp;
274 	int		c;
275 
276 	/* we must have a set */
277 	assert(sp != NULL);
278 	assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
279 
280 	/* initialize */
281 	(void) memset(&msp, '\0', sizeof (msp));
282 
283 	/* reset and parse args */
284 	optind = 1;
285 	opterr = 1;
286 	while ((c = getopt(argc, argv, "s:h:")) != -1) {
287 		switch (c) {
288 		case 's':
289 			break;
290 
291 		case 'h':
292 			if (is_none(optarg)) {
293 				msp.hsp_id = MD_HSP_NONE;
294 			} else if ((hspnp = metahspname(&sp, optarg,
295 			    ep)) == NULL) {
296 				return (-1);
297 			} else if (metachkhsp(sp, hspnp, ep) != 0) {
298 				return (-1);
299 			} else {
300 				msp.hsp_id = hspnp->hsp;
301 			}
302 			msp.change_hsp_id = 1;
303 			modified = 1;
304 			break;
305 
306 		default:
307 			usage(sp, 1);
308 			/*NOTREACHED*/
309 			break;
310 		}
311 	}
312 	argc -= optind;
313 	argv += optind;
314 	if (argc != 1)
315 		usage(sp, 1);
316 
317 	/* if just printing */
318 	if (! modified) {
319 		if (meta_raid_get_params(sp, raidnp, &msp, ep) != 0)
320 			return (-1);
321 		if (msp.hsp_id == MD_HSP_NONE)
322 			hspnp = NULL;
323 		else if ((hspnp = metahsphspname(&sp, msp.hsp_id, ep)) == NULL)
324 			return (-1);
325 		(void) printf(gettext(
326 		    "%s: RAID current parameters are:\n"),
327 		    raidnp->cname);
328 		if (meta_print_raid_options(hspnp, NULL, stdout, ep) != 0)
329 			return (-1);
330 	}
331 
332 	/* otherwise, change parameters */
333 	else {
334 		if (meta_raid_set_params(sp, raidnp, &msp, ep) != 0)
335 			return (-1);
336 
337 		/* update md.cf */
338 		if (meta_update_md_cf(sp, ep) != 0)
339 			return (-1);
340 	}
341 
342 	/* return success */
343 	return (0);
344 }
345 
346 /*
347  * parse args and doit
348  */
349 int
350 main(
351 	int		argc,
352 	char		**argv
353 )
354 {
355 	char		*sname = NULL;
356 	mdsetname_t	*sp = NULL;
357 	mdname_t	*np;
358 	char		*miscname;
359 	int		c;
360 	md_error_t	status = mdnullerror;
361 	md_error_t	*ep = &status;
362 	int		error;
363 	bool_t		called_thru_rpc = FALSE;
364 	char		*cp;
365 	char		*firstarg = NULL;
366 
367 
368 	/*
369 	 * Get the locale set up before calling any other routines
370 	 * with messages to ouput.  Just in case we're not in a build
371 	 * environment, make sure that TEXT_DOMAIN gets set to
372 	 * something.
373 	 */
374 #if !defined(TEXT_DOMAIN)
375 #define	TEXT_DOMAIN "SYS_TEST"
376 #endif
377 	(void) setlocale(LC_ALL, "");
378 	(void) textdomain(TEXT_DOMAIN);
379 
380 	if ((cp = strstr(argv[0], ".rpc_call")) == NULL) {
381 		if (sdssc_bind_library() == SDSSC_OKAY)
382 			if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY,
383 						&error) == SDSSC_PROXY_DONE)
384 				exit(error);
385 	} else {
386 		*cp = '\0'; /* cut off ".rpc_call" */
387 		called_thru_rpc = TRUE;
388 	}
389 
390 
391 	/* initialize */
392 	if (md_init(argc, argv, 0, 1, ep) != 0 ||
393 			meta_check_root(ep) != 0) {
394 		mde_perror(ep, "");
395 		md_exit(sp, 1);
396 	}
397 
398 	/* find set and metadevice first */
399 	optind = 1;
400 	opterr = 1;
401 	while ((c = getopt(argc, argv, "s:h:p:r:w:o:?")) != -1) {
402 		switch (c) {
403 		case 's':
404 			sname = optarg;
405 			break;
406 		case 'h':
407 			firstarg = optarg;
408 			break;
409 		case '?':
410 			if (optopt == '?')
411 				usage(sp, 0);
412 			break;
413 		}
414 	}
415 	if ((argc - optind) <= 0)
416 		usage(sp, 1);
417 
418 	if (sname != NULL) {
419 		if ((sp = metasetname(sname, ep)) == NULL) {
420 			mde_perror(ep, "");
421 			md_exit(sp, 1);
422 		}
423 	}
424 	if (firstarg == NULL)
425 		firstarg = argv[optind];
426 	if ((called_thru_rpc == FALSE) &&
427 	    meta_is_mn_name(&sp, firstarg, ep)) {
428 		/*
429 		 * If we are dealing with a MN set and we were not
430 		 * called thru an rpc call, we are just to send this
431 		 * command string to the master of the set and let it
432 		 * deal with it.
433 		 * Note that if sp is NULL, meta_is_mn_name() derives sp
434 		 * from firstarg which is the metadevice arg
435 		 * If this fails, the master must panic as the mddb may be
436 		 * inconsistent
437 		 */
438 		int result;
439 		result = meta_mn_send_command(sp, argc, argv, MD_DISP_STDERR |
440 		    MD_PANIC_WHEN_INCONSISTENT, NO_CONTEXT_STRING, ep);
441 		/* No further action required */
442 		md_exit(sp, result);
443 	}
444 
445 	if ((np = metaname(&sp, argv[optind], ep)) == NULL) {
446 		mde_perror(ep, "");
447 		md_exit(sp, 1);
448 	}
449 	assert(sp != NULL);
450 	/* grab set lock */
451 	if (meta_lock(sp, TRUE, ep)) {
452 		mde_perror(ep, "");
453 		md_exit(sp, 1);
454 	}
455 
456 	if (meta_check_ownership(sp, ep) != 0) {
457 		mde_perror(ep, "");
458 		md_exit(sp, 1);
459 	}
460 	if ((miscname = metagetmiscname(np, ep)) == NULL) {
461 		mde_perror(ep, "");
462 		md_exit(sp, 1);
463 	}
464 
465 	/* dispatch based on device type */
466 	if (strcmp(miscname, MD_STRIPE) == 0) {
467 		if (stripe_params(sp, np, argc, argv, ep) != 0) {
468 			mde_perror(ep, "");
469 			md_exit(sp, 1);
470 		}
471 	} else 	if (strcmp(miscname, MD_MIRROR) == 0) {
472 		if (mirror_params(sp, np, argc, argv, ep) != 0) {
473 			mde_perror(ep, "");
474 			md_exit(sp, 1);
475 		}
476 	} else 	if (strcmp(miscname, MD_RAID) == 0) {
477 		if (raid_params(sp, np, argc, argv, ep) != 0) {
478 			mde_perror(ep, "");
479 			md_exit(sp, 1);
480 		}
481 	} else {
482 		md_eprintf(gettext(
483 		    "%s: invalid metadevice type %s\n"),
484 		    np->cname, miscname);
485 		md_exit(sp, 1);
486 	}
487 
488 	/* return success */
489 	md_exit(sp, 0);
490 	/*NOTREACHED*/
491 	return (0);
492 }
493