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