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]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
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
);
55 * attach more space to a soft partition
68 sp_ext_offset_t alignment
= 0;
70 /* reset and parse args */
73 while ((c
= getopt(argc
, argv
, "ns:A:")) != -1) {
79 if (meta_sp_parsesize(optarg
, &alignment
) == -1) {
96 if (meta_sp_attach(*spp
, spnp
, argv
[0], options
, alignment
, ep
) != 0) {
100 /* update md.cf file */
101 if (meta_update_md_cf(*spp
, ep
) != 0)
107 * attach components to stripe
119 diskaddr_t interlace
= 0;
121 mdnamelist_t
*compnlp
= NULL
;
124 md_stripe_t
*stripep
;
129 /* reset and parse args */
132 while ((c
= getopt(argc
, argv
, "s:ani:")) != -1) {
139 break; /* obsolete */
142 if (parse_interlace(stripenp
->cname
, optarg
,
143 &interlace
, ep
) != 0) {
146 if (meta_stripe_check_interlace(interlace
,
147 stripenp
->cname
, ep
))
164 /* get list of components */
165 if (metanamelist(spp
, &compnlp
, argc
, argv
,
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)
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
)
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) {
197 "%s: volume mounted as root cannot be "
198 "expanded\n"), stripenp
->cname
);
204 /* attach components */
205 if (meta_stripe_attach(*spp
, stripenp
, compnlp
, interlace
, options
,
210 /* update md.cf file */
211 if (meta_update_md_cf(*spp
, ep
) != 0)
219 * attach components to raid
232 mdnamelist_t
*compnlp
= NULL
;
235 /* reset and parse args */
238 while ((c
= getopt(argc
, argv
, "s:ai:")) != -1) {
245 break; /* obsolete */
258 /* get list of components */
259 if (metanamelist(spp
, &compnlp
, argc
, argv
,
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) {
269 if (metachkcomp(compnp
, ep
) != 0)
274 /* attach components */
275 if (meta_raid_attach(*spp
, raidnp
, compnlp
, options
, ep
) != 0)
278 /* update md.cf file */
279 if (meta_update_md_cf(*spp
, ep
) != 0)
287 * attach submirror to mirror
302 /* reset and parse args */
305 while ((c
= getopt(argc
, argv
, "ns:")) != -1) {
322 if (((submirnp
= metaname(spp
, argv
[0], META_DEVICE
,
324 (metachkmeta(submirnp
, ep
) != 0)) {
327 } else if (argc
== 0) {
333 /* attach submirror */
334 if (meta_mirror_attach(*spp
, mirnp
, submirnp
, options
, ep
) != 0)
337 /* update md.cf file */
338 if (meta_update_md_cf(*spp
, ep
) != 0)
355 mdsetname_t
*sp
= NULL
;
356 mdcmdopts_t options
= (MDCMD_PRINT
|MDCMD_DOIT
);
360 md_error_t status
= mdnullerror
;
361 md_error_t
*ep
= &status
;
363 bool_t called_thru_rpc
= FALSE
;
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
372 #if !defined(TEXT_DOMAIN)
373 #define TEXT_DOMAIN "SYS_TEST"
375 (void) setlocale(LC_ALL
, "");
376 (void) textdomain(TEXT_DOMAIN
);
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
)
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) {
395 /* find set and metadevice first */
398 while ((c
= getopt(argc
, argv
, "hns:A:ai:?")) != -1) {
405 if (called_thru_rpc
== TRUE
) {
406 options
&= ~MDCMD_DOIT
;
422 if ((argc
- optind
) <= 0)
426 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
432 if (((np
= metaname(&sp
, argv
[optind
], META_DEVICE
, ep
)) == NULL
) ||
433 (metachkmeta(np
, ep
) != 0)) {
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
446 * Note that if sp is NULL, meta_is_mn_name() derives sp
447 * from argv[optind] which is the metadevice arg
454 if ((miscname
= metagetmiscname(np
, ep
)) == NULL
) {
459 newargv
= calloc(argc
+1, sizeof (char *));
460 newargv
[0] = "metattach";
461 newargv
[1] = "-n"; /* always do "-n" first */
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 */
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
);
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
))
493 mde_perror(ep
, "Unable to start resync");
497 if (meta_lock(sp
, TRUE
, ep
)) {
502 if (meta_check_ownership(sp
, ep
) != 0) {
506 if ((miscname
= metagetmiscname(np
, ep
)) == NULL
) {
511 /* dispatch based on device type */
512 if (strcmp(miscname
, MD_STRIPE
) == 0) {
513 if (stripe_attach(&sp
, np
, argc
, argv
, options
, ep
) != 0) {
517 } else if (strcmp(miscname
, MD_RAID
) == 0) {
518 if (raid_attach(&sp
, np
, argc
, argv
, options
, ep
) != 0) {
522 } else if (strcmp(miscname
, MD_MIRROR
) == 0) {
523 if (mirror_attach(&sp
, np
, argc
, argv
, options
, ep
) != 0) {
527 } else if (strcmp(miscname
, MD_TRANS
) == 0) {
528 md_eprintf(gettext(MD_EOF_TRANS_MSG
));
530 } else if (strcmp(miscname
, MD_SP
) == 0) {
531 if (sp_attach(&sp
, np
, argc
, argv
, options
, ep
) != 0) {
537 "%s: invalid metadevice type %s\n"),
538 np
->cname
, miscname
);