1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 1992-2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * patch system files for root on metadevice 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <meta.h> 34*0Sstevel@tonic-gate #include <stdlib.h> 35*0Sstevel@tonic-gate #include <sdssc.h> 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate #define METAROOT_OK 0 38*0Sstevel@tonic-gate #define METAROOT_ERR -1 39*0Sstevel@tonic-gate #define METAROOT_NOTFOUND -2 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate struct def_map { 42*0Sstevel@tonic-gate char **dm_fname; /* Location of file name */ 43*0Sstevel@tonic-gate char *dm_default; /* Default name */ 44*0Sstevel@tonic-gate }; 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate /* 47*0Sstevel@tonic-gate * options 48*0Sstevel@tonic-gate */ 49*0Sstevel@tonic-gate static char *cname = NULL; /* take default */ 50*0Sstevel@tonic-gate static char *sname = NULL; /* take default */ 51*0Sstevel@tonic-gate static char *vname = NULL; /* take default */ 52*0Sstevel@tonic-gate static char *dbname = NULL; /* take default bootlist location */ 53*0Sstevel@tonic-gate static int doit = 1; 54*0Sstevel@tonic-gate static int verbose = 0; 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate /* 57*0Sstevel@tonic-gate * Map of default system file names to the place where they are stored. 58*0Sstevel@tonic-gate * This is used if the -R option is specified. Note that the members of 59*0Sstevel@tonic-gate * the map point to the cname, sname, vname and dbname global variables 60*0Sstevel@tonic-gate * above. These global variables are used in the call to 61*0Sstevel@tonic-gate * meta_patch_rootdev() in main(). 62*0Sstevel@tonic-gate */ 63*0Sstevel@tonic-gate static struct def_map default_names[] = { 64*0Sstevel@tonic-gate &cname, META_DBCONF, 65*0Sstevel@tonic-gate &sname, "/etc/system", 66*0Sstevel@tonic-gate &vname, "/etc/vfstab", 67*0Sstevel@tonic-gate &dbname, "/kernel/drv/md.conf" 68*0Sstevel@tonic-gate }; 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate static int validate_stripe_root(); 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate /* 73*0Sstevel@tonic-gate * print usage message, md_exit 74*0Sstevel@tonic-gate */ 75*0Sstevel@tonic-gate static void 76*0Sstevel@tonic-gate usage( 77*0Sstevel@tonic-gate mdsetname_t *sp, 78*0Sstevel@tonic-gate int eval 79*0Sstevel@tonic-gate ) 80*0Sstevel@tonic-gate { 81*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("\ 82*0Sstevel@tonic-gate usage:\t%s [-n] [-k system-name] [-m md.conf-name] [-v vfstab-name] \\\n\ 83*0Sstevel@tonic-gate \t\t[-c mddb.cf-name] device\n\ 84*0Sstevel@tonic-gate \t%s [-n] [-R root-path] device\n"), 85*0Sstevel@tonic-gate myname, myname); 86*0Sstevel@tonic-gate md_exit(sp, eval); 87*0Sstevel@tonic-gate } 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate static void 90*0Sstevel@tonic-gate free_mem() 91*0Sstevel@tonic-gate { 92*0Sstevel@tonic-gate int i; 93*0Sstevel@tonic-gate struct def_map *map; 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate for (i = 0, map = default_names; 96*0Sstevel@tonic-gate i < sizeof (default_names) / sizeof (struct def_map); 97*0Sstevel@tonic-gate i++, map++) { 98*0Sstevel@tonic-gate if (*map->dm_fname != NULL) { 99*0Sstevel@tonic-gate free((void *) *map->dm_fname); 100*0Sstevel@tonic-gate *map->dm_fname = NULL; 101*0Sstevel@tonic-gate } 102*0Sstevel@tonic-gate } 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate /* 106*0Sstevel@tonic-gate * Check if mirror, mirnp, is a valid root filesystem, ie all 107*0Sstevel@tonic-gate * submirrors must be single disk stripe, and that the slice, slicenp, 108*0Sstevel@tonic-gate * if not NULL, is a component of one of the submirrors. 109*0Sstevel@tonic-gate * The arg metaroot is TRUE if mirnp is the current root filesystem. 110*0Sstevel@tonic-gate * Returns: 111*0Sstevel@tonic-gate * METAROOT_OK if mirror is valid and slicenp is a component 112*0Sstevel@tonic-gate * METAROOT_NOTFOUND if mirror valid but slicenp not a component 113*0Sstevel@tonic-gate * METAROOT_ERR if mirror not a valid root 114*0Sstevel@tonic-gate */ 115*0Sstevel@tonic-gate static int 116*0Sstevel@tonic-gate validate_mirror_root( 117*0Sstevel@tonic-gate mdsetname_t *sp, 118*0Sstevel@tonic-gate mdname_t *mirnp, 119*0Sstevel@tonic-gate mdname_t *slicenp, 120*0Sstevel@tonic-gate int metaroot, 121*0Sstevel@tonic-gate md_error_t *ep 122*0Sstevel@tonic-gate ) 123*0Sstevel@tonic-gate { 124*0Sstevel@tonic-gate int smi; 125*0Sstevel@tonic-gate md_mirror_t *mirrorp; 126*0Sstevel@tonic-gate char *miscname; 127*0Sstevel@tonic-gate int found = 0; 128*0Sstevel@tonic-gate int rval; 129*0Sstevel@tonic-gate int err = 0; 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL) { 132*0Sstevel@tonic-gate mde_perror(ep, ""); 133*0Sstevel@tonic-gate return (METAROOT_ERR); 134*0Sstevel@tonic-gate } 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate for (smi = 0; (smi < NMIRROR); ++smi) { 137*0Sstevel@tonic-gate /* Check all submirrors */ 138*0Sstevel@tonic-gate md_submirror_t *mdsp = &mirrorp->submirrors[smi]; 139*0Sstevel@tonic-gate mdname_t *submirnamep = mdsp->submirnamep; 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate /* skip unused submirrors */ 142*0Sstevel@tonic-gate if (submirnamep == NULL) { 143*0Sstevel@tonic-gate assert(mdsp->state == SMS_UNUSED); 144*0Sstevel@tonic-gate continue; 145*0Sstevel@tonic-gate } 146*0Sstevel@tonic-gate if ((miscname = metagetmiscname(submirnamep, ep)) == NULL) { 147*0Sstevel@tonic-gate return (mdmderror(ep, MDE_UNKNOWN_TYPE, 148*0Sstevel@tonic-gate meta_getminor(submirnamep->dev), 149*0Sstevel@tonic-gate submirnamep->cname)); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate if (strcmp(miscname, MD_STRIPE) != 0) { 152*0Sstevel@tonic-gate md_eprintf(gettext("Submirror is not a stripe\n")); 153*0Sstevel@tonic-gate return (METAROOT_ERR); 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate rval = validate_stripe_root(sp, submirnamep, slicenp, 156*0Sstevel@tonic-gate metaroot, ep); 157*0Sstevel@tonic-gate switch (rval) { 158*0Sstevel@tonic-gate case METAROOT_OK: 159*0Sstevel@tonic-gate found = 1; 160*0Sstevel@tonic-gate break; 161*0Sstevel@tonic-gate case METAROOT_ERR: 162*0Sstevel@tonic-gate err++; 163*0Sstevel@tonic-gate break; 164*0Sstevel@tonic-gate case METAROOT_NOTFOUND: 165*0Sstevel@tonic-gate default: 166*0Sstevel@tonic-gate break; 167*0Sstevel@tonic-gate } 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate if (err > 0) 170*0Sstevel@tonic-gate return (METAROOT_ERR); 171*0Sstevel@tonic-gate if (!found) 172*0Sstevel@tonic-gate return (METAROOT_NOTFOUND); 173*0Sstevel@tonic-gate return (METAROOT_OK); 174*0Sstevel@tonic-gate } 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate /* 177*0Sstevel@tonic-gate * Check if stripe, strnp, is a valid root filesystem, ie must 178*0Sstevel@tonic-gate * be single disk stripe, and the the slice, slicenp, if not NULL, must 179*0Sstevel@tonic-gate * be a component of this stripe. 180*0Sstevel@tonic-gate * The arg metaroot is TRUE if strnp is the current root filesystem. 181*0Sstevel@tonic-gate * Returns: 182*0Sstevel@tonic-gate * METAROOT_OK if stripe is valid and slicenp is a component 183*0Sstevel@tonic-gate * METAROOT_NOTFOUND if stripe valid but slicenp not a component 184*0Sstevel@tonic-gate * METAROOT_ERR if stripe not a valid root 185*0Sstevel@tonic-gate */ 186*0Sstevel@tonic-gate static int 187*0Sstevel@tonic-gate validate_stripe_root( 188*0Sstevel@tonic-gate mdsetname_t *sp, 189*0Sstevel@tonic-gate mdname_t *strnp, 190*0Sstevel@tonic-gate mdname_t *slicenp, 191*0Sstevel@tonic-gate int metaroot, 192*0Sstevel@tonic-gate md_error_t *ep 193*0Sstevel@tonic-gate ) 194*0Sstevel@tonic-gate { 195*0Sstevel@tonic-gate md_stripe_t *stripep; 196*0Sstevel@tonic-gate md_row_t *rp; 197*0Sstevel@tonic-gate md_comp_t *cp; 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate if ((stripep = meta_get_stripe(sp, strnp, ep)) == NULL) { 200*0Sstevel@tonic-gate mde_perror(ep, ""); 201*0Sstevel@tonic-gate return (METAROOT_ERR); 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate if (stripep->rows.rows_len != 1) { 204*0Sstevel@tonic-gate md_eprintf(gettext( 205*0Sstevel@tonic-gate "Concat %s has more than 1 slice\n"), strnp->cname); 206*0Sstevel@tonic-gate return (METAROOT_ERR); 207*0Sstevel@tonic-gate } 208*0Sstevel@tonic-gate rp = &stripep->rows.rows_val[0]; 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate if (rp->comps.comps_len != 1) { 211*0Sstevel@tonic-gate md_eprintf(gettext( 212*0Sstevel@tonic-gate "Stripe %s has more than 1 slice\n"), strnp->cname); 213*0Sstevel@tonic-gate return (METAROOT_ERR); 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate cp = &rp->comps.comps_val[0]; 216*0Sstevel@tonic-gate if (!metaismeta(cp->compnamep)) { 217*0Sstevel@tonic-gate if (slicenp == NULL) 218*0Sstevel@tonic-gate return (METAROOT_OK); 219*0Sstevel@tonic-gate if (strcmp(slicenp->cname, cp->compnamep->cname) == 0) 220*0Sstevel@tonic-gate return (METAROOT_OK); 221*0Sstevel@tonic-gate if (!metaroot) { 222*0Sstevel@tonic-gate md_eprintf(gettext( 223*0Sstevel@tonic-gate "Root %s is not a component of metadevice %s\n"), 224*0Sstevel@tonic-gate slicenp->cname, strnp->cname); 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate return (METAROOT_NOTFOUND); 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate md_eprintf(gettext( 229*0Sstevel@tonic-gate "Component %s is not a stripe\n"), cp->compnamep->cname); 230*0Sstevel@tonic-gate return (METAROOT_ERR); 231*0Sstevel@tonic-gate } 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate /* 234*0Sstevel@tonic-gate * Check if the device devnp is valid. It must be a component of the 235*0Sstevel@tonic-gate * metadevice that contains the root filesystem 236*0Sstevel@tonic-gate */ 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate static int 239*0Sstevel@tonic-gate validate_root_device( 240*0Sstevel@tonic-gate mdsetname_t *sp, 241*0Sstevel@tonic-gate mdname_t *devnp, 242*0Sstevel@tonic-gate md_error_t *ep 243*0Sstevel@tonic-gate ) 244*0Sstevel@tonic-gate { 245*0Sstevel@tonic-gate mdname_t *rootnp; 246*0Sstevel@tonic-gate char *curroot; 247*0Sstevel@tonic-gate char *miscname; 248*0Sstevel@tonic-gate int rval; 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate if ((curroot = meta_get_current_root(ep)) == NULL) { 251*0Sstevel@tonic-gate mde_perror(ep, ""); 252*0Sstevel@tonic-gate return (METAROOT_ERR); 253*0Sstevel@tonic-gate } 254*0Sstevel@tonic-gate if ((rootnp = metaname(&sp, curroot, ep)) == NULL) { 255*0Sstevel@tonic-gate mde_perror(ep, ""); 256*0Sstevel@tonic-gate return (METAROOT_ERR); 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate if (metaismeta(rootnp)) { 260*0Sstevel@tonic-gate /* get type */ 261*0Sstevel@tonic-gate if ((miscname = metagetmiscname(rootnp, ep)) == NULL) { 262*0Sstevel@tonic-gate mde_perror(ep, ""); 263*0Sstevel@tonic-gate return (METAROOT_ERR); 264*0Sstevel@tonic-gate } 265*0Sstevel@tonic-gate if (strcmp(miscname, MD_MIRROR) == 0) { 266*0Sstevel@tonic-gate if ((rval = validate_mirror_root(sp, rootnp, 267*0Sstevel@tonic-gate devnp, 1, ep)) == METAROOT_OK) 268*0Sstevel@tonic-gate return (METAROOT_OK); 269*0Sstevel@tonic-gate if (rval == METAROOT_NOTFOUND) { 270*0Sstevel@tonic-gate md_eprintf(gettext( 271*0Sstevel@tonic-gate "Slice %s is not a component of root %s\n"), 272*0Sstevel@tonic-gate devnp->cname, rootnp->cname); 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate return (METAROOT_ERR); 275*0Sstevel@tonic-gate } else if (strcmp(miscname, MD_STRIPE) == 0) { 276*0Sstevel@tonic-gate if ((rval = validate_stripe_root(sp, rootnp, 277*0Sstevel@tonic-gate devnp, 1, ep)) == METAROOT_OK) 278*0Sstevel@tonic-gate return (METAROOT_OK); 279*0Sstevel@tonic-gate if (rval == METAROOT_NOTFOUND) { 280*0Sstevel@tonic-gate md_eprintf(gettext( 281*0Sstevel@tonic-gate "Slice %s is not a component of root %s\n"), 282*0Sstevel@tonic-gate devnp->cname, rootnp->cname); 283*0Sstevel@tonic-gate } 284*0Sstevel@tonic-gate return (METAROOT_ERR); 285*0Sstevel@tonic-gate } else { 286*0Sstevel@tonic-gate md_eprintf(gettext( 287*0Sstevel@tonic-gate "Root metadevice, %s, is not a Slice or Mirror\n"), 288*0Sstevel@tonic-gate rootnp->cname); 289*0Sstevel@tonic-gate return (METAROOT_ERR); 290*0Sstevel@tonic-gate } 291*0Sstevel@tonic-gate } else { 292*0Sstevel@tonic-gate md_eprintf(gettext( 293*0Sstevel@tonic-gate "Current Root %s is not a metadevice\n"), rootnp->cname); 294*0Sstevel@tonic-gate return (METAROOT_ERR); 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate } 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate /* 299*0Sstevel@tonic-gate * What we're going to do: 300*0Sstevel@tonic-gate * 301*0Sstevel@tonic-gate * 1) Check if the device is a metadevice or not. 302*0Sstevel@tonic-gate * 303*0Sstevel@tonic-gate * 2) If a metadevice, and it is valid, ie a stripe or a mirror containing 304*0Sstevel@tonic-gate * a single slice, add "forceload:{drv,misc}/<modname>" of 305*0Sstevel@tonic-gate * underlying drivers for the meta-root and the metadevice 306*0Sstevel@tonic-gate * database to system. Otherwise, remove forceloads from system if the 307*0Sstevel@tonic-gate * slice is a component of the current root metadevice. 308*0Sstevel@tonic-gate * 309*0Sstevel@tonic-gate * 3) Add "rootdev:/devices/..." to system. 310*0Sstevel@tonic-gate * 311*0Sstevel@tonic-gate * 4) Replace / mount in vfstab. 312*0Sstevel@tonic-gate * 313*0Sstevel@tonic-gate * 5) Repatch database locations, just to be safe. 314*0Sstevel@tonic-gate */ 315*0Sstevel@tonic-gate int 316*0Sstevel@tonic-gate main( 317*0Sstevel@tonic-gate int argc, 318*0Sstevel@tonic-gate char *argv[] 319*0Sstevel@tonic-gate ) 320*0Sstevel@tonic-gate { 321*0Sstevel@tonic-gate int i; 322*0Sstevel@tonic-gate mdsetname_t *sp = NULL; 323*0Sstevel@tonic-gate mdname_t *rootnp; 324*0Sstevel@tonic-gate int c; 325*0Sstevel@tonic-gate int ckmv_flag = 0; /* non-zero if -c, -k, -m or -v */ 326*0Sstevel@tonic-gate md_error_t status = mdnullerror; 327*0Sstevel@tonic-gate md_error_t *ep = &status; 328*0Sstevel@tonic-gate char *miscname; 329*0Sstevel@tonic-gate char *curroot; 330*0Sstevel@tonic-gate mdname_t *currootnp; 331*0Sstevel@tonic-gate mdname_t *currootdevnp; 332*0Sstevel@tonic-gate char *root_path = NULL; 333*0Sstevel@tonic-gate struct def_map *map; 334*0Sstevel@tonic-gate size_t root_path_size; 335*0Sstevel@tonic-gate size_t path_buf_size; 336*0Sstevel@tonic-gate int error; 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate /* 339*0Sstevel@tonic-gate * Get the locale set up before calling any other routines 340*0Sstevel@tonic-gate * with messages to ouput. Just in case we're not in a build 341*0Sstevel@tonic-gate * environment, make sure that TEXT_DOMAIN gets set to 342*0Sstevel@tonic-gate * something. 343*0Sstevel@tonic-gate */ 344*0Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 345*0Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 346*0Sstevel@tonic-gate #endif 347*0Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 348*0Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate if ((sdssc_bind_library() == SDSSC_OKAY) && 351*0Sstevel@tonic-gate (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY, 352*0Sstevel@tonic-gate &error) == SDSSC_PROXY_DONE)) 353*0Sstevel@tonic-gate exit(error); 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate /* initialize */ 356*0Sstevel@tonic-gate if (md_init(argc, argv, 0, 1, ep) != 0 || 357*0Sstevel@tonic-gate meta_check_root(ep) != 0) { 358*0Sstevel@tonic-gate mde_perror(ep, ""); 359*0Sstevel@tonic-gate md_exit(sp, 1); 360*0Sstevel@tonic-gate } 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate /* parse options */ 363*0Sstevel@tonic-gate optind = 1; 364*0Sstevel@tonic-gate opterr = 1; 365*0Sstevel@tonic-gate while ((c = getopt(argc, argv, "hnk:m:v:c:R:?")) != -1) { 366*0Sstevel@tonic-gate switch (c) { 367*0Sstevel@tonic-gate case 'h': 368*0Sstevel@tonic-gate usage(sp, 0); 369*0Sstevel@tonic-gate break; 370*0Sstevel@tonic-gate case 'm': 371*0Sstevel@tonic-gate dbname = optarg; 372*0Sstevel@tonic-gate ckmv_flag = 1; 373*0Sstevel@tonic-gate break; 374*0Sstevel@tonic-gate case 'n': 375*0Sstevel@tonic-gate doit = 0; 376*0Sstevel@tonic-gate verbose = 1; 377*0Sstevel@tonic-gate break; 378*0Sstevel@tonic-gate case 'k': 379*0Sstevel@tonic-gate sname = optarg; 380*0Sstevel@tonic-gate ckmv_flag = 1; 381*0Sstevel@tonic-gate break; 382*0Sstevel@tonic-gate case 'v': 383*0Sstevel@tonic-gate vname = optarg; 384*0Sstevel@tonic-gate ckmv_flag = 1; 385*0Sstevel@tonic-gate break; 386*0Sstevel@tonic-gate case 'c': 387*0Sstevel@tonic-gate cname = optarg; 388*0Sstevel@tonic-gate ckmv_flag = 1; 389*0Sstevel@tonic-gate break; 390*0Sstevel@tonic-gate case 'R': 391*0Sstevel@tonic-gate root_path = optarg; 392*0Sstevel@tonic-gate break; 393*0Sstevel@tonic-gate case '?': 394*0Sstevel@tonic-gate if (optopt == '?') 395*0Sstevel@tonic-gate usage(sp, 0); 396*0Sstevel@tonic-gate /*FALLTHROUGH*/ 397*0Sstevel@tonic-gate default: 398*0Sstevel@tonic-gate usage(sp, 1); 399*0Sstevel@tonic-gate break; 400*0Sstevel@tonic-gate } 401*0Sstevel@tonic-gate } 402*0Sstevel@tonic-gate argc -= optind; 403*0Sstevel@tonic-gate argv += optind; 404*0Sstevel@tonic-gate if (argc != 1) 405*0Sstevel@tonic-gate usage(sp, 1); 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate /* Can't use -R with any of -c, -k, -m or -v */ 408*0Sstevel@tonic-gate if ((ckmv_flag != 0) && (root_path != NULL)) { 409*0Sstevel@tonic-gate md_eprintf( 410*0Sstevel@tonic-gate gettext("-R invalid with any of -c, -k, -m or -v\n")); 411*0Sstevel@tonic-gate usage(sp, 1); 412*0Sstevel@tonic-gate } 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate /* get device name */ 415*0Sstevel@tonic-gate if ((rootnp = metaname(&sp, argv[0], ep)) == NULL) { 416*0Sstevel@tonic-gate mde_perror(ep, ""); 417*0Sstevel@tonic-gate md_exit(sp, 1); 418*0Sstevel@tonic-gate } 419*0Sstevel@tonic-gate if ((curroot = meta_get_current_root(ep)) == NULL) { 420*0Sstevel@tonic-gate mde_perror(ep, ""); 421*0Sstevel@tonic-gate md_exit(sp, 1); 422*0Sstevel@tonic-gate } 423*0Sstevel@tonic-gate /* 424*0Sstevel@tonic-gate * Get device name of current root metadevice. If root is net 425*0Sstevel@tonic-gate * mounted as happens if this command is part of the install 426*0Sstevel@tonic-gate * process, currootnp will be set to NULL. 427*0Sstevel@tonic-gate */ 428*0Sstevel@tonic-gate currootnp = metaname(&sp, curroot, ep); 429*0Sstevel@tonic-gate /* 430*0Sstevel@tonic-gate * If the argument is the name of the current root filesystem, then 431*0Sstevel@tonic-gate * the command is allowed, otherwise check that the argument is 432*0Sstevel@tonic-gate * valid. 433*0Sstevel@tonic-gate */ 434*0Sstevel@tonic-gate if ((currootnp == NULL) || 435*0Sstevel@tonic-gate (strcmp(currootnp->cname, rootnp->cname) != 0)) { 436*0Sstevel@tonic-gate if (metaismeta(rootnp)) { 437*0Sstevel@tonic-gate /* 438*0Sstevel@tonic-gate * Validate that the metadevice is based on a 439*0Sstevel@tonic-gate * single slice. If none of the -k, -m, -v, -c or 440*0Sstevel@tonic-gate * -R options are specified, then the default 441*0Sstevel@tonic-gate * system files are being modified and hence the 442*0Sstevel@tonic-gate * current root slice must be a component of the 443*0Sstevel@tonic-gate * metadevice. If any of the previously mentioned 444*0Sstevel@tonic-gate * options are used don't check that the current 445*0Sstevel@tonic-gate * root is a component. 446*0Sstevel@tonic-gate */ 447*0Sstevel@tonic-gate if ((ckmv_flag == 0) && (root_path == NULL)) { 448*0Sstevel@tonic-gate /* Get device name of current root slice */ 449*0Sstevel@tonic-gate if ((currootdevnp = 450*0Sstevel@tonic-gate meta_get_current_root_dev(sp, ep)) 451*0Sstevel@tonic-gate == NULL) { 452*0Sstevel@tonic-gate mde_perror(ep, ""); 453*0Sstevel@tonic-gate md_exit(sp, 1); 454*0Sstevel@tonic-gate } 455*0Sstevel@tonic-gate } else currootdevnp = NULL; 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gate if ((miscname = metagetmiscname(rootnp, ep)) == NULL) { 458*0Sstevel@tonic-gate mde_perror(ep, ""); 459*0Sstevel@tonic-gate md_exit(sp, 1); 460*0Sstevel@tonic-gate } 461*0Sstevel@tonic-gate /* Check that metadevice is a mirror or a stripe */ 462*0Sstevel@tonic-gate if (strcmp(miscname, MD_MIRROR) == 0) { 463*0Sstevel@tonic-gate if (validate_mirror_root(sp, rootnp, 464*0Sstevel@tonic-gate currootdevnp, 0, ep) != METAROOT_OK) { 465*0Sstevel@tonic-gate md_exit(sp, 1); 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate } else if (strcmp(miscname, MD_STRIPE) == 0) { 468*0Sstevel@tonic-gate if (validate_stripe_root(sp, rootnp, 469*0Sstevel@tonic-gate currootdevnp, 0, ep) != METAROOT_OK) { 470*0Sstevel@tonic-gate md_exit(sp, 1); 471*0Sstevel@tonic-gate } 472*0Sstevel@tonic-gate } else { 473*0Sstevel@tonic-gate md_eprintf(gettext( 474*0Sstevel@tonic-gate "%s is not a mirror or stripe\n"), 475*0Sstevel@tonic-gate rootnp->cname); 476*0Sstevel@tonic-gate md_exit(sp, 1); 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate } else { 479*0Sstevel@tonic-gate /* 480*0Sstevel@tonic-gate * Check that the root device is a component of the 481*0Sstevel@tonic-gate * current root filesystem only if the default system 482*0Sstevel@tonic-gate * files are being modified 483*0Sstevel@tonic-gate */ 484*0Sstevel@tonic-gate if ((ckmv_flag == 0) && (root_path == NULL)) { 485*0Sstevel@tonic-gate if (validate_root_device(sp, rootnp, ep) != 0) { 486*0Sstevel@tonic-gate md_exit(sp, 1); 487*0Sstevel@tonic-gate } 488*0Sstevel@tonic-gate } 489*0Sstevel@tonic-gate } 490*0Sstevel@tonic-gate } 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate if (meta_lock(sp, TRUE, ep)) { 493*0Sstevel@tonic-gate mde_perror(ep, ""); 494*0Sstevel@tonic-gate md_exit(sp, 1); 495*0Sstevel@tonic-gate } 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate /* 498*0Sstevel@tonic-gate * If -R is specified, use the default system file names relative 499*0Sstevel@tonic-gate * to the new root location. 500*0Sstevel@tonic-gate */ 501*0Sstevel@tonic-gate if (root_path != NULL) { 502*0Sstevel@tonic-gate root_path_size = strlen(root_path); 503*0Sstevel@tonic-gate for (i = 0, map = default_names; 504*0Sstevel@tonic-gate i < sizeof (default_names) / sizeof (struct def_map); 505*0Sstevel@tonic-gate i++, map++) { 506*0Sstevel@tonic-gate /* Add 1 for null terminator */ 507*0Sstevel@tonic-gate path_buf_size = root_path_size + 508*0Sstevel@tonic-gate strlen(map->dm_default) + 1; 509*0Sstevel@tonic-gate *map->dm_fname = malloc(path_buf_size); 510*0Sstevel@tonic-gate if (*map->dm_fname == NULL) { 511*0Sstevel@tonic-gate md_eprintf(gettext("Cannot allocate memory \ 512*0Sstevel@tonic-gate for system file path relocation\n")); 513*0Sstevel@tonic-gate md_exit(sp, 1); 514*0Sstevel@tonic-gate } 515*0Sstevel@tonic-gate (void) snprintf(*map->dm_fname, path_buf_size, 516*0Sstevel@tonic-gate "%s%s", root_path, map->dm_default); 517*0Sstevel@tonic-gate } 518*0Sstevel@tonic-gate } 519*0Sstevel@tonic-gate 520*0Sstevel@tonic-gate /* patch system and vfstab for root and mddb locations */ 521*0Sstevel@tonic-gate if (meta_patch_rootdev(rootnp, sname, vname, cname, dbname, doit, 522*0Sstevel@tonic-gate verbose, ep) != 0) { 523*0Sstevel@tonic-gate if (root_path != NULL) { 524*0Sstevel@tonic-gate free_mem(); 525*0Sstevel@tonic-gate } 526*0Sstevel@tonic-gate mde_perror(ep, ""); 527*0Sstevel@tonic-gate md_exit(sp, 1); 528*0Sstevel@tonic-gate } 529*0Sstevel@tonic-gate if (root_path != NULL) { 530*0Sstevel@tonic-gate free_mem(); 531*0Sstevel@tonic-gate } 532*0Sstevel@tonic-gate 533*0Sstevel@tonic-gate /* return success */ 534*0Sstevel@tonic-gate md_exit(sp, 0); 535*0Sstevel@tonic-gate /*NOTREACHED*/ 536*0Sstevel@tonic-gate return (0); 537*0Sstevel@tonic-gate } 538