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 /*
221623Stw21770 * 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 * Metadevice database utility.
300Sstevel@tonic-gate */
310Sstevel@tonic-gate
320Sstevel@tonic-gate #include <meta.h>
330Sstevel@tonic-gate #define MDDB
340Sstevel@tonic-gate #include <sys/lvm/md_mddb.h>
350Sstevel@tonic-gate #include <sdssc.h>
360Sstevel@tonic-gate
370Sstevel@tonic-gate enum mddb_cmd {none, attach, detach, patch, infolong, infoshort};
380Sstevel@tonic-gate
390Sstevel@tonic-gate extern int procsigs(int block, sigset_t *oldsigs, md_error_t *ep);
400Sstevel@tonic-gate
410Sstevel@tonic-gate static void
usage(mdsetname_t * sp,char * string)420Sstevel@tonic-gate usage(
430Sstevel@tonic-gate mdsetname_t *sp,
440Sstevel@tonic-gate char *string
450Sstevel@tonic-gate )
460Sstevel@tonic-gate {
470Sstevel@tonic-gate if ((string != NULL) && (*string != '\0'))
480Sstevel@tonic-gate md_eprintf("%s\n", string);
490Sstevel@tonic-gate
500Sstevel@tonic-gate (void) fprintf(stderr, gettext(
510Sstevel@tonic-gate "usage: %s [-s setname] -a [options] mddbnnn\n"
520Sstevel@tonic-gate " %s [-s setname] -a [options] device ...\n"
530Sstevel@tonic-gate " %s [-s setname] -d [options] mddbnnn\n"
540Sstevel@tonic-gate " %s [-s setname] -d [options] device ...\n"
550Sstevel@tonic-gate " %s [-s setname] -i \n"
560Sstevel@tonic-gate " %s -p [options] [ mddb.cf-file ]\n"
570Sstevel@tonic-gate "options:\n"
580Sstevel@tonic-gate "-c count number of replicas (for use with -a only)\n"
590Sstevel@tonic-gate "-f force adding or deleting of replicas\n"
600Sstevel@tonic-gate "-k filename alternate /etc/system file\n"
610Sstevel@tonic-gate "-l length specify size of replica (for use with -a only)\n"),
620Sstevel@tonic-gate myname, myname, myname, myname, myname, myname);
630Sstevel@tonic-gate
640Sstevel@tonic-gate md_exit(sp, (string == NULL) ? 0 : 1);
650Sstevel@tonic-gate }
660Sstevel@tonic-gate
670Sstevel@tonic-gate static mdname_t *
make_dbname(mdsetname_t * sp,mdnamelist_t ** nlp,char * name,md_error_t * ep)680Sstevel@tonic-gate make_dbname(
690Sstevel@tonic-gate mdsetname_t *sp,
700Sstevel@tonic-gate mdnamelist_t **nlp,
710Sstevel@tonic-gate char *name,
720Sstevel@tonic-gate md_error_t *ep
730Sstevel@tonic-gate )
740Sstevel@tonic-gate {
750Sstevel@tonic-gate mdname_t *np;
760Sstevel@tonic-gate
771623Stw21770 if ((np = metaname(&sp, name, LOGICAL_DEVICE, ep)) == NULL)
780Sstevel@tonic-gate return (NULL);
790Sstevel@tonic-gate
800Sstevel@tonic-gate return (metanamelist_append(nlp, np));
810Sstevel@tonic-gate }
820Sstevel@tonic-gate
830Sstevel@tonic-gate static mdnamelist_t *
get_dbnames_fromfile(mdsetname_t * sp,mdnamelist_t ** nlp,char * tabname,int * dbsize,int * dbcnt,int * default_size,md_error_t * ep)840Sstevel@tonic-gate get_dbnames_fromfile(
850Sstevel@tonic-gate mdsetname_t *sp,
860Sstevel@tonic-gate mdnamelist_t **nlp,
870Sstevel@tonic-gate char *tabname,
880Sstevel@tonic-gate int *dbsize,
890Sstevel@tonic-gate int *dbcnt,
900Sstevel@tonic-gate int *default_size,
910Sstevel@tonic-gate md_error_t *ep
920Sstevel@tonic-gate )
930Sstevel@tonic-gate {
940Sstevel@tonic-gate md_tab_t *tabp = NULL;
950Sstevel@tonic-gate md_tab_line_t *linep = NULL;
960Sstevel@tonic-gate int argc;
970Sstevel@tonic-gate char **argv;
980Sstevel@tonic-gate char *context;
990Sstevel@tonic-gate int save = optind;
1000Sstevel@tonic-gate int c;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate /* look in md.tab */
1030Sstevel@tonic-gate if ((tabp = meta_tab_parse(NULL, ep)) == NULL) {
1040Sstevel@tonic-gate if (! mdissyserror(ep, ENOENT))
1050Sstevel@tonic-gate mde_perror(ep, "");
1060Sstevel@tonic-gate mdclrerror(ep);
1070Sstevel@tonic-gate return (NULL);
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate if ((linep = meta_tab_find(sp, tabp, tabname, TAB_MDDB)) == NULL) {
1110Sstevel@tonic-gate (void) mdsyserror(ep, ENOENT, tabname);
1120Sstevel@tonic-gate goto out;
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate argc = linep->argc;
1150Sstevel@tonic-gate argv = linep->argv;
1160Sstevel@tonic-gate context = linep->context;
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate /* parse up entry */
1190Sstevel@tonic-gate optind = 1;
1200Sstevel@tonic-gate opterr = 1;
1210Sstevel@tonic-gate while ((c = getopt(argc, argv, "c:l:")) != -1) {
1220Sstevel@tonic-gate switch (c) {
1230Sstevel@tonic-gate case 'c':
1240Sstevel@tonic-gate if (sscanf(optarg, "%d", dbcnt) != 1) {
1250Sstevel@tonic-gate md_eprintf("%s: %s\n",
1260Sstevel@tonic-gate context, gettext("bad format"));
1270Sstevel@tonic-gate usage(sp, "");
1280Sstevel@tonic-gate }
1290Sstevel@tonic-gate break;
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate case 'l':
1320Sstevel@tonic-gate if (sscanf(optarg, "%d", dbsize) != 1) {
1330Sstevel@tonic-gate md_eprintf("%s: %s\n",
1340Sstevel@tonic-gate context, gettext("bad format"));
1350Sstevel@tonic-gate usage(sp, "");
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate *default_size = FALSE;
1380Sstevel@tonic-gate break;
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate default:
1410Sstevel@tonic-gate usage(sp, "");
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate argc -= optind;
1450Sstevel@tonic-gate argv += optind;
1460Sstevel@tonic-gate for (; (argc > 0); --argc, ++argv) {
1470Sstevel@tonic-gate char *token = argv[0];
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate if (make_dbname(sp, nlp, token, ep) == NULL) {
1500Sstevel@tonic-gate metafreenamelist(*nlp);
1510Sstevel@tonic-gate *nlp = NULL;
1520Sstevel@tonic-gate goto out;
1530Sstevel@tonic-gate }
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate /* cleanup, return list */
1570Sstevel@tonic-gate out:
1580Sstevel@tonic-gate if (tabp != NULL)
1590Sstevel@tonic-gate meta_tab_free(tabp);
1600Sstevel@tonic-gate optind = save;
1610Sstevel@tonic-gate return (*nlp);
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate /*
1650Sstevel@tonic-gate * built list of all devices which are to be detached
1660Sstevel@tonic-gate */
1670Sstevel@tonic-gate static mdnamelist_t *
build_a_namelist(mdsetname_t * sp,int argc,char ** argv,md_error_t * ep)1680Sstevel@tonic-gate build_a_namelist(
1690Sstevel@tonic-gate mdsetname_t *sp,
1700Sstevel@tonic-gate int argc,
1710Sstevel@tonic-gate char **argv,
1720Sstevel@tonic-gate md_error_t *ep
1730Sstevel@tonic-gate )
1740Sstevel@tonic-gate {
1750Sstevel@tonic-gate int i;
1760Sstevel@tonic-gate int dbsize, dbcnt, default_size;
1770Sstevel@tonic-gate mdnamelist_t *dbnlp = NULL;
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate for (i = 0; i < argc; i++) {
1800Sstevel@tonic-gate if (strncmp(argv[i], "mddb", 4) == 0) {
1810Sstevel@tonic-gate if (get_dbnames_fromfile(sp, &dbnlp, argv[i],
1820Sstevel@tonic-gate &dbsize, &dbcnt, &default_size, ep) == NULL) {
1830Sstevel@tonic-gate /* don't freelist here - already been done */
1840Sstevel@tonic-gate return (NULL);
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate continue;
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate if (make_dbname(sp, &dbnlp, argv[i], ep) == NULL) {
1890Sstevel@tonic-gate metafreenamelist(dbnlp);
1900Sstevel@tonic-gate return (NULL);
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate }
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate return (dbnlp);
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate /*
1990Sstevel@tonic-gate * built the next list of devices which are to be attached
2000Sstevel@tonic-gate * that have the same size and count of replicas.
2010Sstevel@tonic-gate */
2020Sstevel@tonic-gate static mdnamelist_t *
build_next_namelist(mdsetname_t * sp,int argc,char ** argv,int * arg_index,int * dbsize,int * dbcnt,int * default_size,md_error_t * ep)2030Sstevel@tonic-gate build_next_namelist(
2040Sstevel@tonic-gate mdsetname_t *sp,
2050Sstevel@tonic-gate int argc,
2060Sstevel@tonic-gate char **argv,
2070Sstevel@tonic-gate int *arg_index,
2080Sstevel@tonic-gate int *dbsize,
2090Sstevel@tonic-gate int *dbcnt,
2100Sstevel@tonic-gate int *default_size,
2110Sstevel@tonic-gate md_error_t *ep
2120Sstevel@tonic-gate )
2130Sstevel@tonic-gate {
2140Sstevel@tonic-gate int i;
2150Sstevel@tonic-gate mdnamelist_t *dbnlp = NULL;
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate for (i = *arg_index; i < argc; i++) {
2180Sstevel@tonic-gate if (strncmp(argv[i], "mddb", 4) == 0) {
2190Sstevel@tonic-gate /*
2200Sstevel@tonic-gate * If we have stuff in the namelist
2210Sstevel@tonic-gate * return it before processing the mddb entry.
2220Sstevel@tonic-gate */
2230Sstevel@tonic-gate if (dbnlp) {
2240Sstevel@tonic-gate *arg_index = i;
2250Sstevel@tonic-gate return (dbnlp);
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate if (get_dbnames_fromfile(sp, &dbnlp, argv[i],
2280Sstevel@tonic-gate dbsize, dbcnt, default_size, ep) == NULL) {
2290Sstevel@tonic-gate /* don't freelist here - already been done */
2300Sstevel@tonic-gate return (NULL);
2310Sstevel@tonic-gate }
2320Sstevel@tonic-gate *arg_index = i + 1;
2330Sstevel@tonic-gate return (dbnlp);
2340Sstevel@tonic-gate }
2350Sstevel@tonic-gate if (make_dbname(sp, &dbnlp, argv[i], ep) == NULL) {
2360Sstevel@tonic-gate metafreenamelist(dbnlp);
2370Sstevel@tonic-gate return (NULL);
2380Sstevel@tonic-gate }
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate *arg_index = argc;
2410Sstevel@tonic-gate return (dbnlp);
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate static int
chngdb(mdsetname_t * sp,enum mddb_cmd cmd,int argc,char * argv[],uint_t options,md_error_t * ep)2460Sstevel@tonic-gate chngdb(
2470Sstevel@tonic-gate mdsetname_t *sp,
2480Sstevel@tonic-gate enum mddb_cmd cmd,
2490Sstevel@tonic-gate int argc,
2500Sstevel@tonic-gate char *argv[],
2510Sstevel@tonic-gate uint_t options,
2520Sstevel@tonic-gate md_error_t *ep
2530Sstevel@tonic-gate )
2540Sstevel@tonic-gate {
2550Sstevel@tonic-gate int c;
2560Sstevel@tonic-gate int i;
2570Sstevel@tonic-gate md_error_t xep = mdnullerror;
2580Sstevel@tonic-gate mdnamelist_t *dbnlp = NULL;
2590Sstevel@tonic-gate int dbsize = MD_DBSIZE;
2600Sstevel@tonic-gate int maxblks = MDDB_MAXBLKS;
2610Sstevel@tonic-gate int minblks = MDDB_MINBLKS;
2620Sstevel@tonic-gate int dbcnt = 1;
2630Sstevel@tonic-gate mdforceopts_t force = MDFORCE_NONE;
2640Sstevel@tonic-gate int rval = 0;
2650Sstevel@tonic-gate char *sysfilename = NULL;
2660Sstevel@tonic-gate int default_size = TRUE;
2670Sstevel@tonic-gate md_set_desc *sd;
2680Sstevel@tonic-gate md_setkey_t *cl_sk;
2690Sstevel@tonic-gate md_mnnode_desc *nd;
2700Sstevel@tonic-gate int suspend1_flag = 0;
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate /* reset and parse args */
2730Sstevel@tonic-gate optind = 1;
2740Sstevel@tonic-gate opterr = 1;
2750Sstevel@tonic-gate while ((c = getopt(argc, argv, "ac:dfk:pl:s:")) != -1) {
2760Sstevel@tonic-gate switch (c) {
2770Sstevel@tonic-gate case 'a':
2780Sstevel@tonic-gate break;
2790Sstevel@tonic-gate case 'c':
2800Sstevel@tonic-gate if (sscanf(optarg, "%d", &dbcnt) != 1) {
2810Sstevel@tonic-gate md_eprintf("%s: %s\n",
2820Sstevel@tonic-gate optarg, gettext("bad format"));
2830Sstevel@tonic-gate usage(sp, "");
2840Sstevel@tonic-gate }
2850Sstevel@tonic-gate break;
2860Sstevel@tonic-gate case 'd':
2870Sstevel@tonic-gate break;
2880Sstevel@tonic-gate case 'f':
2890Sstevel@tonic-gate force = MDFORCE_LOCAL;
2900Sstevel@tonic-gate break;
2910Sstevel@tonic-gate case 'k':
2920Sstevel@tonic-gate sysfilename = optarg;
2930Sstevel@tonic-gate break;
2940Sstevel@tonic-gate case 'l':
2950Sstevel@tonic-gate if (sscanf(optarg, "%d", &dbsize) != 1) {
2960Sstevel@tonic-gate md_eprintf("%s: %s\n",
2970Sstevel@tonic-gate optarg, gettext("bad format"));
2980Sstevel@tonic-gate usage(sp, "");
2990Sstevel@tonic-gate }
3000Sstevel@tonic-gate default_size = FALSE;
3010Sstevel@tonic-gate break;
3020Sstevel@tonic-gate case 'p':
3030Sstevel@tonic-gate break;
3040Sstevel@tonic-gate case 's':
3050Sstevel@tonic-gate break;
3060Sstevel@tonic-gate default:
3070Sstevel@tonic-gate usage(sp, "");
3080Sstevel@tonic-gate }
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate
3110Sstevel@tonic-gate /*
3120Sstevel@tonic-gate * If it is a multinode diskset, use appropriate metadb size.
3130Sstevel@tonic-gate */
3140Sstevel@tonic-gate if (! metaislocalset(sp)) {
3150Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL)
3160Sstevel@tonic-gate return (-1);
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
3190Sstevel@tonic-gate maxblks = MDDB_MN_MAXBLKS;
3200Sstevel@tonic-gate minblks = MDDB_MN_MINBLKS;
3210Sstevel@tonic-gate if (default_size)
3220Sstevel@tonic-gate dbsize = MD_MN_DBSIZE;
3230Sstevel@tonic-gate }
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate
3260Sstevel@tonic-gate if (dbsize > maxblks)
3270Sstevel@tonic-gate usage(sp, gettext("size (-l) is too big"));
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate if (dbsize < minblks)
3310Sstevel@tonic-gate usage(sp, gettext("size (-l) is too small"));
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate if (dbcnt < 1)
3340Sstevel@tonic-gate usage(sp, gettext(
3350Sstevel@tonic-gate "count (-c) must be 1 or more"));
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate argc -= optind;
3390Sstevel@tonic-gate argv += optind;
3400Sstevel@tonic-gate if (argc <= 0) {
3410Sstevel@tonic-gate usage(sp, gettext(
3420Sstevel@tonic-gate "no devices specified to attach or detach"));
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate if (! metaislocalset(sp)) {
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
3480Sstevel@tonic-gate md_error_t xep = mdnullerror;
3490Sstevel@tonic-gate sigset_t sigs;
3500Sstevel@tonic-gate
3510Sstevel@tonic-gate /* Make sure we are blocking all signals */
3520Sstevel@tonic-gate if (procsigs(TRUE, &sigs, &xep) < 0)
3530Sstevel@tonic-gate mdclrerror(&xep);
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate /*
3560Sstevel@tonic-gate * Lock out other metaset or metadb commands
3570Sstevel@tonic-gate * across the diskset.
3580Sstevel@tonic-gate */
3590Sstevel@tonic-gate nd = sd->sd_nodelist;
3600Sstevel@tonic-gate while (nd) {
3610Sstevel@tonic-gate if ((force & MDFORCE_LOCAL) &&
3620Sstevel@tonic-gate strcmp(nd->nd_nodename, mynode()) != 0) {
3630Sstevel@tonic-gate nd = nd->nd_next;
3640Sstevel@tonic-gate continue;
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate if (!(nd->nd_flags & MD_MN_NODE_ALIVE)) {
3680Sstevel@tonic-gate nd = nd->nd_next;
3690Sstevel@tonic-gate continue;
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate if (clnt_lock_set(nd->nd_nodename, sp, ep)) {
3730Sstevel@tonic-gate rval = -1;
3740Sstevel@tonic-gate goto done;
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate nd = nd->nd_next;
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate /*
3790Sstevel@tonic-gate * Lock out other meta* commands by suspending
3800Sstevel@tonic-gate * class 1 messages across the diskset.
3810Sstevel@tonic-gate */
3820Sstevel@tonic-gate nd = sd->sd_nodelist;
3830Sstevel@tonic-gate while (nd) {
3840Sstevel@tonic-gate if (!(nd->nd_flags & MD_MN_NODE_ALIVE)) {
3850Sstevel@tonic-gate nd = nd->nd_next;
3860Sstevel@tonic-gate continue;
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate if (clnt_mdcommdctl(nd->nd_nodename,
3900Sstevel@tonic-gate COMMDCTL_SUSPEND, sp, MD_MSG_CLASS1,
3910Sstevel@tonic-gate MD_MSCF_NO_FLAGS, ep)) {
3920Sstevel@tonic-gate rval = -1;
3930Sstevel@tonic-gate goto done;
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate suspend1_flag = 1;
3960Sstevel@tonic-gate nd = nd->nd_next;
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate } else {
3990Sstevel@tonic-gate /* Lock the set on current set members */
4000Sstevel@tonic-gate for (i = 0; i < MD_MAXSIDES; i++) {
4010Sstevel@tonic-gate /* Skip empty slots */
4020Sstevel@tonic-gate if (sd->sd_nodes[i][0] == '\0')
4030Sstevel@tonic-gate continue;
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate if ((force & MDFORCE_LOCAL) &&
4060Sstevel@tonic-gate strcmp(sd->sd_nodes[i], mynode()) != 0)
4070Sstevel@tonic-gate continue;
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate if (clnt_lock_set(sd->sd_nodes[i], sp, ep)) {
4100Sstevel@tonic-gate rval = -1;
4110Sstevel@tonic-gate goto done;
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate }
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate force |= MDFORCE_SET_LOCKED;
4170Sstevel@tonic-gate options |= MDCHK_SET_LOCKED;
4180Sstevel@tonic-gate }
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate if (cmd == detach) {
4210Sstevel@tonic-gate if ((dbnlp = build_a_namelist(sp, argc, argv, ep)) == NULL) {
4220Sstevel@tonic-gate rval = -1;
4230Sstevel@tonic-gate goto done;
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate rval = meta_db_detach(sp, dbnlp, force, sysfilename, ep);
4270Sstevel@tonic-gate
4280Sstevel@tonic-gate metafreenamelist(dbnlp);
4290Sstevel@tonic-gate }
4300Sstevel@tonic-gate
4310Sstevel@tonic-gate if (cmd == attach) {
4320Sstevel@tonic-gate daddr_t nblks = 0;
4330Sstevel@tonic-gate int arg_index = 0;
4340Sstevel@tonic-gate int saved_dbsize = dbsize;
4350Sstevel@tonic-gate int saved_dbcnt = dbcnt;
4360Sstevel@tonic-gate int saved_default_size = default_size;
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate if (force & MDFORCE_LOCAL)
4390Sstevel@tonic-gate options |= MDCHK_SET_FORCE;
4400Sstevel@tonic-gate
4410Sstevel@tonic-gate if (default_size)
4420Sstevel@tonic-gate if ((nblks = meta_db_minreplica(sp, ep)) < 0)
4430Sstevel@tonic-gate mdclrerror(ep);
4440Sstevel@tonic-gate /*
4450Sstevel@tonic-gate * Loop through build a new namelist
4460Sstevel@tonic-gate * for each "mddb" entry or the devices list
4470Sstevel@tonic-gate * on the command line. This allows each "mddb"
4480Sstevel@tonic-gate * entry to have unique dbsize and dbcnt.
4490Sstevel@tonic-gate */
4500Sstevel@tonic-gate while (arg_index < argc) {
4510Sstevel@tonic-gate
4520Sstevel@tonic-gate dbnlp = build_next_namelist(sp, argc, argv,
4530Sstevel@tonic-gate &arg_index, &dbsize, &dbcnt, &default_size, ep);
4540Sstevel@tonic-gate if (dbnlp == NULL) {
4550Sstevel@tonic-gate rval = -1;
4560Sstevel@tonic-gate goto done;
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate /*
4590Sstevel@tonic-gate * If using the default size,
4600Sstevel@tonic-gate * then let's adjust the default to the minimum
4610Sstevel@tonic-gate * size currently in use.
4620Sstevel@tonic-gate */
4630Sstevel@tonic-gate if (default_size && (nblks > 0))
4640Sstevel@tonic-gate dbsize = nblks; /* adjust replica size */
4650Sstevel@tonic-gate
466*2150Sjeanm if (dbsize > maxblks)
467*2150Sjeanm usage(sp, gettext("size (-l) is too big"));
468*2150Sjeanm
4690Sstevel@tonic-gate rval = meta_db_attach(sp, dbnlp, options, NULL, dbcnt,
4700Sstevel@tonic-gate dbsize, sysfilename, ep);
4710Sstevel@tonic-gate if (rval) {
4720Sstevel@tonic-gate metafreenamelist(dbnlp);
4730Sstevel@tonic-gate break;
4740Sstevel@tonic-gate }
4750Sstevel@tonic-gate dbsize = saved_dbsize;
4760Sstevel@tonic-gate dbcnt = saved_dbcnt;
4770Sstevel@tonic-gate default_size = saved_default_size;
4780Sstevel@tonic-gate
4790Sstevel@tonic-gate metafreenamelist(dbnlp);
4800Sstevel@tonic-gate }
4810Sstevel@tonic-gate }
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate done:
4840Sstevel@tonic-gate if (! metaislocalset(sp)) {
4850Sstevel@tonic-gate cl_sk = cl_get_setkey(sp->setno, sp->setname);
4860Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
4870Sstevel@tonic-gate /*
4880Sstevel@tonic-gate * Unlock diskset by resuming
4890Sstevel@tonic-gate * class 1 messages across the diskset.
4900Sstevel@tonic-gate */
4910Sstevel@tonic-gate if (suspend1_flag) {
4920Sstevel@tonic-gate nd = sd->sd_nodelist;
4930Sstevel@tonic-gate while (nd) {
4940Sstevel@tonic-gate if (!(nd->nd_flags &
4950Sstevel@tonic-gate MD_MN_NODE_ALIVE)) {
4960Sstevel@tonic-gate nd = nd->nd_next;
4970Sstevel@tonic-gate continue;
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate
5000Sstevel@tonic-gate if (clnt_mdcommdctl(nd->nd_nodename,
5010Sstevel@tonic-gate COMMDCTL_RESUME, sp,
5020Sstevel@tonic-gate MD_MSG_CLASS1,
5030Sstevel@tonic-gate MD_MSCF_NO_FLAGS, &xep)) {
5040Sstevel@tonic-gate mde_perror(&xep, "");
5050Sstevel@tonic-gate mdclrerror(&xep);
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate nd = nd->nd_next;
5080Sstevel@tonic-gate }
5090Sstevel@tonic-gate }
5100Sstevel@tonic-gate nd = sd->sd_nodelist;
5110Sstevel@tonic-gate while (nd) {
5120Sstevel@tonic-gate if ((force & MDFORCE_LOCAL) &&
5130Sstevel@tonic-gate strcmp(nd->nd_nodename, mynode()) != 0) {
5140Sstevel@tonic-gate nd = nd->nd_next;
5150Sstevel@tonic-gate continue;
5160Sstevel@tonic-gate }
5170Sstevel@tonic-gate if (!(nd->nd_flags & MD_MN_NODE_ALIVE)) {
5180Sstevel@tonic-gate nd = nd->nd_next;
5190Sstevel@tonic-gate continue;
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate if (clnt_unlock_set(nd->nd_nodename, cl_sk,
5230Sstevel@tonic-gate &xep))
5240Sstevel@tonic-gate mdclrerror(&xep);
5250Sstevel@tonic-gate nd = nd->nd_next;
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate } else {
5280Sstevel@tonic-gate for (i = 0; i < MD_MAXSIDES; i++) {
5290Sstevel@tonic-gate /* Skip empty slots */
5300Sstevel@tonic-gate if (sd->sd_nodes[i][0] == '\0')
5310Sstevel@tonic-gate continue;
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate if ((force & MDFORCE_LOCAL) &&
5340Sstevel@tonic-gate strcmp(sd->sd_nodes[i], mynode()) != 0)
5350Sstevel@tonic-gate continue;
5360Sstevel@tonic-gate
5370Sstevel@tonic-gate if (clnt_unlock_set(sd->sd_nodes[i], cl_sk,
5380Sstevel@tonic-gate &xep))
5390Sstevel@tonic-gate mdclrerror(&xep);
5400Sstevel@tonic-gate }
5410Sstevel@tonic-gate }
5420Sstevel@tonic-gate cl_set_setkey(NULL);
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate return (rval);
5460Sstevel@tonic-gate }
5470Sstevel@tonic-gate
5480Sstevel@tonic-gate static int
info(mdsetname_t * sp,enum mddb_cmd cmd,int print_headers,int print_footers,md_error_t * ep)5490Sstevel@tonic-gate info(
5500Sstevel@tonic-gate mdsetname_t *sp,
5510Sstevel@tonic-gate enum mddb_cmd cmd,
5520Sstevel@tonic-gate int print_headers,
5530Sstevel@tonic-gate int print_footers,
5540Sstevel@tonic-gate md_error_t *ep
5550Sstevel@tonic-gate )
5560Sstevel@tonic-gate {
5570Sstevel@tonic-gate md_replicalist_t *rlp = NULL;
5580Sstevel@tonic-gate md_replicalist_t *rl;
5590Sstevel@tonic-gate md_replica_t *r;
5600Sstevel@tonic-gate int i;
5610Sstevel@tonic-gate char *unk_str = NULL;
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate /* get list of replicas, quit if none */
5640Sstevel@tonic-gate if (metareplicalist(sp, (MD_BASICNAME_OK | PRINT_FAST), &rlp, ep) < 0)
5650Sstevel@tonic-gate return (-1);
5660Sstevel@tonic-gate else if (rlp == NULL)
5670Sstevel@tonic-gate return (0);
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate if (print_headers) {
5700Sstevel@tonic-gate (void) printf("\t%5.5s\t\t%9.9s\t%11.11s\n", gettext("flags"),
5710Sstevel@tonic-gate gettext("first blk"), gettext("block count"));
5720Sstevel@tonic-gate }
5730Sstevel@tonic-gate
5740Sstevel@tonic-gate unk_str = gettext("unknown");
5750Sstevel@tonic-gate for (rl = rlp; rl != NULL; rl = rl->rl_next) {
5760Sstevel@tonic-gate r = rl->rl_repp;
5770Sstevel@tonic-gate
5780Sstevel@tonic-gate for (i = 0; i < MDDB_FLAGS_LEN; i++) {
5790Sstevel@tonic-gate if (r->r_flags & (1 << i))
5800Sstevel@tonic-gate (void) putchar(MDDB_FLAGS_STRING[i]);
5810Sstevel@tonic-gate else
5820Sstevel@tonic-gate (void) putchar(' ');
5830Sstevel@tonic-gate }
5840Sstevel@tonic-gate
5850Sstevel@tonic-gate if ((r->r_blkno == -1) && (r->r_nblk == -1)) {
5860Sstevel@tonic-gate (void) printf("\t%7.7s\t\t%7.7s\t", unk_str, unk_str);
5870Sstevel@tonic-gate } else if (r->r_nblk == -1) {
5880Sstevel@tonic-gate (void) printf("\t%ld\t\t%7.7s\t", r->r_blkno, unk_str);
5890Sstevel@tonic-gate } else {
5900Sstevel@tonic-gate (void) printf("\t%ld\t\t%ld\t", r->r_blkno, r->r_nblk);
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate (void) printf("\t%s\n", r->r_namep->bname);
5940Sstevel@tonic-gate
5950Sstevel@tonic-gate }
5960Sstevel@tonic-gate
5970Sstevel@tonic-gate metafreereplicalist(rlp);
5980Sstevel@tonic-gate
5990Sstevel@tonic-gate if (cmd == infoshort)
6000Sstevel@tonic-gate return (0);
6010Sstevel@tonic-gate
6020Sstevel@tonic-gate if (!print_footers)
6030Sstevel@tonic-gate return (0);
6040Sstevel@tonic-gate
6050Sstevel@tonic-gate (void) printf(gettext(
6060Sstevel@tonic-gate " r - replica does not have device relocation information\n"
6070Sstevel@tonic-gate " o - replica active prior to last mddb configuration change\n"
6080Sstevel@tonic-gate " u - replica is up to date\n"
6090Sstevel@tonic-gate " l - locator for this replica was read successfully\n"
6100Sstevel@tonic-gate " c - replica's location was in %s\n"
6110Sstevel@tonic-gate " p - replica's location was patched in kernel\n"
6120Sstevel@tonic-gate " m - replica is master, this is replica selected as input\n"
613*2150Sjeanm " t - tagged data is associated with the replica\n"
6140Sstevel@tonic-gate " W - replica has device write errors\n"
6150Sstevel@tonic-gate " a - replica is active, commits are occurring to this replica\n"
6160Sstevel@tonic-gate " M - replica had problem with master blocks\n"
6170Sstevel@tonic-gate " D - replica had problem with data blocks\n"
6180Sstevel@tonic-gate " F - replica had format problems\n"
6190Sstevel@tonic-gate " S - replica is too small to hold current data base\n"
620*2150Sjeanm " R - replica had device read errors\n"
621*2150Sjeanm " B - tagged data associated with the replica is not valid\n"),
6220Sstevel@tonic-gate META_DBCONF);
6230Sstevel@tonic-gate return (0);
6240Sstevel@tonic-gate }
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate int
main(int argc,char ** argv)6270Sstevel@tonic-gate main(int argc, char **argv)
6280Sstevel@tonic-gate {
6290Sstevel@tonic-gate mdsetname_t *sp = NULL;
6300Sstevel@tonic-gate int c;
6310Sstevel@tonic-gate enum mddb_cmd cmd = none;
6320Sstevel@tonic-gate char *sname = MD_LOCAL_NAME;
6330Sstevel@tonic-gate char *cffilename = NULL;
6340Sstevel@tonic-gate char *sysfilename = NULL;
6350Sstevel@tonic-gate int forceflg = FALSE;
6360Sstevel@tonic-gate mdchkopts_t options = 0;
6370Sstevel@tonic-gate md_error_t status = mdnullerror;
6380Sstevel@tonic-gate md_error_t *ep = &status;
6390Sstevel@tonic-gate int error;
6400Sstevel@tonic-gate md_set_desc *sd;
6410Sstevel@tonic-gate int multi_node = 0;
6420Sstevel@tonic-gate
6430Sstevel@tonic-gate /*
6440Sstevel@tonic-gate * Get the locale set up before calling any other routines
6450Sstevel@tonic-gate * with messages to ouput. Just in case we're not in a build
6460Sstevel@tonic-gate * environment, make sure that TEXT_DOMAIN gets set to
6470Sstevel@tonic-gate * something.
6480Sstevel@tonic-gate */
6490Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
6500Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
6510Sstevel@tonic-gate #endif
6520Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
6530Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
6540Sstevel@tonic-gate
6550Sstevel@tonic-gate if (sdssc_bind_library() == SDSSC_OKAY)
6560Sstevel@tonic-gate if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY,
6570Sstevel@tonic-gate &error) == SDSSC_PROXY_DONE)
6580Sstevel@tonic-gate exit(error);
6590Sstevel@tonic-gate
6600Sstevel@tonic-gate /* parse args */
6610Sstevel@tonic-gate optind = 1;
6620Sstevel@tonic-gate opterr = 1;
6630Sstevel@tonic-gate
6640Sstevel@tonic-gate /* initialize */
6650Sstevel@tonic-gate if (md_init(argc, argv, 0, 1, ep) != 0) {
6660Sstevel@tonic-gate mde_perror(ep, "");
6670Sstevel@tonic-gate md_exit(sp, 1);
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate
6700Sstevel@tonic-gate /* parse args */
6710Sstevel@tonic-gate optind = 1;
6720Sstevel@tonic-gate opterr = 1;
6730Sstevel@tonic-gate while ((c = getopt(argc, argv, "ac:dfhik:l:ps:?")) != -1) {
6740Sstevel@tonic-gate switch (c) {
6750Sstevel@tonic-gate case 'a':
6760Sstevel@tonic-gate cmd = attach;
6770Sstevel@tonic-gate break;
6780Sstevel@tonic-gate case 'c':
6790Sstevel@tonic-gate break;
6800Sstevel@tonic-gate case 'd':
6810Sstevel@tonic-gate cmd = detach;
6820Sstevel@tonic-gate break;
6830Sstevel@tonic-gate case 'f':
6840Sstevel@tonic-gate forceflg = TRUE;
6850Sstevel@tonic-gate break;
6860Sstevel@tonic-gate case 'h':
6870Sstevel@tonic-gate usage(sp, (char *)0);
6880Sstevel@tonic-gate break;
6890Sstevel@tonic-gate case 'i':
6900Sstevel@tonic-gate cmd = infolong;
6910Sstevel@tonic-gate break;
6920Sstevel@tonic-gate case 'k':
6930Sstevel@tonic-gate sysfilename = optarg;
6940Sstevel@tonic-gate break;
6950Sstevel@tonic-gate case 'l':
6960Sstevel@tonic-gate break;
6970Sstevel@tonic-gate case 'p':
6980Sstevel@tonic-gate cmd = patch;
6990Sstevel@tonic-gate break;
7000Sstevel@tonic-gate case 's':
7010Sstevel@tonic-gate sname = optarg;
7020Sstevel@tonic-gate break;
7030Sstevel@tonic-gate
7040Sstevel@tonic-gate case '?':
7050Sstevel@tonic-gate if (optopt == '?')
7060Sstevel@tonic-gate usage(sp, NULL);
7070Sstevel@tonic-gate /*FALLTHROUGH*/
7080Sstevel@tonic-gate default:
7090Sstevel@tonic-gate usage(sp, gettext("unknown command"));
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate }
7120Sstevel@tonic-gate if (cmd == none)
7130Sstevel@tonic-gate cmd = infoshort;
7140Sstevel@tonic-gate
7150Sstevel@tonic-gate /* get set context */
7160Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
7170Sstevel@tonic-gate mde_perror(ep, "");
7180Sstevel@tonic-gate md_exit(sp, 1);
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate
7210Sstevel@tonic-gate /* print status */
7220Sstevel@tonic-gate if (cmd == infoshort || cmd == infolong) {
7230Sstevel@tonic-gate if (optind != argc)
7240Sstevel@tonic-gate usage(sp, gettext(
7250Sstevel@tonic-gate "too many arguments"));
7260Sstevel@tonic-gate
7270Sstevel@tonic-gate if (info(sp, cmd, 1, 1, ep)) {
7280Sstevel@tonic-gate mde_perror(ep, "");
7290Sstevel@tonic-gate md_exit(sp, 1);
7300Sstevel@tonic-gate }
7310Sstevel@tonic-gate
7320Sstevel@tonic-gate if (meta_smf_isonline(meta_smf_getmask(), ep) == 0) {
7330Sstevel@tonic-gate mde_perror(ep, "");
7340Sstevel@tonic-gate md_exit(sp, 1);
7350Sstevel@tonic-gate }
7360Sstevel@tonic-gate
7370Sstevel@tonic-gate md_exit(sp, 0);
7380Sstevel@tonic-gate }
7390Sstevel@tonic-gate
7400Sstevel@tonic-gate if (meta_check_root(ep) != 0) {
7410Sstevel@tonic-gate mde_perror(ep, "");
7420Sstevel@tonic-gate md_exit(sp, 1);
7430Sstevel@tonic-gate }
7440Sstevel@tonic-gate
7450Sstevel@tonic-gate if (! metaislocalset(sp)) {
7460Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL) {
7470Sstevel@tonic-gate mde_perror(ep, "");
7480Sstevel@tonic-gate md_exit(sp, 1);
7490Sstevel@tonic-gate }
7500Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
7510Sstevel@tonic-gate multi_node = 1;
7520Sstevel@tonic-gate }
7530Sstevel@tonic-gate }
7540Sstevel@tonic-gate
7550Sstevel@tonic-gate /*
7560Sstevel@tonic-gate * Adjust lock for traditional and local diskset.
7570Sstevel@tonic-gate *
7580Sstevel@tonic-gate * A MN diskset does not use the set meta_lock but instead
7590Sstevel@tonic-gate * uses the clnt_lock of rpc.metad and the suspend/resume
7600Sstevel@tonic-gate * feature of the rpc.mdcommd. Can't use set meta_lock since
7610Sstevel@tonic-gate * class 1 messages are grabbing this lock and if this thread
7620Sstevel@tonic-gate * is holding the set meta_lock then no rpc.mdcommd suspend
7630Sstevel@tonic-gate * can occur.
7640Sstevel@tonic-gate */
7650Sstevel@tonic-gate if ((!multi_node) && (meta_lock(sp, TRUE, ep) != 0)) {
7660Sstevel@tonic-gate mde_perror(ep, "");
7670Sstevel@tonic-gate md_exit(sp, 1);
7680Sstevel@tonic-gate }
7690Sstevel@tonic-gate
7700Sstevel@tonic-gate /* check for ownership */
7710Sstevel@tonic-gate if (meta_check_ownership(sp, ep) != 0) {
7720Sstevel@tonic-gate mde_perror(ep, "");
7730Sstevel@tonic-gate md_exit(sp, 1);
7740Sstevel@tonic-gate }
7750Sstevel@tonic-gate
7760Sstevel@tonic-gate /* snarf MDDB locations */
7770Sstevel@tonic-gate if (cmd != patch) {
7780Sstevel@tonic-gate if (meta_setup_db_locations(ep) != 0) {
7790Sstevel@tonic-gate if (! mdismddberror(ep, MDE_DB_STALE)) {
7800Sstevel@tonic-gate if (forceflg == FALSE) {
7810Sstevel@tonic-gate mde_perror(ep, "");
7820Sstevel@tonic-gate md_exit(sp, 1);
7830Sstevel@tonic-gate }
7840Sstevel@tonic-gate options = MDCHK_ALLOW_NODBS;
7850Sstevel@tonic-gate }
7860Sstevel@tonic-gate mdclrerror(ep);
7870Sstevel@tonic-gate }
7880Sstevel@tonic-gate }
7890Sstevel@tonic-gate
7900Sstevel@tonic-gate /* patch MDDB locations */
7910Sstevel@tonic-gate if (cmd == patch) {
7920Sstevel@tonic-gate if (optind < (argc - 1)) {
7930Sstevel@tonic-gate usage(sp, gettext(
7940Sstevel@tonic-gate "too many arguments to -p"));
7950Sstevel@tonic-gate }
7960Sstevel@tonic-gate
7970Sstevel@tonic-gate if (optind == (argc - 1))
7980Sstevel@tonic-gate cffilename = argv[optind];
7990Sstevel@tonic-gate
8000Sstevel@tonic-gate if (metaislocalset(sp)) {
8010Sstevel@tonic-gate if (meta_db_patch(sysfilename, cffilename, 1, ep)) {
8020Sstevel@tonic-gate mde_perror(ep, "");
8030Sstevel@tonic-gate md_exit(sp, 1);
8040Sstevel@tonic-gate }
8050Sstevel@tonic-gate }
8060Sstevel@tonic-gate }
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate /* add/delete replicas */
8090Sstevel@tonic-gate if (cmd == attach || cmd == detach) {
8100Sstevel@tonic-gate if (chngdb(sp, cmd, argc, argv, options, ep)) {
8110Sstevel@tonic-gate mde_perror(ep, "");
8120Sstevel@tonic-gate md_exit(sp, 1);
8130Sstevel@tonic-gate }
8140Sstevel@tonic-gate }
8150Sstevel@tonic-gate
8160Sstevel@tonic-gate md_exit(sp, 0);
8170Sstevel@tonic-gate /*NOTREACHED*/
8180Sstevel@tonic-gate return (0);
8190Sstevel@tonic-gate }
820