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
51623Stw21770 * Common Development and Distribution License (the "License").
61623Stw21770 * 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*7044Smk117520 * Copyright 2008 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 * initialize metadevices
300Sstevel@tonic-gate */
310Sstevel@tonic-gate
320Sstevel@tonic-gate #include <meta.h>
330Sstevel@tonic-gate
340Sstevel@tonic-gate #include <sdssc.h>
350Sstevel@tonic-gate #include <sys/lvm/md_mirror.h>
360Sstevel@tonic-gate #include <syslog.h>
370Sstevel@tonic-gate #include "meta_set_prv.h"
380Sstevel@tonic-gate
390Sstevel@tonic-gate /*
400Sstevel@tonic-gate * try to initialize devices
410Sstevel@tonic-gate */
420Sstevel@tonic-gate #define DO_AGAIN 0
430Sstevel@tonic-gate #define DONT_DO 1
440Sstevel@tonic-gate #define IS_DONE 2
450Sstevel@tonic-gate
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate * mn_send_command
480Sstevel@tonic-gate *
490Sstevel@tonic-gate * generate a command of the form "metainit -s setname [-n] [-f] ....."
500Sstevel@tonic-gate *
510Sstevel@tonic-gate * If -n option is *not* set, send the metainit command *with -n set* to
520Sstevel@tonic-gate * all nodes first. Do this with MD_MSGF_STOP_ON_ERROR set.
530Sstevel@tonic-gate * That means if it fails on one node, it'll return immediately,
540Sstevel@tonic-gate * reporting the error.
550Sstevel@tonic-gate * By doing so, we have a dryrun first that has to succeed on every node
560Sstevel@tonic-gate * before we start the command for real.
570Sstevel@tonic-gate * This saves us from backing out a metainit command that succeeded on
580Sstevel@tonic-gate * some nodes but failed on one.
590Sstevel@tonic-gate */
600Sstevel@tonic-gate static int
mn_send_command(mdsetname_t ** spp,int argc,char ** argv,mdcmdopts_t options,int flags,char * context,md_error_t * ep)610Sstevel@tonic-gate mn_send_command(
620Sstevel@tonic-gate mdsetname_t **spp,
630Sstevel@tonic-gate int argc,
640Sstevel@tonic-gate char **argv,
650Sstevel@tonic-gate mdcmdopts_t options,
660Sstevel@tonic-gate int flags,
670Sstevel@tonic-gate char *context,
680Sstevel@tonic-gate md_error_t *ep
690Sstevel@tonic-gate )
700Sstevel@tonic-gate {
710Sstevel@tonic-gate int newargc;
720Sstevel@tonic-gate char **newargv;
730Sstevel@tonic-gate int i;
740Sstevel@tonic-gate int ret;
750Sstevel@tonic-gate int dryrun_only = 0;
760Sstevel@tonic-gate
770Sstevel@tonic-gate
780Sstevel@tonic-gate newargv = calloc(argc+5, sizeof (char *));
790Sstevel@tonic-gate newargv[0] = "metainit";
800Sstevel@tonic-gate newargv[1] = "-s";
810Sstevel@tonic-gate newargv[2] = (*spp)->setname;
820Sstevel@tonic-gate newargv[3] = "-n"; /* always do "-n" first */
830Sstevel@tonic-gate newargc = 4;
840Sstevel@tonic-gate if ((options & MDCMD_DOIT) == 0) {
850Sstevel@tonic-gate dryrun_only = 1;
860Sstevel@tonic-gate }
870Sstevel@tonic-gate if ((options & MDCMD_FORCE) != 0) {
880Sstevel@tonic-gate newargv[newargc] = "-f";
890Sstevel@tonic-gate newargc++;
900Sstevel@tonic-gate }
910Sstevel@tonic-gate for (i = 0; i < argc; i++, newargc++)
920Sstevel@tonic-gate newargv[newargc] = argv[i];
930Sstevel@tonic-gate ret = meta_mn_send_command(*spp, newargc, newargv,
940Sstevel@tonic-gate flags | MD_DRYRUN | MD_NOLOG, context, ep);
950Sstevel@tonic-gate
960Sstevel@tonic-gate if ((dryrun_only == 0) && (ret == 0)) {
970Sstevel@tonic-gate /*
980Sstevel@tonic-gate * Do it for real now. Remove "-n" from the arguments and
990Sstevel@tonic-gate * MD_DRYRUN from the flags. If we fail this time the master
1000Sstevel@tonic-gate * must panic as the mddbs may be inconsistent.
1010Sstevel@tonic-gate */
1020Sstevel@tonic-gate newargv[3] = ""; /* this was "-n" before */
1030Sstevel@tonic-gate ret = meta_mn_send_command(*spp, newargc, newargv,
1040Sstevel@tonic-gate flags | MD_RETRY_BUSY | MD_PANIC_WHEN_INCONSISTENT,
1050Sstevel@tonic-gate context, ep);
1060Sstevel@tonic-gate }
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate free(newargv);
1090Sstevel@tonic-gate return (ret);
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate static int
init_entries(mdsetname_t ** spp,md_tab_t * tabp,mdcmdopts_t options,uint_t flags,bool_t called_thru_rpc,md_error_t * ep)1130Sstevel@tonic-gate init_entries(
1140Sstevel@tonic-gate mdsetname_t **spp,
1150Sstevel@tonic-gate md_tab_t *tabp,
1160Sstevel@tonic-gate mdcmdopts_t options,
1170Sstevel@tonic-gate uint_t flags,
1180Sstevel@tonic-gate bool_t called_thru_rpc,
1190Sstevel@tonic-gate md_error_t *ep
1200Sstevel@tonic-gate )
1210Sstevel@tonic-gate {
1220Sstevel@tonic-gate uint_t cnt = 0;
1230Sstevel@tonic-gate uint_t line;
1240Sstevel@tonic-gate int rval = 0;
1250Sstevel@tonic-gate int ret;
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate /* for all matching entries, which haven't already been done */
1280Sstevel@tonic-gate for (line = 0; (line < tabp->nlines); ++line) {
1290Sstevel@tonic-gate md_tab_line_t *linep = &tabp->lines[line];
1301623Stw21770 char *uname = linep->argv[0];
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate /* see if already done */
1330Sstevel@tonic-gate if (linep->flags != DO_AGAIN)
1340Sstevel@tonic-gate continue;
1350Sstevel@tonic-gate
1361623Stw21770 /* clear the metadev/hsp caches between inits */
1371623Stw21770 metaflushmetanames();
1381623Stw21770
1390Sstevel@tonic-gate /* try it */
1400Sstevel@tonic-gate if ((called_thru_rpc == FALSE) &&
1411623Stw21770 meta_is_mn_name(spp, uname, ep)) {
1420Sstevel@tonic-gate /*
1430Sstevel@tonic-gate * MN set, send command to all nodes
1440Sstevel@tonic-gate * Note that is sp is NULL, meta_is_mn_name() derives
1450Sstevel@tonic-gate * sp from linep->argv which is the metadevice arg
1460Sstevel@tonic-gate */
1470Sstevel@tonic-gate ret = mn_send_command(spp, linep->argc, linep->argv,
1480Sstevel@tonic-gate options, flags, linep->context, ep);
1490Sstevel@tonic-gate } else {
1501623Stw21770 char *cname = NULL;
1511623Stw21770
1521623Stw21770 cname = meta_name_getname(spp, uname, META_DEVICE, ep);
1531623Stw21770 if (cname == NULL) {
1541623Stw21770 mde_perror(ep, "");
1551623Stw21770 mdclrerror(ep);
1561623Stw21770 } else {
1571623Stw21770
1581623Stw21770 ret = meta_init_name(spp, linep->argc,
1591623Stw21770 linep->argv, cname, options, ep);
1601623Stw21770 Free(cname);
1611623Stw21770
1621623Stw21770 if (ret != 0) {
1631623Stw21770 if (!(flags & MD_IGNORE_STDERR)) {
1641623Stw21770 mderrorextra(ep, linep->context);
1651623Stw21770 mde_perror(ep, "");
1661623Stw21770 rval = -1;
1671623Stw21770 }
1681623Stw21770 mdclrerror(ep);
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate }
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate if (ret == 0) {
1730Sstevel@tonic-gate linep->flags = IS_DONE;
1740Sstevel@tonic-gate ++cnt;
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate /* return success */
1790Sstevel@tonic-gate if (rval != 0)
1800Sstevel@tonic-gate return (rval);
1810Sstevel@tonic-gate return (cnt);
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate /*
1850Sstevel@tonic-gate * initialize all devices in set
1860Sstevel@tonic-gate */
1870Sstevel@tonic-gate static int
init_all(mdsetname_t ** spp,mdcmdopts_t options,bool_t called_thru_rpc,md_error_t * ep)1880Sstevel@tonic-gate init_all(
1890Sstevel@tonic-gate mdsetname_t **spp,
1900Sstevel@tonic-gate mdcmdopts_t options,
1910Sstevel@tonic-gate bool_t called_thru_rpc,
1920Sstevel@tonic-gate md_error_t *ep
1930Sstevel@tonic-gate )
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate md_tab_t *tabp = NULL;
1960Sstevel@tonic-gate size_t setlen;
1970Sstevel@tonic-gate uint_t more;
1980Sstevel@tonic-gate int done;
1990Sstevel@tonic-gate int eval = -1;
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate /*
2020Sstevel@tonic-gate * Only take the lock if this is not a MN set
2030Sstevel@tonic-gate * We can only enter this code for a MN set if we are the initiator
2040Sstevel@tonic-gate * and in this case, we don't want to take locks.
2050Sstevel@tonic-gate */
2060Sstevel@tonic-gate if (meta_is_mn_set((*spp), ep) == 0) {
2070Sstevel@tonic-gate /* grab set lock */
2080Sstevel@tonic-gate if (meta_lock(*spp, TRUE, ep)) {
2090Sstevel@tonic-gate mde_perror(ep, "");
2100Sstevel@tonic-gate mdclrerror(ep);
2110Sstevel@tonic-gate return (eval);
2120Sstevel@tonic-gate }
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate /* check for ownership */
2150Sstevel@tonic-gate if (meta_check_ownership(*spp, ep) != 0) {
2160Sstevel@tonic-gate mde_perror(ep, "");
2170Sstevel@tonic-gate mdclrerror(ep);
2180Sstevel@tonic-gate return (eval);
2190Sstevel@tonic-gate }
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate /* lock is held across init_entries */
2220Sstevel@tonic-gate options |= MDCMD_NOLOCK;
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate /* get md.tab, preen entries */
2260Sstevel@tonic-gate if ((tabp = meta_tab_parse(NULL, ep)) == NULL) {
2270Sstevel@tonic-gate mde_perror(ep, "");
2280Sstevel@tonic-gate mdclrerror(ep);
2290Sstevel@tonic-gate return (eval);
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate
2321623Stw21770 setlen = strlen((*spp)->setname);
2330Sstevel@tonic-gate for (more = 0; (more < tabp->nlines); ++more) {
2340Sstevel@tonic-gate md_tab_line_t *linep = &tabp->lines[more];
2350Sstevel@tonic-gate char *cname = linep->cname;
2360Sstevel@tonic-gate char *p;
2370Sstevel@tonic-gate size_t len;
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate /* better have args */
2400Sstevel@tonic-gate assert((linep->argc > 0) && (linep->argv[0] != NULL));
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate /* only do metadevices and hotspare pools in set */
2430Sstevel@tonic-gate if (linep->type & TAB_MD_HSP) {
2440Sstevel@tonic-gate if ((p = strrchr(cname, '/')) == NULL) {
2450Sstevel@tonic-gate len = 0;
2460Sstevel@tonic-gate } else {
2470Sstevel@tonic-gate len = p - cname;
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate if ((len == setlen) &&
2500Sstevel@tonic-gate (strncmp(cname, (*spp)->setname, len) == 0)) {
2510Sstevel@tonic-gate linep->flags = DO_AGAIN;
2520Sstevel@tonic-gate } else {
2530Sstevel@tonic-gate linep->flags = DONT_DO;
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate } else {
2570Sstevel@tonic-gate linep->flags = DONT_DO;
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate }
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate eval = 1;
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate /* while more devices get made */
2640Sstevel@tonic-gate do {
2650Sstevel@tonic-gate done = init_entries(spp, tabp, options,
2660Sstevel@tonic-gate MD_IGNORE_STDERR|MD_RETRY_BUSY, called_thru_rpc, ep);
2670Sstevel@tonic-gate } while (done > 0);
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate /* now do it and report errors */
2700Sstevel@tonic-gate if (init_entries(spp, tabp, options, MD_RETRY_BUSY,
2710Sstevel@tonic-gate called_thru_rpc, ep) >= 0)
2720Sstevel@tonic-gate eval = 0; /* success */
2730Sstevel@tonic-gate mdclrerror(ep);
2740Sstevel@tonic-gate
2750Sstevel@tonic-gate /* cleanup, return success */
2760Sstevel@tonic-gate out:
2770Sstevel@tonic-gate meta_tab_free(tabp);
2780Sstevel@tonic-gate return (eval);
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate /*
2820Sstevel@tonic-gate * initialize named device or hotspare pool
2830Sstevel@tonic-gate */
2840Sstevel@tonic-gate static int
init_name(mdsetname_t ** spp,int argc,char * argv[],mdcmdopts_t options,int called_thru_rpc,md_error_t * ep)2850Sstevel@tonic-gate init_name(
2860Sstevel@tonic-gate mdsetname_t **spp,
2870Sstevel@tonic-gate int argc,
2880Sstevel@tonic-gate char *argv[],
2890Sstevel@tonic-gate mdcmdopts_t options,
2900Sstevel@tonic-gate int called_thru_rpc,
2910Sstevel@tonic-gate md_error_t *ep
2920Sstevel@tonic-gate )
2930Sstevel@tonic-gate {
2940Sstevel@tonic-gate md_tab_t *tabp = NULL;
2950Sstevel@tonic-gate md_tab_line_t *linep = NULL;
2960Sstevel@tonic-gate int rval = -1;
2970Sstevel@tonic-gate int ret;
2981623Stw21770 char *uname = argv[0];
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate /* look in md.tab */
3010Sstevel@tonic-gate if (argc == 1) {
3020Sstevel@tonic-gate /* get md.tab entries */
3030Sstevel@tonic-gate if ((tabp = meta_tab_parse(NULL, ep)) == NULL) {
3040Sstevel@tonic-gate if (! mdissyserror(ep, ENOENT))
3050Sstevel@tonic-gate return (-1);
3060Sstevel@tonic-gate }
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate /* look in md.tab */
3091623Stw21770 if ((linep = meta_tab_find(*spp, tabp, uname, TAB_MD_HSP))
3100Sstevel@tonic-gate != NULL) {
3110Sstevel@tonic-gate argc = linep->argc;
3120Sstevel@tonic-gate argv = linep->argv;
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate }
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate if ((called_thru_rpc == FALSE) &&
3171623Stw21770 meta_is_mn_name(spp, uname, ep)) {
3180Sstevel@tonic-gate /*
3190Sstevel@tonic-gate * MN set, send command to all nodes
3200Sstevel@tonic-gate */
3210Sstevel@tonic-gate ret = mn_send_command(spp, argc, argv, options,
3220Sstevel@tonic-gate MD_DISP_STDERR, NO_CONTEXT_STRING, ep);
3231623Stw21770 } else {
3241623Stw21770 char *cname = NULL;
3251623Stw21770
3261623Stw21770 cname = meta_name_getname(spp, uname, META_DEVICE, ep);
3271623Stw21770 if (cname == NULL) {
3281623Stw21770 goto out;
3291623Stw21770 }
3301623Stw21770
3311623Stw21770 /* check for ownership */
3321623Stw21770 if (meta_check_ownership(*spp, ep) != 0) {
3331623Stw21770 Free(cname);
3341623Stw21770 goto out;
3351623Stw21770 }
3361623Stw21770
3371623Stw21770 ret = meta_init_name(spp, argc, argv, cname, options, ep);
3381623Stw21770 Free(cname);
3391623Stw21770 }
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate if (ret != 0) {
3420Sstevel@tonic-gate if (linep != NULL)
3430Sstevel@tonic-gate mderrorextra(ep, linep->context);
3440Sstevel@tonic-gate goto out;
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate rval = 0; /* success */
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate /* cleanup, return error */
3490Sstevel@tonic-gate out:
3500Sstevel@tonic-gate if (tabp != NULL)
3510Sstevel@tonic-gate meta_tab_free(tabp);
3520Sstevel@tonic-gate return (rval);
3530Sstevel@tonic-gate }
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate /*
3560Sstevel@tonic-gate * print usage message
3570Sstevel@tonic-gate */
3580Sstevel@tonic-gate static void
usage(mdsetname_t * sp,int eval)3590Sstevel@tonic-gate usage(
3600Sstevel@tonic-gate mdsetname_t *sp,
3610Sstevel@tonic-gate int eval
3620Sstevel@tonic-gate )
3630Sstevel@tonic-gate {
3640Sstevel@tonic-gate #ifndef lint
3650Sstevel@tonic-gate (void) fprintf(stderr, gettext("\
3660Sstevel@tonic-gate usage: %s [-s setname] [-n] [-f] concat/stripe numstripes\n\
3670Sstevel@tonic-gate width component... [-i interlace]\n\
3680Sstevel@tonic-gate [width component... [-i interlace]] [-h hotspare_pool]\n\
3690Sstevel@tonic-gate %s [-s setname] [-n] [-f] mirror -m submirror...\n\
3700Sstevel@tonic-gate [read_options] [write_options] [pass_num]\n\
3710Sstevel@tonic-gate %s [-s setname] [-n] [-f] RAID -r component...\n\
3720Sstevel@tonic-gate [-i interlace] [-h hotspare_pool]\n\
3730Sstevel@tonic-gate [-k] [-o original_column_count]\n\
3740Sstevel@tonic-gate %s [-s setname] [-n] [-f] hotspare_pool [hotspare...]\n\
3750Sstevel@tonic-gate %s [-s setname] [-n] [-f] softpart -p [-A alignment]\n\
3760Sstevel@tonic-gate [-e] device size|all\n\
3770Sstevel@tonic-gate %s [-s setname] [-n] [-f] md.tab_entry\n\
3780Sstevel@tonic-gate %s [-s setname] [-n] [-f] -a\n\
3790Sstevel@tonic-gate %s -r\n"), myname, myname, myname, myname, myname, myname, myname,
3800Sstevel@tonic-gate myname);
3810Sstevel@tonic-gate #endif /* ! lint */
3820Sstevel@tonic-gate md_exit(sp, eval);
3830Sstevel@tonic-gate }
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate /*
3860Sstevel@tonic-gate * If we fail during the attempt to take the auto-take disksets
3870Sstevel@tonic-gate * we need to tell the kernel to cleanup the in-core set struct
3880Sstevel@tonic-gate * so that we have a chance to take the set again later.
3890Sstevel@tonic-gate */
3900Sstevel@tonic-gate static void
auto_take_cleanup(mdsetname_t * sp,side_t sideno)3910Sstevel@tonic-gate auto_take_cleanup(mdsetname_t *sp, side_t sideno)
3920Sstevel@tonic-gate {
3930Sstevel@tonic-gate mddb_config_t c;
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate (void) memset(&c, 0, sizeof (c));
3960Sstevel@tonic-gate c.c_setno = sp->setno;
3970Sstevel@tonic-gate c.c_sideno = sideno;
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate if (metaioctl(MD_RELEASE_SET, &c, &c.c_mde, NULL) != 0) {
4000Sstevel@tonic-gate mde_perror(&c.c_mde, "auto_take_cleanup");
4010Sstevel@tonic-gate return;
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate /*
4060Sstevel@tonic-gate * Take the diskset.
4070Sstevel@tonic-gate *
4080Sstevel@tonic-gate * This is a clean auto-take set, so do the work to take it.
4090Sstevel@tonic-gate * This is a streamlined version of the code in meta_set_take. We avoid the
4100Sstevel@tonic-gate * need for talking to the rpc.metad since that can't run this early during the
4110Sstevel@tonic-gate * boot. We don't need to talk to the metad for this diskset since we're the
4120Sstevel@tonic-gate * only host in the set.
4130Sstevel@tonic-gate */
4140Sstevel@tonic-gate static void
take_set(md_set_record * sr)4150Sstevel@tonic-gate take_set(md_set_record *sr)
4160Sstevel@tonic-gate {
4170Sstevel@tonic-gate mdsetname_t sn;
4180Sstevel@tonic-gate md_drive_desc *dd;
4190Sstevel@tonic-gate md_error_t error = mdnullerror;
4200Sstevel@tonic-gate md_replicalist_t *rlp = NULL;
4210Sstevel@tonic-gate md_replicalist_t *rl;
4220Sstevel@tonic-gate daddr_t nblks = 0;
4230Sstevel@tonic-gate md_drive_record *dr;
4240Sstevel@tonic-gate side_t sideno;
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate /*
4270Sstevel@tonic-gate * Several of the functions we call take a sp param so
4280Sstevel@tonic-gate * construct one from the set record.
4290Sstevel@tonic-gate */
4300Sstevel@tonic-gate sn.setname = sr->sr_setname;
4310Sstevel@tonic-gate sn.setno = sr->sr_setno;
4320Sstevel@tonic-gate sn.setdesc = sr2setdesc(sr);
4330Sstevel@tonic-gate sn.lockfd = MD_NO_LOCK;
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate if (sr->sr_flags & MD_SR_MB_DEVID)
4360Sstevel@tonic-gate dd = metaget_drivedesc(&sn, MD_BASICNAME_OK | PRINT_FAST,
4370Sstevel@tonic-gate &error);
4380Sstevel@tonic-gate else
4390Sstevel@tonic-gate dd = metaget_drivedesc(&sn, MD_BASICNAME_OK, &error);
4400Sstevel@tonic-gate
4410Sstevel@tonic-gate if (dd == NULL) {
4420Sstevel@tonic-gate mde_perror(&error, "");
4430Sstevel@tonic-gate mdclrerror(&error);
4440Sstevel@tonic-gate return;
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate
4470Sstevel@tonic-gate /*
4480Sstevel@tonic-gate * Skip call to tk_own_bydd. This talks to rpc.metamhd (which we can't
4490Sstevel@tonic-gate * do yet) and is not needed for auto-take disksets since we are not
4500Sstevel@tonic-gate * doing SCSI reservations on these drives.
4510Sstevel@tonic-gate */
4520Sstevel@tonic-gate
4530Sstevel@tonic-gate if (setup_db_bydd(&sn, dd, 0, &error) != 0) {
4540Sstevel@tonic-gate if (! mdismddberror(&error, MDE_DB_ACCOK) &&
4550Sstevel@tonic-gate ! mdismddberror(&error, MDE_DB_TAGDATA)) {
4560Sstevel@tonic-gate /*
4570Sstevel@tonic-gate * Skip call to rel_own_bydd since that really just
4580Sstevel@tonic-gate * calls rpc.metamhd which we don't need to do,
4590Sstevel@tonic-gate * so there really isn't anything to rollback here.
4600Sstevel@tonic-gate */
4610Sstevel@tonic-gate mde_perror(&error, "");
4620Sstevel@tonic-gate mdclrerror(&error);
4630Sstevel@tonic-gate return;
4640Sstevel@tonic-gate }
4650Sstevel@tonic-gate mdclrerror(&error);
4660Sstevel@tonic-gate }
4670Sstevel@tonic-gate
4680Sstevel@tonic-gate if ((sideno = getmyside(&sn, &error)) == MD_SIDEWILD) {
4690Sstevel@tonic-gate mde_perror(&error, "");
4700Sstevel@tonic-gate return;
4710Sstevel@tonic-gate }
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate if (snarf_set(&sn, FALSE, &error) != 0) {
4740Sstevel@tonic-gate if (mdismddberror(&error, MDE_DB_STALE) ||
4750Sstevel@tonic-gate mdismddberror(&error, MDE_DB_TAGDATA) ||
4760Sstevel@tonic-gate ! mdismddberror(&error, MDE_DB_NODB) &&
4770Sstevel@tonic-gate ! mdismddberror(&error, MDE_DB_NOTOWNER)) {
4780Sstevel@tonic-gate /*
4790Sstevel@tonic-gate * rollback
4800Sstevel@tonic-gate * Normally MDE_DB_STALE or MDE_DB_TAGDATA
4810Sstevel@tonic-gate * would still keep the set but in this case we don't
4820Sstevel@tonic-gate * want to do that. This will probably result in the
4830Sstevel@tonic-gate * boot going in to single-user since we won't have the
4840Sstevel@tonic-gate * set so any attempted mounts using the set's metadevices
4850Sstevel@tonic-gate * will fail. However, that is a "good thing" so the
4860Sstevel@tonic-gate * sysadmin can fix the set. Normally they would see
4870Sstevel@tonic-gate * all of these problems when they ran the take and be
4880Sstevel@tonic-gate * able to immediately fix the problem.
4890Sstevel@tonic-gate */
4900Sstevel@tonic-gate mde_perror(&error, "");
4910Sstevel@tonic-gate auto_take_cleanup(&sn, sideno);
4920Sstevel@tonic-gate return;
4930Sstevel@tonic-gate }
4940Sstevel@tonic-gate }
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate /*
4970Sstevel@tonic-gate * Call metareplicalist and upd_dr_dbinfo.
4980Sstevel@tonic-gate * Most of that code is only needed to synchronize amongst the multiple
4990Sstevel@tonic-gate * hosts in a set, which is not applicable in our case. But we do a
5000Sstevel@tonic-gate * subset here to handle the case when the user had been
5010Sstevel@tonic-gate * adding/deleting/balancing mddbs when this node panic'd. We are
5020Sstevel@tonic-gate * synchronizing the ondisk mddbs to the list of drive records stored
5030Sstevel@tonic-gate * in the local mddb.
5040Sstevel@tonic-gate */
5050Sstevel@tonic-gate if (metareplicalist(&sn, (MD_BASICNAME_OK | PRINT_FAST), &rlp, &error)
5060Sstevel@tonic-gate < 0) {
5070Sstevel@tonic-gate /* rollback */
5080Sstevel@tonic-gate mde_perror(&error, "");
5090Sstevel@tonic-gate auto_take_cleanup(&sn, sideno);
5100Sstevel@tonic-gate return;
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate /*
5140Sstevel@tonic-gate * The following code is equivalent to upd_dr_dbinfo for syncronizing
5150Sstevel@tonic-gate * the local host only. That function is normally run through the
5160Sstevel@tonic-gate * metad with a local and daemon side but we'll do all of the work
5170Sstevel@tonic-gate * here.
5180Sstevel@tonic-gate */
5190Sstevel@tonic-gate
5200Sstevel@tonic-gate /* find the smallest existing replica */
5210Sstevel@tonic-gate for (rl = rlp; rl != NULL; rl = rl->rl_next) {
5220Sstevel@tonic-gate md_replica_t *r;
5230Sstevel@tonic-gate
5240Sstevel@tonic-gate r = rl->rl_repp;
5250Sstevel@tonic-gate nblks = ((nblks == 0) ? r->r_nblk : min(r->r_nblk, nblks));
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate if (nblks <= 0)
5290Sstevel@tonic-gate nblks = MD_DBSIZE;
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate for (dr = sr->sr_drivechain; dr; dr = dr->dr_next) {
5320Sstevel@tonic-gate int dbcnt;
5330Sstevel@tonic-gate mddrivename_t *dnp;
5340Sstevel@tonic-gate md_replicalist_t *rl;
5350Sstevel@tonic-gate
5360Sstevel@tonic-gate /*
5370Sstevel@tonic-gate * The cname style for dnp and replica list will be same since
5380Sstevel@tonic-gate * both use the the same flags MD_BASICNAME_OK|PRINT_FAST which
5390Sstevel@tonic-gate * will always provide the cached value.
5400Sstevel@tonic-gate */
5410Sstevel@tonic-gate if ((dnp = metadrivename_withdrkey(&sn, sideno, dr->dr_key,
5420Sstevel@tonic-gate MD_BASICNAME_OK | PRINT_FAST, &error)) == NULL) {
5430Sstevel@tonic-gate mde_perror(&error, "");
5440Sstevel@tonic-gate metafreereplicalist(rlp);
5450Sstevel@tonic-gate auto_take_cleanup(&sn, sideno);
5460Sstevel@tonic-gate return;
5470Sstevel@tonic-gate }
5480Sstevel@tonic-gate
5490Sstevel@tonic-gate dbcnt = 0;
5500Sstevel@tonic-gate /* see how many replicas are on this drive */
5510Sstevel@tonic-gate for (rl = rlp; rl != NULL; rl = rl->rl_next) {
5520Sstevel@tonic-gate if (strcmp(rl->rl_repp->r_namep->drivenamep->cname, dnp->cname)
5530Sstevel@tonic-gate == 0)
5540Sstevel@tonic-gate dbcnt++;
5550Sstevel@tonic-gate }
5560Sstevel@tonic-gate
5570Sstevel@tonic-gate /* Adjust the fields in the copy */
5580Sstevel@tonic-gate dr->dr_dbcnt = dbcnt;
5590Sstevel@tonic-gate dr->dr_dbsize = dbcnt > 0 ? nblks : 0;
5600Sstevel@tonic-gate }
5610Sstevel@tonic-gate
5620Sstevel@tonic-gate /*
5630Sstevel@tonic-gate * If the set doesn't have the MD_SR_MB_DEVID bit set, i.e
5640Sstevel@tonic-gate * the drives in the set don't have the device id information,
5650Sstevel@tonic-gate * then stick it in if possible.
5660Sstevel@tonic-gate *
5670Sstevel@tonic-gate * If updating the master block fails for whatever reason, it's
5680Sstevel@tonic-gate * okay. It just means the disk(s) in the diskset won't be self
5690Sstevel@tonic-gate * identifying.
5700Sstevel@tonic-gate */
5710Sstevel@tonic-gate if (!(sr->sr_flags & MD_SR_MB_DEVID)) {
5720Sstevel@tonic-gate if (meta_update_mb(&sn, dd, &error) == 0) {
5730Sstevel@tonic-gate sr->sr_flags |= MD_SR_MB_DEVID;
5740Sstevel@tonic-gate mdclrerror(&error);
5750Sstevel@tonic-gate }
5760Sstevel@tonic-gate }
5770Sstevel@tonic-gate
5780Sstevel@tonic-gate commitset(sr, FALSE, &error);
5790Sstevel@tonic-gate
5800Sstevel@tonic-gate metafreereplicalist(rlp);
5810Sstevel@tonic-gate
5820Sstevel@tonic-gate /*
5830Sstevel@tonic-gate * This finishes up the logical equivalent of meta_set_take.
5840Sstevel@tonic-gate */
5850Sstevel@tonic-gate if (meta_resync_all(&sn, MD_DEF_RESYNC_BUF_SIZE, &error) != 0) {
5860Sstevel@tonic-gate mde_perror(&error, "");
5870Sstevel@tonic-gate mdclrerror(&error);
5880Sstevel@tonic-gate }
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate /*
5920Sstevel@tonic-gate * Take the disksets that are marked to be taken at boot time.
5930Sstevel@tonic-gate */
5940Sstevel@tonic-gate static void
auto_take_sets()5950Sstevel@tonic-gate auto_take_sets()
5960Sstevel@tonic-gate {
5970Sstevel@tonic-gate int max_sets;
5980Sstevel@tonic-gate int i;
5990Sstevel@tonic-gate md_error_t error = mdnullerror;
6000Sstevel@tonic-gate char *hostname;
6010Sstevel@tonic-gate
6020Sstevel@tonic-gate if ((max_sets = get_max_sets(&error)) == 0)
6030Sstevel@tonic-gate return;
6040Sstevel@tonic-gate
6050Sstevel@tonic-gate if (!mdisok(&error)) {
6060Sstevel@tonic-gate mde_perror(&error, "");
6070Sstevel@tonic-gate return;
6080Sstevel@tonic-gate }
6090Sstevel@tonic-gate
6100Sstevel@tonic-gate /* set up so auto-take errors also go to syslog */
6110Sstevel@tonic-gate openlog("metainit", LOG_ODELAY, LOG_USER);
6120Sstevel@tonic-gate metasyslog = 1;
6130Sstevel@tonic-gate
6140Sstevel@tonic-gate hostname = mynode();
6150Sstevel@tonic-gate
6160Sstevel@tonic-gate /*
6170Sstevel@tonic-gate * For each possible set number (skip set 0 which is the unnamed local
6180Sstevel@tonic-gate * set), see if we really have a diskset. If so, check if auto-take
6190Sstevel@tonic-gate * is enabled.
6200Sstevel@tonic-gate *
6210Sstevel@tonic-gate * In order to take the set it must have drives and it must not be
6220Sstevel@tonic-gate * stuck in mid-add. The sr_validate routine within rpc.metad will
6230Sstevel@tonic-gate * delete sets that are in mid-add when it runs.
6240Sstevel@tonic-gate */
6250Sstevel@tonic-gate for (i = 1; i < max_sets; i++) {
6260Sstevel@tonic-gate md_set_record *sr;
6270Sstevel@tonic-gate
6280Sstevel@tonic-gate if ((sr = metad_getsetbynum(i, &error)) == NULL) {
6290Sstevel@tonic-gate mdclrerror(&error);
6300Sstevel@tonic-gate continue;
6310Sstevel@tonic-gate }
6320Sstevel@tonic-gate
6330Sstevel@tonic-gate if (sr->sr_flags & MD_SR_AUTO_TAKE && !(sr->sr_flags & MD_SR_ADD)) {
6340Sstevel@tonic-gate int j;
6350Sstevel@tonic-gate int cnt = 0;
6360Sstevel@tonic-gate int host_mismatch = 0;
6370Sstevel@tonic-gate int take = 0;
6380Sstevel@tonic-gate md_drive_record *dr;
6390Sstevel@tonic-gate
6400Sstevel@tonic-gate /* check for host renames or multiple hosts in set */
6410Sstevel@tonic-gate for (j = 0; j < MD_MAXSIDES; j++) {
6420Sstevel@tonic-gate /* Skip empty slots */
6430Sstevel@tonic-gate if (sr->sr_nodes[j][0] == '\0')
6440Sstevel@tonic-gate continue;
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate cnt++;
6470Sstevel@tonic-gate if (strcmp(sr->sr_nodes[j], hostname) != 0)
6480Sstevel@tonic-gate host_mismatch = 1;
6490Sstevel@tonic-gate }
6500Sstevel@tonic-gate
6510Sstevel@tonic-gate /* paranoid check that we're the only host in the set */
6520Sstevel@tonic-gate if (cnt > 1) {
6530Sstevel@tonic-gate md_eprintf(gettext(
6540Sstevel@tonic-gate "diskset %s: auto-take enabled and multiple hosts in set\n"),
6550Sstevel@tonic-gate sr->sr_setname);
6560Sstevel@tonic-gate continue;
6570Sstevel@tonic-gate }
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate if (host_mismatch) {
6600Sstevel@tonic-gate /* The host was renamed, repair the set. */
6610Sstevel@tonic-gate for (j = 0; j < MD_MAXSIDES; j++) {
6620Sstevel@tonic-gate /* Skip empty slots */
6630Sstevel@tonic-gate if (sr->sr_nodes[j][0] == '\0')
6640Sstevel@tonic-gate continue;
6650Sstevel@tonic-gate
6660Sstevel@tonic-gate (void) strncpy(sr->sr_nodes[j], hostname,
6670Sstevel@tonic-gate sizeof (sr->sr_nodes[j]));
6680Sstevel@tonic-gate commitset(sr, FALSE, &error);
6690Sstevel@tonic-gate if (!mdisok(&error)) {
6700Sstevel@tonic-gate mde_perror(&error, "");
6710Sstevel@tonic-gate mdclrerror(&error);
6720Sstevel@tonic-gate } else {
6730Sstevel@tonic-gate md_eprintf(gettext(
6740Sstevel@tonic-gate "new hostname %s, update auto-take diskset %s\n"),
6750Sstevel@tonic-gate hostname, sr->sr_setname);
6760Sstevel@tonic-gate }
6770Sstevel@tonic-gate break;
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate }
6800Sstevel@tonic-gate
6810Sstevel@tonic-gate /* set must have at least one drive to be taken */
6820Sstevel@tonic-gate for (dr = sr->sr_drivechain; dr != NULL; dr = dr->dr_next) {
6830Sstevel@tonic-gate /* ignore drives in mid-add */
6840Sstevel@tonic-gate if (!(dr->dr_flags & MD_DR_ADD)) {
6850Sstevel@tonic-gate take = 1;
6860Sstevel@tonic-gate break;
6870Sstevel@tonic-gate }
6880Sstevel@tonic-gate }
6890Sstevel@tonic-gate
6900Sstevel@tonic-gate if (take)
6910Sstevel@tonic-gate take_set(sr);
6920Sstevel@tonic-gate else
6930Sstevel@tonic-gate md_eprintf(gettext(
6940Sstevel@tonic-gate "diskset %s: auto-take enabled but set has no drives\n"),
6950Sstevel@tonic-gate sr->sr_setname);
6960Sstevel@tonic-gate }
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate }
6990Sstevel@tonic-gate
7000Sstevel@tonic-gate /*
7010Sstevel@tonic-gate * mainline. crack command line arguments.
7020Sstevel@tonic-gate */
7030Sstevel@tonic-gate int
main(int argc,char * argv[])7040Sstevel@tonic-gate main(
7050Sstevel@tonic-gate int argc,
7060Sstevel@tonic-gate char *argv[]
7070Sstevel@tonic-gate )
7080Sstevel@tonic-gate {
7091623Stw21770 char *sname = MD_LOCAL_NAME;
7100Sstevel@tonic-gate mdsetname_t *sp = NULL;
7110Sstevel@tonic-gate enum action {
7120Sstevel@tonic-gate NONE,
7130Sstevel@tonic-gate INIT,
7140Sstevel@tonic-gate ALL
7150Sstevel@tonic-gate } todo = NONE;
7160Sstevel@tonic-gate mdcmdopts_t options = (MDCMD_DOIT | MDCMD_PRINT);
7170Sstevel@tonic-gate int c;
7180Sstevel@tonic-gate md_error_t status = mdnullerror;
7190Sstevel@tonic-gate md_error_t *ep = &status;
7200Sstevel@tonic-gate
7210Sstevel@tonic-gate md_error_t dummystatus = mdnullerror;
7220Sstevel@tonic-gate md_error_t *dummyep = &dummystatus;
7230Sstevel@tonic-gate int eval = 1;
7240Sstevel@tonic-gate int error;
7250Sstevel@tonic-gate bool_t called_thru_rpc = FALSE;
7260Sstevel@tonic-gate char *cp;
727*7044Smk117520 pid_t pid;
7280Sstevel@tonic-gate
7290Sstevel@tonic-gate /*
7300Sstevel@tonic-gate * Get the locale set up before calling any other routines
7310Sstevel@tonic-gate * with messages to ouput. Just in case we're not in a build
7320Sstevel@tonic-gate * environment, make sure that TEXT_DOMAIN gets set to
7330Sstevel@tonic-gate * something.
7340Sstevel@tonic-gate */
7350Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
7360Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
7370Sstevel@tonic-gate #endif
7380Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
7390Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
7400Sstevel@tonic-gate if ((cp = strstr(argv[0], ".rpc_call")) != NULL) {
7410Sstevel@tonic-gate *cp = '\0'; /* cut off ".rpc_call" */
7420Sstevel@tonic-gate called_thru_rpc = TRUE;
7430Sstevel@tonic-gate } else {
7440Sstevel@tonic-gate if (sdssc_bind_library() == SDSSC_OKAY)
7450Sstevel@tonic-gate if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY,
7460Sstevel@tonic-gate &error) == SDSSC_PROXY_DONE)
7470Sstevel@tonic-gate exit(error);
7480Sstevel@tonic-gate }
7490Sstevel@tonic-gate
7500Sstevel@tonic-gate /* initialize */
7510Sstevel@tonic-gate if (md_init(argc, argv, 0, 1, ep) != 0 ||
7520Sstevel@tonic-gate meta_check_root(ep) != 0) {
7530Sstevel@tonic-gate mde_perror(ep, "");
7540Sstevel@tonic-gate md_exit(sp, 1);
7550Sstevel@tonic-gate }
7560Sstevel@tonic-gate
7570Sstevel@tonic-gate /* parse args */
7580Sstevel@tonic-gate optind = 1;
7590Sstevel@tonic-gate opterr = 1;
7600Sstevel@tonic-gate while ((c = getopt(argc, argv, "afhnrs:?")) != -1) {
7610Sstevel@tonic-gate switch (c) {
7620Sstevel@tonic-gate
7630Sstevel@tonic-gate /* help */
7640Sstevel@tonic-gate case 'h':
7650Sstevel@tonic-gate usage(sp, 0);
7660Sstevel@tonic-gate break;
7670Sstevel@tonic-gate
7680Sstevel@tonic-gate /* set name */
7690Sstevel@tonic-gate case 's':
7700Sstevel@tonic-gate sname = optarg;
7710Sstevel@tonic-gate break;
7720Sstevel@tonic-gate
7730Sstevel@tonic-gate /* all devices in md.tab */
7740Sstevel@tonic-gate case 'a':
7750Sstevel@tonic-gate if (todo != NONE)
7760Sstevel@tonic-gate usage(sp, 1);
7770Sstevel@tonic-gate todo = ALL;
7780Sstevel@tonic-gate options |= MDCMD_ALLOPTION;
7790Sstevel@tonic-gate break;
7800Sstevel@tonic-gate /* check for validity, but don't really init */
7810Sstevel@tonic-gate case 'n':
7820Sstevel@tonic-gate options &= ~MDCMD_DOIT;
7830Sstevel@tonic-gate break;
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate /* for recovery */
7860Sstevel@tonic-gate case 'r':
7870Sstevel@tonic-gate if (todo != NONE)
7880Sstevel@tonic-gate usage(sp, 1);
7890Sstevel@tonic-gate todo = INIT;
7900Sstevel@tonic-gate break;
7910Sstevel@tonic-gate
7920Sstevel@tonic-gate /* mounted and swapped components are OK */
7930Sstevel@tonic-gate case 'f':
7940Sstevel@tonic-gate options |= MDCMD_FORCE;
7950Sstevel@tonic-gate break;
7960Sstevel@tonic-gate
7970Sstevel@tonic-gate case '?':
7980Sstevel@tonic-gate if (optopt == '?')
7990Sstevel@tonic-gate usage(sp, 0);
8000Sstevel@tonic-gate /*FALLTHROUGH*/
8010Sstevel@tonic-gate default:
8020Sstevel@tonic-gate usage(sp, 1);
8030Sstevel@tonic-gate break;
8040Sstevel@tonic-gate }
8050Sstevel@tonic-gate }
8060Sstevel@tonic-gate
8071623Stw21770 /* sname is MD_LOCAL_NAME if not specified on the command line */
8081623Stw21770 if ((sp = metasetname(sname, ep)) == NULL) {
8091623Stw21770 mde_perror(ep, "");
8101623Stw21770 md_exit(sp, 1);
8110Sstevel@tonic-gate }
8121623Stw21770
8130Sstevel@tonic-gate argc -= optind;
8140Sstevel@tonic-gate argv += optind;
8150Sstevel@tonic-gate if (todo == NONE) {
8160Sstevel@tonic-gate if (argc <= 0) {
8170Sstevel@tonic-gate usage(sp, 1);
8180Sstevel@tonic-gate }
8190Sstevel@tonic-gate } else if (argc > 0) {
8200Sstevel@tonic-gate usage(sp, 1);
8210Sstevel@tonic-gate }
8220Sstevel@tonic-gate
8230Sstevel@tonic-gate
8240Sstevel@tonic-gate /* setup database locations */
8250Sstevel@tonic-gate if (meta_setup_db_locations(ep) != 0) {
8260Sstevel@tonic-gate mde_perror(ep, "");
8270Sstevel@tonic-gate if (mdismddberror(ep, MDE_DB_STALE))
8280Sstevel@tonic-gate md_exit(sp, 66);
8290Sstevel@tonic-gate if (! mdiserror(ep, MDE_MDDB_CKSUM)) /* relatively benign */
8300Sstevel@tonic-gate md_exit(sp, 1);
8310Sstevel@tonic-gate }
8320Sstevel@tonic-gate if (todo == INIT) { /* load and take auto-take sets */
8330Sstevel@tonic-gate auto_take_sets();
834*7044Smk117520
835*7044Smk117520 /*
836*7044Smk117520 * During the boot sequence we need to update the mediator
837*7044Smk117520 * records, however this depends upon the rpc.metamedd
838*7044Smk117520 * running. So, in order to not introduce a delay in the
839*7044Smk117520 * boot time, fork a new process to do this work in the
840*7044Smk117520 * background.
841*7044Smk117520 */
842*7044Smk117520 pid = fork1();
843*7044Smk117520 if (pid == (pid_t)-1) {
844*7044Smk117520 /*
845*7044Smk117520 * We could not fork a child process to udpate mediator
846*7044Smk117520 * information on this node. There is no need to panic.
847*7044Smk117520 * We shall simply return 1.
848*7044Smk117520 */
849*7044Smk117520 mde_perror(ep, "Could not fork a child process to"
850*7044Smk117520 " update mediator record");
851*7044Smk117520 md_exit(sp, 1);
852*7044Smk117520 } else if (pid == (pid_t)0) {
853*7044Smk117520 /* child */
854*7044Smk117520 if (meta_mediator_info_from_file(NULL, 0, ep) == 1) {
855*7044Smk117520 /*
856*7044Smk117520 * No need to print any error messages.
857*7044Smk117520 * All the errors messages are printed in the
858*7044Smk117520 * library routine itself.
859*7044Smk117520 */
860*7044Smk117520 md_exit(sp, 1);
861*7044Smk117520 } else {
862*7044Smk117520 md_exit(sp, 0);
863*7044Smk117520 }
864*7044Smk117520 } else {
865*7044Smk117520 /* Parent process */
866*7044Smk117520 md_exit(sp, 0);
867*7044Smk117520 }
8680Sstevel@tonic-gate } else if (todo == ALL) { /* initialize all devices in md.tab */
8690Sstevel@tonic-gate eval = init_all(&sp, options, called_thru_rpc, ep);
8700Sstevel@tonic-gate } else { /* initialize the named device */
8710Sstevel@tonic-gate eval = 0;
8720Sstevel@tonic-gate if (init_name(&sp, argc, argv, options, called_thru_rpc,
8730Sstevel@tonic-gate ep) != 0) {
8740Sstevel@tonic-gate /*
8750Sstevel@tonic-gate * If we're dealing with MN metadevices and we are
8760Sstevel@tonic-gate * directly called, then the appropriate error message
8770Sstevel@tonic-gate * has already been displayed. So just exit.
8780Sstevel@tonic-gate */
8790Sstevel@tonic-gate if (meta_is_mn_set(sp, dummyep) && (!called_thru_rpc)) {
8800Sstevel@tonic-gate md_exit(sp, 1);
8810Sstevel@tonic-gate }
8820Sstevel@tonic-gate mde_perror(ep, "");
8830Sstevel@tonic-gate mdclrerror(ep);
8840Sstevel@tonic-gate eval = 1;
8850Sstevel@tonic-gate goto nomdcf;
8860Sstevel@tonic-gate }
8870Sstevel@tonic-gate }
8880Sstevel@tonic-gate
8890Sstevel@tonic-gate domdcf:
8900Sstevel@tonic-gate /* update md.cf, return success */
8910Sstevel@tonic-gate if (meta_update_md_cf(sp, ep) != 0) {
8920Sstevel@tonic-gate mde_perror(ep, "");
8930Sstevel@tonic-gate eval = 1;
8940Sstevel@tonic-gate }
8950Sstevel@tonic-gate
8960Sstevel@tonic-gate nomdcf:
8970Sstevel@tonic-gate md_exit(sp, eval);
8980Sstevel@tonic-gate /*NOTREACHED*/
8990Sstevel@tonic-gate return (eval);
9000Sstevel@tonic-gate }
901