4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
26 * Metadevice diskset utility.
30 #include <sys/lvm/md_mddb.h>
44 join
, /* Join a multinode diskset */
45 withdraw
/* Withdraw from a multinode diskset */
50 clusterversion
, /* Return the version of the cluster I/F */
51 clusterdisksin
, /* List disks in a given diskset */
52 clustertake
, /* back door for Cluster take */
53 clusterrelease
, /* ditto */
54 clusterpurge
, /* back door for Cluster purge */
55 clusterproxy
/* proxy the args after '--' to primary */
63 if ((string
!= NULL
) && (*string
!= '\0'))
64 md_eprintf("%s\n", string
);
65 (void) fprintf(stderr
, gettext(
66 "usage:\t%s -s setname -a [-A enable | disable] -h hostname ...\n"
67 " %s -s setname -a [-M] -h hostname ...\n"
68 " %s -s setname -a [-M] [-l length] [-L] drivename ...\n"
69 " %s -s setname -d [-M] -h hostname ...\n"
70 " %s -s setname -d [-M] -f -h all-hostnames\n"
71 " %s -s setname -d [-M] [-f] drivename ...\n"
72 " %s -s setname -d [-M] [-f] hostname ...\n"
73 " %s -s setname -A enable | disable\n"
74 " %s -s setname -t [-f]\n"
76 " %s [-s setname] -j [-M]\n"
77 " %s [-s setname] -w [-M]\n"
78 " %s -s setname -P [-M]\n"
79 " %s -s setname -b [-M]\n"
80 " %s -s setname -o [-M] [-h hostname]\n"
83 " hostname = contents of /etc/nodename\n"
84 " drivename = cNtNdN no slice\n"
85 " [-M] for multi-owner set is optional except"
86 " on set creation\n"),
87 myname
, myname
, myname
, myname
, myname
, myname
, myname
, myname
,
88 myname
, myname
, myname
, myname
, myname
, myname
, myname
, myname
);
89 md_exit(sp
, (string
== NULL
) ? 0 : 1);
93 * The svm.sync rc script relies heavily on the metaset output.
94 * Any changes to the metaset output MUST verify that the rc script
95 * does not break. Not doing so may potentially leave the system
96 * unusable. You have been WARNED.
99 printset(mdsetname_t
*sp
, md_error_t
*ep
)
103 md_drive_desc
*dd
, *p
;
107 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
)
111 * Only get set owner information for traditional diskset.
112 * This set owner information is stored in the node records
115 if (!(MD_MNSET_DESC(sd
))) {
116 if (metaget_setownership(sp
, ep
) == -1)
120 if (((dd
= metaget_drivedesc(sp
, (MD_BASICNAME_OK
| PRINT_FAST
),
121 ep
)) == NULL
) && !mdisok(ep
))
124 if (MD_MNSET_DESC(sd
)) {
125 (void) printf(gettext(
126 "\nMulti-owner Set name = %s, Set number = %d, Master = %s\n"),
127 sp
->setname
, sp
->setno
, sd
->sd_mn_master_nodenm
);
128 if ((sd
->sd_mn_master_nodeid
== MD_MN_INVALID_NID
) &&
130 (void) printf(gettext(
131 "Master and owner information unavailable "
132 "until joined (metaset -j)\n"));
135 (void) printf(gettext(
136 "\nSet name = %s, Set number = %d\n"),
137 sp
->setname
, sp
->setno
);
140 if (MD_MNSET_DESC(sd
)) {
141 (void) printf(gettext("\n%-19.19s %-14.14s %-6.6s\n"),
142 gettext("Host"), gettext("Owner"), gettext("Member"));
143 nd
= sd
->sd_nodelist
;
146 * Don't print nodes that aren't ok since they may be
147 * removed from config during a reconfig cycle. If a
148 * node was being added to a diskset and the entire
149 * cluster went down but the node being added was unable
150 * to reboot, there's no way to know if that node had
151 * its own node record set to OK or not. So, node
152 * record is left in ADD state during reconfig cycle.
153 * When that node reboots and returns to the cluster,
154 * the reconfig cycle will either remove the node
155 * record (if not marked OK on that node) or will mark
156 * it OK on all nodes.
157 * It is very important to only remove a node record
158 * from the other nodes when that node record is not
159 * marked OK on its own node - otherwise, different
160 * nodes would have different nodelists possibly
161 * causing different nodes to to choose different
164 * Standard hostname field is 17 bytes but metaset
165 * will display up to MD_MAX_NODENAME, defined in
168 if (!(nd
->nd_flags
& MD_MN_NODE_OK
)) {
172 if ((nd
->nd_flags
& MD_MN_NODE_ALIVE
) &&
173 (nd
->nd_flags
& MD_MN_NODE_OWN
)) {
175 gettext(" %-17.*s %-12.12s %-4.4s\n"),
177 nd
->nd_nodename
, gettext("multi-owner"),
179 } else if ((!(nd
->nd_flags
& MD_MN_NODE_ALIVE
)) &&
180 (nd
->nd_flags
& MD_MN_NODE_OWN
)) {
181 /* Should never be able to happen */
183 gettext(" %-17.*s %-12.12s %-4.4s\n"),
185 nd
->nd_nodename
, gettext("multi-owner"),
187 } else if ((nd
->nd_flags
& MD_MN_NODE_ALIVE
) &&
188 (!(nd
->nd_flags
& MD_MN_NODE_OWN
))) {
190 gettext(" %-17.*s %-12.12s %-4.4s\n"),
192 nd
->nd_nodename
, gettext(""),
194 } else if ((!(nd
->nd_flags
& MD_MN_NODE_ALIVE
)) &&
195 (!(nd
->nd_flags
& MD_MN_NODE_OWN
))) {
197 gettext(" %-17.*s %-12.12s %-4.4s\n"),
199 nd
->nd_nodename
, gettext(""),
205 (void) printf("\n%-19.19s %-5.5s\n",
206 gettext("Host"), gettext("Owner"));
207 for (i
= 0; i
< MD_MAXSIDES
; i
++) {
208 /* Skip empty slots */
209 if (sd
->sd_nodes
[i
][0] == '\0')
213 * Standard hostname field is 17 bytes but metaset will
214 * display up to MD_MAX_NODENAME, def in meta_basic.h
216 (void) printf(" %-17.*s %s\n", MD_MAX_NODENAME
,
217 sd
->sd_nodes
[i
], (sd
->sd_flags
& MD_SR_AUTO_TAKE
?
218 (sd
->sd_isown
[i
] ? gettext("Yes (auto)") :
219 gettext("No (auto)"))
220 : (sd
->sd_isown
[i
] ? gettext("Yes") : "")));
224 if (sd
->sd_med
.n_cnt
> 0)
225 (void) printf("\n%-19.19s %-7.7s\n",
226 gettext("Mediator Host(s)"), gettext("Aliases"));
228 if ((max_meds
= get_max_meds(ep
)) == 0)
231 for (i
= 0; i
< max_meds
; i
++) {
232 if (sd
->sd_med
.n_lst
[i
].a_cnt
== 0)
235 * Standard hostname field is 17 bytes but metaset will
236 * display up to MD_MAX_NODENAME, def in meta_basic.h
238 (void) printf(" %-17.*s ", MD_MAX_NODENAME
,
239 sd
->sd_med
.n_lst
[i
].a_nm
[0]);
240 for (j
= 1; j
< sd
->sd_med
.n_lst
[i
].a_cnt
; j
++) {
241 (void) printf("%s", sd
->sd_med
.n_lst
[i
].a_nm
[j
]);
242 if (sd
->sd_med
.n_lst
[i
].a_cnt
- j
> 1)
243 (void) printf(gettext(", "));
253 * Building a format string on the fly that will
254 * be used in (f)printf. This allows the length
255 * of the ctd to vary from small to large without
258 for (p
= dd
; p
!= NULL
; p
= p
->dd_next
)
259 len
= max(len
, strlen(p
->dd_dnp
->cname
));
262 (void) printf("\n%-*.*s %-5.5s\n", len
, len
,
265 for (p
= dd
; p
!= NULL
; p
= p
->dd_next
) {
266 (void) printf("\n%-*.*s %-5.5s\n", len
, len
,
268 (p
->dd_dbcnt
? gettext("Yes") :
277 printsets(mdsetname_t
*sp
, md_error_t
*ep
)
284 * print setname given.
286 if (! metaislocalset(sp
)) {
287 if (printset(sp
, ep
))
292 if ((max_sets
= get_max_sets(ep
)) == 0)
296 * Print all known sets
298 for (i
= 1; i
< max_sets
; i
++) {
299 if ((sp1
= metasetnosetname(i
, ep
)) == NULL
) {
300 if (! mdiserror(ep
, MDE_NO_SET
))
306 if (printset(sp1
, ep
))
316 * Print the current versionn of the cluster contract private interface.
319 printclusterversion()
321 (void) printf("%s\n", METASETIFVERSION
);
325 * Print the disks that make up the given disk set. This is used
326 * exclusively by Sun Cluster and is contract private.
327 * Should never be called with sname of a Multinode diskset.
330 printdisksin(char *sname
, md_error_t
*ep
)
333 md_drive_desc
*dd
, *p
;
335 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
338 * During a deletion of a set the associated service is
339 * put offline. The SC3.0 reservation code calls disksuite
340 * to find a list of disks associated with the set so that
341 * it can release the reservation on those disks. In this
342 * case there won't be any disks or even a set left. So just
348 if (metaget_setownership(sp
, ep
) == -1)
351 if (((dd
= metaget_drivedesc(sp
, (MD_BASICNAME_OK
| PRINT_FAST
),
352 ep
)) == NULL
) && !mdisok(ep
))
355 for (p
= dd
; p
!= NULL
; p
= p
->dd_next
)
356 (void) printf("%s\n", p
->dd_dnp
->rname
);
362 parse_printset(int argc
, char **argv
)
365 mdsetname_t
*sp
= NULL
;
366 char *sname
= MD_LOCAL_NAME
;
367 md_error_t status
= mdnullerror
;
368 md_error_t
*ep
= &status
;
370 /* reset and parse args */
373 while ((c
= getopt(argc
, argv
, "s:")) != -1) {
379 usage(sp
, gettext("unknown options"));
387 usage(sp
, gettext("too many args"));
389 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
394 if (printsets(sp
, ep
) && !mdiserror(ep
, MDE_SMF_NO_SERVICE
)) {
399 if (meta_smf_isonline(meta_smf_getmask(), ep
) == 0) {
408 parse_add(int argc
, char **argv
)
413 int auto_take
= FALSE
;
414 int force_label
= FALSE
;
415 int default_size
= TRUE
;
416 mdsetname_t
*sp
= NULL
;
417 char *sname
= MD_LOCAL_NAME
;
418 md_error_t status
= mdnullerror
;
419 md_error_t
*ep
= &status
;
420 mddrivenamelist_t
*dnlp
= NULL
;
421 mddrivenamelist_t
*p
;
422 daddr_t dbsize
, nblks
;
423 mdsetname_t
*local_sp
= NULL
;
428 /* reset and parse args */
431 while ((c
= getopt(argc
, argv
, "MaA:hl:Lms:")) != -1) {
437 /* verified sub-option in main */
438 if (strcmp(optarg
, "enable") == 0)
445 if (meds
== TRUE
|| hosts
== TRUE
)
447 "only one -m or -h option allowed"));
449 if (default_size
== FALSE
|| force_label
== TRUE
)
451 "conflicting options"));
459 if (hosts
== TRUE
|| meds
== TRUE
)
461 "conflicting options"));
462 if (sscanf(optarg
, "%ld", &dbsize
) != 1) {
464 "%s: bad format\n"), optarg
);
468 default_size
= FALSE
;
471 /* Same criteria as -l */
472 if (hosts
== TRUE
|| meds
== TRUE
)
474 "conflicting options"));
486 /* Can only use -A enable when creating the single-node set */
487 if (auto_take
&& hosts
!= TRUE
)
488 usage(sp
, gettext("conflicting options"));
498 if ((local_sp
= metasetname(MD_LOCAL_NAME
, ep
)) == NULL
) {
500 md_exit(local_sp
, 1);
503 if (meta_lock(local_sp
, TRUE
, ep
) != 0) {
505 md_exit(local_sp
, 1);
509 * Keep track of Cluster set creation. Need to complete
510 * the transaction no matter if the set was created or not.
515 * Have no set, cannot take the lock, so only take the
518 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
522 * When running on a cluster system that
523 * does not support MN disksets, the routine
524 * sdssc_mo_create_begin will be bound
525 * to the SVM routine not_bound_error
526 * which returns SDSSC_NOT_BOUND_ERROR.
528 * When running on a cluster system that
529 * does support MN disksets, the routine
530 * sdssc_mo_create_begin will be bound to
531 * the sdssc_mo_create_begin routine in
532 * library libsdssc_so. A call to
533 * sdssc_mo_create_begin will return with
534 * either SDSSC_ERROR or SDSSC_OKAY. If
535 * an SDSSC_OKAY is returned, then the
536 * cluster framework has allocated a
537 * set number for this new set that is unique
538 * across traditional and MN disksets.
539 * Libmeta will get this unique set number
540 * by calling sdssc_get_index.
542 * When running on a non-cluster system,
543 * the routine sdssc_mo_create_begin
544 * will be bound to the SVM routine
545 * not_bound which returns SDSSC_NOT_BOUND.
546 * In this case, all sdssc routines will
547 * return SDSSC_NOT_BOUND. No need to check
548 * for return value of SDSSC_NOT_BOUND since
549 * the libmeta call to get the set number
550 * (sdssc_get_index) will also fail with
551 * SDSSC_NOT_BOUND causing libmeta to
552 * determine its own set number.
554 sdssc_rval
= sdssc_mo_create_begin(sname
, argc
,
555 argv
, SDSSC_PICK_SETNO
);
556 if (sdssc_rval
== SDSSC_NOT_BOUND_ERROR
) {
557 (void) mderror(ep
, MDE_NOT_MN
, NULL
);
559 "Cluster node does not support "
560 "multi-owner diskset operations");
561 md_exit(local_sp
, 1);
562 } else if (sdssc_rval
== SDSSC_ERROR
) {
564 md_exit(local_sp
, 1);
567 sdssc_rval
= sdssc_create_begin(sname
, argc
,
568 argv
, SDSSC_PICK_SETNO
);
569 if (sdssc_rval
== SDSSC_ERROR
) {
571 md_exit(local_sp
, 1);
575 * Created diskset (as opposed to adding a
576 * host to an existing diskset).
580 sp
= Zalloc(sizeof (*sp
));
581 sp
->setname
= Strdup(sname
);
582 sp
->lockfd
= MD_NO_LOCK
;
585 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
) {
587 md_exit(local_sp
, 1);
589 if (MD_MNSET_DESC(sd
)) {
594 * can't add hosts to an existing set & enable
598 usage(sp
, gettext("conflicting options"));
601 * Have a valid set, take the set lock also.
603 * A MN diskset does not use the set meta_lock but
604 * instead uses the clnt_lock of rpc.metad and the
605 * suspend/resume feature of the rpc.mdcommd. Can't
606 * use set meta_lock since class 1 messages are
607 * grabbing this lock and if this thread is holding
608 * the set meta_lock then no rpc.mdcommd suspend
612 if (meta_lock(sp
, TRUE
, ep
) != 0) {
614 md_exit(local_sp
, 1);
619 if (meta_set_addhosts(sp
, multi_node
, argc
, argv
, auto_take
,
622 sdssc_create_end(sname
, SDSSC_CLEANUP
);
623 mde_perror(&status
, "");
625 (void) meta_unlock(sp
, ep
);
626 md_exit(local_sp
, 1);
630 sdssc_create_end(sname
, SDSSC_COMMIT
);
634 * If adding hosts to existing diskset,
637 sdssc_add_hosts(sname
, argc
, argv
);
640 (void) meta_unlock(sp
, ep
);
641 md_exit(local_sp
, 0);
649 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
651 md_exit(local_sp
, 1);
654 if ((local_sp
= metasetname(MD_LOCAL_NAME
, ep
)) == NULL
) {
656 md_exit(local_sp
, 1);
659 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
) {
661 md_exit(local_sp
, 1);
663 if (MD_MNSET_DESC(sd
)) {
667 if (meta_lock(local_sp
, TRUE
, ep
) != 0) {
669 md_exit(local_sp
, 1);
672 * A MN diskset does not use the set meta_lock but
673 * instead uses the clnt_lock of rpc.metad and the
674 * suspend/resume feature of the rpc.mdcommd. Can't
675 * use set meta_lock since class 1 messages are
676 * grabbing this lock and if this thread is holding
677 * the set meta_lock then no rpc.mdcommd suspend
681 if (meta_lock(sp
, TRUE
, ep
) != 0) {
683 md_exit(local_sp
, 1);
687 if (meta_set_addmeds(sp
, argc
, argv
, ep
)) {
688 mde_perror(&status
, "");
690 (void) meta_unlock(sp
, ep
);
691 md_exit(local_sp
, 1);
695 (void) meta_unlock(sp
, ep
);
696 md_exit(local_sp
, 0);
702 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
704 md_exit(local_sp
, 1);
707 if ((local_sp
= metasetname(MD_LOCAL_NAME
, ep
)) == NULL
) {
709 md_exit(local_sp
, 1);
712 /* Determine if diskset is a MN diskset or not */
713 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
) {
715 md_exit(local_sp
, 1);
717 if (MD_MNSET_DESC(sd
)) {
721 if (meta_lock(local_sp
, TRUE
, ep
) != 0) {
723 md_exit(local_sp
, 1);
726 /* Make sure database size is within limits */
727 if (default_size
== FALSE
) {
728 if ((multi_node
&& dbsize
< MDDB_MN_MINBLKS
) ||
729 (!multi_node
&& dbsize
< MDDB_MINBLKS
))
731 "size (-l) is too small"));
733 if ((multi_node
&& dbsize
> MDDB_MN_MAXBLKS
) ||
734 (!multi_node
&& dbsize
> MDDB_MAXBLKS
))
736 "size (-l) is too big"));
740 * Have a valid set, take the set lock also.
742 * A MN diskset does not use the set meta_lock but
743 * instead uses the clnt_lock of rpc.metad and the
744 * suspend/resume feature of the rpc.mdcommd. Can't
745 * use set meta_lock since class 1 messages are
746 * grabbing this lock and if this thread is holding
747 * the set meta_lock then no rpc.mdcommd suspend
751 if (meta_lock(sp
, TRUE
, ep
) != 0) {
753 md_exit(local_sp
, 1);
759 * If using the default size,
760 * then let's adjust the default to the minimum
761 * size currently in use.
764 dbsize
= multi_node
? MD_MN_DBSIZE
: MD_DBSIZE
;
765 if ((nblks
= meta_db_minreplica(sp
, ep
)) < 0)
768 dbsize
= nblks
; /* adjust replica size */
771 if ((c
= metadrivenamelist(&sp
, &dnlp
, argc
, argv
, ep
)) < 0) {
774 (void) meta_unlock(sp
, ep
);
775 md_exit(local_sp
, 1);
780 "No drives specified to add.\n"));
782 (void) meta_unlock(sp
, ep
);
783 md_exit(local_sp
, 1);
786 if (meta_set_adddrives(sp
, dnlp
, dbsize
, force_label
, ep
)) {
787 metafreedrivenamelist(dnlp
);
790 (void) meta_unlock(sp
, ep
);
791 md_exit(local_sp
, 1);
795 * MN disksets don't have a device id in the master block
796 * For traditional disksets, check for the drive device
797 * id not fitting in the master block
800 for (p
= dnlp
; p
!= NULL
; p
= p
->next
) {
805 np
= metaslicename(p
->drivenamep
, 0, ep
);
809 if ((fd
= open(np
->rname
, O_RDONLY
| O_NDELAY
)) < 0)
812 if (devid_get(fd
, &devid
) == 0) {
815 len
= devid_sizeof(devid
);
816 if (len
> (DEV_BSIZE
- sizeof (mddb_mb_t
)))
818 MDE_DS_NOTSELFIDENTIFY
, NULL
, NULL
,
822 (void) mddserror(ep
, MDE_DS_NOTSELFIDENTIFY
,
823 NULL
, NULL
, np
->rname
, NULL
);
830 * MN disksets don't use DCS clustering services.
831 * For traditional disksets:
832 * There's not really much we can do here if this call fails.
833 * The drives have been added to the set and DiskSuite believes
834 * it owns the drives.
835 * Relase the set and hope for the best.
838 (sdssc_notify_service(sname
, Make_Primary
) == SDSSC_ERROR
)) {
839 (void) meta_set_release(sp
, ep
);
840 (void) printf(gettext(
841 "Sun Clustering failed to make set primary\n"));
844 metafreedrivenamelist(dnlp
);
846 (void) meta_unlock(sp
, ep
);
847 md_exit(local_sp
, 0);
851 parse_balance(int argc
, char **argv
)
854 mdsetname_t
*sp
= NULL
;
855 char *sname
= MD_LOCAL_NAME
;
856 md_error_t status
= mdnullerror
;
860 /* reset and parse args */
863 while ((c
= getopt(argc
, argv
, "Mbs:")) != -1) {
873 usage(sp
, gettext("unknown options"));
881 usage(sp
, gettext("too many args"));
883 if ((sp
= metasetname(sname
, &status
)) == NULL
) {
884 mde_perror(&status
, "");
887 if ((sd
= metaget_setdesc(sp
, &status
)) == NULL
) {
888 mde_perror(&status
, "");
891 if (MD_MNSET_DESC(sd
)) {
895 * Have a valid set, take the set lock also.
897 * A MN diskset does not use the set meta_lock but
898 * instead uses the clnt_lock of rpc.metad and the
899 * suspend/resume feature of the rpc.mdcommd. Can't
900 * use set meta_lock since class 1 messages are
901 * grabbing this lock and if this thread is holding
902 * the set meta_lock then no rpc.mdcommd suspend
906 if (meta_lock(sp
, TRUE
, &status
) != 0) {
907 mde_perror(&status
, "");
912 if (meta_set_balance(sp
, &status
) != 0) {
913 mde_perror(&status
, "");
920 parse_autotake(int argc
, char **argv
)
924 mdsetname_t
*sp
= NULL
;
925 char *sname
= MD_LOCAL_NAME
;
926 md_error_t status
= mdnullerror
;
927 md_error_t
*ep
= &status
;
929 /* reset and parse args */
932 while ((c
= getopt(argc
, argv
, "A:s:")) != -1) {
935 /* verified sub-option in main */
936 if (strcmp(optarg
, "enable") == 0)
940 /* verified presence of setname in main */
944 usage(sp
, gettext("unknown options"));
948 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
953 if (meta_lock(sp
, TRUE
, ep
) != 0) {
958 if (meta_check_ownership(sp
, ep
) != 0) {
963 if (meta_set_auto_take(sp
, enable
, ep
) != 0) {
972 parse_del(int argc
, char **argv
)
975 mdsetname_t
*sp
= NULL
;
976 char *sname
= MD_LOCAL_NAME
;
979 int forceflg
= FALSE
;
980 md_error_t status
= mdnullerror
;
981 md_error_t
*ep
= &status
;
982 mddrivenamelist_t
*dnlp
= NULL
;
983 mdsetname_t
*local_sp
= NULL
;
987 /* reset and parse args */
990 while ((c
= getopt(argc
, argv
, "Mdfhms:")) != -1) {
1001 if (meds
== TRUE
|| hosts
== TRUE
)
1003 "only one -m or -h option allowed"));
1014 usage(sp
, gettext("unknown options"));
1021 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
1023 md_exit(local_sp
, 1);
1026 if ((local_sp
= metasetname(MD_LOCAL_NAME
, ep
)) == NULL
) {
1028 md_exit(local_sp
, 1);
1031 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
) {
1033 md_exit(local_sp
, 1);
1035 if (MD_MNSET_DESC(sd
))
1038 if (meta_lock(local_sp
, TRUE
, ep
) != 0) {
1040 md_exit(local_sp
, 1);
1044 * Have a valid set, take the set lock also.
1046 * A MN diskset does not use the set meta_lock but
1047 * instead uses the clnt_lock of rpc.metad and the
1048 * suspend/resume feature of the rpc.mdcommd. Can't
1049 * use set meta_lock since class 1 messages are
1050 * grabbing this lock and if this thread is holding
1051 * the set meta_lock then no rpc.mdcommd suspend
1055 if (meta_lock(sp
, TRUE
, ep
) != 0) {
1057 md_exit(local_sp
, 1);
1064 if (hosts
== TRUE
) {
1065 if (meta_check_ownership(sp
, ep
) != 0) {
1067 * If we don't own the set bail out here otherwise
1068 * we could delete the node from the DCS service
1069 * yet not delete the host from the set.
1073 (void) meta_unlock(sp
, ep
);
1074 md_exit(local_sp
, 1);
1076 if (sdssc_delete_hosts(sname
, argc
, argv
) == SDSSC_ERROR
) {
1077 if (!metad_isautotakebyname(sname
)) {
1079 * SC could have been installed after the set
1080 * was created. We still want to be able to
1081 * delete these sets.
1084 "Failed to delete hosts from DCS service"));
1086 (void) meta_unlock(sp
, ep
);
1087 md_exit(local_sp
, 1);
1090 if (meta_set_deletehosts(sp
, argc
, argv
, forceflg
, ep
)) {
1091 if (sdssc_add_hosts(sname
, argc
, argv
) == SDSSC_ERROR
) {
1092 (void) printf(gettext(
1093 "Failed to restore host(s) in DCS "
1098 (void) meta_unlock(sp
, ep
);
1099 md_exit(local_sp
, 1);
1102 (void) meta_unlock(sp
, ep
);
1103 md_exit(local_sp
, 0);
1110 if (meta_set_deletemeds(sp
, argc
, argv
, forceflg
, ep
)) {
1113 (void) meta_unlock(sp
, ep
);
1114 md_exit(local_sp
, 1);
1117 (void) meta_unlock(sp
, ep
);
1118 md_exit(local_sp
, 0);
1125 if ((c
= metadrivenamelist(&sp
, &dnlp
, argc
, argv
, ep
)) < 0) {
1128 (void) meta_unlock(sp
, ep
);
1129 md_exit(local_sp
, 1);
1134 "No drives specified to delete.\n"));
1136 (void) meta_unlock(sp
, ep
);
1137 md_exit(local_sp
, 1);
1140 if (meta_set_deletedrives(sp
, dnlp
, forceflg
, ep
)) {
1141 metafreedrivenamelist(dnlp
);
1144 (void) meta_unlock(sp
, ep
);
1145 md_exit(local_sp
, 1);
1148 metafreedrivenamelist(dnlp
);
1150 (void) meta_unlock(sp
, ep
);
1151 md_exit(local_sp
, 0);
1155 parse_isowner(int argc
, char **argv
)
1158 mdsetname_t
*sp
= NULL
;
1159 char *sname
= MD_LOCAL_NAME
;
1160 md_error_t status
= mdnullerror
;
1161 md_error_t
*ep
= &status
;
1164 /* reset and parse args */
1167 while ((c
= getopt(argc
, argv
, "Moh:s:")) != -1) {
1176 "only one -h option allowed"));
1184 usage(sp
, gettext("unknown options"));
1192 usage(sp
, gettext("too many args"));
1194 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
1200 if (meta_check_ownership(sp
, ep
) != 0) {
1205 if (meta_check_ownership_on_host(sp
, host
, ep
) != 0) {
1214 parse_purge(int argc
, char **argv
)
1217 mdsetname_t
*sp
= NULL
;
1218 mdsetname_t
*local_sp
= NULL
;
1220 char *sname
= MD_LOCAL_NAME
;
1221 char *thishost
= mynode();
1222 md_error_t status
= mdnullerror
;
1223 md_error_t
*ep
= &status
;
1224 int bypass_cluster_purge
= 0;
1225 int forceflg
= FALSE
;
1232 while ((c
= getopt(argc
, argv
, "C:fPs:")) != -1) {
1237 bypass_cluster_purge
= 1;
1248 usage(sp
, gettext("unknown options"));
1256 usage(sp
, gettext("too many arguments"));
1258 if ((local_sp
= metasetname(MD_LOCAL_NAME
, ep
)) == NULL
) {
1260 md_exit(local_sp
, 1);
1263 if (meta_lock(local_sp
, TRUE
, ep
) != 0) {
1265 md_exit(local_sp
, 1);
1268 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
1273 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
) {
1275 md_exit(local_sp
, 1);
1277 if (MD_MNSET_DESC(sd
))
1281 if (meta_lock(sp
, TRUE
, ep
) != 0) {
1283 md_exit(local_sp
, 1);
1287 /* Must not own the set if purging it from this host */
1288 if (meta_check_ownership(sp
, ep
) == 0) {
1290 * Need to see if there are disks in the set, if not then
1291 * there is no ownership but meta_check_ownership returns 0
1293 dd
= metaget_drivedesc(sp
, (MD_BASICNAME_OK
| PRINT_FAST
), ep
);
1297 (void) meta_unlock(sp
, ep
);
1298 md_exit(local_sp
, 1);
1301 (void) printf(gettext
1302 ("Must not be owner of the set when purging it\n"));
1304 (void) meta_unlock(sp
, ep
);
1305 md_exit(local_sp
, 1);
1309 * Remove the node from the DCS service
1311 if (!bypass_cluster_purge
) {
1312 if (sdssc_delete_hosts(sname
, 1, &thishost
) == SDSSC_ERROR
) {
1314 ("Failed to purge hosts from DCS service"));
1316 (void) meta_unlock(sp
, ep
);
1317 md_exit(local_sp
, 1);
1321 if ((ret
= meta_set_purge(sp
, bypass_cluster_purge
, forceflg
,
1323 if (!bypass_cluster_purge
) {
1324 if (sdssc_add_hosts(sname
, 1, &thishost
) ==
1326 (void) printf(gettext(
1327 "Failed to restore host in DCS "
1333 (void) meta_unlock(sp
, ep
);
1334 md_exit(local_sp
, ret
);
1338 (void) meta_unlock(sp
, ep
);
1339 md_exit(local_sp
, 0);
1343 parse_query(int argc
, char **argv
)
1346 mdsetname_t
*sp
= NULL
;
1347 mddb_dtag_lst_t
*dtlp
= NULL
;
1348 mddb_dtag_lst_t
*tdtlp
;
1349 char *sname
= MD_LOCAL_NAME
;
1350 md_error_t status
= mdnullerror
;
1352 /* reset and parse args */
1355 while ((c
= getopt(argc
, argv
, "Mqs:")) != -1) {
1365 usage(sp
, gettext("unknown options"));
1373 usage(sp
, gettext("too many args"));
1375 if ((sp
= metasetname(sname
, &status
)) == NULL
) {
1376 mde_perror(&status
, "");
1380 if (meta_lock(sp
, TRUE
, &status
) != 0) {
1381 mde_perror(&status
, "");
1385 if (meta_set_query(sp
, &dtlp
, &status
) != 0) {
1386 mde_perror(&status
, "");
1391 (void) printf("The following tag(s) were found:\n");
1393 for (tdtlp
= dtlp
; tdtlp
!= NULL
; tdtlp
= dtlp
) {
1394 dtlp
= tdtlp
->dtl_nx
;
1395 (void) printf("%2d - %s - %s", tdtlp
->dtl_dt
.dt_id
,
1396 tdtlp
->dtl_dt
.dt_hn
,
1397 ctime((long *)&tdtlp
->dtl_dt
.dt_tv
.tv_sec
));
1404 /* Should never be called with sname of a Multinode diskset. */
1406 parse_releaseset(int argc
, char **argv
)
1409 mdsetname_t
*sp
= NULL
;
1410 md_error_t status
= mdnullerror
;
1411 md_error_t
*ep
= &status
;
1412 char *sname
= MD_LOCAL_NAME
;
1413 sdssc_boolean_e cluster_release
= SDSSC_False
;
1414 sdssc_version_t vers
;
1418 /* reset and parse args */
1421 while ((c
= getopt(argc
, argv
, "C:s:r")) != -1) {
1424 cluster_release
= SDSSC_True
;
1432 usage(sp
, gettext("unknown options"));
1440 usage(sp
, gettext("too many args"));
1442 (void) memset(&vers
, 0, sizeof (vers
));
1444 if ((sdssc_version(&vers
) == SDSSC_OKAY
) &&
1445 (vers
.major
== 3) &&
1446 (cluster_release
== SDSSC_False
)) {
1449 * If the release is being done by the user via the CLI
1450 * we need to notify the DCS to release this node as being
1451 * the primary. The reason nothing else needs to be done
1452 * is due to the fact that the reservation code will exec
1453 * metaset -C release to complete the operation.
1455 rval
= sdssc_notify_service(sname
, Release_Primary
);
1456 if (rval
== SDSSC_ERROR
) {
1457 (void) printf(gettext(
1458 "metaset: failed to notify DCS of release\n"));
1460 md_exit(NULL
, rval
== SDSSC_ERROR
);
1463 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
1466 * It's entirely possible for the SC3.0 reservation code
1467 * to call for DiskSet to release a diskset and have that
1468 * diskset not exist. During a diskset removal DiskSuite
1469 * maybe able to remove all traces of the diskset before
1470 * the reservation code execs metaset -C release in which
1471 * case the metasetname will fail, but the overall command
1474 if (vers
.major
== 3)
1482 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
) {
1487 if (sd
->sd_flags
& MD_SR_AUTO_TAKE
) {
1488 md_eprintf(gettext("cannot release auto-take diskset\n"));
1492 if (meta_lock_nowait(sp
, ep
) != 0) {
1494 md_exit(sp
, 10); /* special errcode */
1497 if (meta_set_release(sp
, ep
)) {
1504 /* Should never be called with sname of a Multinode diskset. */
1506 parse_takeset(int argc
, char **argv
)
1509 mdsetname_t
*sp
= NULL
;
1511 char *sname
= MD_LOCAL_NAME
;
1512 mhd_mhiargs_t mhiargs
;
1514 int pos
= -1; /* position of timeout value */
1516 static char *nullopts
[] = { NULL
};
1517 md_error_t status
= mdnullerror
;
1518 md_error_t
*ep
= &status
;
1519 sdssc_boolean_e cluster_take
= SDSSC_False
;
1520 sdssc_version_t vers
;
1524 /* reset and parse args */
1527 while ((c
= getopt(argc
, argv
, "C:fs:tu:y")) != -1) {
1530 cluster_take
= SDSSC_True
;
1533 flags
|= TAKE_FORCE
;
1541 usetag
= atoi(optarg
);
1542 flags
|= TAKE_USETAG
;
1545 flags
|= TAKE_USEIT
;
1548 usage(sp
, gettext("unknown options"));
1552 mhiargs
= defmhiargs
;
1558 usage(sp
, gettext("too many args"));
1561 * If we have a list of timeout value overrides, handle it here
1563 while (argv
[0] != NULL
&& *argv
[0] != '\0') {
1565 * The use of the nullopts[] "token list" here is to make
1566 * getsubopts() simply parse a comma separated list
1567 * returning either "" or the contents of the field, the
1568 * end condition is exaustion of the initial string, which
1569 * is modified in the process.
1571 (void) getsubopt(&argv
[0], nullopts
, &cp
);
1573 c
= 0; /* re-use c as temp value of timeout */
1575 if (*cp
!= '-') /* '-' uses default */
1580 "time out values must be > 0"));
1585 "too many timeout values specified."));
1588 if (c
== 0) /* 0 or "" field uses default */
1592 * Assign temp value to appropriate structure member based on
1593 * its position in the comma separated list.
1601 mhiargs
.mh_tk
.reinstate_resv_delay
= c
;
1605 mhiargs
.mh_tk
.min_ownership_delay
= c
;
1609 mhiargs
.mh_tk
.max_ownership_delay
= c
;
1614 (void) memset(&vers
, 0, sizeof (vers
));
1616 if ((sdssc_version(&vers
) == SDSSC_OKAY
) &&
1617 (vers
.major
== 3) &&
1618 (cluster_take
== SDSSC_False
)) {
1621 * If the take is beging done by the user via the CLI we need
1622 * to notify the DCS to make this current node the primary.
1623 * The SC3.0 reservation code will in turn exec metaset with
1624 * the -C take arg to complete this operation.
1626 if ((rval
= sdssc_notify_service(sname
, Make_Primary
)) ==
1628 (void) printf(gettext(
1629 "metaset: failed to notify DCS of take\n"));
1631 md_exit(NULL
, rval
== SDSSC_ERROR
);
1634 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
1639 if ((vers
.major
== 3) && (meta_check_ownership(sp
, ep
) == 0)) {
1642 * If we're running in a cluster environment and this
1643 * node already owns the set. Don't bother trying to
1644 * take the set again. There's one case where an adminstrator
1645 * is adding disks to a set for the first time. metaset
1646 * will take the ownership of the set at that point. During
1647 * that add operation SC3.0 notices activity on the device
1648 * and also tries to perform a take operation. The SC3.0 take
1649 * will fail because the adminstrative add has the set locked
1654 if (meta_lock_nowait(sp
, ep
) != 0) {
1656 md_exit(sp
, 10); /* special errcode */
1660 * If a 2 is returned from meta_set_take, this take was able to resolve
1661 * an unresolved replicated disk (i.e. a disk is now available that
1662 * had been missing during the import of the replicated diskset).
1663 * Need to release the diskset and re-take in order to have
1664 * the subdrivers re-snarf using the newly resolved (or newly mapped)
1665 * devids. This also allows the namespace to be updated with the
1666 * correct major names in the case where the disk being replicated
1667 * was handled by a different driver than the replicated disk.
1669 set_take_rval
= meta_set_take(sp
, &mhiargs
, flags
, usetag
, &status
);
1670 if (set_take_rval
== 2) {
1671 if (meta_set_release(sp
, &status
)) {
1673 "Need to release and take set to resolve names.");
1676 metaflushdrivenames();
1677 metaflushsetname(sp
);
1678 set_take_rval
= meta_set_take(sp
, &mhiargs
,
1679 (flags
| TAKE_RETAKE
), usetag
, &status
);
1682 if (set_take_rval
== -1) {
1683 mde_perror(&status
, "");
1684 if (mdismddberror(&status
, MDE_DB_TAGDATA
))
1686 if (mdismddberror(&status
, MDE_DB_ACCOK
))
1688 if (mdismddberror(&status
, MDE_DB_STALE
))
1696 * Joins a node to a specific set or to all multinode disksets known
1697 * by this node. If set is specified then caller should have verified
1698 * that the set is a multinode diskset.
1700 * If an error occurs, metaset exits with a 1.
1701 * If there is no error, metaset exits with a 0.
1704 parse_joinset(int argc
, char **argv
)
1707 mdsetname_t
*sp
= NULL
, *local_sp
= NULL
;
1708 char *sname
= MD_LOCAL_NAME
;
1709 md_error_t status
= mdnullerror
;
1710 md_error_t
*ep
= &status
;
1714 set_t max_sets
, setno
;
1715 int err
, cumm_err
= 0;
1718 bufsz
= sizeof (buf
);
1719 /* reset and parse args */
1722 while ((c
= getopt(argc
, argv
, "Ms:j")) != -1) {
1732 usage(sp
, gettext("unknown options"));
1740 usage(sp
, gettext("too many args"));
1743 * If no setname option was used, then join all disksets
1744 * that this node knows about. Attempt to join all
1745 * disksets that this node knows about.
1747 * Additional text is added to the error messages during
1748 * this section of code in order to help the user understand
1749 * why the 'join of all sets' failed and which set caused
1754 * Hold local set lock throughout this call to keep
1755 * other actions from interfering (such as creating a new
1758 if ((local_sp
= metasetname(MD_LOCAL_NAME
, ep
)) == NULL
) {
1763 if (meta_lock(local_sp
, TRUE
, ep
) != 0) {
1765 md_exit(local_sp
, 1);
1768 if (strcmp(sname
, MD_LOCAL_NAME
) == 0) {
1770 * If no set name is given, then walk through all sets
1771 * on this node which could include:
1773 * - traditional disksets
1774 * - non-existent disksets
1775 * Attempt to join the MN disksets.
1776 * If the join of one set fails, print out an error message
1777 * about that set and continue the walk.
1779 if ((max_sets
= get_max_sets(ep
)) == 0) {
1781 md_exit(local_sp
, 1);
1784 /* Start walking through all possible disksets */
1785 for (setno
= 1; setno
< max_sets
; setno
++) {
1786 if ((sp
= metasetnosetname(setno
, ep
)) == NULL
) {
1787 if (mdiserror(ep
, MDE_NO_SET
)) {
1788 /* No set for this setno - continue */
1792 (void) sprintf(p
, gettext(
1793 "Unable to get set %d information"),
1802 /* If setname is there, set desc should exist. */
1803 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
) {
1804 (void) snprintf(p
, bufsz
, gettext(
1805 "Unable to get set %s desc information"),
1813 /* Only check MN disksets */
1814 if (!MD_MNSET_DESC(sd
)) {
1819 * Return value of 0 is success.
1820 * Return value of -1 means a failure.
1821 * Return value of -2 means set could not be
1822 * joined, but shouldn't cause an error.
1824 * - no drives in set
1825 * - node already joined to set
1826 * Return value of -3 means joined stale set.
1827 * Can't check for all reasons here
1828 * since set isn't locked yet across all
1829 * nodes in the cluster. The call
1830 * to libmeta routine, meta_set_join, will
1831 * lock across the cluster and perform
1834 if ((err
= meta_set_join(sp
, ep
)) == -1) {
1835 /* Print error of diskset join failure */
1836 (void) snprintf(p
, bufsz
,
1837 gettext("Join to diskset %s failed"),
1846 /* Print error of diskset join failure */
1847 (void) snprintf(p
, bufsz
,
1848 gettext("Joined to stale diskset %s"),
1857 md_exit(local_sp
, cumm_err
);
1861 * Code for a specific set is much simpler.
1862 * Error messages don't need extra text since specific setname
1864 * Don't need to lock the local set, just the specific set given.
1866 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
1868 md_exit(local_sp
, 1);
1872 * Fail command if meta_set_join returns -1.
1874 * Return of 0 means that node joined set.
1876 * Return of -2 means that node was unable to
1877 * join a set since that set had no drives
1878 * or that had already joined the set. No
1879 * need to fail the command for these reasons.
1881 * Return of -3 means that set is stale.
1882 * Return a value of 66 to historically match traditional disksets.
1884 if ((err
= meta_set_join(sp
, ep
)) == -1) {
1885 mde_perror(&status
, "");
1886 md_exit(local_sp
, 1);
1890 /* Print error of diskset join failure */
1891 (void) snprintf(p
, bufsz
,
1892 gettext("Joined to stale diskset %s"),
1894 mde_perror(&status
, "");
1895 md_exit(local_sp
, 66);
1898 md_exit(local_sp
, 0);
1902 * Withdraws a node from a specific set or from all multinode disksets known
1903 * by this node. If set is specified then caller should have verified
1904 * that the set is a multinode diskset.
1906 * If an error occurs, metaset exits with a 1.
1907 * If there is no error, metaset exits with a 0.
1910 parse_withdrawset(int argc
, char **argv
)
1913 mdsetname_t
*sp
= NULL
, *local_sp
= NULL
;
1914 char *sname
= MD_LOCAL_NAME
;
1915 md_error_t status
= mdnullerror
;
1916 md_error_t
*ep
= &status
;
1920 set_t max_sets
, setno
;
1921 int err
, cumm_err
= 0;
1924 bufsz
= sizeof (buf
);
1925 /* reset and parse args */
1928 while ((c
= getopt(argc
, argv
, "Ms:w")) != -1) {
1938 usage(sp
, gettext("unknown options"));
1946 usage(sp
, gettext("too many args"));
1949 * If no setname option was used, then withdraw from all disksets
1950 * that this node knows about.
1952 * Additional text is added to the error messages during
1953 * this section of code in order to help the user understand
1954 * why the 'withdraw from all sets' failed and which set caused
1959 * Hold local set lock throughout this call to keep
1960 * other actions from interfering (such as creating a new
1963 if ((local_sp
= metasetname(MD_LOCAL_NAME
, ep
)) == NULL
) {
1968 if (meta_lock(local_sp
, TRUE
, ep
) != 0) {
1970 md_exit(local_sp
, 1);
1973 if (strcmp(sname
, MD_LOCAL_NAME
) == 0) {
1975 * If no set name is given, then walk through all sets
1976 * on this node which could include:
1978 * - traditional disksets
1979 * - non-existent disksets
1980 * Attempt to withdraw from the MN disksets.
1981 * If the withdraw of one set fails, print out an error
1982 * message about that set and continue the walk.
1984 if ((max_sets
= get_max_sets(ep
)) == 0) {
1986 md_exit(local_sp
, 1);
1989 /* Start walking through all possible disksets */
1990 for (setno
= 1; setno
< max_sets
; setno
++) {
1991 if ((sp
= metasetnosetname(setno
, ep
)) == NULL
) {
1992 if (mdiserror(ep
, MDE_NO_SET
)) {
1993 /* No set for this setno - continue */
1997 (void) sprintf(p
, gettext(
1998 "Unable to get set %d information"),
2007 /* If setname is there, set desc should exist. */
2008 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
) {
2009 (void) snprintf(p
, bufsz
, gettext(
2010 "Unable to get set %s desc information"),
2018 /* Only check MN disksets */
2019 if (!MD_MNSET_DESC(sd
)) {
2024 * Return value of 0 is success.
2025 * Return value of -1 means a failure.
2026 * Return value of -2 means set could not be
2027 * withdrawn from, but this shouldn't cause
2028 * an error. Reasons would be:
2029 * - no drives in set
2030 * - node already withdrawn from set
2031 * Can't check for all reasons here
2032 * since set isn't locked yet across all
2033 * nodes in the cluster. The call
2034 * to libmeta routine, meta_set_withdraw, will
2035 * lock across the cluster and perform
2038 if ((err
= meta_set_withdraw(sp
, ep
)) == -1) {
2039 /* Print error of diskset withdraw failure */
2040 (void) snprintf(p
, bufsz
,
2041 gettext("Withdraw from diskset %s failed"),
2056 md_exit(local_sp
, cumm_err
);
2061 * Code for a specific set is much simpler.
2062 * Error messages don't need extra text since specific setname
2064 * Don't need to lock the local set, just the specific set given.
2066 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
2068 md_exit(local_sp
, 1);
2072 * Fail command if meta_set_withdraw returns -1.
2074 * Return of 0 means that node withdrew from set.
2076 * Return of -2 means that node was unable to
2077 * withdraw from a set since that set had no drives
2078 * or node was not joined to set. No
2079 * need to fail the command for these reasons.
2081 if (meta_set_withdraw(sp
, ep
) == -1) {
2082 mde_perror(&status
, "");
2083 md_exit(local_sp
, 1);
2086 md_exit(local_sp
, 0);
2090 parse_cluster(int argc
, char **argv
, int multi_node
)
2092 int c
, error
, new_argc
, x
;
2093 enum cluster_cmd cmd
= ccnotspecified
;
2094 char *hostname
= SDSSC_PROXY_PRIMARY
;
2095 char *argument
= NULL
;
2096 char *sname
= MD_LOCAL_NAME
;
2097 char primary_node
[SDSSC_NODE_NAME_LEN
];
2098 char **new_argv
= NULL
;
2100 mdsetname_t
*sp
= NULL
;
2101 md_error_t status
= mdnullerror
;
2102 md_error_t
*ep
= &status
;
2104 /* reset and parse args */
2107 while ((c
= getopt(argc
, argv
, "C:s:h:ftu:yr")) != -1) {
2110 if (cmd
!= ccnotspecified
) {
2115 if (strcmp(argument
, "disksin") == 0) {
2116 cmd
= clusterdisksin
;
2117 } else if (strcmp(argument
, "version") == 0) {
2118 cmd
= clusterversion
;
2119 } else if (strcmp(argument
, "release") == 0) {
2120 cmd
= clusterrelease
;
2121 } else if (strcmp(argument
, "take") == 0) {
2123 } else if (strcmp(argument
, "proxy") == 0) {
2125 } else if (strcmp(argument
, "purge") == 0) {
2153 /* Now call the appropriate command function. */
2155 case clusterversion
:
2156 printclusterversion();
2159 case clusterdisksin
:
2160 if (printdisksin(sname
, ep
)) {
2165 case clusterrelease
:
2168 "-C release is not allowed on multi-owner"
2171 parse_releaseset(argc
, argv
);
2177 "-C take is not allowed on multi-owner disksets"));
2179 parse_takeset(argc
, argv
);
2185 "-C proxy is not allowed on multi-owner disksets"));
2188 if ((new_argv
= calloc(argc
, sizeof (char *))) == NULL
) {
2189 (void) printf(gettext("Out of memory\n"));
2195 (void) memset(primary_node
, '\0', SDSSC_NODE_NAME_LEN
);
2197 for (x
= 0; x
< argc
; x
++) {
2198 if (strcmp(argv
[x
], "-C") == 0) {
2201 * Need to skip the '-C proxy' args so
2202 * just increase x by one and the work is
2207 *np
++ = strdup(argv
[x
]);
2212 switch (sdssc_get_primary_host(sname
, primary_node
,
2213 SDSSC_NODE_NAME_LEN
)) {
2218 case SDSSC_NO_SERVICE
:
2219 if (hostname
!= SDSSC_PROXY_PRIMARY
) {
2220 (void) strlcpy(primary_node
, hostname
,
2221 SDSSC_NODE_NAME_LEN
);
2226 if (sdssc_cmd_proxy(new_argc
, new_argv
,
2227 primary_node
[0] == '\0' ? SDSSC_PROXY_PRIMARY
:
2228 primary_node
, &error
) == SDSSC_PROXY_DONE
) {
2231 (void) printf(gettext(
2232 "Couldn't proxy command\n"));
2238 parse_purge(argc
, argv
);
2249 * parse args and do it
2252 main(int argc
, char *argv
[])
2254 enum metaset_cmd cmd
= notspecified
;
2255 md_error_t status
= mdnullerror
;
2256 md_error_t
*ep
= &status
;
2257 mdsetname_t
*sp
= NULL
;
2258 char *hostname
= SDSSC_PROXY_PRIMARY
;
2259 char *sname
= MD_LOCAL_NAME
;
2260 char *auto_take_option
= NULL
;
2261 char primary_node
[SDSSC_NODE_NAME_LEN
];
2263 int auto_take
= FALSE
;
2270 * Get the locale set up before calling any other routines
2271 * with messages to ouput. Just in case we're not in a build
2272 * environment, make sure that TEXT_DOMAIN gets set to
2275 #if !defined(TEXT_DOMAIN)
2276 #define TEXT_DOMAIN "SYS_TEST"
2278 (void) setlocale(LC_ALL
, "");
2279 (void) textdomain(TEXT_DOMAIN
);
2281 sdssc_res
= sdssc_bind_library();
2282 if (sdssc_res
== SDSSC_ERROR
) {
2283 (void) printf(gettext(
2284 "%s: Interface error with libsds_sc.so\n"), argv
[0]);
2289 if (md_init(argc
, argv
, 0, 1, ep
) != 0) {
2298 * NOTE: The "C" option is strictly for cluster use. it is not
2299 * and should not be documented for the customer. - JST
2301 while ((c
= getopt(argc
, argv
, "C:MaA:bdfh:jl:Lm:oPqrs:tu:wy?"))
2309 if (optarg
== NULL
|| !(strcmp(optarg
, "enable") == 0 ||
2310 strcmp(optarg
, "disable") == 0))
2312 "-A: enable or disable must be specified"));
2313 auto_take_option
= optarg
;
2316 if (cmd
!= notspecified
) {
2318 "conflicting options"));
2323 if (cmd
!= notspecified
) {
2325 "conflicting options"));
2330 if (cmd
!= notspecified
) {
2332 "conflicting options"));
2336 case 'C': /* cluster commands */
2337 if (cmd
!= notspecified
) {
2338 md_exit(sp
, -1); /* conflicting options */
2348 if (cmd
!= notspecified
) {
2350 "conflicting options"));
2361 if (cmd
!= notspecified
) {
2363 "conflicting options"));
2368 if (cmd
!= notspecified
) {
2370 "conflicting options"));
2375 if (cmd
!= notspecified
) {
2377 "conflicting options"));
2382 if (cmd
!= notspecified
) {
2384 "conflicting options"));
2392 if (cmd
!= notspecified
) {
2394 "conflicting options"));
2401 if (cmd
!= notspecified
) {
2403 "conflicting options"));
2414 if (cmd
== cluster
) { /* cluster is silent */
2418 "unknown command"));
2423 /* check if suncluster is installed and -A enable specified */
2424 if (auto_take
&& sdssc_res
!= SDSSC_NOT_BOUND
&&
2425 strcmp(auto_take_option
, "enable") == 0) {
2427 "cannot enable auto-take when SunCluster is installed\n"));
2432 * At this point we know that if the -A enable option is specified
2433 * for an auto-take diskset that SC is not installed on the machine, so
2434 * all of the sdssc calls will just be no-ops.
2438 if (cmd
== notspecified
&& auto_take
== FALSE
) {
2439 parse_printset(argc
, argv
);
2443 if (meta_check_root(ep
) != 0) {
2449 if (meta_setup_db_locations(ep
) != 0) {
2455 * If sname is a diskset - check for multi_node.
2456 * It is possible for sname to not exist.
2458 if (strcmp(sname
, MD_LOCAL_NAME
)) {
2459 if ((sp
= metasetname(sname
, ep
)) != NULL
) {
2460 /* Set exists - check for MN diskset */
2461 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
) {
2465 if (MD_MNSET_DESC(sd
)) {
2467 * If a MN diskset always set multi_node
2468 * regardless of whether the -M option was
2469 * used or not (mflag).
2474 * If a traditional diskset, mflag must
2479 "-M option only allowed "
2480 "on multi-owner diskset"));
2485 * Set name does not exist, set multi_node
2486 * based on -M option.
2494 if (auto_take
&& multi_node
) {
2495 /* Can't mix multinode and auto-take on a diskset */
2497 gettext("-A option not allowed on multi-owner diskset"));
2501 * MN disksets don't use DCS clustering services, so
2502 * do not get primary_node for MN diskset since no command
2503 * proxying is done to Primary cluster node. Do not proxy
2504 * MN diskset commands of join and withdraw when issued without
2506 * For traditional disksets: proxy all commands except a take
2507 * and release. Use first host listed as the host to send the
2508 * command to if there isn't already a primary
2510 if (strcmp(sname
, MD_LOCAL_NAME
) && (multi_node
== 0) &&
2511 (cmd
!= take
) && (cmd
!= release
) &&
2512 (cmd
!= cluster
) && (cmd
!= join
) &&
2513 (cmd
!= withdraw
) && (cmd
!= purge
)) {
2514 stat
= sdssc_get_primary_host(sname
, primary_node
,
2515 SDSSC_NODE_NAME_LEN
);
2520 case SDSSC_NO_SERVICE
:
2521 if (hostname
!= SDSSC_PROXY_PRIMARY
) {
2522 (void) strlcpy(primary_node
, hostname
,
2523 SDSSC_NODE_NAME_LEN
);
2525 (void) memset(primary_node
, '\0',
2526 SDSSC_NODE_NAME_LEN
);
2532 * We've got a complicated decision here regarding
2533 * the hostname. If we didn't get a primary host
2534 * and a host name wasn't supplied on the command line
2535 * then we need to revert to SDSSC_PROXY_PRIMARY. Otherwise
2536 * use what's been found.
2538 if (sdssc_cmd_proxy(argc
, argv
,
2539 primary_node
[0] == '\0' ?
2540 SDSSC_PROXY_PRIMARY
: primary_node
,
2541 &error
) == SDSSC_PROXY_DONE
) {
2546 /* cluster-specific commands */
2547 if (cmd
== cluster
) {
2548 parse_cluster(argc
, argv
, multi_node
);
2552 /* join MultiNode diskset */
2555 * If diskset specified, verify that it exists
2556 * and is a multinode diskset.
2558 if (strcmp(sname
, MD_LOCAL_NAME
)) {
2559 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
2566 "-j option only allowed on "
2567 "multi-owner diskset"));
2571 * Start mddoors daemon here.
2572 * mddoors itself takes care there will be only one
2573 * instance running, so starting it twice won't hurt
2575 (void) pclose(popen("/usr/lib/lvm/mddoors", "w"));
2576 parse_joinset(argc
, argv
);
2580 /* withdraw from MultiNode diskset */
2581 if (cmd
== withdraw
) {
2583 * If diskset specified, verify that it exists
2584 * and is a multinode diskset.
2586 if (strcmp(sname
, MD_LOCAL_NAME
)) {
2587 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
2594 "-w option only allowed on "
2595 "multi-owner diskset"));
2598 parse_withdrawset(argc
, argv
);
2602 /* must have set for everything else */
2603 if (strcmp(sname
, MD_LOCAL_NAME
) == 0)
2604 usage(sp
, gettext("setname must be specified"));
2606 /* add hosts or drives */
2609 * In the multi node case start mddoors daemon.
2610 * mddoors itself takes care there will be
2611 * only one instance running, so starting it twice won't hurt
2614 (void) pclose(popen("/usr/lib/lvm/mddoors", "w"));
2617 parse_add(argc
, argv
);
2621 /* re-balance the replicas */
2622 if (cmd
== balance
) {
2623 parse_balance(argc
, argv
);
2627 /* delete hosts or drives */
2628 if (cmd
== delete) {
2629 parse_del(argc
, argv
);
2633 /* check ownership */
2634 if (cmd
== isowner
) {
2635 parse_isowner(argc
, argv
);
2639 /* purge the diskset */
2641 parse_purge(argc
, argv
);
2645 /* query for data marks */
2647 parse_query(argc
, argv
);
2651 /* release ownership */
2652 if (cmd
== release
) {
2654 /* Can't release multinode diskset */
2656 "-r option not allowed on multi-owner diskset"));
2658 parse_releaseset(argc
, argv
);
2663 /* take ownership */
2666 /* Can't take multinode diskset */
2668 "-t option not allowed on multi-owner diskset"));
2670 parse_takeset(argc
, argv
);
2675 /* take ownership of auto-take sets */
2677 parse_autotake(argc
, argv
);