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 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 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 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 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 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 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