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"
29 * patch system files for root on metadevice
37 #define METAROOT_ERR -1
38 #define METAROOT_NOTFOUND -2
41 char **dm_fname
; /* Location of file name */
42 char *dm_default
; /* Default name */
48 static char *cname
= NULL
; /* take default */
49 static char *sname
= NULL
; /* take default */
50 static char *vname
= NULL
; /* take default */
51 static char *dbname
= NULL
; /* take default bootlist location */
53 static int verbose
= 0;
56 * Map of default system file names to the place where they are stored.
57 * This is used if the -R option is specified. Note that the members of
58 * the map point to the cname, sname, vname and dbname global variables
59 * above. These global variables are used in the call to
60 * meta_patch_rootdev() in main().
62 static struct def_map default_names
[] = {
64 &sname
, "/etc/system",
65 &vname
, "/etc/vfstab",
66 &dbname
, "/kernel/drv/md.conf"
69 static int validate_stripe_root();
72 * print usage message, md_exit
80 (void) fprintf(stderr
, gettext("\
81 usage:\t%s [-n] [-k system-name] [-m md.conf-name] [-v vfstab-name] \\\n\
82 \t\t[-c mddb.cf-name] device\n\
83 \t%s [-n] [-R root-path] device\n"),
94 for (i
= 0, map
= default_names
;
95 i
< sizeof (default_names
) / sizeof (struct def_map
);
97 if (*map
->dm_fname
!= NULL
) {
98 free((void *) *map
->dm_fname
);
99 *map
->dm_fname
= NULL
;
105 * Check if mirror, mirnp, is a valid root filesystem, ie all
106 * submirrors must be single disk stripe, and that the slice, slicenp,
107 * if not NULL, is a component of one of the submirrors.
108 * The arg metaroot is TRUE if mirnp is the current root filesystem.
110 * METAROOT_OK if mirror is valid and slicenp is a component
111 * METAROOT_NOTFOUND if mirror valid but slicenp not a component
112 * METAROOT_ERR if mirror not a valid root
115 validate_mirror_root(
124 md_mirror_t
*mirrorp
;
130 if ((mirrorp
= meta_get_mirror(sp
, mirnp
, ep
)) == NULL
) {
132 return (METAROOT_ERR
);
135 for (smi
= 0; (smi
< NMIRROR
); ++smi
) {
136 /* Check all submirrors */
137 md_submirror_t
*mdsp
= &mirrorp
->submirrors
[smi
];
138 mdname_t
*submirnamep
= mdsp
->submirnamep
;
140 /* skip unused submirrors */
141 if (submirnamep
== NULL
) {
142 assert(mdsp
->state
== SMS_UNUSED
);
145 if ((miscname
= metagetmiscname(submirnamep
, ep
)) == NULL
) {
146 return (mdmderror(ep
, MDE_UNKNOWN_TYPE
,
147 meta_getminor(submirnamep
->dev
),
148 submirnamep
->cname
));
150 if (strcmp(miscname
, MD_STRIPE
) != 0) {
151 md_eprintf(gettext("Submirror is not a stripe\n"));
152 return (METAROOT_ERR
);
154 rval
= validate_stripe_root(sp
, submirnamep
, slicenp
,
163 case METAROOT_NOTFOUND
:
169 return (METAROOT_ERR
);
171 return (METAROOT_NOTFOUND
);
172 return (METAROOT_OK
);
176 * Check if stripe, strnp, is a valid root filesystem, ie must
177 * be single disk stripe, and the the slice, slicenp, if not NULL, must
178 * be a component of this stripe.
179 * The arg metaroot is TRUE if strnp is the current root filesystem.
181 * METAROOT_OK if stripe is valid and slicenp is a component
182 * METAROOT_NOTFOUND if stripe valid but slicenp not a component
183 * METAROOT_ERR if stripe not a valid root
186 validate_stripe_root(
194 md_stripe_t
*stripep
;
198 if ((stripep
= meta_get_stripe(sp
, strnp
, ep
)) == NULL
) {
200 return (METAROOT_ERR
);
202 if (stripep
->rows
.rows_len
!= 1) {
204 "Concat %s has more than 1 slice\n"), strnp
->cname
);
205 return (METAROOT_ERR
);
207 rp
= &stripep
->rows
.rows_val
[0];
209 if (rp
->comps
.comps_len
!= 1) {
211 "Stripe %s has more than 1 slice\n"), strnp
->cname
);
212 return (METAROOT_ERR
);
214 cp
= &rp
->comps
.comps_val
[0];
215 if (!metaismeta(cp
->compnamep
)) {
217 return (METAROOT_OK
);
218 if (strcmp(slicenp
->cname
, cp
->compnamep
->cname
) == 0)
219 return (METAROOT_OK
);
222 "Root %s is not a component of metadevice %s\n"),
223 slicenp
->cname
, strnp
->cname
);
225 return (METAROOT_NOTFOUND
);
228 "Component %s is not a stripe\n"), cp
->compnamep
->cname
);
229 return (METAROOT_ERR
);
233 * Check if the device devnp is valid. It must be a component of the
234 * metadevice that contains the root filesystem
238 validate_root_device(
249 if ((curroot
= meta_get_current_root(ep
)) == NULL
) {
251 return (METAROOT_ERR
);
253 if ((rootnp
= metaname(&sp
, curroot
, UNKNOWN
, ep
)) == NULL
) {
255 return (METAROOT_ERR
);
258 if (metaismeta(rootnp
)) {
260 if ((miscname
= metagetmiscname(rootnp
, ep
)) == NULL
) {
262 return (METAROOT_ERR
);
264 if (strcmp(miscname
, MD_MIRROR
) == 0) {
265 if ((rval
= validate_mirror_root(sp
, rootnp
,
266 devnp
, 1, ep
)) == METAROOT_OK
)
267 return (METAROOT_OK
);
268 if (rval
== METAROOT_NOTFOUND
) {
270 "Slice %s is not a component of root %s\n"),
271 devnp
->cname
, rootnp
->cname
);
273 return (METAROOT_ERR
);
274 } else if (strcmp(miscname
, MD_STRIPE
) == 0) {
275 if ((rval
= validate_stripe_root(sp
, rootnp
,
276 devnp
, 1, ep
)) == METAROOT_OK
)
277 return (METAROOT_OK
);
278 if (rval
== METAROOT_NOTFOUND
) {
280 "Slice %s is not a component of root %s\n"),
281 devnp
->cname
, rootnp
->cname
);
283 return (METAROOT_ERR
);
286 "Root metadevice, %s, is not a Slice or Mirror\n"),
288 return (METAROOT_ERR
);
292 "Current Root %s is not a metadevice\n"), rootnp
->cname
);
293 return (METAROOT_ERR
);
298 * What we're going to do:
300 * 1) Check if the device is a metadevice or not.
302 * 2) If a metadevice, and it is valid, ie a stripe or a mirror containing
303 * a single slice, add "forceload:{drv,misc}/<modname>" of
304 * underlying drivers for the meta-root and the metadevice
305 * database to system. Otherwise, remove forceloads from system if the
306 * slice is a component of the current root metadevice.
308 * 3) Add "rootdev:/devices/..." to system.
310 * 4) Replace / mount in vfstab.
312 * 5) Repatch database locations, just to be safe.
321 mdsetname_t
*sp
= NULL
;
324 int ckmv_flag
= 0; /* non-zero if -c, -k, -m or -v */
325 md_error_t status
= mdnullerror
;
326 md_error_t
*ep
= &status
;
330 mdname_t
*currootdevnp
;
331 char *root_path
= NULL
;
333 size_t root_path_size
;
334 size_t path_buf_size
;
338 * Get the locale set up before calling any other routines
339 * with messages to ouput. Just in case we're not in a build
340 * environment, make sure that TEXT_DOMAIN gets set to
343 #if !defined(TEXT_DOMAIN)
344 #define TEXT_DOMAIN "SYS_TEST"
346 (void) setlocale(LC_ALL
, "");
347 (void) textdomain(TEXT_DOMAIN
);
349 if ((sdssc_bind_library() == SDSSC_OKAY
) &&
350 (sdssc_cmd_proxy(argc
, argv
, SDSSC_PROXY_PRIMARY
,
351 &error
) == SDSSC_PROXY_DONE
))
355 if (md_init(argc
, argv
, 0, 1, ep
) != 0 ||
356 meta_check_root(ep
) != 0) {
364 while ((c
= getopt(argc
, argv
, "hnk:m:v:c:R:?")) != -1) {
406 /* Can't use -R with any of -c, -k, -m or -v */
407 if ((ckmv_flag
!= 0) && (root_path
!= NULL
)) {
409 gettext("-R invalid with any of -c, -k, -m or -v\n"));
413 /* get device name */
414 if ((rootnp
= metaname(&sp
, argv
[0], UNKNOWN
, ep
)) == NULL
) {
418 if ((curroot
= meta_get_current_root(ep
)) == NULL
) {
423 * Get device name of current root metadevice. If root is net
424 * mounted as happens if this command is part of the install
425 * process, currootnp will be set to NULL.
427 currootnp
= metaname(&sp
, curroot
, UNKNOWN
, ep
);
429 * If the argument is the name of the current root filesystem, then
430 * the command is allowed, otherwise check that the argument is
433 if ((currootnp
== NULL
) ||
434 (strcmp(currootnp
->cname
, rootnp
->cname
) != 0)) {
435 if (metaismeta(rootnp
)) {
437 * Validate that the metadevice is based on a
438 * single slice. If none of the -k, -m, -v, -c or
439 * -R options are specified, then the default
440 * system files are being modified and hence the
441 * current root slice must be a component of the
442 * metadevice. If any of the previously mentioned
443 * options are used don't check that the current
444 * root is a component.
446 if ((ckmv_flag
== 0) && (root_path
== NULL
)) {
447 /* Get device name of current root slice */
449 meta_get_current_root_dev(sp
, ep
))
454 } else currootdevnp
= NULL
;
456 if ((miscname
= metagetmiscname(rootnp
, ep
)) == NULL
) {
460 /* Check that metadevice is a mirror or a stripe */
461 if (strcmp(miscname
, MD_MIRROR
) == 0) {
462 if (validate_mirror_root(sp
, rootnp
,
463 currootdevnp
, 0, ep
) != METAROOT_OK
) {
466 } else if (strcmp(miscname
, MD_STRIPE
) == 0) {
467 if (validate_stripe_root(sp
, rootnp
,
468 currootdevnp
, 0, ep
) != METAROOT_OK
) {
473 "%s is not a mirror or stripe\n"),
479 * Check that the root device is a component of the
480 * current root filesystem only if the default system
481 * files are being modified
483 if ((ckmv_flag
== 0) && (root_path
== NULL
)) {
484 if (validate_root_device(sp
, rootnp
, ep
) != 0) {
491 if (meta_lock(sp
, TRUE
, ep
)) {
497 * If -R is specified, use the default system file names relative
498 * to the new root location.
500 if (root_path
!= NULL
) {
501 root_path_size
= strlen(root_path
);
502 for (i
= 0, map
= default_names
;
503 i
< sizeof (default_names
) / sizeof (struct def_map
);
505 /* Add 1 for null terminator */
506 path_buf_size
= root_path_size
+
507 strlen(map
->dm_default
) + 1;
508 *map
->dm_fname
= malloc(path_buf_size
);
509 if (*map
->dm_fname
== NULL
) {
510 md_eprintf(gettext("Cannot allocate memory \
511 for system file path relocation\n"));
514 (void) snprintf(*map
->dm_fname
, path_buf_size
,
515 "%s%s", root_path
, map
->dm_default
);
519 /* patch system and vfstab for root and mddb locations */
520 if (meta_patch_rootdev(rootnp
, sname
, vname
, cname
, dbname
, doit
,
522 if (root_path
!= NULL
) {
528 if (root_path
!= NULL
) {