7712 mandoc -Tlint does always exit with error code 0
[unleashed.git] / usr / src / cmd / lvm / util / metattach.c
blob8bd9551053481b904c69559fd0424aaafe5dad7a
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * attach submirrors
32 #include <meta.h>
34 #include <sdssc.h>
37 * print usage message
39 static void
40 usage(
41 mdsetname_t *sp,
42 int eval
45 (void) fprintf(stderr, gettext("\
46 usage: %s [-s setname] mirror [metadevice]\n\
47 %s [-s setname] [-i interlace] concat/stripe component...\n\
48 %s [-s setname] RAID component...\n\
49 %s [-s setname] [-A alignment] softpart size|all\n"),
50 myname, myname, myname, myname);
51 md_exit(sp, eval);
55 * attach more space to a soft partition
57 static int
58 sp_attach(
59 mdsetname_t **spp,
60 mdname_t *spnp,
61 int argc,
62 char *argv[],
63 mdcmdopts_t options,
64 md_error_t *ep
67 int c;
68 sp_ext_offset_t alignment = 0;
70 /* reset and parse args */
71 optind = 1;
72 opterr = 1;
73 while ((c = getopt(argc, argv, "ns:A:")) != -1) {
74 switch (c) {
75 case 'n':
76 case 's':
77 break;
78 case 'A':
79 if (meta_sp_parsesize(optarg, &alignment) == -1) {
80 usage(*spp, 1);
81 /* NOTREACHED */
83 break;
84 default:
85 usage(*spp, 1);
86 /* NOTREACHED */
87 break;
90 argc -= optind + 1;
91 argv += optind + 1;
93 if (argc != 1)
94 usage(*spp, 1);
96 if (meta_sp_attach(*spp, spnp, argv[0], options, alignment, ep) != 0) {
97 return (-1);
100 /* update md.cf file */
101 if (meta_update_md_cf(*spp, ep) != 0)
102 return (-1);
104 return (0);
107 * attach components to stripe
109 static int
110 stripe_attach(
111 mdsetname_t **spp,
112 mdname_t *stripenp,
113 int argc,
114 char *argv[],
115 mdcmdopts_t options,
116 md_error_t *ep
119 diskaddr_t interlace = 0;
120 int c;
121 mdnamelist_t *compnlp = NULL;
122 mdnamelist_t *p;
123 mdname_t *currootnp;
124 md_stripe_t *stripep;
125 md_row_t *rp;
126 md_comp_t *cp;
129 /* reset and parse args */
130 optind = 1;
131 opterr = 1;
132 while ((c = getopt(argc, argv, "s:ani:")) != -1) {
133 switch (c) {
134 case 'n':
135 case 's':
136 break;
138 case 'a':
139 break; /* obsolete */
141 case 'i':
142 if (parse_interlace(stripenp->cname, optarg,
143 &interlace, ep) != 0) {
144 return (-1);
146 if (meta_stripe_check_interlace(interlace,
147 stripenp->cname, ep))
148 return (-1);
149 break;
151 default:
152 usage(*spp, 1);
153 /*NOTREACHED*/
154 break;
158 argc -= optind + 1;
159 argv += optind + 1;
161 if (argc <= 0)
162 usage(*spp, 1);
164 /* get list of components */
165 if (metanamelist(spp, &compnlp, argc, argv,
166 UNKNOWN, ep) < 0)
167 return (-1);
168 assert(compnlp != NULL);
169 for (p = compnlp; (p != NULL); p = p->next) {
170 mdname_t *compnp = p->namep;
172 /* see if we are a soft partition */
173 if (meta_sp_issp(*spp, compnp, ep) != 0) {
174 /* nope, check component */
175 if (metachkcomp(compnp, ep) != 0)
176 return (-1);
180 /* get root device */
181 if ((currootnp = meta_get_current_root_dev(*spp, ep)) != NULL) {
183 * Root is either a stripe or a slice
184 * If root device is the 1st component of the stripe
185 * Then fail as root cannot be expanded
187 if ((stripep = meta_get_stripe(*spp, stripenp, ep)) == NULL)
188 return (-1);
190 rp = &stripep->rows.rows_val[0];
191 cp = &rp->comps.comps_val[0];
192 if (metachkcomp(cp->compnamep, ep) == 0) {
193 /* Component is a disk */
194 if (strcmp(currootnp->cname,
195 cp->compnamep->cname) == 0) {
196 md_eprintf(gettext(
197 "%s: volume mounted as root cannot be "
198 "expanded\n"), stripenp->cname);
199 md_exit(*spp, 1);
204 /* attach components */
205 if (meta_stripe_attach(*spp, stripenp, compnlp, interlace, options,
206 ep) != 0) {
207 return (-1);
210 /* update md.cf file */
211 if (meta_update_md_cf(*spp, ep) != 0)
212 return (-1);
214 /* return success */
215 return (0);
219 * attach components to raid
221 static int
222 raid_attach(
223 mdsetname_t **spp,
224 mdname_t *raidnp,
225 int argc,
226 char *argv[],
227 mdcmdopts_t options,
228 md_error_t *ep
231 int c;
232 mdnamelist_t *compnlp = NULL;
233 mdnamelist_t *p;
235 /* reset and parse args */
236 optind = 1;
237 opterr = 1;
238 while ((c = getopt(argc, argv, "s:ai:")) != -1) {
239 switch (c) {
240 case 'n':
241 case 's':
242 break;
244 case 'a':
245 break; /* obsolete */
247 default:
248 usage(*spp, 1);
249 /*NOTREACHED*/
250 break;
253 argc -= optind + 1;
254 argv += optind + 1;
255 if (argc <= 0)
256 usage(*spp, 1);
258 /* get list of components */
259 if (metanamelist(spp, &compnlp, argc, argv,
260 UNKNOWN, ep) < 0)
261 return (-1);
262 assert(compnlp != NULL);
263 for (p = compnlp; (p != NULL); p = p->next) {
264 mdname_t *compnp = p->namep;
266 /* check for soft partitions */
267 if (meta_sp_issp(*spp, compnp, ep) != 0) {
268 /* check disk */
269 if (metachkcomp(compnp, ep) != 0)
270 return (-1);
274 /* attach components */
275 if (meta_raid_attach(*spp, raidnp, compnlp, options, ep) != 0)
276 return (-1);
278 /* update md.cf file */
279 if (meta_update_md_cf(*spp, ep) != 0)
280 return (-1);
282 /* return success */
283 return (0);
287 * attach submirror to mirror
289 static int
290 mirror_attach(
291 mdsetname_t **spp,
292 mdname_t *mirnp,
293 int argc,
294 char *argv[],
295 mdcmdopts_t options,
296 md_error_t *ep
299 int c;
300 mdname_t *submirnp;
302 /* reset and parse args */
303 optind = 1;
304 opterr = 1;
305 while ((c = getopt(argc, argv, "ns:")) != -1) {
306 switch (c) {
307 case 'n':
308 case 's':
309 break;
311 default:
312 usage(*spp, 1);
313 /*NOTREACHED*/
314 break;
317 argc -= optind + 1;
318 argv += optind + 1;
320 /* get submirror */
321 if (argc == 1) {
322 if (((submirnp = metaname(spp, argv[0], META_DEVICE,
323 ep)) == NULL) ||
324 (metachkmeta(submirnp, ep) != 0)) {
325 return (-1);
327 } else if (argc == 0) {
328 submirnp = NULL;
329 } else {
330 usage(*spp, 1);
333 /* attach submirror */
334 if (meta_mirror_attach(*spp, mirnp, submirnp, options, ep) != 0)
335 return (-1);
337 /* update md.cf file */
338 if (meta_update_md_cf(*spp, ep) != 0)
339 return (-1);
341 /* return success */
342 return (0);
346 * attach devices
349 main(
350 int argc,
351 char *argv[]
354 char *sname = NULL;
355 mdsetname_t *sp = NULL;
356 mdcmdopts_t options = (MDCMD_PRINT|MDCMD_DOIT);
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;
367 * Get the locale set up before calling any other routines
368 * with messages to ouput. Just in case we're not in a build
369 * environment, make sure that TEXT_DOMAIN gets set to
370 * something.
372 #if !defined(TEXT_DOMAIN)
373 #define TEXT_DOMAIN "SYS_TEST"
374 #endif
375 (void) setlocale(LC_ALL, "");
376 (void) textdomain(TEXT_DOMAIN);
378 /* initialize */
379 if ((cp = strstr(argv[0], ".rpc_call")) == NULL) {
380 if (sdssc_bind_library() == SDSSC_OKAY)
381 if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY,
382 &error) == SDSSC_PROXY_DONE)
383 exit(error);
384 } else {
385 *cp = '\0'; /* cut off ".rpc_call" */
386 called_thru_rpc = TRUE;
389 if (md_init(argc, argv, 0, 1, ep) != 0 ||
390 meta_check_root(ep) != 0) {
391 mde_perror(ep, "");
392 md_exit(sp, 1);
395 /* find set and metadevice first */
396 optind = 1;
397 opterr = 1;
398 while ((c = getopt(argc, argv, "hns:A:ai:?")) != -1) {
399 switch (c) {
400 case 'h':
401 usage(sp, 0);
402 break;
404 case 'n':
405 if (called_thru_rpc == TRUE) {
406 options &= ~MDCMD_DOIT;
407 } else {
408 usage(sp, 1);
410 break;
412 case 's':
413 sname = optarg;
414 break;
416 case '?':
417 if (optopt == '?')
418 usage(sp, 0);
419 break;
422 if ((argc - optind) <= 0)
423 usage(sp, 1);
425 if (sname != NULL) {
426 if ((sp = metasetname(sname, ep)) == NULL) {
427 mde_perror(ep, "");
428 md_exit(sp, 1);
432 if (((np = metaname(&sp, argv[optind], META_DEVICE, ep)) == NULL) ||
433 (metachkmeta(np, ep) != 0)) {
434 mde_perror(ep, "");
435 md_exit(sp, 1);
437 assert(sp != NULL);
439 if ((called_thru_rpc == FALSE) &&
440 meta_is_mn_name(&sp, argv[optind], ep)) {
442 * If we are dealing with a MN set and we were not
443 * called thru an rpc call, we are just to send this
444 * command string to the master of the set and let it
445 * deal with it.
446 * Note that if sp is NULL, meta_is_mn_name() derives sp
447 * from argv[optind] which is the metadevice arg
449 int i;
450 int newargc;
451 int result;
452 char **newargv;
454 if ((miscname = metagetmiscname(np, ep)) == NULL) {
455 mde_perror(ep, "");
456 md_exit(sp, 1);
459 newargv = calloc(argc+1, sizeof (char *));
460 newargv[0] = "metattach";
461 newargv[1] = "-n"; /* always do "-n" first */
462 newargc = 2;
463 for (i = 1; i < argc; i++, newargc++)
464 newargv[newargc] = argv[i];
466 result = meta_mn_send_command(sp, newargc, newargv,
467 MD_DISP_STDERR | MD_DRYRUN, NO_CONTEXT_STRING, ep);
469 /* If we found a problem don't do it for real */
470 if (result != 0) {
471 md_exit(sp, result);
475 * Do it for real now. Remove "-n" from the arguments and
476 * MD_DRYRUN from the flags. If we fail now, the master must
477 * panic as the mddbs may be inconsistent.
479 newargv[1] = ""; /* this was "-n" before */
480 result = meta_mn_send_command(sp, newargc, newargv,
481 MD_DISP_STDERR | MD_RETRY_BUSY | MD_PANIC_WHEN_INCONSISTENT,
482 NO_CONTEXT_STRING, ep);
484 free(newargv);
487 * If the metattach command succeeds, for a mirror, send a
488 * resync starting message for the metadevice
490 if ((result == 0) && (strcmp(miscname, MD_MIRROR) == 0))
491 if ((result = meta_mn_send_resync_starting(np, ep))
492 != 0)
493 mde_perror(ep, "Unable to start resync");
494 md_exit(sp, result);
497 if (meta_lock(sp, TRUE, ep)) {
498 mde_perror(ep, "");
499 md_exit(sp, 1);
502 if (meta_check_ownership(sp, ep) != 0) {
503 mde_perror(ep, "");
504 md_exit(sp, 1);
506 if ((miscname = metagetmiscname(np, ep)) == NULL) {
507 mde_perror(ep, "");
508 md_exit(sp, 1);
511 /* dispatch based on device type */
512 if (strcmp(miscname, MD_STRIPE) == 0) {
513 if (stripe_attach(&sp, np, argc, argv, options, ep) != 0) {
514 mde_perror(ep, "");
515 md_exit(sp, 1);
517 } else if (strcmp(miscname, MD_RAID) == 0) {
518 if (raid_attach(&sp, np, argc, argv, options, ep) != 0) {
519 mde_perror(ep, "");
520 md_exit(sp, 1);
522 } else if (strcmp(miscname, MD_MIRROR) == 0) {
523 if (mirror_attach(&sp, np, argc, argv, options, ep) != 0) {
524 mde_perror(ep, "");
525 md_exit(sp, 1);
527 } else if (strcmp(miscname, MD_TRANS) == 0) {
528 md_eprintf(gettext(MD_EOF_TRANS_MSG));
529 md_exit(sp, 1);
530 } else if (strcmp(miscname, MD_SP) == 0) {
531 if (sp_attach(&sp, np, argc, argv, options, ep) != 0) {
532 mde_perror(ep, "");
533 md_exit(sp, 1);
535 } else {
536 md_eprintf(gettext(
537 "%s: invalid metadevice type %s\n"),
538 np->cname, miscname);
539 md_exit(sp, 1);
542 /* return success */
543 md_exit(sp, 0);
544 /*NOTREACHED*/
545 return (0);