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
51320Srd117015 * Common Development and Distribution License (the "License").
61320Srd117015 * 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*12215SJames.Hall@Sun.COM * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate * Metadevice diskset utility.
270Sstevel@tonic-gate */
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include <meta.h>
300Sstevel@tonic-gate #include <sys/lvm/md_mddb.h>
310Sstevel@tonic-gate #include <sdssc.h>
320Sstevel@tonic-gate
330Sstevel@tonic-gate enum metaset_cmd {
340Sstevel@tonic-gate notspecified,
350Sstevel@tonic-gate add,
360Sstevel@tonic-gate balance,
370Sstevel@tonic-gate delete,
380Sstevel@tonic-gate cluster,
390Sstevel@tonic-gate isowner,
400Sstevel@tonic-gate purge,
410Sstevel@tonic-gate query,
420Sstevel@tonic-gate release,
430Sstevel@tonic-gate take,
440Sstevel@tonic-gate join, /* Join a multinode diskset */
450Sstevel@tonic-gate withdraw /* Withdraw from a multinode diskset */
460Sstevel@tonic-gate };
470Sstevel@tonic-gate
480Sstevel@tonic-gate enum cluster_cmd {
490Sstevel@tonic-gate ccnotspecified,
500Sstevel@tonic-gate clusterversion, /* Return the version of the cluster I/F */
510Sstevel@tonic-gate clusterdisksin, /* List disks in a given diskset */
520Sstevel@tonic-gate clustertake, /* back door for Cluster take */
530Sstevel@tonic-gate clusterrelease, /* ditto */
540Sstevel@tonic-gate clusterpurge, /* back door for Cluster purge */
550Sstevel@tonic-gate clusterproxy /* proxy the args after '--' to primary */
560Sstevel@tonic-gate };
570Sstevel@tonic-gate
580Sstevel@tonic-gate static void
usage(mdsetname_t * sp,char * string)590Sstevel@tonic-gate usage(
600Sstevel@tonic-gate mdsetname_t *sp,
610Sstevel@tonic-gate char *string)
620Sstevel@tonic-gate {
630Sstevel@tonic-gate if ((string != NULL) && (*string != '\0'))
640Sstevel@tonic-gate md_eprintf("%s\n", string);
650Sstevel@tonic-gate (void) fprintf(stderr, gettext(
664932Spetede "usage:\t%s -s setname -a [-A enable | disable] -h hostname ...\n"
674932Spetede " %s -s setname -a [-M] -h hostname ...\n"
684932Spetede " %s -s setname -a [-M] [-l length] [-L] drivename ...\n"
694932Spetede " %s -s setname -d [-M] -h hostname ...\n"
704932Spetede " %s -s setname -d [-M] -f -h all-hostnames\n"
714932Spetede " %s -s setname -d [-M] [-f] drivename ...\n"
724932Spetede " %s -s setname -d [-M] [-f] hostname ...\n"
734932Spetede " %s -s setname -A enable | disable\n"
744932Spetede " %s -s setname -t [-f]\n"
754932Spetede " %s -s setname -r\n"
764932Spetede " %s [-s setname] -j [-M]\n"
774932Spetede " %s [-s setname] -w [-M]\n"
784932Spetede " %s -s setname -P [-M]\n"
794932Spetede " %s -s setname -b [-M]\n"
804932Spetede " %s -s setname -o [-M] [-h hostname]\n"
814932Spetede " %s [-s setname]\n"
824932Spetede "\n"
834932Spetede " hostname = contents of /etc/nodename\n"
844932Spetede " drivename = cNtNdN no slice\n"
854932Spetede " [-M] for multi-owner set is optional except"
864932Spetede " on set creation\n"),
874932Spetede myname, myname, myname, myname, myname, myname, myname, myname,
884932Spetede myname, myname, myname, myname, myname, myname, myname, myname);
890Sstevel@tonic-gate md_exit(sp, (string == NULL) ? 0 : 1);
900Sstevel@tonic-gate }
910Sstevel@tonic-gate
920Sstevel@tonic-gate /*
930Sstevel@tonic-gate * The svm.sync rc script relies heavily on the metaset output.
940Sstevel@tonic-gate * Any changes to the metaset output MUST verify that the rc script
950Sstevel@tonic-gate * does not break. Not doing so may potentially leave the system
960Sstevel@tonic-gate * unusable. You have been WARNED.
970Sstevel@tonic-gate */
980Sstevel@tonic-gate static int
printset(mdsetname_t * sp,md_error_t * ep)990Sstevel@tonic-gate printset(mdsetname_t *sp, md_error_t *ep)
1000Sstevel@tonic-gate {
1010Sstevel@tonic-gate int i, j;
1020Sstevel@tonic-gate md_set_desc *sd;
1030Sstevel@tonic-gate md_drive_desc *dd, *p;
1040Sstevel@tonic-gate int max_meds;
1050Sstevel@tonic-gate md_mnnode_desc *nd;
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL)
1080Sstevel@tonic-gate return (-1);
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate /*
1110Sstevel@tonic-gate * Only get set owner information for traditional diskset.
1120Sstevel@tonic-gate * This set owner information is stored in the node records
1130Sstevel@tonic-gate * for a MN diskset.
1140Sstevel@tonic-gate */
1150Sstevel@tonic-gate if (!(MD_MNSET_DESC(sd))) {
1160Sstevel@tonic-gate if (metaget_setownership(sp, ep) == -1)
1170Sstevel@tonic-gate return (-1);
1180Sstevel@tonic-gate }
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate if (((dd = metaget_drivedesc(sp, (MD_BASICNAME_OK | PRINT_FAST),
1210Sstevel@tonic-gate ep)) == NULL) && !mdisok(ep))
1220Sstevel@tonic-gate return (-1);
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
1250Sstevel@tonic-gate (void) printf(gettext(
1260Sstevel@tonic-gate "\nMulti-owner Set name = %s, Set number = %d, Master = %s\n"),
1270Sstevel@tonic-gate sp->setname, sp->setno, sd->sd_mn_master_nodenm);
1280Sstevel@tonic-gate if ((sd->sd_mn_master_nodeid == MD_MN_INVALID_NID) &&
1290Sstevel@tonic-gate (dd != NULL)) {
1300Sstevel@tonic-gate (void) printf(gettext(
1314932Spetede "Master and owner information unavailable "
1324932Spetede "until joined (metaset -j)\n"));
1330Sstevel@tonic-gate }
1340Sstevel@tonic-gate } else {
1350Sstevel@tonic-gate (void) printf(gettext(
1360Sstevel@tonic-gate "\nSet name = %s, Set number = %d\n"),
1370Sstevel@tonic-gate sp->setname, sp->setno);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
1410Sstevel@tonic-gate (void) printf(gettext("\n%-19.19s %-14.14s %-6.6s\n"),
1424932Spetede gettext("Host"), gettext("Owner"), gettext("Member"));
1430Sstevel@tonic-gate nd = sd->sd_nodelist;
1440Sstevel@tonic-gate while (nd) {
1450Sstevel@tonic-gate /*
1460Sstevel@tonic-gate * Don't print nodes that aren't ok since they may be
1470Sstevel@tonic-gate * removed from config during a reconfig cycle. If a
1480Sstevel@tonic-gate * node was being added to a diskset and the entire
1490Sstevel@tonic-gate * cluster went down but the node being added was unable
1500Sstevel@tonic-gate * to reboot, there's no way to know if that node had
1510Sstevel@tonic-gate * its own node record set to OK or not. So, node
1520Sstevel@tonic-gate * record is left in ADD state during reconfig cycle.
1530Sstevel@tonic-gate * When that node reboots and returns to the cluster,
1540Sstevel@tonic-gate * the reconfig cycle will either remove the node
1550Sstevel@tonic-gate * record (if not marked OK on that node) or will mark
1560Sstevel@tonic-gate * it OK on all nodes.
1570Sstevel@tonic-gate * It is very important to only remove a node record
1580Sstevel@tonic-gate * from the other nodes when that node record is not
1590Sstevel@tonic-gate * marked OK on its own node - otherwise, different
1600Sstevel@tonic-gate * nodes would have different nodelists possibly
1610Sstevel@tonic-gate * causing different nodes to to choose different
1620Sstevel@tonic-gate * masters.
163*12215SJames.Hall@Sun.COM *
164*12215SJames.Hall@Sun.COM * Standard hostname field is 17 bytes but metaset
165*12215SJames.Hall@Sun.COM * will display up to MD_MAX_NODENAME, defined in
166*12215SJames.Hall@Sun.COM * meta_basic.h
1670Sstevel@tonic-gate */
1680Sstevel@tonic-gate if (!(nd->nd_flags & MD_MN_NODE_OK)) {
1690Sstevel@tonic-gate nd = nd->nd_next;
1700Sstevel@tonic-gate continue;
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate if ((nd->nd_flags & MD_MN_NODE_ALIVE) &&
1730Sstevel@tonic-gate (nd->nd_flags & MD_MN_NODE_OWN)) {
1740Sstevel@tonic-gate (void) printf(
175*12215SJames.Hall@Sun.COM gettext(" %-17.*s %-12.12s %-4.4s\n"),
176*12215SJames.Hall@Sun.COM MD_MAX_NODENAME,
1770Sstevel@tonic-gate nd->nd_nodename, gettext("multi-owner"),
1780Sstevel@tonic-gate gettext("Yes"));
1794932Spetede } else if ((!(nd->nd_flags & MD_MN_NODE_ALIVE)) &&
1800Sstevel@tonic-gate (nd->nd_flags & MD_MN_NODE_OWN)) {
1814932Spetede /* Should never be able to happen */
1820Sstevel@tonic-gate (void) printf(
183*12215SJames.Hall@Sun.COM gettext(" %-17.*s %-12.12s %-4.4s\n"),
184*12215SJames.Hall@Sun.COM MD_MAX_NODENAME,
1850Sstevel@tonic-gate nd->nd_nodename, gettext("multi-owner"),
1860Sstevel@tonic-gate gettext("No"));
1870Sstevel@tonic-gate } else if ((nd->nd_flags & MD_MN_NODE_ALIVE) &&
1880Sstevel@tonic-gate (!(nd->nd_flags & MD_MN_NODE_OWN))) {
1890Sstevel@tonic-gate (void) printf(
190*12215SJames.Hall@Sun.COM gettext(" %-17.*s %-12.12s %-4.4s\n"),
191*12215SJames.Hall@Sun.COM MD_MAX_NODENAME,
1920Sstevel@tonic-gate nd->nd_nodename, gettext(""),
1930Sstevel@tonic-gate gettext("Yes"));
1940Sstevel@tonic-gate } else if ((!(nd->nd_flags & MD_MN_NODE_ALIVE)) &&
1950Sstevel@tonic-gate (!(nd->nd_flags & MD_MN_NODE_OWN))) {
1960Sstevel@tonic-gate (void) printf(
197*12215SJames.Hall@Sun.COM gettext(" %-17.*s %-12.12s %-4.4s\n"),
198*12215SJames.Hall@Sun.COM MD_MAX_NODENAME,
1990Sstevel@tonic-gate nd->nd_nodename, gettext(""),
2000Sstevel@tonic-gate gettext("No"));
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate nd = nd->nd_next;
2030Sstevel@tonic-gate }
2040Sstevel@tonic-gate } else {
2050Sstevel@tonic-gate (void) printf("\n%-19.19s %-5.5s\n",
2064932Spetede gettext("Host"), gettext("Owner"));
2070Sstevel@tonic-gate for (i = 0; i < MD_MAXSIDES; i++) {
2080Sstevel@tonic-gate /* Skip empty slots */
2090Sstevel@tonic-gate if (sd->sd_nodes[i][0] == '\0')
2100Sstevel@tonic-gate continue;
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate /*
2130Sstevel@tonic-gate * Standard hostname field is 17 bytes but metaset will
2140Sstevel@tonic-gate * display up to MD_MAX_NODENAME, def in meta_basic.h
2150Sstevel@tonic-gate */
2160Sstevel@tonic-gate (void) printf(" %-17.*s %s\n", MD_MAX_NODENAME,
2170Sstevel@tonic-gate sd->sd_nodes[i], (sd->sd_flags & MD_SR_AUTO_TAKE ?
2184932Spetede (sd->sd_isown[i] ? gettext("Yes (auto)") :
2194932Spetede gettext("No (auto)"))
2204932Spetede : (sd->sd_isown[i] ? gettext("Yes") : "")));
2210Sstevel@tonic-gate }
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate if (sd->sd_med.n_cnt > 0)
2250Sstevel@tonic-gate (void) printf("\n%-19.19s %-7.7s\n",
2260Sstevel@tonic-gate gettext("Mediator Host(s)"), gettext("Aliases"));
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate if ((max_meds = get_max_meds(ep)) == 0)
2290Sstevel@tonic-gate return (-1);
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate for (i = 0; i < max_meds; i++) {
2320Sstevel@tonic-gate if (sd->sd_med.n_lst[i].a_cnt == 0)
2330Sstevel@tonic-gate continue;
2342063Shshaw /*
2352063Shshaw * Standard hostname field is 17 bytes but metaset will
2362063Shshaw * display up to MD_MAX_NODENAME, def in meta_basic.h
2372063Shshaw */
2382063Shshaw (void) printf(" %-17.*s ", MD_MAX_NODENAME,
2394932Spetede sd->sd_med.n_lst[i].a_nm[0]);
2400Sstevel@tonic-gate for (j = 1; j < sd->sd_med.n_lst[i].a_cnt; j++) {
2410Sstevel@tonic-gate (void) printf("%s", sd->sd_med.n_lst[i].a_nm[j]);
2420Sstevel@tonic-gate if (sd->sd_med.n_lst[i].a_cnt - j > 1)
2430Sstevel@tonic-gate (void) printf(gettext(", "));
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate (void) printf("\n");
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate if (dd) {
2490Sstevel@tonic-gate int len = 0;
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate /*
2530Sstevel@tonic-gate * Building a format string on the fly that will
2540Sstevel@tonic-gate * be used in (f)printf. This allows the length
2550Sstevel@tonic-gate * of the ctd to vary from small to large without
2560Sstevel@tonic-gate * looking horrible.
2570Sstevel@tonic-gate */
2580Sstevel@tonic-gate for (p = dd; p != NULL; p = p->dd_next)
2590Sstevel@tonic-gate len = max(len, strlen(p->dd_dnp->cname));
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate len += 2;
2620Sstevel@tonic-gate (void) printf("\n%-*.*s %-5.5s\n", len, len,
2630Sstevel@tonic-gate gettext("Drive"),
2640Sstevel@tonic-gate gettext("Dbase"));
2650Sstevel@tonic-gate for (p = dd; p != NULL; p = p->dd_next) {
2660Sstevel@tonic-gate (void) printf("\n%-*.*s %-5.5s\n", len, len,
2670Sstevel@tonic-gate p->dd_dnp->cname,
2680Sstevel@tonic-gate (p->dd_dbcnt ? gettext("Yes") :
2690Sstevel@tonic-gate gettext("No")));
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate }
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate return (0);
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate static int
printsets(mdsetname_t * sp,md_error_t * ep)2770Sstevel@tonic-gate printsets(mdsetname_t *sp, md_error_t *ep)
2780Sstevel@tonic-gate {
2790Sstevel@tonic-gate int i;
2800Sstevel@tonic-gate mdsetname_t *sp1;
2810Sstevel@tonic-gate set_t max_sets;
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate /*
2840Sstevel@tonic-gate * print setname given.
2850Sstevel@tonic-gate */
2860Sstevel@tonic-gate if (! metaislocalset(sp)) {
2870Sstevel@tonic-gate if (printset(sp, ep))
2880Sstevel@tonic-gate return (-1);
2890Sstevel@tonic-gate return (0);
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate if ((max_sets = get_max_sets(ep)) == 0)
2930Sstevel@tonic-gate return (-1);
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate /*
2960Sstevel@tonic-gate * Print all known sets
2970Sstevel@tonic-gate */
2980Sstevel@tonic-gate for (i = 1; i < max_sets; i++) {
2990Sstevel@tonic-gate if ((sp1 = metasetnosetname(i, ep)) == NULL) {
3000Sstevel@tonic-gate if (! mdiserror(ep, MDE_NO_SET))
3010Sstevel@tonic-gate break;
3020Sstevel@tonic-gate mdclrerror(ep);
3030Sstevel@tonic-gate continue;
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate
3060Sstevel@tonic-gate if (printset(sp1, ep))
3070Sstevel@tonic-gate break;
3080Sstevel@tonic-gate }
3090Sstevel@tonic-gate if (! mdisok(ep))
3100Sstevel@tonic-gate return (-1);
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate return (0);
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate /*
3160Sstevel@tonic-gate * Print the current versionn of the cluster contract private interface.
3170Sstevel@tonic-gate */
3180Sstevel@tonic-gate static void
printclusterversion()3190Sstevel@tonic-gate printclusterversion()
3200Sstevel@tonic-gate {
32111053SSurya.Prakki@Sun.COM (void) printf("%s\n", METASETIFVERSION);
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate /*
3250Sstevel@tonic-gate * Print the disks that make up the given disk set. This is used
3260Sstevel@tonic-gate * exclusively by Sun Cluster and is contract private.
3270Sstevel@tonic-gate * Should never be called with sname of a Multinode diskset.
3280Sstevel@tonic-gate */
3290Sstevel@tonic-gate static int
printdisksin(char * sname,md_error_t * ep)3300Sstevel@tonic-gate printdisksin(char *sname, md_error_t *ep)
3310Sstevel@tonic-gate {
3320Sstevel@tonic-gate mdsetname_t *sp;
3330Sstevel@tonic-gate md_drive_desc *dd, *p;
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate /*
3380Sstevel@tonic-gate * During a deletion of a set the associated service is
3390Sstevel@tonic-gate * put offline. The SC3.0 reservation code calls disksuite
3400Sstevel@tonic-gate * to find a list of disks associated with the set so that
3410Sstevel@tonic-gate * it can release the reservation on those disks. In this
3420Sstevel@tonic-gate * case there won't be any disks or even a set left. So just
3430Sstevel@tonic-gate * return.
3440Sstevel@tonic-gate */
3450Sstevel@tonic-gate return (0);
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate if (metaget_setownership(sp, ep) == -1)
3490Sstevel@tonic-gate return (-1);
3500Sstevel@tonic-gate
3510Sstevel@tonic-gate if (((dd = metaget_drivedesc(sp, (MD_BASICNAME_OK | PRINT_FAST),
3520Sstevel@tonic-gate ep)) == NULL) && !mdisok(ep))
3530Sstevel@tonic-gate return (-1);
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate for (p = dd; p != NULL; p = p->dd_next)
3560Sstevel@tonic-gate (void) printf("%s\n", p->dd_dnp->rname);
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate return (0);
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate static void
parse_printset(int argc,char ** argv)3620Sstevel@tonic-gate parse_printset(int argc, char **argv)
3630Sstevel@tonic-gate {
3640Sstevel@tonic-gate int c;
3650Sstevel@tonic-gate mdsetname_t *sp = NULL;
3660Sstevel@tonic-gate char *sname = MD_LOCAL_NAME;
3670Sstevel@tonic-gate md_error_t status = mdnullerror;
3680Sstevel@tonic-gate md_error_t *ep = &status;
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate /* reset and parse args */
3710Sstevel@tonic-gate optind = 1;
3720Sstevel@tonic-gate opterr = 1;
3730Sstevel@tonic-gate while ((c = getopt(argc, argv, "s:")) != -1) {
3740Sstevel@tonic-gate switch (c) {
3750Sstevel@tonic-gate case 's':
3760Sstevel@tonic-gate sname = optarg;
3770Sstevel@tonic-gate break;
3780Sstevel@tonic-gate default:
3790Sstevel@tonic-gate usage(sp, gettext("unknown options"));
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate }
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate argc -= optind;
3840Sstevel@tonic-gate argv += optind;
3850Sstevel@tonic-gate
3860Sstevel@tonic-gate if (argc != 0)
3870Sstevel@tonic-gate usage(sp, gettext("too many args"));
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
3900Sstevel@tonic-gate mde_perror(ep, "");
3910Sstevel@tonic-gate md_exit(sp, 1);
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate if (printsets(sp, ep) && !mdiserror(ep, MDE_SMF_NO_SERVICE)) {
3950Sstevel@tonic-gate mde_perror(ep, "");
3960Sstevel@tonic-gate md_exit(sp, 1);
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate if (meta_smf_isonline(meta_smf_getmask(), ep) == 0) {
4000Sstevel@tonic-gate mde_perror(ep, "");
4010Sstevel@tonic-gate md_exit(sp, 1);
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate
4040Sstevel@tonic-gate md_exit(sp, 0);
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate static void
parse_add(int argc,char ** argv)4080Sstevel@tonic-gate parse_add(int argc, char **argv)
4090Sstevel@tonic-gate {
4104932Spetede int c, created_set;
4114932Spetede int hosts = FALSE;
4124932Spetede int meds = FALSE;
4134932Spetede int auto_take = FALSE;
4144932Spetede int force_label = FALSE;
4154932Spetede int default_size = TRUE;
4160Sstevel@tonic-gate mdsetname_t *sp = NULL;
4170Sstevel@tonic-gate char *sname = MD_LOCAL_NAME;
4184932Spetede md_error_t status = mdnullerror;
4194932Spetede md_error_t *ep = &status;
4200Sstevel@tonic-gate mddrivenamelist_t *dnlp = NULL;
4210Sstevel@tonic-gate mddrivenamelist_t *p;
4224932Spetede daddr_t dbsize, nblks;
4230Sstevel@tonic-gate mdsetname_t *local_sp = NULL;
4240Sstevel@tonic-gate int multi_node = 0;
4250Sstevel@tonic-gate md_set_desc *sd;
4260Sstevel@tonic-gate rval_e sdssc_rval;
4270Sstevel@tonic-gate
4280Sstevel@tonic-gate /* reset and parse args */
4290Sstevel@tonic-gate optind = 1;
4300Sstevel@tonic-gate opterr = 1;
4310Sstevel@tonic-gate while ((c = getopt(argc, argv, "MaA:hl:Lms:")) != -1) {
4320Sstevel@tonic-gate switch (c) {
4330Sstevel@tonic-gate case 'M':
4340Sstevel@tonic-gate multi_node = 1;
4350Sstevel@tonic-gate break;
4360Sstevel@tonic-gate case 'A':
4370Sstevel@tonic-gate /* verified sub-option in main */
4380Sstevel@tonic-gate if (strcmp(optarg, "enable") == 0)
4390Sstevel@tonic-gate auto_take = TRUE;
4400Sstevel@tonic-gate break;
4410Sstevel@tonic-gate case 'a':
4420Sstevel@tonic-gate break;
4430Sstevel@tonic-gate case 'h':
4440Sstevel@tonic-gate case 'm':
4450Sstevel@tonic-gate if (meds == TRUE || hosts == TRUE)
4460Sstevel@tonic-gate usage(sp, gettext(
4470Sstevel@tonic-gate "only one -m or -h option allowed"));
4480Sstevel@tonic-gate
4490Sstevel@tonic-gate if (default_size == FALSE || force_label == TRUE)
4500Sstevel@tonic-gate usage(sp, gettext(
4510Sstevel@tonic-gate "conflicting options"));
4520Sstevel@tonic-gate
4530Sstevel@tonic-gate if (c == 'h')
4540Sstevel@tonic-gate hosts = TRUE;
4550Sstevel@tonic-gate else
4560Sstevel@tonic-gate meds = TRUE;
4570Sstevel@tonic-gate break;
4580Sstevel@tonic-gate case 'l':
4590Sstevel@tonic-gate if (hosts == TRUE || meds == TRUE)
4600Sstevel@tonic-gate usage(sp, gettext(
4610Sstevel@tonic-gate "conflicting options"));
4620Sstevel@tonic-gate if (sscanf(optarg, "%ld", &dbsize) != 1) {
4630Sstevel@tonic-gate md_eprintf(gettext(
4640Sstevel@tonic-gate "%s: bad format\n"), optarg);
4650Sstevel@tonic-gate usage(sp, "");
4660Sstevel@tonic-gate }
4670Sstevel@tonic-gate
4680Sstevel@tonic-gate default_size = FALSE;
4690Sstevel@tonic-gate break;
4700Sstevel@tonic-gate case 'L':
4710Sstevel@tonic-gate /* Same criteria as -l */
4720Sstevel@tonic-gate if (hosts == TRUE || meds == TRUE)
4730Sstevel@tonic-gate usage(sp, gettext(
4740Sstevel@tonic-gate "conflicting options"));
4750Sstevel@tonic-gate force_label = TRUE;
4760Sstevel@tonic-gate break;
4770Sstevel@tonic-gate case 's':
4780Sstevel@tonic-gate sname = optarg;
4790Sstevel@tonic-gate break;
4800Sstevel@tonic-gate default:
4810Sstevel@tonic-gate usage(sp, gettext(
4820Sstevel@tonic-gate "unknown options"));
4830Sstevel@tonic-gate }
4840Sstevel@tonic-gate }
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate /* Can only use -A enable when creating the single-node set */
4870Sstevel@tonic-gate if (auto_take && hosts != TRUE)
4880Sstevel@tonic-gate usage(sp, gettext("conflicting options"));
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate argc -= optind;
4910Sstevel@tonic-gate argv += optind;
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate /*
4940Sstevel@tonic-gate * Add hosts
4950Sstevel@tonic-gate */
4960Sstevel@tonic-gate if (hosts == TRUE) {
4970Sstevel@tonic-gate
4980Sstevel@tonic-gate if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) {
4990Sstevel@tonic-gate mde_perror(ep, "");
5000Sstevel@tonic-gate md_exit(local_sp, 1);
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate if (meta_lock(local_sp, TRUE, ep) != 0) {
5040Sstevel@tonic-gate mde_perror(ep, "");
5050Sstevel@tonic-gate md_exit(local_sp, 1);
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate /*
5090Sstevel@tonic-gate * Keep track of Cluster set creation. Need to complete
5100Sstevel@tonic-gate * the transaction no matter if the set was created or not.
5110Sstevel@tonic-gate */
5120Sstevel@tonic-gate created_set = 0;
5130Sstevel@tonic-gate
5140Sstevel@tonic-gate /*
5150Sstevel@tonic-gate * Have no set, cannot take the lock, so only take the
5160Sstevel@tonic-gate * local lock.
5170Sstevel@tonic-gate */
5180Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
5190Sstevel@tonic-gate sdssc_rval = 0;
5200Sstevel@tonic-gate if (multi_node) {
5210Sstevel@tonic-gate /*
5220Sstevel@tonic-gate * When running on a cluster system that
5230Sstevel@tonic-gate * does not support MN disksets, the routine
5240Sstevel@tonic-gate * sdssc_mo_create_begin will be bound
5250Sstevel@tonic-gate * to the SVM routine not_bound_error
5260Sstevel@tonic-gate * which returns SDSSC_NOT_BOUND_ERROR.
5270Sstevel@tonic-gate *
5280Sstevel@tonic-gate * When running on a cluster system that
5290Sstevel@tonic-gate * does support MN disksets, the routine
5300Sstevel@tonic-gate * sdssc_mo_create_begin will be bound to
5310Sstevel@tonic-gate * the sdssc_mo_create_begin routine in
5320Sstevel@tonic-gate * library libsdssc_so. A call to
5330Sstevel@tonic-gate * sdssc_mo_create_begin will return with
5340Sstevel@tonic-gate * either SDSSC_ERROR or SDSSC_OKAY. If
5350Sstevel@tonic-gate * an SDSSC_OKAY is returned, then the
5360Sstevel@tonic-gate * cluster framework has allocated a
5370Sstevel@tonic-gate * set number for this new set that is unique
5380Sstevel@tonic-gate * across traditional and MN disksets.
5390Sstevel@tonic-gate * Libmeta will get this unique set number
5400Sstevel@tonic-gate * by calling sdssc_get_index.
5410Sstevel@tonic-gate *
5420Sstevel@tonic-gate * When running on a non-cluster system,
5430Sstevel@tonic-gate * the routine sdssc_mo_create_begin
5440Sstevel@tonic-gate * will be bound to the SVM routine
5450Sstevel@tonic-gate * not_bound which returns SDSSC_NOT_BOUND.
5460Sstevel@tonic-gate * In this case, all sdssc routines will
5470Sstevel@tonic-gate * return SDSSC_NOT_BOUND. No need to check
5480Sstevel@tonic-gate * for return value of SDSSC_NOT_BOUND since
5490Sstevel@tonic-gate * the libmeta call to get the set number
5500Sstevel@tonic-gate * (sdssc_get_index) will also fail with
5510Sstevel@tonic-gate * SDSSC_NOT_BOUND causing libmeta to
5520Sstevel@tonic-gate * determine its own set number.
5530Sstevel@tonic-gate */
5540Sstevel@tonic-gate sdssc_rval = sdssc_mo_create_begin(sname, argc,
5554932Spetede argv, SDSSC_PICK_SETNO);
5560Sstevel@tonic-gate if (sdssc_rval == SDSSC_NOT_BOUND_ERROR) {
55711053SSurya.Prakki@Sun.COM (void) mderror(ep, MDE_NOT_MN, NULL);
5580Sstevel@tonic-gate mde_perror(ep,
5590Sstevel@tonic-gate "Cluster node does not support "
5600Sstevel@tonic-gate "multi-owner diskset operations");
5610Sstevel@tonic-gate md_exit(local_sp, 1);
5620Sstevel@tonic-gate } else if (sdssc_rval == SDSSC_ERROR) {
5630Sstevel@tonic-gate mde_perror(ep, "");
5640Sstevel@tonic-gate md_exit(local_sp, 1);
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate } else {
5670Sstevel@tonic-gate sdssc_rval = sdssc_create_begin(sname, argc,
5684932Spetede argv, SDSSC_PICK_SETNO);
5690Sstevel@tonic-gate if (sdssc_rval == SDSSC_ERROR) {
5700Sstevel@tonic-gate mde_perror(ep, "");
5710Sstevel@tonic-gate md_exit(local_sp, 1);
5720Sstevel@tonic-gate }
5730Sstevel@tonic-gate }
5740Sstevel@tonic-gate /*
5750Sstevel@tonic-gate * Created diskset (as opposed to adding a
5760Sstevel@tonic-gate * host to an existing diskset).
5770Sstevel@tonic-gate */
5780Sstevel@tonic-gate created_set = 1;
5790Sstevel@tonic-gate
5800Sstevel@tonic-gate sp = Zalloc(sizeof (*sp));
5810Sstevel@tonic-gate sp->setname = Strdup(sname);
5820Sstevel@tonic-gate sp->lockfd = MD_NO_LOCK;
5830Sstevel@tonic-gate mdclrerror(ep);
5840Sstevel@tonic-gate } else {
5850Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL) {
5860Sstevel@tonic-gate mde_perror(ep, "");
5870Sstevel@tonic-gate md_exit(local_sp, 1);
5880Sstevel@tonic-gate }
5890Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
5900Sstevel@tonic-gate multi_node = 1;
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate /*
5940Sstevel@tonic-gate * can't add hosts to an existing set & enable
5950Sstevel@tonic-gate * auto-take
5960Sstevel@tonic-gate */
5970Sstevel@tonic-gate if (auto_take)
5980Sstevel@tonic-gate usage(sp, gettext("conflicting options"));
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate /*
6010Sstevel@tonic-gate * Have a valid set, take the set lock also.
6020Sstevel@tonic-gate *
6030Sstevel@tonic-gate * A MN diskset does not use the set meta_lock but
6040Sstevel@tonic-gate * instead uses the clnt_lock of rpc.metad and the
6050Sstevel@tonic-gate * suspend/resume feature of the rpc.mdcommd. Can't
6060Sstevel@tonic-gate * use set meta_lock since class 1 messages are
6070Sstevel@tonic-gate * grabbing this lock and if this thread is holding
6080Sstevel@tonic-gate * the set meta_lock then no rpc.mdcommd suspend
6090Sstevel@tonic-gate * can occur.
6100Sstevel@tonic-gate */
6110Sstevel@tonic-gate if (!multi_node) {
6120Sstevel@tonic-gate if (meta_lock(sp, TRUE, ep) != 0) {
6130Sstevel@tonic-gate mde_perror(ep, "");
6140Sstevel@tonic-gate md_exit(local_sp, 1);
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate }
6170Sstevel@tonic-gate }
6180Sstevel@tonic-gate
6190Sstevel@tonic-gate if (meta_set_addhosts(sp, multi_node, argc, argv, auto_take,
6200Sstevel@tonic-gate ep)) {
6210Sstevel@tonic-gate if (created_set)
6220Sstevel@tonic-gate sdssc_create_end(sname, SDSSC_CLEANUP);
6230Sstevel@tonic-gate mde_perror(&status, "");
6240Sstevel@tonic-gate if (!multi_node)
6250Sstevel@tonic-gate (void) meta_unlock(sp, ep);
6260Sstevel@tonic-gate md_exit(local_sp, 1);
6270Sstevel@tonic-gate }
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate if (created_set)
6300Sstevel@tonic-gate sdssc_create_end(sname, SDSSC_COMMIT);
6310Sstevel@tonic-gate
6320Sstevel@tonic-gate else {
6330Sstevel@tonic-gate /*
6340Sstevel@tonic-gate * If adding hosts to existing diskset,
6350Sstevel@tonic-gate * call DCS svcs
6360Sstevel@tonic-gate */
6370Sstevel@tonic-gate sdssc_add_hosts(sname, argc, argv);
6380Sstevel@tonic-gate }
6390Sstevel@tonic-gate if (!multi_node)
6400Sstevel@tonic-gate (void) meta_unlock(sp, ep);
6410Sstevel@tonic-gate md_exit(local_sp, 0);
6420Sstevel@tonic-gate }
6430Sstevel@tonic-gate
6440Sstevel@tonic-gate /*
6450Sstevel@tonic-gate * Add mediators
6460Sstevel@tonic-gate */
6470Sstevel@tonic-gate if (meds == TRUE) {
6480Sstevel@tonic-gate
6490Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
6500Sstevel@tonic-gate mde_perror(ep, "");
6510Sstevel@tonic-gate md_exit(local_sp, 1);
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate
6540Sstevel@tonic-gate if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) {
6550Sstevel@tonic-gate mde_perror(ep, "");
6560Sstevel@tonic-gate md_exit(local_sp, 1);
6570Sstevel@tonic-gate }
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL) {
6600Sstevel@tonic-gate mde_perror(ep, "");
6610Sstevel@tonic-gate md_exit(local_sp, 1);
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
6640Sstevel@tonic-gate multi_node = 1;
6650Sstevel@tonic-gate }
6660Sstevel@tonic-gate
6670Sstevel@tonic-gate if (meta_lock(local_sp, TRUE, ep) != 0) {
6680Sstevel@tonic-gate mde_perror(ep, "");
6690Sstevel@tonic-gate md_exit(local_sp, 1);
6700Sstevel@tonic-gate }
6710Sstevel@tonic-gate /*
6720Sstevel@tonic-gate * A MN diskset does not use the set meta_lock but
6730Sstevel@tonic-gate * instead uses the clnt_lock of rpc.metad and the
6740Sstevel@tonic-gate * suspend/resume feature of the rpc.mdcommd. Can't
6750Sstevel@tonic-gate * use set meta_lock since class 1 messages are
6760Sstevel@tonic-gate * grabbing this lock and if this thread is holding
6770Sstevel@tonic-gate * the set meta_lock then no rpc.mdcommd suspend
6780Sstevel@tonic-gate * can occur.
6790Sstevel@tonic-gate */
6800Sstevel@tonic-gate if (!multi_node) {
6810Sstevel@tonic-gate if (meta_lock(sp, TRUE, ep) != 0) {
6820Sstevel@tonic-gate mde_perror(ep, "");
6830Sstevel@tonic-gate md_exit(local_sp, 1);
6840Sstevel@tonic-gate }
6850Sstevel@tonic-gate }
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate if (meta_set_addmeds(sp, argc, argv, ep)) {
6880Sstevel@tonic-gate mde_perror(&status, "");
6890Sstevel@tonic-gate if (!multi_node)
6900Sstevel@tonic-gate (void) meta_unlock(sp, ep);
6910Sstevel@tonic-gate md_exit(local_sp, 1);
6920Sstevel@tonic-gate }
6930Sstevel@tonic-gate
6940Sstevel@tonic-gate if (!multi_node)
6950Sstevel@tonic-gate (void) meta_unlock(sp, ep);
6960Sstevel@tonic-gate md_exit(local_sp, 0);
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate
6990Sstevel@tonic-gate /*
7000Sstevel@tonic-gate * Add drives
7010Sstevel@tonic-gate */
7020Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
7030Sstevel@tonic-gate mde_perror(ep, "");
7040Sstevel@tonic-gate md_exit(local_sp, 1);
7050Sstevel@tonic-gate }
7060Sstevel@tonic-gate
7070Sstevel@tonic-gate if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) {
7080Sstevel@tonic-gate mde_perror(ep, "");
7090Sstevel@tonic-gate md_exit(local_sp, 1);
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate
7120Sstevel@tonic-gate /* Determine if diskset is a MN diskset or not */
7130Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL) {
7140Sstevel@tonic-gate mde_perror(ep, "");
7150Sstevel@tonic-gate md_exit(local_sp, 1);
7160Sstevel@tonic-gate }
7170Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
7180Sstevel@tonic-gate multi_node = 1;
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate
7210Sstevel@tonic-gate if (meta_lock(local_sp, TRUE, ep) != 0) {
7220Sstevel@tonic-gate mde_perror(ep, "");
7230Sstevel@tonic-gate md_exit(local_sp, 1);
7240Sstevel@tonic-gate }
7250Sstevel@tonic-gate
7260Sstevel@tonic-gate /* Make sure database size is within limits */
7270Sstevel@tonic-gate if (default_size == FALSE) {
7280Sstevel@tonic-gate if ((multi_node && dbsize < MDDB_MN_MINBLKS) ||
7290Sstevel@tonic-gate (!multi_node && dbsize < MDDB_MINBLKS))
7300Sstevel@tonic-gate usage(sp, gettext(
7310Sstevel@tonic-gate "size (-l) is too small"));
7320Sstevel@tonic-gate
7330Sstevel@tonic-gate if ((multi_node && dbsize > MDDB_MN_MAXBLKS) ||
7340Sstevel@tonic-gate (!multi_node && dbsize > MDDB_MAXBLKS))
7350Sstevel@tonic-gate usage(sp, gettext(
7360Sstevel@tonic-gate "size (-l) is too big"));
7370Sstevel@tonic-gate }
7380Sstevel@tonic-gate
7390Sstevel@tonic-gate /*
7400Sstevel@tonic-gate * Have a valid set, take the set lock also.
7410Sstevel@tonic-gate *
7420Sstevel@tonic-gate * A MN diskset does not use the set meta_lock but
7430Sstevel@tonic-gate * instead uses the clnt_lock of rpc.metad and the
7440Sstevel@tonic-gate * suspend/resume feature of the rpc.mdcommd. Can't
7450Sstevel@tonic-gate * use set meta_lock since class 1 messages are
7460Sstevel@tonic-gate * grabbing this lock and if this thread is holding
7470Sstevel@tonic-gate * the set meta_lock then no rpc.mdcommd suspend
7480Sstevel@tonic-gate * can occur.
7490Sstevel@tonic-gate */
7500Sstevel@tonic-gate if (!multi_node) {
7510Sstevel@tonic-gate if (meta_lock(sp, TRUE, ep) != 0) {
7520Sstevel@tonic-gate mde_perror(ep, "");
7530Sstevel@tonic-gate md_exit(local_sp, 1);
7540Sstevel@tonic-gate }
7550Sstevel@tonic-gate }
7560Sstevel@tonic-gate
7570Sstevel@tonic-gate
7580Sstevel@tonic-gate /*
7590Sstevel@tonic-gate * If using the default size,
7600Sstevel@tonic-gate * then let's adjust the default to the minimum
7610Sstevel@tonic-gate * size currently in use.
7620Sstevel@tonic-gate */
7630Sstevel@tonic-gate if (default_size) {
7640Sstevel@tonic-gate dbsize = multi_node ? MD_MN_DBSIZE : MD_DBSIZE;
7650Sstevel@tonic-gate if ((nblks = meta_db_minreplica(sp, ep)) < 0)
7660Sstevel@tonic-gate mdclrerror(ep);
7670Sstevel@tonic-gate else
7680Sstevel@tonic-gate dbsize = nblks; /* adjust replica size */
7690Sstevel@tonic-gate }
7700Sstevel@tonic-gate
7710Sstevel@tonic-gate if ((c = metadrivenamelist(&sp, &dnlp, argc, argv, ep)) < 0) {
7720Sstevel@tonic-gate mde_perror(ep, "");
7730Sstevel@tonic-gate if (!multi_node)
7740Sstevel@tonic-gate (void) meta_unlock(sp, ep);
7750Sstevel@tonic-gate md_exit(local_sp, 1);
7760Sstevel@tonic-gate }
7770Sstevel@tonic-gate
7780Sstevel@tonic-gate if (c == 0) {
7790Sstevel@tonic-gate md_perror(gettext(
7800Sstevel@tonic-gate "No drives specified to add.\n"));
7810Sstevel@tonic-gate if (!multi_node)
7820Sstevel@tonic-gate (void) meta_unlock(sp, ep);
7830Sstevel@tonic-gate md_exit(local_sp, 1);
7840Sstevel@tonic-gate }
7850Sstevel@tonic-gate
7860Sstevel@tonic-gate if (meta_set_adddrives(sp, dnlp, dbsize, force_label, ep)) {
7870Sstevel@tonic-gate metafreedrivenamelist(dnlp);
7880Sstevel@tonic-gate mde_perror(ep, "");
7890Sstevel@tonic-gate if (!multi_node)
7900Sstevel@tonic-gate (void) meta_unlock(sp, ep);
7910Sstevel@tonic-gate md_exit(local_sp, 1);
7920Sstevel@tonic-gate }
7930Sstevel@tonic-gate
7940Sstevel@tonic-gate /*
7950Sstevel@tonic-gate * MN disksets don't have a device id in the master block
7960Sstevel@tonic-gate * For traditional disksets, check for the drive device
7970Sstevel@tonic-gate * id not fitting in the master block
7980Sstevel@tonic-gate */
7990Sstevel@tonic-gate if (!multi_node) {
8000Sstevel@tonic-gate for (p = dnlp; p != NULL; p = p->next) {
8010Sstevel@tonic-gate int fd;
8020Sstevel@tonic-gate ddi_devid_t devid;
8030Sstevel@tonic-gate mdname_t *np;
8040Sstevel@tonic-gate
8050Sstevel@tonic-gate np = metaslicename(p->drivenamep, 0, ep);
8060Sstevel@tonic-gate if (np == NULL)
8070Sstevel@tonic-gate continue;
8080Sstevel@tonic-gate
8090Sstevel@tonic-gate if ((fd = open(np->rname, O_RDONLY | O_NDELAY)) < 0)
8100Sstevel@tonic-gate continue;
8110Sstevel@tonic-gate
8120Sstevel@tonic-gate if (devid_get(fd, &devid) == 0) {
8130Sstevel@tonic-gate size_t len;
8140Sstevel@tonic-gate
8150Sstevel@tonic-gate len = devid_sizeof(devid);
8160Sstevel@tonic-gate if (len > (DEV_BSIZE - sizeof (mddb_mb_t)))
8170Sstevel@tonic-gate (void) mddserror(ep,
8180Sstevel@tonic-gate MDE_DS_NOTSELFIDENTIFY, NULL, NULL,
8190Sstevel@tonic-gate np->rname, NULL);
8200Sstevel@tonic-gate devid_free(devid);
8210Sstevel@tonic-gate } else {
8220Sstevel@tonic-gate (void) mddserror(ep, MDE_DS_NOTSELFIDENTIFY,
8230Sstevel@tonic-gate NULL, NULL, np->rname, NULL);
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate (void) close(fd);
8260Sstevel@tonic-gate }
8270Sstevel@tonic-gate }
8280Sstevel@tonic-gate
8290Sstevel@tonic-gate /*
8300Sstevel@tonic-gate * MN disksets don't use DCS clustering services.
8310Sstevel@tonic-gate * For traditional disksets:
8320Sstevel@tonic-gate * There's not really much we can do here if this call fails.
8330Sstevel@tonic-gate * The drives have been added to the set and DiskSuite believes
8340Sstevel@tonic-gate * it owns the drives.
8350Sstevel@tonic-gate * Relase the set and hope for the best.
8360Sstevel@tonic-gate */
8370Sstevel@tonic-gate if ((!multi_node) &&
8380Sstevel@tonic-gate (sdssc_notify_service(sname, Make_Primary) == SDSSC_ERROR)) {
83911053SSurya.Prakki@Sun.COM (void) meta_set_release(sp, ep);
84011053SSurya.Prakki@Sun.COM (void) printf(gettext(
8410Sstevel@tonic-gate "Sun Clustering failed to make set primary\n"));
8420Sstevel@tonic-gate }
8430Sstevel@tonic-gate
8440Sstevel@tonic-gate metafreedrivenamelist(dnlp);
8450Sstevel@tonic-gate if (!multi_node)
8460Sstevel@tonic-gate (void) meta_unlock(sp, ep);
8470Sstevel@tonic-gate md_exit(local_sp, 0);
8480Sstevel@tonic-gate }
8490Sstevel@tonic-gate
8500Sstevel@tonic-gate static void
parse_balance(int argc,char ** argv)8510Sstevel@tonic-gate parse_balance(int argc, char **argv)
8520Sstevel@tonic-gate {
8530Sstevel@tonic-gate int c;
8540Sstevel@tonic-gate mdsetname_t *sp = NULL;
8550Sstevel@tonic-gate char *sname = MD_LOCAL_NAME;
8560Sstevel@tonic-gate md_error_t status = mdnullerror;
8570Sstevel@tonic-gate md_set_desc *sd;
8580Sstevel@tonic-gate int multi_node = 0;
8590Sstevel@tonic-gate
8600Sstevel@tonic-gate /* reset and parse args */
8610Sstevel@tonic-gate optind = 1;
8620Sstevel@tonic-gate opterr = 1;
8630Sstevel@tonic-gate while ((c = getopt(argc, argv, "Mbs:")) != -1) {
8640Sstevel@tonic-gate switch (c) {
8650Sstevel@tonic-gate case 'M':
8660Sstevel@tonic-gate break;
8670Sstevel@tonic-gate case 'b':
8680Sstevel@tonic-gate break;
8690Sstevel@tonic-gate case 's':
8700Sstevel@tonic-gate sname = optarg;
8710Sstevel@tonic-gate break;
8720Sstevel@tonic-gate default:
8730Sstevel@tonic-gate usage(sp, gettext("unknown options"));
8740Sstevel@tonic-gate }
8750Sstevel@tonic-gate }
8760Sstevel@tonic-gate
8770Sstevel@tonic-gate argc -= optind;
8780Sstevel@tonic-gate argv += optind;
8790Sstevel@tonic-gate
8800Sstevel@tonic-gate if (argc != 0)
8810Sstevel@tonic-gate usage(sp, gettext("too many args"));
8820Sstevel@tonic-gate
8830Sstevel@tonic-gate if ((sp = metasetname(sname, &status)) == NULL) {
8840Sstevel@tonic-gate mde_perror(&status, "");
8850Sstevel@tonic-gate md_exit(sp, 1);
8860Sstevel@tonic-gate }
8870Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, &status)) == NULL) {
8880Sstevel@tonic-gate mde_perror(&status, "");
8890Sstevel@tonic-gate md_exit(sp, 1);
8900Sstevel@tonic-gate }
8910Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
8920Sstevel@tonic-gate multi_node = 1;
8930Sstevel@tonic-gate }
8940Sstevel@tonic-gate /*
8950Sstevel@tonic-gate * Have a valid set, take the set lock also.
8960Sstevel@tonic-gate *
8970Sstevel@tonic-gate * A MN diskset does not use the set meta_lock but
8980Sstevel@tonic-gate * instead uses the clnt_lock of rpc.metad and the
8990Sstevel@tonic-gate * suspend/resume feature of the rpc.mdcommd. Can't
9000Sstevel@tonic-gate * use set meta_lock since class 1 messages are
9010Sstevel@tonic-gate * grabbing this lock and if this thread is holding
9020Sstevel@tonic-gate * the set meta_lock then no rpc.mdcommd suspend
9030Sstevel@tonic-gate * can occur.
9040Sstevel@tonic-gate */
9050Sstevel@tonic-gate if (!multi_node) {
9060Sstevel@tonic-gate if (meta_lock(sp, TRUE, &status) != 0) {
9070Sstevel@tonic-gate mde_perror(&status, "");
9080Sstevel@tonic-gate md_exit(sp, 1);
9090Sstevel@tonic-gate }
9100Sstevel@tonic-gate }
9110Sstevel@tonic-gate
9120Sstevel@tonic-gate if (meta_set_balance(sp, &status) != 0) {
9130Sstevel@tonic-gate mde_perror(&status, "");
9140Sstevel@tonic-gate md_exit(sp, 1);
9150Sstevel@tonic-gate }
9160Sstevel@tonic-gate md_exit(sp, 0);
9170Sstevel@tonic-gate }
9180Sstevel@tonic-gate
9190Sstevel@tonic-gate static void
parse_autotake(int argc,char ** argv)9200Sstevel@tonic-gate parse_autotake(int argc, char **argv)
9210Sstevel@tonic-gate {
9220Sstevel@tonic-gate int c;
9230Sstevel@tonic-gate int enable = 0;
9240Sstevel@tonic-gate mdsetname_t *sp = NULL;
9250Sstevel@tonic-gate char *sname = MD_LOCAL_NAME;
9260Sstevel@tonic-gate md_error_t status = mdnullerror;
9270Sstevel@tonic-gate md_error_t *ep = &status;
9280Sstevel@tonic-gate
9290Sstevel@tonic-gate /* reset and parse args */
9300Sstevel@tonic-gate optind = 1;
9310Sstevel@tonic-gate opterr = 1;
9320Sstevel@tonic-gate while ((c = getopt(argc, argv, "A:s:")) != -1) {
9330Sstevel@tonic-gate switch (c) {
9340Sstevel@tonic-gate case 'A':
9350Sstevel@tonic-gate /* verified sub-option in main */
9360Sstevel@tonic-gate if (strcmp(optarg, "enable") == 0)
9370Sstevel@tonic-gate enable = 1;
9380Sstevel@tonic-gate break;
9390Sstevel@tonic-gate case 's':
9400Sstevel@tonic-gate /* verified presence of setname in main */
9410Sstevel@tonic-gate sname = optarg;
9420Sstevel@tonic-gate break;
9430Sstevel@tonic-gate default:
9440Sstevel@tonic-gate usage(sp, gettext("unknown options"));
9450Sstevel@tonic-gate }
9460Sstevel@tonic-gate }
9470Sstevel@tonic-gate
9480Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
9490Sstevel@tonic-gate mde_perror(ep, "");
9500Sstevel@tonic-gate md_exit(sp, 1);
9510Sstevel@tonic-gate }
9520Sstevel@tonic-gate
9530Sstevel@tonic-gate if (meta_lock(sp, TRUE, ep) != 0) {
9540Sstevel@tonic-gate mde_perror(ep, "");
9550Sstevel@tonic-gate md_exit(sp, 1);
9560Sstevel@tonic-gate }
9570Sstevel@tonic-gate
9580Sstevel@tonic-gate if (meta_check_ownership(sp, ep) != 0) {
9590Sstevel@tonic-gate mde_perror(ep, "");
9600Sstevel@tonic-gate md_exit(sp, 1);
9610Sstevel@tonic-gate }
9620Sstevel@tonic-gate
9630Sstevel@tonic-gate if (meta_set_auto_take(sp, enable, ep) != 0) {
9640Sstevel@tonic-gate mde_perror(ep, "");
9650Sstevel@tonic-gate md_exit(sp, 1);
9660Sstevel@tonic-gate }
9670Sstevel@tonic-gate
9680Sstevel@tonic-gate md_exit(sp, 0);
9690Sstevel@tonic-gate }
9700Sstevel@tonic-gate
9710Sstevel@tonic-gate static void
parse_del(int argc,char ** argv)9720Sstevel@tonic-gate parse_del(int argc, char **argv)
9730Sstevel@tonic-gate {
9740Sstevel@tonic-gate int c;
9750Sstevel@tonic-gate mdsetname_t *sp = NULL;
9760Sstevel@tonic-gate char *sname = MD_LOCAL_NAME;
9770Sstevel@tonic-gate int hosts = FALSE;
9780Sstevel@tonic-gate int meds = FALSE;
9790Sstevel@tonic-gate int forceflg = FALSE;
9800Sstevel@tonic-gate md_error_t status = mdnullerror;
9810Sstevel@tonic-gate md_error_t *ep = &status;
9820Sstevel@tonic-gate mddrivenamelist_t *dnlp = NULL;
9830Sstevel@tonic-gate mdsetname_t *local_sp = NULL;
9840Sstevel@tonic-gate md_set_desc *sd;
9850Sstevel@tonic-gate int multi_node = 0;
9860Sstevel@tonic-gate
9870Sstevel@tonic-gate /* reset and parse args */
9880Sstevel@tonic-gate optind = 1;
9890Sstevel@tonic-gate opterr = 1;
9900Sstevel@tonic-gate while ((c = getopt(argc, argv, "Mdfhms:")) != -1) {
9910Sstevel@tonic-gate switch (c) {
9920Sstevel@tonic-gate case 'M':
9930Sstevel@tonic-gate break;
9940Sstevel@tonic-gate case 'd':
9950Sstevel@tonic-gate break;
9960Sstevel@tonic-gate case 'f':
9970Sstevel@tonic-gate forceflg = TRUE;
9980Sstevel@tonic-gate break;
9990Sstevel@tonic-gate case 'h':
10000Sstevel@tonic-gate case 'm':
10010Sstevel@tonic-gate if (meds == TRUE || hosts == TRUE)
10020Sstevel@tonic-gate usage(sp, gettext(
10030Sstevel@tonic-gate "only one -m or -h option allowed"));
10040Sstevel@tonic-gate
10050Sstevel@tonic-gate if (c == 'h')
10060Sstevel@tonic-gate hosts = TRUE;
10070Sstevel@tonic-gate else
10080Sstevel@tonic-gate meds = TRUE;
10090Sstevel@tonic-gate break;
10100Sstevel@tonic-gate case 's':
10110Sstevel@tonic-gate sname = optarg;
10120Sstevel@tonic-gate break;
10130Sstevel@tonic-gate default:
10140Sstevel@tonic-gate usage(sp, gettext("unknown options"));
10150Sstevel@tonic-gate }
10160Sstevel@tonic-gate }
10170Sstevel@tonic-gate
10180Sstevel@tonic-gate argc -= optind;
10190Sstevel@tonic-gate argv += optind;
10200Sstevel@tonic-gate
10210Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
10220Sstevel@tonic-gate mde_perror(ep, "");
10230Sstevel@tonic-gate md_exit(local_sp, 1);
10240Sstevel@tonic-gate }
10250Sstevel@tonic-gate
10260Sstevel@tonic-gate if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) {
10270Sstevel@tonic-gate mde_perror(ep, "");
10280Sstevel@tonic-gate md_exit(local_sp, 1);
10290Sstevel@tonic-gate }
10300Sstevel@tonic-gate
10310Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL) {
10320Sstevel@tonic-gate mde_perror(ep, "");
10330Sstevel@tonic-gate md_exit(local_sp, 1);
10340Sstevel@tonic-gate }
10350Sstevel@tonic-gate if (MD_MNSET_DESC(sd))
10360Sstevel@tonic-gate multi_node = 1;
10370Sstevel@tonic-gate
10380Sstevel@tonic-gate if (meta_lock(local_sp, TRUE, ep) != 0) {
10390Sstevel@tonic-gate mde_perror(ep, "");
10400Sstevel@tonic-gate md_exit(local_sp, 1);
10410Sstevel@tonic-gate }
10420Sstevel@tonic-gate
10430Sstevel@tonic-gate /*
10440Sstevel@tonic-gate * Have a valid set, take the set lock also.
10450Sstevel@tonic-gate *
10460Sstevel@tonic-gate * A MN diskset does not use the set meta_lock but
10470Sstevel@tonic-gate * instead uses the clnt_lock of rpc.metad and the
10480Sstevel@tonic-gate * suspend/resume feature of the rpc.mdcommd. Can't
10490Sstevel@tonic-gate * use set meta_lock since class 1 messages are
10500Sstevel@tonic-gate * grabbing this lock and if this thread is holding
10510Sstevel@tonic-gate * the set meta_lock then no rpc.mdcommd suspend
10520Sstevel@tonic-gate * can occur.
10530Sstevel@tonic-gate */
10540Sstevel@tonic-gate if (!multi_node) {
10550Sstevel@tonic-gate if (meta_lock(sp, TRUE, ep) != 0) {
10560Sstevel@tonic-gate mde_perror(ep, "");
10570Sstevel@tonic-gate md_exit(local_sp, 1);
10580Sstevel@tonic-gate }
10590Sstevel@tonic-gate }
10600Sstevel@tonic-gate
10610Sstevel@tonic-gate /*
10620Sstevel@tonic-gate * Delete hosts
10630Sstevel@tonic-gate */
10640Sstevel@tonic-gate if (hosts == TRUE) {
10650Sstevel@tonic-gate if (meta_check_ownership(sp, ep) != 0) {
10660Sstevel@tonic-gate /*
10670Sstevel@tonic-gate * If we don't own the set bail out here otherwise
10680Sstevel@tonic-gate * we could delete the node from the DCS service
10690Sstevel@tonic-gate * yet not delete the host from the set.
10700Sstevel@tonic-gate */
10710Sstevel@tonic-gate mde_perror(ep, "");
10720Sstevel@tonic-gate if (!multi_node)
10730Sstevel@tonic-gate (void) meta_unlock(sp, ep);
10740Sstevel@tonic-gate md_exit(local_sp, 1);
10750Sstevel@tonic-gate }
10760Sstevel@tonic-gate if (sdssc_delete_hosts(sname, argc, argv) == SDSSC_ERROR) {
10774932Spetede if (!metad_isautotakebyname(sname)) {
10784932Spetede /*
10794932Spetede * SC could have been installed after the set
10804932Spetede * was created. We still want to be able to
10814932Spetede * delete these sets.
10824932Spetede */
10834932Spetede md_perror(gettext(
10844932Spetede "Failed to delete hosts from DCS service"));
10854932Spetede if (!multi_node)
10864932Spetede (void) meta_unlock(sp, ep);
10874932Spetede md_exit(local_sp, 1);
10884932Spetede }
10890Sstevel@tonic-gate }
10900Sstevel@tonic-gate if (meta_set_deletehosts(sp, argc, argv, forceflg, ep)) {
10910Sstevel@tonic-gate if (sdssc_add_hosts(sname, argc, argv) == SDSSC_ERROR) {
10920Sstevel@tonic-gate (void) printf(gettext(
10930Sstevel@tonic-gate "Failed to restore host(s) in DCS "
10940Sstevel@tonic-gate "database\n"));
10950Sstevel@tonic-gate }
10960Sstevel@tonic-gate mde_perror(ep, "");
10970Sstevel@tonic-gate if (!multi_node)
10980Sstevel@tonic-gate (void) meta_unlock(sp, ep);
10990Sstevel@tonic-gate md_exit(local_sp, 1);
11000Sstevel@tonic-gate }
11010Sstevel@tonic-gate if (!multi_node)
11020Sstevel@tonic-gate (void) meta_unlock(sp, ep);
11030Sstevel@tonic-gate md_exit(local_sp, 0);
11040Sstevel@tonic-gate }
11050Sstevel@tonic-gate
11060Sstevel@tonic-gate /*
11070Sstevel@tonic-gate * Delete mediators
11080Sstevel@tonic-gate */
11090Sstevel@tonic-gate if (meds == TRUE) {
11100Sstevel@tonic-gate if (meta_set_deletemeds(sp, argc, argv, forceflg, ep)) {
11110Sstevel@tonic-gate mde_perror(ep, "");
11120Sstevel@tonic-gate if (!multi_node)
11130Sstevel@tonic-gate (void) meta_unlock(sp, ep);
11140Sstevel@tonic-gate md_exit(local_sp, 1);
11150Sstevel@tonic-gate }
11160Sstevel@tonic-gate if (!multi_node)
11170Sstevel@tonic-gate (void) meta_unlock(sp, ep);
11180Sstevel@tonic-gate md_exit(local_sp, 0);
11190Sstevel@tonic-gate }
11200Sstevel@tonic-gate
11210Sstevel@tonic-gate /*
11220Sstevel@tonic-gate * Delete drives
11230Sstevel@tonic-gate */
11240Sstevel@tonic-gate
11250Sstevel@tonic-gate if ((c = metadrivenamelist(&sp, &dnlp, argc, argv, ep)) < 0) {
11260Sstevel@tonic-gate mde_perror(ep, "");
11270Sstevel@tonic-gate if (!multi_node)
11280Sstevel@tonic-gate (void) meta_unlock(sp, ep);
11290Sstevel@tonic-gate md_exit(local_sp, 1);
11300Sstevel@tonic-gate }
11310Sstevel@tonic-gate
11320Sstevel@tonic-gate if (c == 0) {
11330Sstevel@tonic-gate md_perror(gettext(
11340Sstevel@tonic-gate "No drives specified to delete.\n"));
11350Sstevel@tonic-gate if (!multi_node)
11360Sstevel@tonic-gate (void) meta_unlock(sp, ep);
11370Sstevel@tonic-gate md_exit(local_sp, 1);
11380Sstevel@tonic-gate }
11390Sstevel@tonic-gate
11400Sstevel@tonic-gate if (meta_set_deletedrives(sp, dnlp, forceflg, ep)) {
11410Sstevel@tonic-gate metafreedrivenamelist(dnlp);
11420Sstevel@tonic-gate mde_perror(ep, "");
11430Sstevel@tonic-gate if (!multi_node)
11440Sstevel@tonic-gate (void) meta_unlock(sp, ep);
11450Sstevel@tonic-gate md_exit(local_sp, 1);
11460Sstevel@tonic-gate }
11470Sstevel@tonic-gate
11480Sstevel@tonic-gate metafreedrivenamelist(dnlp);
11490Sstevel@tonic-gate if (!multi_node)
11500Sstevel@tonic-gate (void) meta_unlock(sp, ep);
11510Sstevel@tonic-gate md_exit(local_sp, 0);
11520Sstevel@tonic-gate }
11530Sstevel@tonic-gate
11540Sstevel@tonic-gate static void
parse_isowner(int argc,char ** argv)11550Sstevel@tonic-gate parse_isowner(int argc, char **argv)
11560Sstevel@tonic-gate {
11570Sstevel@tonic-gate int c;
11580Sstevel@tonic-gate mdsetname_t *sp = NULL;
11590Sstevel@tonic-gate char *sname = MD_LOCAL_NAME;
11600Sstevel@tonic-gate md_error_t status = mdnullerror;
11610Sstevel@tonic-gate md_error_t *ep = &status;
11620Sstevel@tonic-gate char *host = NULL;
11630Sstevel@tonic-gate
11640Sstevel@tonic-gate /* reset and parse args */
11650Sstevel@tonic-gate optind = 1;
11660Sstevel@tonic-gate opterr = 1;
11670Sstevel@tonic-gate while ((c = getopt(argc, argv, "Moh:s:")) != -1) {
11680Sstevel@tonic-gate switch (c) {
11690Sstevel@tonic-gate case 'M':
11700Sstevel@tonic-gate break;
11710Sstevel@tonic-gate case 'o':
11720Sstevel@tonic-gate break;
11730Sstevel@tonic-gate case 'h':
11740Sstevel@tonic-gate if (host != NULL) {
11750Sstevel@tonic-gate usage(sp, gettext(
11760Sstevel@tonic-gate "only one -h option allowed"));
11770Sstevel@tonic-gate }
11780Sstevel@tonic-gate host = optarg;
11790Sstevel@tonic-gate break;
11800Sstevel@tonic-gate case 's':
11810Sstevel@tonic-gate sname = optarg;
11820Sstevel@tonic-gate break;
11830Sstevel@tonic-gate default:
11840Sstevel@tonic-gate usage(sp, gettext("unknown options"));
11850Sstevel@tonic-gate }
11860Sstevel@tonic-gate }
11870Sstevel@tonic-gate
11880Sstevel@tonic-gate argc -= optind;
11890Sstevel@tonic-gate argv += optind;
11900Sstevel@tonic-gate
11910Sstevel@tonic-gate if (argc != 0)
11920Sstevel@tonic-gate usage(sp, gettext("too many args"));
11930Sstevel@tonic-gate
11940Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
11950Sstevel@tonic-gate mde_perror(ep, "");
11960Sstevel@tonic-gate md_exit(sp, 1);
11970Sstevel@tonic-gate }
11980Sstevel@tonic-gate
11990Sstevel@tonic-gate if (host == NULL) {
12000Sstevel@tonic-gate if (meta_check_ownership(sp, ep) != 0) {
12010Sstevel@tonic-gate mde_perror(ep, "");
12020Sstevel@tonic-gate md_exit(sp, 1);
12030Sstevel@tonic-gate }
12040Sstevel@tonic-gate } else {
12050Sstevel@tonic-gate if (meta_check_ownership_on_host(sp, host, ep) != 0) {
12060Sstevel@tonic-gate mde_perror(ep, "");
12070Sstevel@tonic-gate md_exit(sp, 1);
12080Sstevel@tonic-gate }
12090Sstevel@tonic-gate }
12100Sstevel@tonic-gate md_exit(sp, 0);
12110Sstevel@tonic-gate }
12120Sstevel@tonic-gate
12130Sstevel@tonic-gate static void
parse_purge(int argc,char ** argv)12140Sstevel@tonic-gate parse_purge(int argc, char **argv)
12150Sstevel@tonic-gate {
12160Sstevel@tonic-gate int c;
12170Sstevel@tonic-gate mdsetname_t *sp = NULL;
12180Sstevel@tonic-gate mdsetname_t *local_sp = NULL;
12190Sstevel@tonic-gate md_drive_desc *dd;
12200Sstevel@tonic-gate char *sname = MD_LOCAL_NAME;
12210Sstevel@tonic-gate char *thishost = mynode();
12220Sstevel@tonic-gate md_error_t status = mdnullerror;
12230Sstevel@tonic-gate md_error_t *ep = &status;
12240Sstevel@tonic-gate int bypass_cluster_purge = 0;
12250Sstevel@tonic-gate int forceflg = FALSE;
12260Sstevel@tonic-gate int ret = 0;
12270Sstevel@tonic-gate int multi_node = 0;
12280Sstevel@tonic-gate md_set_desc *sd;
12290Sstevel@tonic-gate
12300Sstevel@tonic-gate optind = 1;
12310Sstevel@tonic-gate opterr = 1;
12320Sstevel@tonic-gate while ((c = getopt(argc, argv, "C:fPs:")) != -1) {
12330Sstevel@tonic-gate switch (c) {
12340Sstevel@tonic-gate case 'M':
12350Sstevel@tonic-gate break;
12360Sstevel@tonic-gate case 'C':
12370Sstevel@tonic-gate bypass_cluster_purge = 1;
12380Sstevel@tonic-gate break;
12390Sstevel@tonic-gate case 'f':
12400Sstevel@tonic-gate forceflg = TRUE;
12410Sstevel@tonic-gate break;
12420Sstevel@tonic-gate case 'P':
12430Sstevel@tonic-gate break;
12440Sstevel@tonic-gate case 's':
12450Sstevel@tonic-gate sname = optarg;
12460Sstevel@tonic-gate break;
12470Sstevel@tonic-gate default:
12480Sstevel@tonic-gate usage(sp, gettext("unknown options"));
12490Sstevel@tonic-gate }
12500Sstevel@tonic-gate }
12510Sstevel@tonic-gate
12520Sstevel@tonic-gate argc -= optind;
12530Sstevel@tonic-gate argv += optind;
12540Sstevel@tonic-gate
12550Sstevel@tonic-gate if (argc != 0)
12560Sstevel@tonic-gate usage(sp, gettext("too many arguments"));
12570Sstevel@tonic-gate
12580Sstevel@tonic-gate if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) {
12590Sstevel@tonic-gate mde_perror(ep, "");
12600Sstevel@tonic-gate md_exit(local_sp, 1);
12610Sstevel@tonic-gate }
12620Sstevel@tonic-gate
12630Sstevel@tonic-gate if (meta_lock(local_sp, TRUE, ep) != 0) {
12640Sstevel@tonic-gate mde_perror(ep, "");
12650Sstevel@tonic-gate md_exit(local_sp, 1);
12660Sstevel@tonic-gate }
12670Sstevel@tonic-gate
12680Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
12690Sstevel@tonic-gate mde_perror(ep, "");
12700Sstevel@tonic-gate md_exit(sp, 1);
12710Sstevel@tonic-gate }
12720Sstevel@tonic-gate
12730Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL) {
12740Sstevel@tonic-gate mde_perror(ep, "");
12750Sstevel@tonic-gate md_exit(local_sp, 1);
12760Sstevel@tonic-gate }
12770Sstevel@tonic-gate if (MD_MNSET_DESC(sd))
12780Sstevel@tonic-gate multi_node = 1;
12790Sstevel@tonic-gate
12800Sstevel@tonic-gate if (!multi_node) {
12810Sstevel@tonic-gate if (meta_lock(sp, TRUE, ep) != 0) {
12820Sstevel@tonic-gate mde_perror(ep, "");
12830Sstevel@tonic-gate md_exit(local_sp, 1);
12840Sstevel@tonic-gate }
12850Sstevel@tonic-gate }
12860Sstevel@tonic-gate
12870Sstevel@tonic-gate /* Must not own the set if purging it from this host */
12880Sstevel@tonic-gate if (meta_check_ownership(sp, ep) == 0) {
12890Sstevel@tonic-gate /*
12900Sstevel@tonic-gate * Need to see if there are disks in the set, if not then
12910Sstevel@tonic-gate * there is no ownership but meta_check_ownership returns 0
12920Sstevel@tonic-gate */
12930Sstevel@tonic-gate dd = metaget_drivedesc(sp, (MD_BASICNAME_OK | PRINT_FAST), ep);
12940Sstevel@tonic-gate if (!mdisok(ep)) {
12950Sstevel@tonic-gate mde_perror(ep, "");
12960Sstevel@tonic-gate if (!multi_node)
12970Sstevel@tonic-gate (void) meta_unlock(sp, ep);
12980Sstevel@tonic-gate md_exit(local_sp, 1);
12990Sstevel@tonic-gate }
13000Sstevel@tonic-gate if (dd != NULL) {
13010Sstevel@tonic-gate (void) printf(gettext
13020Sstevel@tonic-gate ("Must not be owner of the set when purging it\n"));
13030Sstevel@tonic-gate if (!multi_node)
13040Sstevel@tonic-gate (void) meta_unlock(sp, ep);
13050Sstevel@tonic-gate md_exit(local_sp, 1);
13060Sstevel@tonic-gate }
13070Sstevel@tonic-gate }
13080Sstevel@tonic-gate /*
13090Sstevel@tonic-gate * Remove the node from the DCS service
13100Sstevel@tonic-gate */
13110Sstevel@tonic-gate if (!bypass_cluster_purge) {
13120Sstevel@tonic-gate if (sdssc_delete_hosts(sname, 1, &thishost) == SDSSC_ERROR) {
13130Sstevel@tonic-gate md_perror(gettext
13140Sstevel@tonic-gate ("Failed to purge hosts from DCS service"));
13150Sstevel@tonic-gate if (!multi_node)
13160Sstevel@tonic-gate (void) meta_unlock(sp, ep);
13170Sstevel@tonic-gate md_exit(local_sp, 1);
13180Sstevel@tonic-gate }
13190Sstevel@tonic-gate }
13200Sstevel@tonic-gate
13210Sstevel@tonic-gate if ((ret = meta_set_purge(sp, bypass_cluster_purge, forceflg,
13220Sstevel@tonic-gate ep)) != 0) {
13230Sstevel@tonic-gate if (!bypass_cluster_purge) {
13240Sstevel@tonic-gate if (sdssc_add_hosts(sname, 1, &thishost) ==
13250Sstevel@tonic-gate SDSSC_ERROR) {
13260Sstevel@tonic-gate (void) printf(gettext(
13270Sstevel@tonic-gate "Failed to restore host in DCS "
13280Sstevel@tonic-gate "database\n"));
13290Sstevel@tonic-gate }
13300Sstevel@tonic-gate }
13310Sstevel@tonic-gate mde_perror(ep, "");
13320Sstevel@tonic-gate if (!multi_node)
13330Sstevel@tonic-gate (void) meta_unlock(sp, ep);
13340Sstevel@tonic-gate md_exit(local_sp, ret);
13350Sstevel@tonic-gate }
13360Sstevel@tonic-gate
13370Sstevel@tonic-gate if (!multi_node)
13380Sstevel@tonic-gate (void) meta_unlock(sp, ep);
13390Sstevel@tonic-gate md_exit(local_sp, 0);
13400Sstevel@tonic-gate }
13410Sstevel@tonic-gate
13420Sstevel@tonic-gate static void
parse_query(int argc,char ** argv)13430Sstevel@tonic-gate parse_query(int argc, char **argv)
13440Sstevel@tonic-gate {
13450Sstevel@tonic-gate int c;
13460Sstevel@tonic-gate mdsetname_t *sp = NULL;
13470Sstevel@tonic-gate mddb_dtag_lst_t *dtlp = NULL;
13480Sstevel@tonic-gate mddb_dtag_lst_t *tdtlp;
13490Sstevel@tonic-gate char *sname = MD_LOCAL_NAME;
13500Sstevel@tonic-gate md_error_t status = mdnullerror;
13510Sstevel@tonic-gate
13520Sstevel@tonic-gate /* reset and parse args */
13530Sstevel@tonic-gate optind = 1;
13540Sstevel@tonic-gate opterr = 1;
13550Sstevel@tonic-gate while ((c = getopt(argc, argv, "Mqs:")) != -1) {
13560Sstevel@tonic-gate switch (c) {
13570Sstevel@tonic-gate case 'M':
13580Sstevel@tonic-gate break;
13590Sstevel@tonic-gate case 'q':
13600Sstevel@tonic-gate break;
13610Sstevel@tonic-gate case 's':
13620Sstevel@tonic-gate sname = optarg;
13630Sstevel@tonic-gate break;
13640Sstevel@tonic-gate default:
13650Sstevel@tonic-gate usage(sp, gettext("unknown options"));
13660Sstevel@tonic-gate }
13670Sstevel@tonic-gate }
13680Sstevel@tonic-gate
13690Sstevel@tonic-gate argc -= optind;
13700Sstevel@tonic-gate argv += optind;
13710Sstevel@tonic-gate
13720Sstevel@tonic-gate if (argc != 0)
13730Sstevel@tonic-gate usage(sp, gettext("too many args"));
13740Sstevel@tonic-gate
13750Sstevel@tonic-gate if ((sp = metasetname(sname, &status)) == NULL) {
13760Sstevel@tonic-gate mde_perror(&status, "");
13770Sstevel@tonic-gate md_exit(sp, 1);
13780Sstevel@tonic-gate }
13790Sstevel@tonic-gate
13800Sstevel@tonic-gate if (meta_lock(sp, TRUE, &status) != 0) {
13810Sstevel@tonic-gate mde_perror(&status, "");
13820Sstevel@tonic-gate md_exit(sp, 1);
13830Sstevel@tonic-gate }
13840Sstevel@tonic-gate
13850Sstevel@tonic-gate if (meta_set_query(sp, &dtlp, &status) != 0) {
13860Sstevel@tonic-gate mde_perror(&status, "");
13870Sstevel@tonic-gate md_exit(sp, 1);
13880Sstevel@tonic-gate }
13890Sstevel@tonic-gate
13900Sstevel@tonic-gate if (dtlp != NULL)
13910Sstevel@tonic-gate (void) printf("The following tag(s) were found:\n");
13920Sstevel@tonic-gate
13930Sstevel@tonic-gate for (tdtlp = dtlp; tdtlp != NULL; tdtlp = dtlp) {
13940Sstevel@tonic-gate dtlp = tdtlp->dtl_nx;
13950Sstevel@tonic-gate (void) printf("%2d - %s - %s", tdtlp->dtl_dt.dt_id,
13960Sstevel@tonic-gate tdtlp->dtl_dt.dt_hn,
13970Sstevel@tonic-gate ctime((long *)&tdtlp->dtl_dt.dt_tv.tv_sec));
13980Sstevel@tonic-gate Free(tdtlp);
13990Sstevel@tonic-gate }
14000Sstevel@tonic-gate
14010Sstevel@tonic-gate md_exit(sp, 0);
14020Sstevel@tonic-gate }
14030Sstevel@tonic-gate
14040Sstevel@tonic-gate /* Should never be called with sname of a Multinode diskset. */
14050Sstevel@tonic-gate static void
parse_releaseset(int argc,char ** argv)14060Sstevel@tonic-gate parse_releaseset(int argc, char **argv)
14070Sstevel@tonic-gate {
14080Sstevel@tonic-gate int c;
14090Sstevel@tonic-gate mdsetname_t *sp = NULL;
14100Sstevel@tonic-gate md_error_t status = mdnullerror;
14110Sstevel@tonic-gate md_error_t *ep = &status;
14120Sstevel@tonic-gate char *sname = MD_LOCAL_NAME;
14130Sstevel@tonic-gate sdssc_boolean_e cluster_release = SDSSC_False;
14140Sstevel@tonic-gate sdssc_version_t vers;
14150Sstevel@tonic-gate rval_e rval;
14160Sstevel@tonic-gate md_set_desc *sd;
14170Sstevel@tonic-gate
14180Sstevel@tonic-gate /* reset and parse args */
14190Sstevel@tonic-gate optind = 1;
14200Sstevel@tonic-gate opterr = 1;
14211320Srd117015 while ((c = getopt(argc, argv, "C:s:r")) != -1) {
14220Sstevel@tonic-gate switch (c) {
14230Sstevel@tonic-gate case 'C':
14240Sstevel@tonic-gate cluster_release = SDSSC_True;
14250Sstevel@tonic-gate break;
14260Sstevel@tonic-gate case 's':
14270Sstevel@tonic-gate sname = optarg;
14280Sstevel@tonic-gate break;
14290Sstevel@tonic-gate case 'r':
14300Sstevel@tonic-gate break;
14310Sstevel@tonic-gate default:
14320Sstevel@tonic-gate usage(sp, gettext("unknown options"));
14330Sstevel@tonic-gate }
14340Sstevel@tonic-gate }
14350Sstevel@tonic-gate
14360Sstevel@tonic-gate argc -= optind;
14370Sstevel@tonic-gate argv += optind;
14380Sstevel@tonic-gate
14390Sstevel@tonic-gate if (argc > 0)
14400Sstevel@tonic-gate usage(sp, gettext("too many args"));
14410Sstevel@tonic-gate
144211053SSurya.Prakki@Sun.COM (void) memset(&vers, 0, sizeof (vers));
14430Sstevel@tonic-gate
14440Sstevel@tonic-gate if ((sdssc_version(&vers) == SDSSC_OKAY) &&
14450Sstevel@tonic-gate (vers.major == 3) &&
14460Sstevel@tonic-gate (cluster_release == SDSSC_False)) {
14470Sstevel@tonic-gate
14480Sstevel@tonic-gate /*
14490Sstevel@tonic-gate * If the release is being done by the user via the CLI
14500Sstevel@tonic-gate * we need to notify the DCS to release this node as being
14510Sstevel@tonic-gate * the primary. The reason nothing else needs to be done
14520Sstevel@tonic-gate * is due to the fact that the reservation code will exec
14530Sstevel@tonic-gate * metaset -C release to complete the operation.
14540Sstevel@tonic-gate */
14550Sstevel@tonic-gate rval = sdssc_notify_service(sname, Release_Primary);
14560Sstevel@tonic-gate if (rval == SDSSC_ERROR) {
145711053SSurya.Prakki@Sun.COM (void) printf(gettext(
14580Sstevel@tonic-gate "metaset: failed to notify DCS of release\n"));
14590Sstevel@tonic-gate }
14600Sstevel@tonic-gate md_exit(NULL, rval == SDSSC_ERROR);
14610Sstevel@tonic-gate }
14620Sstevel@tonic-gate
14630Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
14640Sstevel@tonic-gate
14650Sstevel@tonic-gate /*
14660Sstevel@tonic-gate * It's entirely possible for the SC3.0 reservation code
14670Sstevel@tonic-gate * to call for DiskSet to release a diskset and have that
14680Sstevel@tonic-gate * diskset not exist. During a diskset removal DiskSuite
14690Sstevel@tonic-gate * maybe able to remove all traces of the diskset before
14700Sstevel@tonic-gate * the reservation code execs metaset -C release in which
14710Sstevel@tonic-gate * case the metasetname will fail, but the overall command
14720Sstevel@tonic-gate * shouldn't.
14730Sstevel@tonic-gate */
14740Sstevel@tonic-gate if (vers.major == 3)
14750Sstevel@tonic-gate md_exit(sp, 0);
14760Sstevel@tonic-gate else {
14770Sstevel@tonic-gate mde_perror(ep, "");
14780Sstevel@tonic-gate md_exit(sp, 1);
14790Sstevel@tonic-gate }
14800Sstevel@tonic-gate }
14810Sstevel@tonic-gate
14820Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL) {
14830Sstevel@tonic-gate mde_perror(ep, "");
14840Sstevel@tonic-gate md_exit(sp, 1);
14850Sstevel@tonic-gate }
14860Sstevel@tonic-gate
14870Sstevel@tonic-gate if (sd->sd_flags & MD_SR_AUTO_TAKE) {
14880Sstevel@tonic-gate md_eprintf(gettext("cannot release auto-take diskset\n"));
14890Sstevel@tonic-gate md_exit(sp, 1);
14900Sstevel@tonic-gate }
14910Sstevel@tonic-gate
14920Sstevel@tonic-gate if (meta_lock_nowait(sp, ep) != 0) {
14931320Srd117015 mde_perror(ep, "");
14941320Srd117015 md_exit(sp, 10); /* special errcode */
14950Sstevel@tonic-gate }
14960Sstevel@tonic-gate
14970Sstevel@tonic-gate if (meta_set_release(sp, ep)) {
14980Sstevel@tonic-gate mde_perror(ep, "");
14990Sstevel@tonic-gate md_exit(sp, 1);
15000Sstevel@tonic-gate }
15010Sstevel@tonic-gate md_exit(sp, 0);
15020Sstevel@tonic-gate }
15030Sstevel@tonic-gate
15040Sstevel@tonic-gate /* Should never be called with sname of a Multinode diskset. */
15050Sstevel@tonic-gate static void
parse_takeset(int argc,char ** argv)15060Sstevel@tonic-gate parse_takeset(int argc, char **argv)
15070Sstevel@tonic-gate {
15080Sstevel@tonic-gate int c;
15090Sstevel@tonic-gate mdsetname_t *sp = NULL;
15100Sstevel@tonic-gate int flags = 0;
15110Sstevel@tonic-gate char *sname = MD_LOCAL_NAME;
15120Sstevel@tonic-gate mhd_mhiargs_t mhiargs;
15130Sstevel@tonic-gate char *cp = NULL;
15140Sstevel@tonic-gate int pos = -1; /* position of timeout value */
15150Sstevel@tonic-gate int usetag = 0;
15160Sstevel@tonic-gate static char *nullopts[] = { NULL };
15170Sstevel@tonic-gate md_error_t status = mdnullerror;
15180Sstevel@tonic-gate md_error_t *ep = &status;
15190Sstevel@tonic-gate sdssc_boolean_e cluster_take = SDSSC_False;
15200Sstevel@tonic-gate sdssc_version_t vers;
15210Sstevel@tonic-gate rval_e rval;
15221945Sjeanm int set_take_rval;
15230Sstevel@tonic-gate
15240Sstevel@tonic-gate /* reset and parse args */
15250Sstevel@tonic-gate optind = 1;
15260Sstevel@tonic-gate opterr = 1;
15271320Srd117015 while ((c = getopt(argc, argv, "C:fs:tu:y")) != -1) {
15280Sstevel@tonic-gate switch (c) {
15290Sstevel@tonic-gate case 'C':
15300Sstevel@tonic-gate cluster_take = SDSSC_True;
15310Sstevel@tonic-gate break;
15320Sstevel@tonic-gate case 'f':
15330Sstevel@tonic-gate flags |= TAKE_FORCE;
15340Sstevel@tonic-gate break;
15350Sstevel@tonic-gate case 's':
15360Sstevel@tonic-gate sname = optarg;
15370Sstevel@tonic-gate break;
15380Sstevel@tonic-gate case 't':
15390Sstevel@tonic-gate break;
15400Sstevel@tonic-gate case 'u':
15410Sstevel@tonic-gate usetag = atoi(optarg);
15420Sstevel@tonic-gate flags |= TAKE_USETAG;
15430Sstevel@tonic-gate break;
15440Sstevel@tonic-gate case 'y':
15450Sstevel@tonic-gate flags |= TAKE_USEIT;
15460Sstevel@tonic-gate break;
15470Sstevel@tonic-gate default:
15480Sstevel@tonic-gate usage(sp, gettext("unknown options"));
15490Sstevel@tonic-gate }
15500Sstevel@tonic-gate }
15510Sstevel@tonic-gate
15520Sstevel@tonic-gate mhiargs = defmhiargs;
15530Sstevel@tonic-gate
15540Sstevel@tonic-gate argc -= optind;
15550Sstevel@tonic-gate argv += optind;
15560Sstevel@tonic-gate
15570Sstevel@tonic-gate if (argc > 1)
15580Sstevel@tonic-gate usage(sp, gettext("too many args"));
15590Sstevel@tonic-gate
15600Sstevel@tonic-gate /*
15610Sstevel@tonic-gate * If we have a list of timeout value overrides, handle it here
15620Sstevel@tonic-gate */
15630Sstevel@tonic-gate while (argv[0] != NULL && *argv[0] != '\0') {
15640Sstevel@tonic-gate /*
15650Sstevel@tonic-gate * The use of the nullopts[] "token list" here is to make
15660Sstevel@tonic-gate * getsubopts() simply parse a comma separated list
15670Sstevel@tonic-gate * returning either "" or the contents of the field, the
15680Sstevel@tonic-gate * end condition is exaustion of the initial string, which
15690Sstevel@tonic-gate * is modified in the process.
15700Sstevel@tonic-gate */
15710Sstevel@tonic-gate (void) getsubopt(&argv[0], nullopts, &cp);
15720Sstevel@tonic-gate
15730Sstevel@tonic-gate c = 0; /* re-use c as temp value of timeout */
15740Sstevel@tonic-gate
15750Sstevel@tonic-gate if (*cp != '-') /* '-' uses default */
15760Sstevel@tonic-gate c = atoi(cp);
15770Sstevel@tonic-gate
15780Sstevel@tonic-gate if (c < 0) {
15790Sstevel@tonic-gate usage(sp, gettext(
15800Sstevel@tonic-gate "time out values must be > 0"));
15810Sstevel@tonic-gate }
15820Sstevel@tonic-gate
15830Sstevel@tonic-gate if (++pos > 3) {
15840Sstevel@tonic-gate usage(sp, gettext(
15850Sstevel@tonic-gate "too many timeout values specified."));
15860Sstevel@tonic-gate }
15870Sstevel@tonic-gate
15880Sstevel@tonic-gate if (c == 0) /* 0 or "" field uses default */
15890Sstevel@tonic-gate continue;
15900Sstevel@tonic-gate
15910Sstevel@tonic-gate /*
15920Sstevel@tonic-gate * Assign temp value to appropriate structure member based on
15930Sstevel@tonic-gate * its position in the comma separated list.
15940Sstevel@tonic-gate */
15950Sstevel@tonic-gate switch (pos) {
15964932Spetede case 0:
15974932Spetede mhiargs.mh_ff = c;
15984932Spetede break;
15990Sstevel@tonic-gate
16004932Spetede case 1:
16014932Spetede mhiargs.mh_tk.reinstate_resv_delay = c;
16024932Spetede break;
16030Sstevel@tonic-gate
16044932Spetede case 2:
16054932Spetede mhiargs.mh_tk.min_ownership_delay = c;
16064932Spetede break;
16070Sstevel@tonic-gate
16084932Spetede case 3:
16094932Spetede mhiargs.mh_tk.max_ownership_delay = c;
16104932Spetede break;
16110Sstevel@tonic-gate }
16120Sstevel@tonic-gate }
16130Sstevel@tonic-gate
161411053SSurya.Prakki@Sun.COM (void) memset(&vers, 0, sizeof (vers));
16150Sstevel@tonic-gate
16160Sstevel@tonic-gate if ((sdssc_version(&vers) == SDSSC_OKAY) &&
16170Sstevel@tonic-gate (vers.major == 3) &&
16180Sstevel@tonic-gate (cluster_take == SDSSC_False)) {
16190Sstevel@tonic-gate
16200Sstevel@tonic-gate /*
16210Sstevel@tonic-gate * If the take is beging done by the user via the CLI we need
16220Sstevel@tonic-gate * to notify the DCS to make this current node the primary.
16230Sstevel@tonic-gate * The SC3.0 reservation code will in turn exec metaset with
16240Sstevel@tonic-gate * the -C take arg to complete this operation.
16250Sstevel@tonic-gate */
16260Sstevel@tonic-gate if ((rval = sdssc_notify_service(sname, Make_Primary)) ==
16270Sstevel@tonic-gate SDSSC_ERROR) {
162811053SSurya.Prakki@Sun.COM (void) printf(gettext(
16290Sstevel@tonic-gate "metaset: failed to notify DCS of take\n"));
16300Sstevel@tonic-gate }
16310Sstevel@tonic-gate md_exit(NULL, rval == SDSSC_ERROR);
16320Sstevel@tonic-gate }
16330Sstevel@tonic-gate
16340Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
16350Sstevel@tonic-gate mde_perror(ep, "");
16360Sstevel@tonic-gate md_exit(sp, 1);
16370Sstevel@tonic-gate }
16380Sstevel@tonic-gate
16390Sstevel@tonic-gate if ((vers.major == 3) && (meta_check_ownership(sp, ep) == 0)) {
16400Sstevel@tonic-gate
16410Sstevel@tonic-gate /*
16420Sstevel@tonic-gate * If we're running in a cluster environment and this
16430Sstevel@tonic-gate * node already owns the set. Don't bother trying to
16440Sstevel@tonic-gate * take the set again. There's one case where an adminstrator
16450Sstevel@tonic-gate * is adding disks to a set for the first time. metaset
16460Sstevel@tonic-gate * will take the ownership of the set at that point. During
16470Sstevel@tonic-gate * that add operation SC3.0 notices activity on the device
16480Sstevel@tonic-gate * and also tries to perform a take operation. The SC3.0 take
16490Sstevel@tonic-gate * will fail because the adminstrative add has the set locked
16500Sstevel@tonic-gate */
16510Sstevel@tonic-gate md_exit(sp, 0);
16520Sstevel@tonic-gate }
16530Sstevel@tonic-gate
16540Sstevel@tonic-gate if (meta_lock_nowait(sp, ep) != 0) {
16551320Srd117015 mde_perror(ep, "");
16561320Srd117015 md_exit(sp, 10); /* special errcode */
16570Sstevel@tonic-gate }
16580Sstevel@tonic-gate
16591945Sjeanm /*
16601945Sjeanm * If a 2 is returned from meta_set_take, this take was able to resolve
16611945Sjeanm * an unresolved replicated disk (i.e. a disk is now available that
16621945Sjeanm * had been missing during the import of the replicated diskset).
16631945Sjeanm * Need to release the diskset and re-take in order to have
16641945Sjeanm * the subdrivers re-snarf using the newly resolved (or newly mapped)
16651945Sjeanm * devids. This also allows the namespace to be updated with the
16661945Sjeanm * correct major names in the case where the disk being replicated
16671945Sjeanm * was handled by a different driver than the replicated disk.
16681945Sjeanm */
16691945Sjeanm set_take_rval = meta_set_take(sp, &mhiargs, flags, usetag, &status);
16701945Sjeanm if (set_take_rval == 2) {
16711945Sjeanm if (meta_set_release(sp, &status)) {
16721945Sjeanm mde_perror(&status,
16731945Sjeanm "Need to release and take set to resolve names.");
16741945Sjeanm md_exit(sp, 1);
16751945Sjeanm }
16761945Sjeanm metaflushdrivenames();
16771945Sjeanm metaflushsetname(sp);
16781945Sjeanm set_take_rval = meta_set_take(sp, &mhiargs,
16791945Sjeanm (flags | TAKE_RETAKE), usetag, &status);
16801945Sjeanm }
16811945Sjeanm
16821945Sjeanm if (set_take_rval == -1) {
16830Sstevel@tonic-gate mde_perror(&status, "");
16840Sstevel@tonic-gate if (mdismddberror(&status, MDE_DB_TAGDATA))
16850Sstevel@tonic-gate md_exit(sp, 2);
16860Sstevel@tonic-gate if (mdismddberror(&status, MDE_DB_ACCOK))
16870Sstevel@tonic-gate md_exit(sp, 3);
16880Sstevel@tonic-gate if (mdismddberror(&status, MDE_DB_STALE))
16890Sstevel@tonic-gate md_exit(sp, 66);
16900Sstevel@tonic-gate md_exit(sp, 1);
16910Sstevel@tonic-gate }
16920Sstevel@tonic-gate md_exit(sp, 0);
16930Sstevel@tonic-gate }
16940Sstevel@tonic-gate
16950Sstevel@tonic-gate /*
16960Sstevel@tonic-gate * Joins a node to a specific set or to all multinode disksets known
16970Sstevel@tonic-gate * by this node. If set is specified then caller should have verified
16980Sstevel@tonic-gate * that the set is a multinode diskset.
16990Sstevel@tonic-gate *
17000Sstevel@tonic-gate * If an error occurs, metaset exits with a 1.
17010Sstevel@tonic-gate * If there is no error, metaset exits with a 0.
17020Sstevel@tonic-gate */
17030Sstevel@tonic-gate static void
parse_joinset(int argc,char ** argv)17040Sstevel@tonic-gate parse_joinset(int argc, char **argv)
17050Sstevel@tonic-gate {
17060Sstevel@tonic-gate int c;
17070Sstevel@tonic-gate mdsetname_t *sp = NULL, *local_sp = NULL;
17080Sstevel@tonic-gate char *sname = MD_LOCAL_NAME;
17090Sstevel@tonic-gate md_error_t status = mdnullerror;
17100Sstevel@tonic-gate md_error_t *ep = &status;
17110Sstevel@tonic-gate md_set_desc *sd;
17120Sstevel@tonic-gate char buf[BUFSIZ];
17130Sstevel@tonic-gate char *p = buf;
17140Sstevel@tonic-gate set_t max_sets, setno;
17150Sstevel@tonic-gate int err, cumm_err = 0;
17160Sstevel@tonic-gate size_t bufsz;
17170Sstevel@tonic-gate
17180Sstevel@tonic-gate bufsz = sizeof (buf);
17190Sstevel@tonic-gate /* reset and parse args */
17200Sstevel@tonic-gate optind = 1;
17210Sstevel@tonic-gate opterr = 1;
17220Sstevel@tonic-gate while ((c = getopt(argc, argv, "Ms:j")) != -1) {
17230Sstevel@tonic-gate switch (c) {
17240Sstevel@tonic-gate case 'M':
17250Sstevel@tonic-gate break;
17260Sstevel@tonic-gate case 'j':
17270Sstevel@tonic-gate break;
17280Sstevel@tonic-gate case 's':
17290Sstevel@tonic-gate sname = optarg;
17300Sstevel@tonic-gate break;
17310Sstevel@tonic-gate default:
17320Sstevel@tonic-gate usage(sp, gettext("unknown options"));
17330Sstevel@tonic-gate }
17340Sstevel@tonic-gate }
17350Sstevel@tonic-gate
17360Sstevel@tonic-gate argc -= optind;
17370Sstevel@tonic-gate argv += optind;
17380Sstevel@tonic-gate
17390Sstevel@tonic-gate if (argc > 1)
17400Sstevel@tonic-gate usage(sp, gettext("too many args"));
17410Sstevel@tonic-gate
17420Sstevel@tonic-gate /*
17430Sstevel@tonic-gate * If no setname option was used, then join all disksets
17440Sstevel@tonic-gate * that this node knows about. Attempt to join all
17450Sstevel@tonic-gate * disksets that this node knows about.
17460Sstevel@tonic-gate *
17470Sstevel@tonic-gate * Additional text is added to the error messages during
17480Sstevel@tonic-gate * this section of code in order to help the user understand
17490Sstevel@tonic-gate * why the 'join of all sets' failed and which set caused
17500Sstevel@tonic-gate * the failure.
17510Sstevel@tonic-gate */
17520Sstevel@tonic-gate
17530Sstevel@tonic-gate /*
17540Sstevel@tonic-gate * Hold local set lock throughout this call to keep
17550Sstevel@tonic-gate * other actions from interfering (such as creating a new
17560Sstevel@tonic-gate * set, etc.).
17570Sstevel@tonic-gate */
17580Sstevel@tonic-gate if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) {
17590Sstevel@tonic-gate mde_perror(ep, "");
17600Sstevel@tonic-gate md_exit(sp, 1);
17610Sstevel@tonic-gate }
17620Sstevel@tonic-gate
17630Sstevel@tonic-gate if (meta_lock(local_sp, TRUE, ep) != 0) {
17640Sstevel@tonic-gate mde_perror(ep, "");
17650Sstevel@tonic-gate md_exit(local_sp, 1);
17660Sstevel@tonic-gate }
17670Sstevel@tonic-gate
17680Sstevel@tonic-gate if (strcmp(sname, MD_LOCAL_NAME) == 0) {
17690Sstevel@tonic-gate /*
17700Sstevel@tonic-gate * If no set name is given, then walk through all sets
17710Sstevel@tonic-gate * on this node which could include:
17720Sstevel@tonic-gate * - MN disksets
17730Sstevel@tonic-gate * - traditional disksets
17740Sstevel@tonic-gate * - non-existent disksets
17750Sstevel@tonic-gate * Attempt to join the MN disksets.
17760Sstevel@tonic-gate * If the join of one set fails, print out an error message
17770Sstevel@tonic-gate * about that set and continue the walk.
17780Sstevel@tonic-gate */
17790Sstevel@tonic-gate if ((max_sets = get_max_sets(ep)) == 0) {
17800Sstevel@tonic-gate mde_perror(ep, "");
17810Sstevel@tonic-gate md_exit(local_sp, 1);
17820Sstevel@tonic-gate }
17830Sstevel@tonic-gate
17840Sstevel@tonic-gate /* Start walking through all possible disksets */
17850Sstevel@tonic-gate for (setno = 1; setno < max_sets; setno++) {
17860Sstevel@tonic-gate if ((sp = metasetnosetname(setno, ep)) == NULL) {
17870Sstevel@tonic-gate if (mdiserror(ep, MDE_NO_SET)) {
17880Sstevel@tonic-gate /* No set for this setno - continue */
17890Sstevel@tonic-gate mdclrerror(ep);
17900Sstevel@tonic-gate continue;
17910Sstevel@tonic-gate } else {
17920Sstevel@tonic-gate (void) sprintf(p, gettext(
17930Sstevel@tonic-gate "Unable to get set %d information"),
17940Sstevel@tonic-gate setno);
17950Sstevel@tonic-gate mde_perror(ep, p);
17960Sstevel@tonic-gate cumm_err = 1;
17970Sstevel@tonic-gate mdclrerror(ep);
17980Sstevel@tonic-gate continue;
17990Sstevel@tonic-gate }
18000Sstevel@tonic-gate }
18010Sstevel@tonic-gate
18020Sstevel@tonic-gate /* If setname is there, set desc should exist. */
18030Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL) {
18040Sstevel@tonic-gate (void) snprintf(p, bufsz, gettext(
18050Sstevel@tonic-gate "Unable to get set %s desc information"),
18060Sstevel@tonic-gate sp->setname);
18070Sstevel@tonic-gate mde_perror(ep, p);
18080Sstevel@tonic-gate cumm_err = 1;
18090Sstevel@tonic-gate mdclrerror(ep);
18100Sstevel@tonic-gate continue;
18110Sstevel@tonic-gate }
18120Sstevel@tonic-gate
18130Sstevel@tonic-gate /* Only check MN disksets */
18140Sstevel@tonic-gate if (!MD_MNSET_DESC(sd)) {
18150Sstevel@tonic-gate continue;
18160Sstevel@tonic-gate }
18170Sstevel@tonic-gate
18180Sstevel@tonic-gate /*
18190Sstevel@tonic-gate * Return value of 0 is success.
18200Sstevel@tonic-gate * Return value of -1 means a failure.
18210Sstevel@tonic-gate * Return value of -2 means set could not be
18220Sstevel@tonic-gate * joined, but shouldn't cause an error.
18230Sstevel@tonic-gate * Reasons would be:
18240Sstevel@tonic-gate * - no drives in set
18250Sstevel@tonic-gate * - node already joined to set
18260Sstevel@tonic-gate * Return value of -3 means joined stale set.
18270Sstevel@tonic-gate * Can't check for all reasons here
18280Sstevel@tonic-gate * since set isn't locked yet across all
18290Sstevel@tonic-gate * nodes in the cluster. The call
18300Sstevel@tonic-gate * to libmeta routine, meta_set_join, will
18310Sstevel@tonic-gate * lock across the cluster and perform
18320Sstevel@tonic-gate * the checks.
18330Sstevel@tonic-gate */
18340Sstevel@tonic-gate if ((err = meta_set_join(sp, ep)) == -1) {
18350Sstevel@tonic-gate /* Print error of diskset join failure */
18360Sstevel@tonic-gate (void) snprintf(p, bufsz,
18370Sstevel@tonic-gate gettext("Join to diskset %s failed"),
18380Sstevel@tonic-gate sp->setname);
18390Sstevel@tonic-gate mde_perror(ep, p);
18400Sstevel@tonic-gate cumm_err = 1;
18410Sstevel@tonic-gate mdclrerror(ep);
18420Sstevel@tonic-gate continue;
18430Sstevel@tonic-gate }
18440Sstevel@tonic-gate
18450Sstevel@tonic-gate if (err == -3) {
18460Sstevel@tonic-gate /* Print error of diskset join failure */
18470Sstevel@tonic-gate (void) snprintf(p, bufsz,
18480Sstevel@tonic-gate gettext("Joined to stale diskset %s"),
18490Sstevel@tonic-gate sp->setname);
18500Sstevel@tonic-gate mde_perror(ep, p);
18510Sstevel@tonic-gate mdclrerror(ep);
18520Sstevel@tonic-gate }
18530Sstevel@tonic-gate
18540Sstevel@tonic-gate mdclrerror(ep);
18550Sstevel@tonic-gate }
18560Sstevel@tonic-gate
18570Sstevel@tonic-gate md_exit(local_sp, cumm_err);
18580Sstevel@tonic-gate }
18590Sstevel@tonic-gate
18600Sstevel@tonic-gate /*
18610Sstevel@tonic-gate * Code for a specific set is much simpler.
18620Sstevel@tonic-gate * Error messages don't need extra text since specific setname
18630Sstevel@tonic-gate * was used.
18640Sstevel@tonic-gate * Don't need to lock the local set, just the specific set given.
18650Sstevel@tonic-gate */
18660Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
18670Sstevel@tonic-gate mde_perror(ep, "");
18680Sstevel@tonic-gate md_exit(local_sp, 1);
18690Sstevel@tonic-gate }
18700Sstevel@tonic-gate
18710Sstevel@tonic-gate /*
18720Sstevel@tonic-gate * Fail command if meta_set_join returns -1.
18730Sstevel@tonic-gate *
18740Sstevel@tonic-gate * Return of 0 means that node joined set.
18750Sstevel@tonic-gate *
18760Sstevel@tonic-gate * Return of -2 means that node was unable to
18770Sstevel@tonic-gate * join a set since that set had no drives
18780Sstevel@tonic-gate * or that had already joined the set. No
18790Sstevel@tonic-gate * need to fail the command for these reasons.
18800Sstevel@tonic-gate *
18810Sstevel@tonic-gate * Return of -3 means that set is stale.
18820Sstevel@tonic-gate * Return a value of 66 to historically match traditional disksets.
18830Sstevel@tonic-gate */
18840Sstevel@tonic-gate if ((err = meta_set_join(sp, ep)) == -1) {
18850Sstevel@tonic-gate mde_perror(&status, "");
18860Sstevel@tonic-gate md_exit(local_sp, 1);
18870Sstevel@tonic-gate }
18880Sstevel@tonic-gate
18890Sstevel@tonic-gate if (err == -3) {
18900Sstevel@tonic-gate /* Print error of diskset join failure */
18910Sstevel@tonic-gate (void) snprintf(p, bufsz,
18920Sstevel@tonic-gate gettext("Joined to stale diskset %s"),
18930Sstevel@tonic-gate sp->setname);
18940Sstevel@tonic-gate mde_perror(&status, "");
18950Sstevel@tonic-gate md_exit(local_sp, 66);
18960Sstevel@tonic-gate }
18970Sstevel@tonic-gate
18980Sstevel@tonic-gate md_exit(local_sp, 0);
18990Sstevel@tonic-gate }
19000Sstevel@tonic-gate
19010Sstevel@tonic-gate /*
19020Sstevel@tonic-gate * Withdraws a node from a specific set or from all multinode disksets known
19030Sstevel@tonic-gate * by this node. If set is specified then caller should have verified
19040Sstevel@tonic-gate * that the set is a multinode diskset.
19050Sstevel@tonic-gate *
19060Sstevel@tonic-gate * If an error occurs, metaset exits with a 1.
19070Sstevel@tonic-gate * If there is no error, metaset exits with a 0.
19080Sstevel@tonic-gate */
19090Sstevel@tonic-gate static void
parse_withdrawset(int argc,char ** argv)19100Sstevel@tonic-gate parse_withdrawset(int argc, char **argv)
19110Sstevel@tonic-gate {
19120Sstevel@tonic-gate int c;
19130Sstevel@tonic-gate mdsetname_t *sp = NULL, *local_sp = NULL;
19140Sstevel@tonic-gate char *sname = MD_LOCAL_NAME;
19150Sstevel@tonic-gate md_error_t status = mdnullerror;
19160Sstevel@tonic-gate md_error_t *ep = &status;
19170Sstevel@tonic-gate char buf[BUFSIZ];
19180Sstevel@tonic-gate char *p = buf;
19190Sstevel@tonic-gate md_set_desc *sd;
19200Sstevel@tonic-gate set_t max_sets, setno;
19210Sstevel@tonic-gate int err, cumm_err = 0;
19220Sstevel@tonic-gate size_t bufsz;
19230Sstevel@tonic-gate
19240Sstevel@tonic-gate bufsz = sizeof (buf);
19250Sstevel@tonic-gate /* reset and parse args */
19260Sstevel@tonic-gate optind = 1;
19270Sstevel@tonic-gate opterr = 1;
19280Sstevel@tonic-gate while ((c = getopt(argc, argv, "Ms:w")) != -1) {
19290Sstevel@tonic-gate switch (c) {
19300Sstevel@tonic-gate case 'M':
19310Sstevel@tonic-gate break;
19320Sstevel@tonic-gate case 'w':
19330Sstevel@tonic-gate break;
19340Sstevel@tonic-gate case 's':
19350Sstevel@tonic-gate sname = optarg;
19360Sstevel@tonic-gate break;
19370Sstevel@tonic-gate default:
19380Sstevel@tonic-gate usage(sp, gettext("unknown options"));
19390Sstevel@tonic-gate }
19400Sstevel@tonic-gate }
19410Sstevel@tonic-gate
19420Sstevel@tonic-gate argc -= optind;
19430Sstevel@tonic-gate argv += optind;
19440Sstevel@tonic-gate
19450Sstevel@tonic-gate if (argc > 1)
19460Sstevel@tonic-gate usage(sp, gettext("too many args"));
19470Sstevel@tonic-gate
19480Sstevel@tonic-gate /*
19490Sstevel@tonic-gate * If no setname option was used, then withdraw from all disksets
19500Sstevel@tonic-gate * that this node knows about.
19510Sstevel@tonic-gate *
19520Sstevel@tonic-gate * Additional text is added to the error messages during
19530Sstevel@tonic-gate * this section of code in order to help the user understand
19540Sstevel@tonic-gate * why the 'withdraw from all sets' failed and which set caused
19550Sstevel@tonic-gate * the failure.
19560Sstevel@tonic-gate */
19570Sstevel@tonic-gate
19580Sstevel@tonic-gate /*
19590Sstevel@tonic-gate * Hold local set lock throughout this call to keep
19600Sstevel@tonic-gate * other actions from interfering (such as creating a new
19610Sstevel@tonic-gate * set, etc.).
19620Sstevel@tonic-gate */
19630Sstevel@tonic-gate if ((local_sp = metasetname(MD_LOCAL_NAME, ep)) == NULL) {
19640Sstevel@tonic-gate mde_perror(ep, "");
19650Sstevel@tonic-gate md_exit(sp, 1);
19660Sstevel@tonic-gate }
19670Sstevel@tonic-gate
19680Sstevel@tonic-gate if (meta_lock(local_sp, TRUE, ep) != 0) {
19690Sstevel@tonic-gate mde_perror(ep, "");
19700Sstevel@tonic-gate md_exit(local_sp, 1);
19710Sstevel@tonic-gate }
19720Sstevel@tonic-gate
19730Sstevel@tonic-gate if (strcmp(sname, MD_LOCAL_NAME) == 0) {
19740Sstevel@tonic-gate /*
19750Sstevel@tonic-gate * If no set name is given, then walk through all sets
19760Sstevel@tonic-gate * on this node which could include:
19770Sstevel@tonic-gate * - MN disksets
19780Sstevel@tonic-gate * - traditional disksets
19790Sstevel@tonic-gate * - non-existent disksets
19800Sstevel@tonic-gate * Attempt to withdraw from the MN disksets.
19810Sstevel@tonic-gate * If the withdraw of one set fails, print out an error
19820Sstevel@tonic-gate * message about that set and continue the walk.
19830Sstevel@tonic-gate */
19840Sstevel@tonic-gate if ((max_sets = get_max_sets(ep)) == 0) {
19850Sstevel@tonic-gate mde_perror(ep, "");
19860Sstevel@tonic-gate md_exit(local_sp, 1);
19870Sstevel@tonic-gate }
19880Sstevel@tonic-gate
19890Sstevel@tonic-gate /* Start walking through all possible disksets */
19900Sstevel@tonic-gate for (setno = 1; setno < max_sets; setno++) {
19910Sstevel@tonic-gate if ((sp = metasetnosetname(setno, ep)) == NULL) {
19920Sstevel@tonic-gate if (mdiserror(ep, MDE_NO_SET)) {
19930Sstevel@tonic-gate /* No set for this setno - continue */
19940Sstevel@tonic-gate mdclrerror(ep);
19950Sstevel@tonic-gate continue;
19960Sstevel@tonic-gate } else {
19970Sstevel@tonic-gate (void) sprintf(p, gettext(
19980Sstevel@tonic-gate "Unable to get set %d information"),
19990Sstevel@tonic-gate setno);
20000Sstevel@tonic-gate mde_perror(ep, p);
20010Sstevel@tonic-gate cumm_err = 1;
20020Sstevel@tonic-gate mdclrerror(ep);
20030Sstevel@tonic-gate continue;
20040Sstevel@tonic-gate }
20050Sstevel@tonic-gate }
20060Sstevel@tonic-gate
20070Sstevel@tonic-gate /* If setname is there, set desc should exist. */
20080Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL) {
20090Sstevel@tonic-gate (void) snprintf(p, bufsz, gettext(
20100Sstevel@tonic-gate "Unable to get set %s desc information"),
20110Sstevel@tonic-gate sp->setname);
20120Sstevel@tonic-gate mde_perror(ep, p);
20130Sstevel@tonic-gate cumm_err = 1;
20140Sstevel@tonic-gate mdclrerror(ep);
20150Sstevel@tonic-gate continue;
20160Sstevel@tonic-gate }
20170Sstevel@tonic-gate
20180Sstevel@tonic-gate /* Only check MN disksets */
20190Sstevel@tonic-gate if (!MD_MNSET_DESC(sd)) {
20200Sstevel@tonic-gate continue;
20210Sstevel@tonic-gate }
20220Sstevel@tonic-gate
20230Sstevel@tonic-gate /*
20240Sstevel@tonic-gate * Return value of 0 is success.
20250Sstevel@tonic-gate * Return value of -1 means a failure.
20260Sstevel@tonic-gate * Return value of -2 means set could not be
20270Sstevel@tonic-gate * withdrawn from, but this shouldn't cause
20280Sstevel@tonic-gate * an error. Reasons would be:
20290Sstevel@tonic-gate * - no drives in set
20300Sstevel@tonic-gate * - node already withdrawn from set
20310Sstevel@tonic-gate * Can't check for all reasons here
20320Sstevel@tonic-gate * since set isn't locked yet across all
20330Sstevel@tonic-gate * nodes in the cluster. The call
20340Sstevel@tonic-gate * to libmeta routine, meta_set_withdraw, will
20350Sstevel@tonic-gate * lock across the cluster and perform
20360Sstevel@tonic-gate * the checks.
20370Sstevel@tonic-gate */
20380Sstevel@tonic-gate if ((err = meta_set_withdraw(sp, ep)) == -1) {
20390Sstevel@tonic-gate /* Print error of diskset withdraw failure */
20400Sstevel@tonic-gate (void) snprintf(p, bufsz,
20410Sstevel@tonic-gate gettext("Withdraw from diskset %s failed"),
20420Sstevel@tonic-gate sp->setname);
20430Sstevel@tonic-gate mde_perror(ep, p);
20440Sstevel@tonic-gate mdclrerror(ep);
20450Sstevel@tonic-gate cumm_err = 1;
20460Sstevel@tonic-gate continue;
20470Sstevel@tonic-gate }
20480Sstevel@tonic-gate
20490Sstevel@tonic-gate if (err == -2) {
20500Sstevel@tonic-gate mdclrerror(ep);
20510Sstevel@tonic-gate continue;
20520Sstevel@tonic-gate }
20530Sstevel@tonic-gate
20540Sstevel@tonic-gate mdclrerror(ep);
20550Sstevel@tonic-gate }
20560Sstevel@tonic-gate md_exit(local_sp, cumm_err);
20570Sstevel@tonic-gate }
20580Sstevel@tonic-gate
20590Sstevel@tonic-gate
20600Sstevel@tonic-gate /*
20610Sstevel@tonic-gate * Code for a specific set is much simpler.
20620Sstevel@tonic-gate * Error messages don't need extra text since specific setname
20630Sstevel@tonic-gate * was used.
20640Sstevel@tonic-gate * Don't need to lock the local set, just the specific set given.
20650Sstevel@tonic-gate */
20660Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
20670Sstevel@tonic-gate mde_perror(ep, "");
20680Sstevel@tonic-gate md_exit(local_sp, 1);
20690Sstevel@tonic-gate }
20700Sstevel@tonic-gate
20710Sstevel@tonic-gate /*
20720Sstevel@tonic-gate * Fail command if meta_set_withdraw returns -1.
20730Sstevel@tonic-gate *
20740Sstevel@tonic-gate * Return of 0 means that node withdrew from set.
20750Sstevel@tonic-gate *
20760Sstevel@tonic-gate * Return of -2 means that node was unable to
20770Sstevel@tonic-gate * withdraw from a set since that set had no drives
20780Sstevel@tonic-gate * or node was not joined to set. No
20790Sstevel@tonic-gate * need to fail the command for these reasons.
20800Sstevel@tonic-gate */
20810Sstevel@tonic-gate if (meta_set_withdraw(sp, ep) == -1) {
20820Sstevel@tonic-gate mde_perror(&status, "");
20830Sstevel@tonic-gate md_exit(local_sp, 1);
20840Sstevel@tonic-gate }
20850Sstevel@tonic-gate
20860Sstevel@tonic-gate md_exit(local_sp, 0);
20870Sstevel@tonic-gate }
20880Sstevel@tonic-gate
20890Sstevel@tonic-gate static void
parse_cluster(int argc,char ** argv,int multi_node)20904932Spetede parse_cluster(int argc, char **argv, int multi_node)
20910Sstevel@tonic-gate {
20924932Spetede int c, error, new_argc, x;
20930Sstevel@tonic-gate enum cluster_cmd cmd = ccnotspecified;
20944932Spetede char *hostname = SDSSC_PROXY_PRIMARY;
20954932Spetede char *argument = NULL;
20964932Spetede char *sname = MD_LOCAL_NAME;
20974932Spetede char primary_node[SDSSC_NODE_NAME_LEN];
20984932Spetede char **new_argv = NULL;
20994932Spetede char **np = NULL;
21000Sstevel@tonic-gate mdsetname_t *sp = NULL;
21010Sstevel@tonic-gate md_error_t status = mdnullerror;
21020Sstevel@tonic-gate md_error_t *ep = &status;
21030Sstevel@tonic-gate
21040Sstevel@tonic-gate /* reset and parse args */
21050Sstevel@tonic-gate optind = 1;
21060Sstevel@tonic-gate opterr = 1;
21071320Srd117015 while ((c = getopt(argc, argv, "C:s:h:ftu:yr")) != -1) {
21080Sstevel@tonic-gate switch (c) {
21090Sstevel@tonic-gate case 'C':
21100Sstevel@tonic-gate if (cmd != ccnotspecified) {
21110Sstevel@tonic-gate md_exit(sp, -1);
21120Sstevel@tonic-gate }
21130Sstevel@tonic-gate argument = optarg;
21140Sstevel@tonic-gate
21150Sstevel@tonic-gate if (strcmp(argument, "disksin") == 0) {
21160Sstevel@tonic-gate cmd = clusterdisksin;
21170Sstevel@tonic-gate } else if (strcmp(argument, "version") == 0) {
21180Sstevel@tonic-gate cmd = clusterversion;
21190Sstevel@tonic-gate } else if (strcmp(argument, "release") == 0) {
21200Sstevel@tonic-gate cmd = clusterrelease;
21210Sstevel@tonic-gate } else if (strcmp(argument, "take") == 0) {
21220Sstevel@tonic-gate cmd = clustertake;
21230Sstevel@tonic-gate } else if (strcmp(argument, "proxy") == 0) {
21240Sstevel@tonic-gate cmd = clusterproxy;
21250Sstevel@tonic-gate } else if (strcmp(argument, "purge") == 0) {
21260Sstevel@tonic-gate cmd = clusterpurge;
21270Sstevel@tonic-gate } else {
21280Sstevel@tonic-gate md_exit(sp, -1);
21290Sstevel@tonic-gate }
21300Sstevel@tonic-gate
21310Sstevel@tonic-gate break;
21320Sstevel@tonic-gate
21330Sstevel@tonic-gate case 'h':
21340Sstevel@tonic-gate hostname = optarg;
21350Sstevel@tonic-gate break;
21360Sstevel@tonic-gate
21370Sstevel@tonic-gate case 's':
21380Sstevel@tonic-gate sname = optarg;
21390Sstevel@tonic-gate break;
21400Sstevel@tonic-gate
21410Sstevel@tonic-gate case 'f':
21420Sstevel@tonic-gate case 't':
21430Sstevel@tonic-gate case 'u':
21440Sstevel@tonic-gate case 'y':
21450Sstevel@tonic-gate case 'r':
21460Sstevel@tonic-gate break;
21470Sstevel@tonic-gate
21480Sstevel@tonic-gate default:
21490Sstevel@tonic-gate md_exit(sp, -1);
21500Sstevel@tonic-gate }
21510Sstevel@tonic-gate }
21520Sstevel@tonic-gate
21530Sstevel@tonic-gate /* Now call the appropriate command function. */
21540Sstevel@tonic-gate switch (cmd) {
21550Sstevel@tonic-gate case clusterversion:
21564932Spetede printclusterversion();
21574932Spetede break;
21580Sstevel@tonic-gate
21590Sstevel@tonic-gate case clusterdisksin:
21604932Spetede if (printdisksin(sname, ep)) {
21614932Spetede md_exit(sp, -1);
21624932Spetede }
21634932Spetede break;
21640Sstevel@tonic-gate
21650Sstevel@tonic-gate case clusterrelease:
21664932Spetede if (multi_node) {
21674932Spetede usage(sp, gettext(
21684932Spetede "-C release is not allowed on multi-owner"
21694932Spetede " disksets"));
21704932Spetede }
21714932Spetede parse_releaseset(argc, argv);
21724932Spetede break;
21730Sstevel@tonic-gate
21740Sstevel@tonic-gate case clustertake:
21754932Spetede if (multi_node) {
21764932Spetede usage(sp, gettext(
21774932Spetede "-C take is not allowed on multi-owner disksets"));
21784932Spetede }
21794932Spetede parse_takeset(argc, argv);
21804932Spetede break;
21810Sstevel@tonic-gate
21820Sstevel@tonic-gate case clusterproxy:
21834932Spetede if (multi_node) {
21844932Spetede usage(sp, gettext(
21854932Spetede "-C proxy is not allowed on multi-owner disksets"));
21864932Spetede }
21870Sstevel@tonic-gate
21880Sstevel@tonic-gate if ((new_argv = calloc(argc, sizeof (char *))) == NULL) {
218911053SSurya.Prakki@Sun.COM (void) printf(gettext("Out of memory\n"));
21900Sstevel@tonic-gate md_exit(sp, 1);
21910Sstevel@tonic-gate }
21920Sstevel@tonic-gate
21930Sstevel@tonic-gate np = new_argv;
21940Sstevel@tonic-gate new_argc = 0;
219511053SSurya.Prakki@Sun.COM (void) memset(primary_node, '\0', SDSSC_NODE_NAME_LEN);
21960Sstevel@tonic-gate
21970Sstevel@tonic-gate for (x = 0; x < argc; x++) {
21980Sstevel@tonic-gate if (strcmp(argv[x], "-C") == 0) {
21990Sstevel@tonic-gate
22000Sstevel@tonic-gate /*
22010Sstevel@tonic-gate * Need to skip the '-C proxy' args so
22020Sstevel@tonic-gate * just increase x by one and the work is
22030Sstevel@tonic-gate * done.
22040Sstevel@tonic-gate */
22050Sstevel@tonic-gate x++;
22060Sstevel@tonic-gate } else {
22070Sstevel@tonic-gate *np++ = strdup(argv[x]);
22080Sstevel@tonic-gate new_argc++;
22090Sstevel@tonic-gate }
22100Sstevel@tonic-gate }
22110Sstevel@tonic-gate
22120Sstevel@tonic-gate switch (sdssc_get_primary_host(sname, primary_node,
22130Sstevel@tonic-gate SDSSC_NODE_NAME_LEN)) {
22140Sstevel@tonic-gate case SDSSC_ERROR:
22150Sstevel@tonic-gate md_exit(sp, 1);
22160Sstevel@tonic-gate break;
22170Sstevel@tonic-gate
22180Sstevel@tonic-gate case SDSSC_NO_SERVICE:
22190Sstevel@tonic-gate if (hostname != SDSSC_PROXY_PRIMARY) {
22200Sstevel@tonic-gate (void) strlcpy(primary_node, hostname,
22210Sstevel@tonic-gate SDSSC_NODE_NAME_LEN);
22220Sstevel@tonic-gate }
22230Sstevel@tonic-gate break;
22240Sstevel@tonic-gate }
22250Sstevel@tonic-gate
22260Sstevel@tonic-gate if (sdssc_cmd_proxy(new_argc, new_argv,
22270Sstevel@tonic-gate primary_node[0] == '\0' ? SDSSC_PROXY_PRIMARY :
22280Sstevel@tonic-gate primary_node, &error) == SDSSC_PROXY_DONE) {
22290Sstevel@tonic-gate md_exit(sp, error);
22300Sstevel@tonic-gate } else {
223111053SSurya.Prakki@Sun.COM (void) printf(gettext(
22320Sstevel@tonic-gate "Couldn't proxy command\n"));
22330Sstevel@tonic-gate md_exit(sp, 1);
22340Sstevel@tonic-gate }
22350Sstevel@tonic-gate break;
22360Sstevel@tonic-gate
22370Sstevel@tonic-gate case clusterpurge:
22380Sstevel@tonic-gate parse_purge(argc, argv);
22390Sstevel@tonic-gate break;
22400Sstevel@tonic-gate
22410Sstevel@tonic-gate default:
22424932Spetede break;
22430Sstevel@tonic-gate }
22440Sstevel@tonic-gate
22450Sstevel@tonic-gate md_exit(sp, 0);
22460Sstevel@tonic-gate }
22470Sstevel@tonic-gate
22480Sstevel@tonic-gate /*
22490Sstevel@tonic-gate * parse args and do it
22500Sstevel@tonic-gate */
22510Sstevel@tonic-gate int
main(int argc,char * argv[])22520Sstevel@tonic-gate main(int argc, char *argv[])
22530Sstevel@tonic-gate {
22540Sstevel@tonic-gate enum metaset_cmd cmd = notspecified;
22550Sstevel@tonic-gate md_error_t status = mdnullerror;
22560Sstevel@tonic-gate md_error_t *ep = &status;
22570Sstevel@tonic-gate mdsetname_t *sp = NULL;
22584932Spetede char *hostname = SDSSC_PROXY_PRIMARY;
22594932Spetede char *sname = MD_LOCAL_NAME;
22604932Spetede char *auto_take_option = NULL;
22614932Spetede char primary_node[SDSSC_NODE_NAME_LEN];
22624932Spetede int error, c, stat;
22634932Spetede int auto_take = FALSE;
22640Sstevel@tonic-gate md_set_desc *sd;
22650Sstevel@tonic-gate int mflag = 0;
22660Sstevel@tonic-gate int multi_node = 0;
22670Sstevel@tonic-gate rval_e sdssc_res;
22680Sstevel@tonic-gate
22690Sstevel@tonic-gate /*
22700Sstevel@tonic-gate * Get the locale set up before calling any other routines
22710Sstevel@tonic-gate * with messages to ouput. Just in case we're not in a build
22720Sstevel@tonic-gate * environment, make sure that TEXT_DOMAIN gets set to
22730Sstevel@tonic-gate * something.
22740Sstevel@tonic-gate */
22750Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
22760Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
22770Sstevel@tonic-gate #endif
22780Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
22790Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
22800Sstevel@tonic-gate
22810Sstevel@tonic-gate sdssc_res = sdssc_bind_library();
22820Sstevel@tonic-gate if (sdssc_res == SDSSC_ERROR) {
228311053SSurya.Prakki@Sun.COM (void) printf(gettext(
22840Sstevel@tonic-gate "%s: Interface error with libsds_sc.so\n"), argv[0]);
22850Sstevel@tonic-gate exit(1);
22860Sstevel@tonic-gate }
22870Sstevel@tonic-gate
22880Sstevel@tonic-gate /* initialize */
22890Sstevel@tonic-gate if (md_init(argc, argv, 0, 1, ep) != 0) {
22900Sstevel@tonic-gate mde_perror(ep, "");
22910Sstevel@tonic-gate md_exit(sp, 1);
22920Sstevel@tonic-gate }
22930Sstevel@tonic-gate
22940Sstevel@tonic-gate optind = 1;
22950Sstevel@tonic-gate opterr = 1;
22960Sstevel@tonic-gate
22970Sstevel@tonic-gate /*
22980Sstevel@tonic-gate * NOTE: The "C" option is strictly for cluster use. it is not
22990Sstevel@tonic-gate * and should not be documented for the customer. - JST
23000Sstevel@tonic-gate */
23011320Srd117015 while ((c = getopt(argc, argv, "C:MaA:bdfh:jl:Lm:oPqrs:tu:wy?"))
23020Sstevel@tonic-gate != -1) {
23030Sstevel@tonic-gate switch (c) {
23040Sstevel@tonic-gate case 'M':
23050Sstevel@tonic-gate mflag = 1;
23060Sstevel@tonic-gate break;
23070Sstevel@tonic-gate case 'A':
23080Sstevel@tonic-gate auto_take = TRUE;
23090Sstevel@tonic-gate if (optarg == NULL || !(strcmp(optarg, "enable") == 0 ||
23100Sstevel@tonic-gate strcmp(optarg, "disable") == 0))
23110Sstevel@tonic-gate usage(sp, gettext(
23120Sstevel@tonic-gate "-A: enable or disable must be specified"));
23130Sstevel@tonic-gate auto_take_option = optarg;
23140Sstevel@tonic-gate break;
23150Sstevel@tonic-gate case 'a':
23160Sstevel@tonic-gate if (cmd != notspecified) {
23170Sstevel@tonic-gate usage(sp, gettext(
23180Sstevel@tonic-gate "conflicting options"));
23190Sstevel@tonic-gate }
23200Sstevel@tonic-gate cmd = add;
23210Sstevel@tonic-gate break;
23220Sstevel@tonic-gate case 'b':
23230Sstevel@tonic-gate if (cmd != notspecified) {
23240Sstevel@tonic-gate usage(sp, gettext(
23250Sstevel@tonic-gate "conflicting options"));
23260Sstevel@tonic-gate }
23270Sstevel@tonic-gate cmd = balance;
23280Sstevel@tonic-gate break;
23290Sstevel@tonic-gate case 'd':
23300Sstevel@tonic-gate if (cmd != notspecified) {
23310Sstevel@tonic-gate usage(sp, gettext(
23320Sstevel@tonic-gate "conflicting options"));
23330Sstevel@tonic-gate }
23340Sstevel@tonic-gate cmd = delete;
23350Sstevel@tonic-gate break;
23360Sstevel@tonic-gate case 'C': /* cluster commands */
23370Sstevel@tonic-gate if (cmd != notspecified) {
23380Sstevel@tonic-gate md_exit(sp, -1); /* conflicting options */
23390Sstevel@tonic-gate }
23400Sstevel@tonic-gate cmd = cluster;
23410Sstevel@tonic-gate break;
23420Sstevel@tonic-gate case 'f':
23430Sstevel@tonic-gate break;
23440Sstevel@tonic-gate case 'h':
23450Sstevel@tonic-gate hostname = optarg;
23460Sstevel@tonic-gate break;
23470Sstevel@tonic-gate case 'j':
23480Sstevel@tonic-gate if (cmd != notspecified) {
23490Sstevel@tonic-gate usage(sp, gettext(
23500Sstevel@tonic-gate "conflicting options"));
23510Sstevel@tonic-gate }
23520Sstevel@tonic-gate cmd = join;
23530Sstevel@tonic-gate break;
23540Sstevel@tonic-gate case 'l':
23550Sstevel@tonic-gate break;
23560Sstevel@tonic-gate case 'L':
23570Sstevel@tonic-gate break;
23580Sstevel@tonic-gate case 'm':
23590Sstevel@tonic-gate break;
23600Sstevel@tonic-gate case 'o':
23610Sstevel@tonic-gate if (cmd != notspecified) {
23620Sstevel@tonic-gate usage(sp, gettext(
23630Sstevel@tonic-gate "conflicting options"));
23640Sstevel@tonic-gate }
23650Sstevel@tonic-gate cmd = isowner;
23660Sstevel@tonic-gate break;
23670Sstevel@tonic-gate case 'P':
23680Sstevel@tonic-gate if (cmd != notspecified) {
23690Sstevel@tonic-gate usage(sp, gettext(
23700Sstevel@tonic-gate "conflicting options"));
23710Sstevel@tonic-gate }
23720Sstevel@tonic-gate cmd = purge;
23730Sstevel@tonic-gate break;
23740Sstevel@tonic-gate case 'q':
23750Sstevel@tonic-gate if (cmd != notspecified) {
23760Sstevel@tonic-gate usage(sp, gettext(
23770Sstevel@tonic-gate "conflicting options"));
23780Sstevel@tonic-gate }
23790Sstevel@tonic-gate cmd = query;
23800Sstevel@tonic-gate break;
23810Sstevel@tonic-gate case 'r':
23820Sstevel@tonic-gate if (cmd != notspecified) {
23830Sstevel@tonic-gate usage(sp, gettext(
23840Sstevel@tonic-gate "conflicting options"));
23850Sstevel@tonic-gate }
23860Sstevel@tonic-gate cmd = release;
23870Sstevel@tonic-gate break;
23880Sstevel@tonic-gate case 's':
23890Sstevel@tonic-gate sname = optarg;
23900Sstevel@tonic-gate break;
23910Sstevel@tonic-gate case 't':
23920Sstevel@tonic-gate if (cmd != notspecified) {
23930Sstevel@tonic-gate usage(sp, gettext(
23940Sstevel@tonic-gate "conflicting options"));
23950Sstevel@tonic-gate }
23960Sstevel@tonic-gate cmd = take;
23970Sstevel@tonic-gate break;
23980Sstevel@tonic-gate case 'u':
23990Sstevel@tonic-gate break;
24000Sstevel@tonic-gate case 'w':
24010Sstevel@tonic-gate if (cmd != notspecified) {
24020Sstevel@tonic-gate usage(sp, gettext(
24030Sstevel@tonic-gate "conflicting options"));
24040Sstevel@tonic-gate }
24050Sstevel@tonic-gate cmd = withdraw;
24060Sstevel@tonic-gate break;
24070Sstevel@tonic-gate case 'y':
24080Sstevel@tonic-gate break;
24090Sstevel@tonic-gate case '?':
24100Sstevel@tonic-gate if (optopt == '?')
24110Sstevel@tonic-gate usage(sp, NULL);
24120Sstevel@tonic-gate /*FALLTHROUGH*/
24130Sstevel@tonic-gate default:
24140Sstevel@tonic-gate if (cmd == cluster) { /* cluster is silent */
24150Sstevel@tonic-gate md_exit(sp, -1);
24160Sstevel@tonic-gate } else {
24170Sstevel@tonic-gate usage(sp, gettext(
24180Sstevel@tonic-gate "unknown command"));
24190Sstevel@tonic-gate }
24200Sstevel@tonic-gate }
24210Sstevel@tonic-gate }
24220Sstevel@tonic-gate
24230Sstevel@tonic-gate /* check if suncluster is installed and -A enable specified */
24240Sstevel@tonic-gate if (auto_take && sdssc_res != SDSSC_NOT_BOUND &&
24250Sstevel@tonic-gate strcmp(auto_take_option, "enable") == 0) {
24264932Spetede md_eprintf(gettext(
24274932Spetede "cannot enable auto-take when SunCluster is installed\n"));
24284932Spetede md_exit(sp, 1);
24290Sstevel@tonic-gate }
24300Sstevel@tonic-gate
24310Sstevel@tonic-gate /*
24320Sstevel@tonic-gate * At this point we know that if the -A enable option is specified
24330Sstevel@tonic-gate * for an auto-take diskset that SC is not installed on the machine, so
24340Sstevel@tonic-gate * all of the sdssc calls will just be no-ops.
24350Sstevel@tonic-gate */
24360Sstevel@tonic-gate
24370Sstevel@tonic-gate /* list sets */
24380Sstevel@tonic-gate if (cmd == notspecified && auto_take == FALSE) {
24390Sstevel@tonic-gate parse_printset(argc, argv);
24400Sstevel@tonic-gate /*NOTREACHED*/
24410Sstevel@tonic-gate }
24420Sstevel@tonic-gate
24430Sstevel@tonic-gate if (meta_check_root(ep) != 0) {
24440Sstevel@tonic-gate mde_perror(ep, "");
24450Sstevel@tonic-gate md_exit(sp, 1);
24460Sstevel@tonic-gate }
24470Sstevel@tonic-gate
24480Sstevel@tonic-gate /* snarf MDDB */
24490Sstevel@tonic-gate if (meta_setup_db_locations(ep) != 0) {
24500Sstevel@tonic-gate mde_perror(ep, "");
24510Sstevel@tonic-gate md_exit(sp, 1);
24520Sstevel@tonic-gate }
24530Sstevel@tonic-gate
24540Sstevel@tonic-gate /*
24550Sstevel@tonic-gate * If sname is a diskset - check for multi_node.
24560Sstevel@tonic-gate * It is possible for sname to not exist.
24570Sstevel@tonic-gate */
24580Sstevel@tonic-gate if (strcmp(sname, MD_LOCAL_NAME)) {
24590Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) != NULL) {
24600Sstevel@tonic-gate /* Set exists - check for MN diskset */
24610Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL) {
24620Sstevel@tonic-gate mde_perror(ep, "");
24630Sstevel@tonic-gate md_exit(sp, 1);
24640Sstevel@tonic-gate }
24650Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
24660Sstevel@tonic-gate /*
24670Sstevel@tonic-gate * If a MN diskset always set multi_node
24680Sstevel@tonic-gate * regardless of whether the -M option was
24690Sstevel@tonic-gate * used or not (mflag).
24700Sstevel@tonic-gate */
24710Sstevel@tonic-gate multi_node = 1;
24720Sstevel@tonic-gate } else {
24730Sstevel@tonic-gate /*
24740Sstevel@tonic-gate * If a traditional diskset, mflag must
24750Sstevel@tonic-gate * not be set.
24760Sstevel@tonic-gate */
24770Sstevel@tonic-gate if (mflag) {
24780Sstevel@tonic-gate usage(sp, gettext(
24790Sstevel@tonic-gate "-M option only allowed "
24800Sstevel@tonic-gate "on multi-owner diskset"));
24810Sstevel@tonic-gate }
24820Sstevel@tonic-gate }
24830Sstevel@tonic-gate } else {
24840Sstevel@tonic-gate /*
24850Sstevel@tonic-gate * Set name does not exist, set multi_node
24860Sstevel@tonic-gate * based on -M option.
24870Sstevel@tonic-gate */
24880Sstevel@tonic-gate if (mflag) {
24890Sstevel@tonic-gate multi_node = 1;
24900Sstevel@tonic-gate }
24910Sstevel@tonic-gate }
24920Sstevel@tonic-gate }
24930Sstevel@tonic-gate
24940Sstevel@tonic-gate if (auto_take && multi_node) {
24950Sstevel@tonic-gate /* Can't mix multinode and auto-take on a diskset */
24960Sstevel@tonic-gate usage(sp,
24970Sstevel@tonic-gate gettext("-A option not allowed on multi-owner diskset"));
24980Sstevel@tonic-gate }
24990Sstevel@tonic-gate
25000Sstevel@tonic-gate /*
25010Sstevel@tonic-gate * MN disksets don't use DCS clustering services, so
25020Sstevel@tonic-gate * do not get primary_node for MN diskset since no command
25030Sstevel@tonic-gate * proxying is done to Primary cluster node. Do not proxy
25040Sstevel@tonic-gate * MN diskset commands of join and withdraw when issued without
25050Sstevel@tonic-gate * a valid setname.
25060Sstevel@tonic-gate * For traditional disksets: proxy all commands except a take
25070Sstevel@tonic-gate * and release. Use first host listed as the host to send the
25080Sstevel@tonic-gate * command to if there isn't already a primary
25090Sstevel@tonic-gate */
25100Sstevel@tonic-gate if (strcmp(sname, MD_LOCAL_NAME) && (multi_node == 0) &&
25110Sstevel@tonic-gate (cmd != take) && (cmd != release) &&
25120Sstevel@tonic-gate (cmd != cluster) && (cmd != join) &&
25130Sstevel@tonic-gate (cmd != withdraw) && (cmd != purge)) {
25140Sstevel@tonic-gate stat = sdssc_get_primary_host(sname, primary_node,
25150Sstevel@tonic-gate SDSSC_NODE_NAME_LEN);
25160Sstevel@tonic-gate switch (stat) {
25170Sstevel@tonic-gate case SDSSC_ERROR:
25180Sstevel@tonic-gate return (0);
25190Sstevel@tonic-gate
25200Sstevel@tonic-gate case SDSSC_NO_SERVICE:
25210Sstevel@tonic-gate if (hostname != SDSSC_PROXY_PRIMARY) {
25220Sstevel@tonic-gate (void) strlcpy(primary_node, hostname,
25230Sstevel@tonic-gate SDSSC_NODE_NAME_LEN);
25240Sstevel@tonic-gate } else {
252511053SSurya.Prakki@Sun.COM (void) memset(primary_node, '\0',
25260Sstevel@tonic-gate SDSSC_NODE_NAME_LEN);
25270Sstevel@tonic-gate }
25280Sstevel@tonic-gate break;
25290Sstevel@tonic-gate }
25300Sstevel@tonic-gate
25310Sstevel@tonic-gate /*
25320Sstevel@tonic-gate * We've got a complicated decision here regarding
25330Sstevel@tonic-gate * the hostname. If we didn't get a primary host
25340Sstevel@tonic-gate * and a host name wasn't supplied on the command line
25350Sstevel@tonic-gate * then we need to revert to SDSSC_PROXY_PRIMARY. Otherwise
25360Sstevel@tonic-gate * use what's been found.
25370Sstevel@tonic-gate */
25380Sstevel@tonic-gate if (sdssc_cmd_proxy(argc, argv,
25390Sstevel@tonic-gate primary_node[0] == '\0' ?
25404932Spetede SDSSC_PROXY_PRIMARY : primary_node,
25410Sstevel@tonic-gate &error) == SDSSC_PROXY_DONE) {
25420Sstevel@tonic-gate exit(error);
25430Sstevel@tonic-gate }
25440Sstevel@tonic-gate }
25450Sstevel@tonic-gate
25460Sstevel@tonic-gate /* cluster-specific commands */
25470Sstevel@tonic-gate if (cmd == cluster) {
25484932Spetede parse_cluster(argc, argv, multi_node);
25494932Spetede /*NOTREACHED*/
25500Sstevel@tonic-gate }
25510Sstevel@tonic-gate
25520Sstevel@tonic-gate /* join MultiNode diskset */
25530Sstevel@tonic-gate if (cmd == join) {
25540Sstevel@tonic-gate /*
25550Sstevel@tonic-gate * If diskset specified, verify that it exists
25560Sstevel@tonic-gate * and is a multinode diskset.
25570Sstevel@tonic-gate */
25580Sstevel@tonic-gate if (strcmp(sname, MD_LOCAL_NAME)) {
25590Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
25600Sstevel@tonic-gate mde_perror(ep, "");
25610Sstevel@tonic-gate md_exit(sp, 1);
25620Sstevel@tonic-gate }
25630Sstevel@tonic-gate
25640Sstevel@tonic-gate if (!multi_node) {
25650Sstevel@tonic-gate usage(sp, gettext(
25660Sstevel@tonic-gate "-j option only allowed on "
25670Sstevel@tonic-gate "multi-owner diskset"));
25680Sstevel@tonic-gate }
25690Sstevel@tonic-gate }
25700Sstevel@tonic-gate /*
25710Sstevel@tonic-gate * Start mddoors daemon here.
25720Sstevel@tonic-gate * mddoors itself takes care there will be only one
25730Sstevel@tonic-gate * instance running, so starting it twice won't hurt
25740Sstevel@tonic-gate */
257511053SSurya.Prakki@Sun.COM (void) pclose(popen("/usr/lib/lvm/mddoors", "w"));
25760Sstevel@tonic-gate parse_joinset(argc, argv);
25770Sstevel@tonic-gate /*NOTREACHED*/
25780Sstevel@tonic-gate }
25790Sstevel@tonic-gate
25800Sstevel@tonic-gate /* withdraw from MultiNode diskset */
25810Sstevel@tonic-gate if (cmd == withdraw) {
25820Sstevel@tonic-gate /*
25830Sstevel@tonic-gate * If diskset specified, verify that it exists
25840Sstevel@tonic-gate * and is a multinode diskset.
25850Sstevel@tonic-gate */
25860Sstevel@tonic-gate if (strcmp(sname, MD_LOCAL_NAME)) {
25870Sstevel@tonic-gate if ((sp = metasetname(sname, ep)) == NULL) {
25880Sstevel@tonic-gate mde_perror(ep, "");
25890Sstevel@tonic-gate md_exit(sp, 1);
25900Sstevel@tonic-gate }
25910Sstevel@tonic-gate
25920Sstevel@tonic-gate if (!multi_node) {
25930Sstevel@tonic-gate usage(sp, gettext(
25940Sstevel@tonic-gate "-w option only allowed on "
25950Sstevel@tonic-gate "multi-owner diskset"));
25960Sstevel@tonic-gate }
25970Sstevel@tonic-gate }
25980Sstevel@tonic-gate parse_withdrawset(argc, argv);
25990Sstevel@tonic-gate /*NOTREACHED*/
26000Sstevel@tonic-gate }
26010Sstevel@tonic-gate
26020Sstevel@tonic-gate /* must have set for everything else */
26030Sstevel@tonic-gate if (strcmp(sname, MD_LOCAL_NAME) == 0)
26040Sstevel@tonic-gate usage(sp, gettext("setname must be specified"));
26050Sstevel@tonic-gate
26060Sstevel@tonic-gate /* add hosts or drives */
26070Sstevel@tonic-gate if (cmd == add) {
26080Sstevel@tonic-gate /*
26090Sstevel@tonic-gate * In the multi node case start mddoors daemon.
26100Sstevel@tonic-gate * mddoors itself takes care there will be
26110Sstevel@tonic-gate * only one instance running, so starting it twice won't hurt
26120Sstevel@tonic-gate */
26130Sstevel@tonic-gate if (multi_node) {
261411053SSurya.Prakki@Sun.COM (void) pclose(popen("/usr/lib/lvm/mddoors", "w"));
26150Sstevel@tonic-gate }
26160Sstevel@tonic-gate
26170Sstevel@tonic-gate parse_add(argc, argv);
26180Sstevel@tonic-gate /*NOTREACHED*/
26190Sstevel@tonic-gate }
26200Sstevel@tonic-gate
26210Sstevel@tonic-gate /* re-balance the replicas */
26220Sstevel@tonic-gate if (cmd == balance) {
26230Sstevel@tonic-gate parse_balance(argc, argv);
26240Sstevel@tonic-gate /*NOTREACHED*/
26250Sstevel@tonic-gate }
26260Sstevel@tonic-gate
26270Sstevel@tonic-gate /* delete hosts or drives */
26280Sstevel@tonic-gate if (cmd == delete) {
26290Sstevel@tonic-gate parse_del(argc, argv);
26300Sstevel@tonic-gate /*NOTREACHED*/
26310Sstevel@tonic-gate }
26320Sstevel@tonic-gate
26330Sstevel@tonic-gate /* check ownership */
26340Sstevel@tonic-gate if (cmd == isowner) {
26350Sstevel@tonic-gate parse_isowner(argc, argv);
26360Sstevel@tonic-gate /*NOTREACHED*/
26370Sstevel@tonic-gate }
26380Sstevel@tonic-gate
26390Sstevel@tonic-gate /* purge the diskset */
26400Sstevel@tonic-gate if (cmd == purge) {
26410Sstevel@tonic-gate parse_purge(argc, argv);
26420Sstevel@tonic-gate /*NOTREACHED*/
26430Sstevel@tonic-gate }
26440Sstevel@tonic-gate
26450Sstevel@tonic-gate /* query for data marks */
26460Sstevel@tonic-gate if (cmd == query) {
26470Sstevel@tonic-gate parse_query(argc, argv);
26480Sstevel@tonic-gate /*NOTREACHED*/
26490Sstevel@tonic-gate }
26500Sstevel@tonic-gate
26510Sstevel@tonic-gate /* release ownership */
26520Sstevel@tonic-gate if (cmd == release) {
26530Sstevel@tonic-gate if (multi_node) {
26540Sstevel@tonic-gate /* Can't release multinode diskset */
26550Sstevel@tonic-gate usage(sp, gettext(
26560Sstevel@tonic-gate "-r option not allowed on multi-owner diskset"));
26570Sstevel@tonic-gate } else {
26580Sstevel@tonic-gate parse_releaseset(argc, argv);
26590Sstevel@tonic-gate /*NOTREACHED*/
26600Sstevel@tonic-gate }
26610Sstevel@tonic-gate }
26620Sstevel@tonic-gate
26630Sstevel@tonic-gate /* take ownership */
26640Sstevel@tonic-gate if (cmd == take) {
26650Sstevel@tonic-gate if (multi_node) {
26660Sstevel@tonic-gate /* Can't take multinode diskset */
26670Sstevel@tonic-gate usage(sp, gettext(
26680Sstevel@tonic-gate "-t option not allowed on multi-owner diskset"));
26690Sstevel@tonic-gate } else {
26700Sstevel@tonic-gate parse_takeset(argc, argv);
26710Sstevel@tonic-gate /*NOTREACHED*/
26720Sstevel@tonic-gate }
26730Sstevel@tonic-gate }
26740Sstevel@tonic-gate
26750Sstevel@tonic-gate /* take ownership of auto-take sets */
26760Sstevel@tonic-gate if (auto_take) {
26770Sstevel@tonic-gate parse_autotake(argc, argv);
26780Sstevel@tonic-gate /*NOTREACHED*/
26790Sstevel@tonic-gate }
26800Sstevel@tonic-gate
26810Sstevel@tonic-gate /*NOTREACHED*/
26820Sstevel@tonic-gate return (0);
26830Sstevel@tonic-gate }
2684