10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*1623Stw21770 * Common Development and Distribution License (the "License").
6*1623Stw21770 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*1623Stw21770 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate * patch system files for root on metadevice
300Sstevel@tonic-gate */
310Sstevel@tonic-gate
320Sstevel@tonic-gate #include <meta.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <sdssc.h>
350Sstevel@tonic-gate
360Sstevel@tonic-gate #define METAROOT_OK 0
370Sstevel@tonic-gate #define METAROOT_ERR -1
380Sstevel@tonic-gate #define METAROOT_NOTFOUND -2
390Sstevel@tonic-gate
400Sstevel@tonic-gate struct def_map {
410Sstevel@tonic-gate char **dm_fname; /* Location of file name */
420Sstevel@tonic-gate char *dm_default; /* Default name */
430Sstevel@tonic-gate };
440Sstevel@tonic-gate
450Sstevel@tonic-gate /*
460Sstevel@tonic-gate * options
470Sstevel@tonic-gate */
480Sstevel@tonic-gate static char *cname = NULL; /* take default */
490Sstevel@tonic-gate static char *sname = NULL; /* take default */
500Sstevel@tonic-gate static char *vname = NULL; /* take default */
510Sstevel@tonic-gate static char *dbname = NULL; /* take default bootlist location */
520Sstevel@tonic-gate static int doit = 1;
530Sstevel@tonic-gate static int verbose = 0;
540Sstevel@tonic-gate
550Sstevel@tonic-gate /*
560Sstevel@tonic-gate * Map of default system file names to the place where they are stored.
570Sstevel@tonic-gate * This is used if the -R option is specified. Note that the members of
580Sstevel@tonic-gate * the map point to the cname, sname, vname and dbname global variables
590Sstevel@tonic-gate * above. These global variables are used in the call to
600Sstevel@tonic-gate * meta_patch_rootdev() in main().
610Sstevel@tonic-gate */
620Sstevel@tonic-gate static struct def_map default_names[] = {
630Sstevel@tonic-gate &cname, META_DBCONF,
640Sstevel@tonic-gate &sname, "/etc/system",
650Sstevel@tonic-gate &vname, "/etc/vfstab",
660Sstevel@tonic-gate &dbname, "/kernel/drv/md.conf"
670Sstevel@tonic-gate };
680Sstevel@tonic-gate
690Sstevel@tonic-gate static int validate_stripe_root();
700Sstevel@tonic-gate
710Sstevel@tonic-gate /*
720Sstevel@tonic-gate * print usage message, md_exit
730Sstevel@tonic-gate */
740Sstevel@tonic-gate static void
usage(mdsetname_t * sp,int eval)750Sstevel@tonic-gate usage(
760Sstevel@tonic-gate mdsetname_t *sp,
770Sstevel@tonic-gate int eval
780Sstevel@tonic-gate )
790Sstevel@tonic-gate {
800Sstevel@tonic-gate (void) fprintf(stderr, gettext("\
810Sstevel@tonic-gate usage:\t%s [-n] [-k system-name] [-m md.conf-name] [-v vfstab-name] \\\n\
820Sstevel@tonic-gate \t\t[-c mddb.cf-name] device\n\
830Sstevel@tonic-gate \t%s [-n] [-R root-path] device\n"),
840Sstevel@tonic-gate myname, myname);
850Sstevel@tonic-gate md_exit(sp, eval);
860Sstevel@tonic-gate }
870Sstevel@tonic-gate
880Sstevel@tonic-gate static void
free_mem()890Sstevel@tonic-gate free_mem()
900Sstevel@tonic-gate {
910Sstevel@tonic-gate int i;
920Sstevel@tonic-gate struct def_map *map;
930Sstevel@tonic-gate
940Sstevel@tonic-gate for (i = 0, map = default_names;
950Sstevel@tonic-gate i < sizeof (default_names) / sizeof (struct def_map);
960Sstevel@tonic-gate i++, map++) {
970Sstevel@tonic-gate if (*map->dm_fname != NULL) {
980Sstevel@tonic-gate free((void *) *map->dm_fname);
990Sstevel@tonic-gate *map->dm_fname = NULL;
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate }
1020Sstevel@tonic-gate }
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate /*
1050Sstevel@tonic-gate * Check if mirror, mirnp, is a valid root filesystem, ie all
1060Sstevel@tonic-gate * submirrors must be single disk stripe, and that the slice, slicenp,
1070Sstevel@tonic-gate * if not NULL, is a component of one of the submirrors.
1080Sstevel@tonic-gate * The arg metaroot is TRUE if mirnp is the current root filesystem.
1090Sstevel@tonic-gate * Returns:
1100Sstevel@tonic-gate * METAROOT_OK if mirror is valid and slicenp is a component
1110Sstevel@tonic-gate * METAROOT_NOTFOUND if mirror valid but slicenp not a component
1120Sstevel@tonic-gate * METAROOT_ERR if mirror not a valid root
1130Sstevel@tonic-gate */
1140Sstevel@tonic-gate static int
validate_mirror_root(mdsetname_t * sp,mdname_t * mirnp,mdname_t * slicenp,int metaroot,md_error_t * ep)1150Sstevel@tonic-gate validate_mirror_root(
1160Sstevel@tonic-gate mdsetname_t *sp,
1170Sstevel@tonic-gate mdname_t *mirnp,
1180Sstevel@tonic-gate mdname_t *slicenp,
1190Sstevel@tonic-gate int metaroot,
1200Sstevel@tonic-gate md_error_t *ep
1210Sstevel@tonic-gate )
1220Sstevel@tonic-gate {
1230Sstevel@tonic-gate int smi;
1240Sstevel@tonic-gate md_mirror_t *mirrorp;
1250Sstevel@tonic-gate char *miscname;
1260Sstevel@tonic-gate int found = 0;
1270Sstevel@tonic-gate int rval;
1280Sstevel@tonic-gate int err = 0;
1290Sstevel@tonic-gate
1300Sstevel@tonic-gate if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL) {
1310Sstevel@tonic-gate mde_perror(ep, "");
1320Sstevel@tonic-gate return (METAROOT_ERR);
1330Sstevel@tonic-gate }
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate for (smi = 0; (smi < NMIRROR); ++smi) {
1360Sstevel@tonic-gate /* Check all submirrors */
1370Sstevel@tonic-gate md_submirror_t *mdsp = &mirrorp->submirrors[smi];
1380Sstevel@tonic-gate mdname_t *submirnamep = mdsp->submirnamep;
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate /* skip unused submirrors */
1410Sstevel@tonic-gate if (submirnamep == NULL) {
1420Sstevel@tonic-gate assert(mdsp->state == SMS_UNUSED);
1430Sstevel@tonic-gate continue;
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate if ((miscname = metagetmiscname(submirnamep, ep)) == NULL) {
1460Sstevel@tonic-gate return (mdmderror(ep, MDE_UNKNOWN_TYPE,
1470Sstevel@tonic-gate meta_getminor(submirnamep->dev),
1480Sstevel@tonic-gate submirnamep->cname));
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate if (strcmp(miscname, MD_STRIPE) != 0) {
1510Sstevel@tonic-gate md_eprintf(gettext("Submirror is not a stripe\n"));
1520Sstevel@tonic-gate return (METAROOT_ERR);
1530Sstevel@tonic-gate }
1540Sstevel@tonic-gate rval = validate_stripe_root(sp, submirnamep, slicenp,
1550Sstevel@tonic-gate metaroot, ep);
1560Sstevel@tonic-gate switch (rval) {
1570Sstevel@tonic-gate case METAROOT_OK:
1580Sstevel@tonic-gate found = 1;
1590Sstevel@tonic-gate break;
1600Sstevel@tonic-gate case METAROOT_ERR:
1610Sstevel@tonic-gate err++;
1620Sstevel@tonic-gate break;
1630Sstevel@tonic-gate case METAROOT_NOTFOUND:
1640Sstevel@tonic-gate default:
1650Sstevel@tonic-gate break;
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate if (err > 0)
1690Sstevel@tonic-gate return (METAROOT_ERR);
1700Sstevel@tonic-gate if (!found)
1710Sstevel@tonic-gate return (METAROOT_NOTFOUND);
1720Sstevel@tonic-gate return (METAROOT_OK);
1730Sstevel@tonic-gate }
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate /*
1760Sstevel@tonic-gate * Check if stripe, strnp, is a valid root filesystem, ie must
1770Sstevel@tonic-gate * be single disk stripe, and the the slice, slicenp, if not NULL, must
1780Sstevel@tonic-gate * be a component of this stripe.
1790Sstevel@tonic-gate * The arg metaroot is TRUE if strnp is the current root filesystem.
1800Sstevel@tonic-gate * Returns:
1810Sstevel@tonic-gate * METAROOT_OK if stripe is valid and slicenp is a component
1820Sstevel@tonic-gate * METAROOT_NOTFOUND if stripe valid but slicenp not a component
1830Sstevel@tonic-gate * METAROOT_ERR if stripe not a valid root
1840Sstevel@tonic-gate */
1850Sstevel@tonic-gate static int
validate_stripe_root(mdsetname_t * sp,mdname_t * strnp,mdname_t * slicenp,int metaroot,md_error_t * ep)1860Sstevel@tonic-gate validate_stripe_root(
1870Sstevel@tonic-gate mdsetname_t *sp,
1880Sstevel@tonic-gate mdname_t *strnp,
1890Sstevel@tonic-gate mdname_t *slicenp,
1900Sstevel@tonic-gate int metaroot,
1910Sstevel@tonic-gate md_error_t *ep
1920Sstevel@tonic-gate )
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate md_stripe_t *stripep;
1950Sstevel@tonic-gate md_row_t *rp;
1960Sstevel@tonic-gate md_comp_t *cp;
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate if ((stripep = meta_get_stripe(sp, strnp, ep)) == NULL) {
1990Sstevel@tonic-gate mde_perror(ep, "");
2000Sstevel@tonic-gate return (METAROOT_ERR);
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate if (stripep->rows.rows_len != 1) {
2030Sstevel@tonic-gate md_eprintf(gettext(
2040Sstevel@tonic-gate "Concat %s has more than 1 slice\n"), strnp->cname);
2050Sstevel@tonic-gate return (METAROOT_ERR);
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate rp = &stripep->rows.rows_val[0];
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate if (rp->comps.comps_len != 1) {
2100Sstevel@tonic-gate md_eprintf(gettext(
2110Sstevel@tonic-gate "Stripe %s has more than 1 slice\n"), strnp->cname);
2120Sstevel@tonic-gate return (METAROOT_ERR);
2130Sstevel@tonic-gate }
2140Sstevel@tonic-gate cp = &rp->comps.comps_val[0];
2150Sstevel@tonic-gate if (!metaismeta(cp->compnamep)) {
2160Sstevel@tonic-gate if (slicenp == NULL)
2170Sstevel@tonic-gate return (METAROOT_OK);
2180Sstevel@tonic-gate if (strcmp(slicenp->cname, cp->compnamep->cname) == 0)
2190Sstevel@tonic-gate return (METAROOT_OK);
2200Sstevel@tonic-gate if (!metaroot) {
2210Sstevel@tonic-gate md_eprintf(gettext(
2220Sstevel@tonic-gate "Root %s is not a component of metadevice %s\n"),
2230Sstevel@tonic-gate slicenp->cname, strnp->cname);
2240Sstevel@tonic-gate }
2250Sstevel@tonic-gate return (METAROOT_NOTFOUND);
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate md_eprintf(gettext(
2280Sstevel@tonic-gate "Component %s is not a stripe\n"), cp->compnamep->cname);
2290Sstevel@tonic-gate return (METAROOT_ERR);
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate /*
2330Sstevel@tonic-gate * Check if the device devnp is valid. It must be a component of the
2340Sstevel@tonic-gate * metadevice that contains the root filesystem
2350Sstevel@tonic-gate */
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate static int
validate_root_device(mdsetname_t * sp,mdname_t * devnp,md_error_t * ep)2380Sstevel@tonic-gate validate_root_device(
2390Sstevel@tonic-gate mdsetname_t *sp,
2400Sstevel@tonic-gate mdname_t *devnp,
2410Sstevel@tonic-gate md_error_t *ep
2420Sstevel@tonic-gate )
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate mdname_t *rootnp;
2450Sstevel@tonic-gate char *curroot;
2460Sstevel@tonic-gate char *miscname;
2470Sstevel@tonic-gate int rval;
2480Sstevel@tonic-gate
2490Sstevel@tonic-gate if ((curroot = meta_get_current_root(ep)) == NULL) {
2500Sstevel@tonic-gate mde_perror(ep, "");
2510Sstevel@tonic-gate return (METAROOT_ERR);
2520Sstevel@tonic-gate }
253*1623Stw21770 if ((rootnp = metaname(&sp, curroot, UNKNOWN, ep)) == NULL) {
2540Sstevel@tonic-gate mde_perror(ep, "");
2550Sstevel@tonic-gate return (METAROOT_ERR);
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate if (metaismeta(rootnp)) {
2590Sstevel@tonic-gate /* get type */
2600Sstevel@tonic-gate if ((miscname = metagetmiscname(rootnp, ep)) == NULL) {
2610Sstevel@tonic-gate mde_perror(ep, "");
2620Sstevel@tonic-gate return (METAROOT_ERR);
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate if (strcmp(miscname, MD_MIRROR) == 0) {
2650Sstevel@tonic-gate if ((rval = validate_mirror_root(sp, rootnp,
2660Sstevel@tonic-gate devnp, 1, ep)) == METAROOT_OK)
2670Sstevel@tonic-gate return (METAROOT_OK);
2680Sstevel@tonic-gate if (rval == METAROOT_NOTFOUND) {
2690Sstevel@tonic-gate md_eprintf(gettext(
2700Sstevel@tonic-gate "Slice %s is not a component of root %s\n"),
2710Sstevel@tonic-gate devnp->cname, rootnp->cname);
2720Sstevel@tonic-gate }
2730Sstevel@tonic-gate return (METAROOT_ERR);
2740Sstevel@tonic-gate } else if (strcmp(miscname, MD_STRIPE) == 0) {
2750Sstevel@tonic-gate if ((rval = validate_stripe_root(sp, rootnp,
2760Sstevel@tonic-gate devnp, 1, ep)) == METAROOT_OK)
2770Sstevel@tonic-gate return (METAROOT_OK);
2780Sstevel@tonic-gate if (rval == METAROOT_NOTFOUND) {
2790Sstevel@tonic-gate md_eprintf(gettext(
2800Sstevel@tonic-gate "Slice %s is not a component of root %s\n"),
2810Sstevel@tonic-gate devnp->cname, rootnp->cname);
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate return (METAROOT_ERR);
2840Sstevel@tonic-gate } else {
2850Sstevel@tonic-gate md_eprintf(gettext(
2860Sstevel@tonic-gate "Root metadevice, %s, is not a Slice or Mirror\n"),
2870Sstevel@tonic-gate rootnp->cname);
2880Sstevel@tonic-gate return (METAROOT_ERR);
2890Sstevel@tonic-gate }
2900Sstevel@tonic-gate } else {
2910Sstevel@tonic-gate md_eprintf(gettext(
2920Sstevel@tonic-gate "Current Root %s is not a metadevice\n"), rootnp->cname);
2930Sstevel@tonic-gate return (METAROOT_ERR);
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate /*
2980Sstevel@tonic-gate * What we're going to do:
2990Sstevel@tonic-gate *
3000Sstevel@tonic-gate * 1) Check if the device is a metadevice or not.
3010Sstevel@tonic-gate *
3020Sstevel@tonic-gate * 2) If a metadevice, and it is valid, ie a stripe or a mirror containing
3030Sstevel@tonic-gate * a single slice, add "forceload:{drv,misc}/<modname>" of
3040Sstevel@tonic-gate * underlying drivers for the meta-root and the metadevice
3050Sstevel@tonic-gate * database to system. Otherwise, remove forceloads from system if the
3060Sstevel@tonic-gate * slice is a component of the current root metadevice.
3070Sstevel@tonic-gate *
3080Sstevel@tonic-gate * 3) Add "rootdev:/devices/..." to system.
3090Sstevel@tonic-gate *
3100Sstevel@tonic-gate * 4) Replace / mount in vfstab.
3110Sstevel@tonic-gate *
3120Sstevel@tonic-gate * 5) Repatch database locations, just to be safe.
3130Sstevel@tonic-gate */
3140Sstevel@tonic-gate int
main(int argc,char * argv[])3150Sstevel@tonic-gate main(
3160Sstevel@tonic-gate int argc,
3170Sstevel@tonic-gate char *argv[]
3180Sstevel@tonic-gate )
3190Sstevel@tonic-gate {
3200Sstevel@tonic-gate int i;
3210Sstevel@tonic-gate mdsetname_t *sp = NULL;
3220Sstevel@tonic-gate mdname_t *rootnp;
3230Sstevel@tonic-gate int c;
3240Sstevel@tonic-gate int ckmv_flag = 0; /* non-zero if -c, -k, -m or -v */
3250Sstevel@tonic-gate md_error_t status = mdnullerror;
3260Sstevel@tonic-gate md_error_t *ep = &status;
3270Sstevel@tonic-gate char *miscname;
3280Sstevel@tonic-gate char *curroot;
3290Sstevel@tonic-gate mdname_t *currootnp;
3300Sstevel@tonic-gate mdname_t *currootdevnp;
3310Sstevel@tonic-gate char *root_path = NULL;
3320Sstevel@tonic-gate struct def_map *map;
3330Sstevel@tonic-gate size_t root_path_size;
3340Sstevel@tonic-gate size_t path_buf_size;
3350Sstevel@tonic-gate int error;
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate /*
3380Sstevel@tonic-gate * Get the locale set up before calling any other routines
3390Sstevel@tonic-gate * with messages to ouput. Just in case we're not in a build
3400Sstevel@tonic-gate * environment, make sure that TEXT_DOMAIN gets set to
3410Sstevel@tonic-gate * something.
3420Sstevel@tonic-gate */
3430Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
3440Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
3450Sstevel@tonic-gate #endif
3460Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
3470Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate if ((sdssc_bind_library() == SDSSC_OKAY) &&
3500Sstevel@tonic-gate (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY,
3510Sstevel@tonic-gate &error) == SDSSC_PROXY_DONE))
3520Sstevel@tonic-gate exit(error);
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate /* initialize */
3550Sstevel@tonic-gate if (md_init(argc, argv, 0, 1, ep) != 0 ||
3560Sstevel@tonic-gate meta_check_root(ep) != 0) {
3570Sstevel@tonic-gate mde_perror(ep, "");
3580Sstevel@tonic-gate md_exit(sp, 1);
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate /* parse options */
3620Sstevel@tonic-gate optind = 1;
3630Sstevel@tonic-gate opterr = 1;
3640Sstevel@tonic-gate while ((c = getopt(argc, argv, "hnk:m:v:c:R:?")) != -1) {
3650Sstevel@tonic-gate switch (c) {
3660Sstevel@tonic-gate case 'h':
3670Sstevel@tonic-gate usage(sp, 0);
3680Sstevel@tonic-gate break;
3690Sstevel@tonic-gate case 'm':
3700Sstevel@tonic-gate dbname = optarg;
3710Sstevel@tonic-gate ckmv_flag = 1;
3720Sstevel@tonic-gate break;
3730Sstevel@tonic-gate case 'n':
3740Sstevel@tonic-gate doit = 0;
3750Sstevel@tonic-gate verbose = 1;
3760Sstevel@tonic-gate break;
3770Sstevel@tonic-gate case 'k':
3780Sstevel@tonic-gate sname = optarg;
3790Sstevel@tonic-gate ckmv_flag = 1;
3800Sstevel@tonic-gate break;
3810Sstevel@tonic-gate case 'v':
3820Sstevel@tonic-gate vname = optarg;
3830Sstevel@tonic-gate ckmv_flag = 1;
3840Sstevel@tonic-gate break;
3850Sstevel@tonic-gate case 'c':
3860Sstevel@tonic-gate cname = optarg;
3870Sstevel@tonic-gate ckmv_flag = 1;
3880Sstevel@tonic-gate break;
3890Sstevel@tonic-gate case 'R':
3900Sstevel@tonic-gate root_path = optarg;
3910Sstevel@tonic-gate break;
3920Sstevel@tonic-gate case '?':
3930Sstevel@tonic-gate if (optopt == '?')
3940Sstevel@tonic-gate usage(sp, 0);
3950Sstevel@tonic-gate /*FALLTHROUGH*/
3960Sstevel@tonic-gate default:
3970Sstevel@tonic-gate usage(sp, 1);
3980Sstevel@tonic-gate break;
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate argc -= optind;
4020Sstevel@tonic-gate argv += optind;
4030Sstevel@tonic-gate if (argc != 1)
4040Sstevel@tonic-gate usage(sp, 1);
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate /* Can't use -R with any of -c, -k, -m or -v */
4070Sstevel@tonic-gate if ((ckmv_flag != 0) && (root_path != NULL)) {
4080Sstevel@tonic-gate md_eprintf(
4090Sstevel@tonic-gate gettext("-R invalid with any of -c, -k, -m or -v\n"));
4100Sstevel@tonic-gate usage(sp, 1);
4110Sstevel@tonic-gate }
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate /* get device name */
414*1623Stw21770 if ((rootnp = metaname(&sp, argv[0], UNKNOWN, ep)) == NULL) {
4150Sstevel@tonic-gate mde_perror(ep, "");
4160Sstevel@tonic-gate md_exit(sp, 1);
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate if ((curroot = meta_get_current_root(ep)) == NULL) {
4190Sstevel@tonic-gate mde_perror(ep, "");
4200Sstevel@tonic-gate md_exit(sp, 1);
4210Sstevel@tonic-gate }
4220Sstevel@tonic-gate /*
4230Sstevel@tonic-gate * Get device name of current root metadevice. If root is net
4240Sstevel@tonic-gate * mounted as happens if this command is part of the install
4250Sstevel@tonic-gate * process, currootnp will be set to NULL.
4260Sstevel@tonic-gate */
427*1623Stw21770 currootnp = metaname(&sp, curroot, UNKNOWN, ep);
4280Sstevel@tonic-gate /*
4290Sstevel@tonic-gate * If the argument is the name of the current root filesystem, then
4300Sstevel@tonic-gate * the command is allowed, otherwise check that the argument is
4310Sstevel@tonic-gate * valid.
4320Sstevel@tonic-gate */
4330Sstevel@tonic-gate if ((currootnp == NULL) ||
4340Sstevel@tonic-gate (strcmp(currootnp->cname, rootnp->cname) != 0)) {
4350Sstevel@tonic-gate if (metaismeta(rootnp)) {
4360Sstevel@tonic-gate /*
4370Sstevel@tonic-gate * Validate that the metadevice is based on a
4380Sstevel@tonic-gate * single slice. If none of the -k, -m, -v, -c or
4390Sstevel@tonic-gate * -R options are specified, then the default
4400Sstevel@tonic-gate * system files are being modified and hence the
4410Sstevel@tonic-gate * current root slice must be a component of the
4420Sstevel@tonic-gate * metadevice. If any of the previously mentioned
4430Sstevel@tonic-gate * options are used don't check that the current
4440Sstevel@tonic-gate * root is a component.
4450Sstevel@tonic-gate */
4460Sstevel@tonic-gate if ((ckmv_flag == 0) && (root_path == NULL)) {
4470Sstevel@tonic-gate /* Get device name of current root slice */
4480Sstevel@tonic-gate if ((currootdevnp =
4490Sstevel@tonic-gate meta_get_current_root_dev(sp, ep))
4500Sstevel@tonic-gate == NULL) {
4510Sstevel@tonic-gate mde_perror(ep, "");
4520Sstevel@tonic-gate md_exit(sp, 1);
4530Sstevel@tonic-gate }
4540Sstevel@tonic-gate } else currootdevnp = NULL;
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate if ((miscname = metagetmiscname(rootnp, ep)) == NULL) {
4570Sstevel@tonic-gate mde_perror(ep, "");
4580Sstevel@tonic-gate md_exit(sp, 1);
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate /* Check that metadevice is a mirror or a stripe */
4610Sstevel@tonic-gate if (strcmp(miscname, MD_MIRROR) == 0) {
4620Sstevel@tonic-gate if (validate_mirror_root(sp, rootnp,
4630Sstevel@tonic-gate currootdevnp, 0, ep) != METAROOT_OK) {
4640Sstevel@tonic-gate md_exit(sp, 1);
4650Sstevel@tonic-gate }
4660Sstevel@tonic-gate } else if (strcmp(miscname, MD_STRIPE) == 0) {
4670Sstevel@tonic-gate if (validate_stripe_root(sp, rootnp,
4680Sstevel@tonic-gate currootdevnp, 0, ep) != METAROOT_OK) {
4690Sstevel@tonic-gate md_exit(sp, 1);
4700Sstevel@tonic-gate }
4710Sstevel@tonic-gate } else {
4720Sstevel@tonic-gate md_eprintf(gettext(
4730Sstevel@tonic-gate "%s is not a mirror or stripe\n"),
4740Sstevel@tonic-gate rootnp->cname);
4750Sstevel@tonic-gate md_exit(sp, 1);
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate } else {
4780Sstevel@tonic-gate /*
4790Sstevel@tonic-gate * Check that the root device is a component of the
4800Sstevel@tonic-gate * current root filesystem only if the default system
4810Sstevel@tonic-gate * files are being modified
4820Sstevel@tonic-gate */
4830Sstevel@tonic-gate if ((ckmv_flag == 0) && (root_path == NULL)) {
4840Sstevel@tonic-gate if (validate_root_device(sp, rootnp, ep) != 0) {
4850Sstevel@tonic-gate md_exit(sp, 1);
4860Sstevel@tonic-gate }
4870Sstevel@tonic-gate }
4880Sstevel@tonic-gate }
4890Sstevel@tonic-gate }
4900Sstevel@tonic-gate
4910Sstevel@tonic-gate if (meta_lock(sp, TRUE, ep)) {
4920Sstevel@tonic-gate mde_perror(ep, "");
4930Sstevel@tonic-gate md_exit(sp, 1);
4940Sstevel@tonic-gate }
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate /*
4970Sstevel@tonic-gate * If -R is specified, use the default system file names relative
4980Sstevel@tonic-gate * to the new root location.
4990Sstevel@tonic-gate */
5000Sstevel@tonic-gate if (root_path != NULL) {
5010Sstevel@tonic-gate root_path_size = strlen(root_path);
5020Sstevel@tonic-gate for (i = 0, map = default_names;
5030Sstevel@tonic-gate i < sizeof (default_names) / sizeof (struct def_map);
5040Sstevel@tonic-gate i++, map++) {
5050Sstevel@tonic-gate /* Add 1 for null terminator */
5060Sstevel@tonic-gate path_buf_size = root_path_size +
5070Sstevel@tonic-gate strlen(map->dm_default) + 1;
5080Sstevel@tonic-gate *map->dm_fname = malloc(path_buf_size);
5090Sstevel@tonic-gate if (*map->dm_fname == NULL) {
5100Sstevel@tonic-gate md_eprintf(gettext("Cannot allocate memory \
5110Sstevel@tonic-gate for system file path relocation\n"));
5120Sstevel@tonic-gate md_exit(sp, 1);
5130Sstevel@tonic-gate }
5140Sstevel@tonic-gate (void) snprintf(*map->dm_fname, path_buf_size,
5150Sstevel@tonic-gate "%s%s", root_path, map->dm_default);
5160Sstevel@tonic-gate }
5170Sstevel@tonic-gate }
5180Sstevel@tonic-gate
5190Sstevel@tonic-gate /* patch system and vfstab for root and mddb locations */
5200Sstevel@tonic-gate if (meta_patch_rootdev(rootnp, sname, vname, cname, dbname, doit,
5210Sstevel@tonic-gate verbose, ep) != 0) {
5220Sstevel@tonic-gate if (root_path != NULL) {
5230Sstevel@tonic-gate free_mem();
5240Sstevel@tonic-gate }
5250Sstevel@tonic-gate mde_perror(ep, "");
5260Sstevel@tonic-gate md_exit(sp, 1);
5270Sstevel@tonic-gate }
5280Sstevel@tonic-gate if (root_path != NULL) {
5290Sstevel@tonic-gate free_mem();
5300Sstevel@tonic-gate }
5310Sstevel@tonic-gate
5320Sstevel@tonic-gate /* return success */
5330Sstevel@tonic-gate md_exit(sp, 0);
5340Sstevel@tonic-gate /*NOTREACHED*/
5350Sstevel@tonic-gate return (0);
5360Sstevel@tonic-gate }
537