4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * Metadevice database utility.
34 #include <sys/lvm/md_mddb.h>
37 enum mddb_cmd
{none
, attach
, detach
, patch
, infolong
, infoshort
};
39 extern int procsigs(int block
, sigset_t
*oldsigs
, md_error_t
*ep
);
47 if ((string
!= NULL
) && (*string
!= '\0'))
48 md_eprintf("%s\n", string
);
50 (void) fprintf(stderr
, gettext(
51 "usage: %s [-s setname] -a [options] mddbnnn\n"
52 " %s [-s setname] -a [options] device ...\n"
53 " %s [-s setname] -d [options] mddbnnn\n"
54 " %s [-s setname] -d [options] device ...\n"
55 " %s [-s setname] -i \n"
56 " %s -p [options] [ mddb.cf-file ]\n"
58 "-c count number of replicas (for use with -a only)\n"
59 "-f force adding or deleting of replicas\n"
60 "-k filename alternate /etc/system file\n"
61 "-l length specify size of replica (for use with -a only)\n"),
62 myname
, myname
, myname
, myname
, myname
, myname
);
64 md_exit(sp
, (string
== NULL
) ? 0 : 1);
77 if ((np
= metaname(&sp
, name
, LOGICAL_DEVICE
, ep
)) == NULL
)
80 return (metanamelist_append(nlp
, np
));
94 md_tab_t
*tabp
= NULL
;
95 md_tab_line_t
*linep
= NULL
;
103 if ((tabp
= meta_tab_parse(NULL
, ep
)) == NULL
) {
104 if (! mdissyserror(ep
, ENOENT
))
110 if ((linep
= meta_tab_find(sp
, tabp
, tabname
, TAB_MDDB
)) == NULL
) {
111 (void) mdsyserror(ep
, ENOENT
, tabname
);
116 context
= linep
->context
;
121 while ((c
= getopt(argc
, argv
, "c:l:")) != -1) {
124 if (sscanf(optarg
, "%d", dbcnt
) != 1) {
125 md_eprintf("%s: %s\n",
126 context
, gettext("bad format"));
132 if (sscanf(optarg
, "%d", dbsize
) != 1) {
133 md_eprintf("%s: %s\n",
134 context
, gettext("bad format"));
137 *default_size
= FALSE
;
146 for (; (argc
> 0); --argc
, ++argv
) {
147 char *token
= argv
[0];
149 if (make_dbname(sp
, nlp
, token
, ep
) == NULL
) {
150 metafreenamelist(*nlp
);
156 /* cleanup, return list */
165 * built list of all devices which are to be detached
167 static mdnamelist_t
*
176 int dbsize
, dbcnt
, default_size
;
177 mdnamelist_t
*dbnlp
= NULL
;
179 for (i
= 0; i
< argc
; i
++) {
180 if (strncmp(argv
[i
], "mddb", 4) == 0) {
181 if (get_dbnames_fromfile(sp
, &dbnlp
, argv
[i
],
182 &dbsize
, &dbcnt
, &default_size
, ep
) == NULL
) {
183 /* don't freelist here - already been done */
188 if (make_dbname(sp
, &dbnlp
, argv
[i
], ep
) == NULL
) {
189 metafreenamelist(dbnlp
);
199 * built the next list of devices which are to be attached
200 * that have the same size and count of replicas.
202 static mdnamelist_t
*
215 mdnamelist_t
*dbnlp
= NULL
;
217 for (i
= *arg_index
; i
< argc
; i
++) {
218 if (strncmp(argv
[i
], "mddb", 4) == 0) {
220 * If we have stuff in the namelist
221 * return it before processing the mddb entry.
227 if (get_dbnames_fromfile(sp
, &dbnlp
, argv
[i
],
228 dbsize
, dbcnt
, default_size
, ep
) == NULL
) {
229 /* don't freelist here - already been done */
235 if (make_dbname(sp
, &dbnlp
, argv
[i
], ep
) == NULL
) {
236 metafreenamelist(dbnlp
);
257 md_error_t xep
= mdnullerror
;
258 mdnamelist_t
*dbnlp
= NULL
;
259 int dbsize
= MD_DBSIZE
;
260 int maxblks
= MDDB_MAXBLKS
;
261 int minblks
= MDDB_MINBLKS
;
263 mdforceopts_t force
= MDFORCE_NONE
;
265 char *sysfilename
= NULL
;
266 int default_size
= TRUE
;
270 int suspend1_flag
= 0;
272 /* reset and parse args */
275 while ((c
= getopt(argc
, argv
, "ac:dfk:pl:s:")) != -1) {
280 if (sscanf(optarg
, "%d", &dbcnt
) != 1) {
281 md_eprintf("%s: %s\n",
282 optarg
, gettext("bad format"));
289 force
= MDFORCE_LOCAL
;
292 sysfilename
= optarg
;
295 if (sscanf(optarg
, "%d", &dbsize
) != 1) {
296 md_eprintf("%s: %s\n",
297 optarg
, gettext("bad format"));
300 default_size
= FALSE
;
312 * If it is a multinode diskset, use appropriate metadb size.
314 if (! metaislocalset(sp
)) {
315 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
)
318 if (MD_MNSET_DESC(sd
)) {
319 maxblks
= MDDB_MN_MAXBLKS
;
320 minblks
= MDDB_MN_MINBLKS
;
322 dbsize
= MD_MN_DBSIZE
;
326 if (dbsize
> maxblks
)
327 usage(sp
, gettext("size (-l) is too big"));
330 if (dbsize
< minblks
)
331 usage(sp
, gettext("size (-l) is too small"));
335 "count (-c) must be 1 or more"));
342 "no devices specified to attach or detach"));
345 if (! metaislocalset(sp
)) {
347 if (MD_MNSET_DESC(sd
)) {
348 md_error_t xep
= mdnullerror
;
351 /* Make sure we are blocking all signals */
352 if (procsigs(TRUE
, &sigs
, &xep
) < 0)
356 * Lock out other metaset or metadb commands
357 * across the diskset.
359 nd
= sd
->sd_nodelist
;
361 if ((force
& MDFORCE_LOCAL
) &&
362 strcmp(nd
->nd_nodename
, mynode()) != 0) {
367 if (!(nd
->nd_flags
& MD_MN_NODE_ALIVE
)) {
372 if (clnt_lock_set(nd
->nd_nodename
, sp
, ep
)) {
379 * Lock out other meta* commands by suspending
380 * class 1 messages across the diskset.
382 nd
= sd
->sd_nodelist
;
384 if (!(nd
->nd_flags
& MD_MN_NODE_ALIVE
)) {
389 if (clnt_mdcommdctl(nd
->nd_nodename
,
390 COMMDCTL_SUSPEND
, sp
, MD_MSG_CLASS1
,
391 MD_MSCF_NO_FLAGS
, ep
)) {
399 /* Lock the set on current set members */
400 for (i
= 0; i
< MD_MAXSIDES
; i
++) {
401 /* Skip empty slots */
402 if (sd
->sd_nodes
[i
][0] == '\0')
405 if ((force
& MDFORCE_LOCAL
) &&
406 strcmp(sd
->sd_nodes
[i
], mynode()) != 0)
409 if (clnt_lock_set(sd
->sd_nodes
[i
], sp
, ep
)) {
416 force
|= MDFORCE_SET_LOCKED
;
417 options
|= MDCHK_SET_LOCKED
;
421 if ((dbnlp
= build_a_namelist(sp
, argc
, argv
, ep
)) == NULL
) {
426 rval
= meta_db_detach(sp
, dbnlp
, force
, sysfilename
, ep
);
428 metafreenamelist(dbnlp
);
434 int saved_dbsize
= dbsize
;
435 int saved_dbcnt
= dbcnt
;
436 int saved_default_size
= default_size
;
438 if (force
& MDFORCE_LOCAL
)
439 options
|= MDCHK_SET_FORCE
;
442 if ((nblks
= meta_db_minreplica(sp
, ep
)) < 0)
445 * Loop through build a new namelist
446 * for each "mddb" entry or the devices list
447 * on the command line. This allows each "mddb"
448 * entry to have unique dbsize and dbcnt.
450 while (arg_index
< argc
) {
452 dbnlp
= build_next_namelist(sp
, argc
, argv
,
453 &arg_index
, &dbsize
, &dbcnt
, &default_size
, ep
);
459 * If using the default size,
460 * then let's adjust the default to the minimum
461 * size currently in use.
463 if (default_size
&& (nblks
> 0))
464 dbsize
= nblks
; /* adjust replica size */
466 if (dbsize
> maxblks
)
467 usage(sp
, gettext("size (-l) is too big"));
469 rval
= meta_db_attach(sp
, dbnlp
, options
, NULL
, dbcnt
,
470 dbsize
, sysfilename
, ep
);
472 metafreenamelist(dbnlp
);
475 dbsize
= saved_dbsize
;
477 default_size
= saved_default_size
;
479 metafreenamelist(dbnlp
);
484 if (! metaislocalset(sp
)) {
485 cl_sk
= cl_get_setkey(sp
->setno
, sp
->setname
);
486 if (MD_MNSET_DESC(sd
)) {
488 * Unlock diskset by resuming
489 * class 1 messages across the diskset.
492 nd
= sd
->sd_nodelist
;
500 if (clnt_mdcommdctl(nd
->nd_nodename
,
503 MD_MSCF_NO_FLAGS
, &xep
)) {
504 mde_perror(&xep
, "");
510 nd
= sd
->sd_nodelist
;
512 if ((force
& MDFORCE_LOCAL
) &&
513 strcmp(nd
->nd_nodename
, mynode()) != 0) {
517 if (!(nd
->nd_flags
& MD_MN_NODE_ALIVE
)) {
522 if (clnt_unlock_set(nd
->nd_nodename
, cl_sk
,
528 for (i
= 0; i
< MD_MAXSIDES
; i
++) {
529 /* Skip empty slots */
530 if (sd
->sd_nodes
[i
][0] == '\0')
533 if ((force
& MDFORCE_LOCAL
) &&
534 strcmp(sd
->sd_nodes
[i
], mynode()) != 0)
537 if (clnt_unlock_set(sd
->sd_nodes
[i
], cl_sk
,
557 md_replicalist_t
*rlp
= NULL
;
558 md_replicalist_t
*rl
;
561 char *unk_str
= NULL
;
563 /* get list of replicas, quit if none */
564 if (metareplicalist(sp
, (MD_BASICNAME_OK
| PRINT_FAST
), &rlp
, ep
) < 0)
566 else if (rlp
== NULL
)
570 (void) printf("\t%5.5s\t\t%9.9s\t%11.11s\n", gettext("flags"),
571 gettext("first blk"), gettext("block count"));
574 unk_str
= gettext("unknown");
575 for (rl
= rlp
; rl
!= NULL
; rl
= rl
->rl_next
) {
578 for (i
= 0; i
< MDDB_FLAGS_LEN
; i
++) {
579 if (r
->r_flags
& (1 << i
))
580 (void) putchar(MDDB_FLAGS_STRING
[i
]);
585 if ((r
->r_blkno
== -1) && (r
->r_nblk
== -1)) {
586 (void) printf("\t%7.7s\t\t%7.7s\t", unk_str
, unk_str
);
587 } else if (r
->r_nblk
== -1) {
588 (void) printf("\t%ld\t\t%7.7s\t", r
->r_blkno
, unk_str
);
590 (void) printf("\t%ld\t\t%ld\t", r
->r_blkno
, r
->r_nblk
);
593 (void) printf("\t%s\n", r
->r_namep
->bname
);
597 metafreereplicalist(rlp
);
599 if (cmd
== infoshort
)
605 (void) printf(gettext(
606 " r - replica does not have device relocation information\n"
607 " o - replica active prior to last mddb configuration change\n"
608 " u - replica is up to date\n"
609 " l - locator for this replica was read successfully\n"
610 " c - replica's location was in %s\n"
611 " p - replica's location was patched in kernel\n"
612 " m - replica is master, this is replica selected as input\n"
613 " t - tagged data is associated with the replica\n"
614 " W - replica has device write errors\n"
615 " a - replica is active, commits are occurring to this replica\n"
616 " M - replica had problem with master blocks\n"
617 " D - replica had problem with data blocks\n"
618 " F - replica had format problems\n"
619 " S - replica is too small to hold current data base\n"
620 " R - replica had device read errors\n"
621 " B - tagged data associated with the replica is not valid\n"),
627 main(int argc
, char **argv
)
629 mdsetname_t
*sp
= NULL
;
631 enum mddb_cmd cmd
= none
;
632 char *sname
= MD_LOCAL_NAME
;
633 char *cffilename
= NULL
;
634 char *sysfilename
= NULL
;
635 int forceflg
= FALSE
;
636 mdchkopts_t options
= 0;
637 md_error_t status
= mdnullerror
;
638 md_error_t
*ep
= &status
;
644 * Get the locale set up before calling any other routines
645 * with messages to ouput. Just in case we're not in a build
646 * environment, make sure that TEXT_DOMAIN gets set to
649 #if !defined(TEXT_DOMAIN)
650 #define TEXT_DOMAIN "SYS_TEST"
652 (void) setlocale(LC_ALL
, "");
653 (void) textdomain(TEXT_DOMAIN
);
655 if (sdssc_bind_library() == SDSSC_OKAY
)
656 if (sdssc_cmd_proxy(argc
, argv
, SDSSC_PROXY_PRIMARY
,
657 &error
) == SDSSC_PROXY_DONE
)
665 if (md_init(argc
, argv
, 0, 1, ep
) != 0) {
673 while ((c
= getopt(argc
, argv
, "ac:dfhik:l:ps:?")) != -1) {
687 usage(sp
, (char *)0);
693 sysfilename
= optarg
;
709 usage(sp
, gettext("unknown command"));
715 /* get set context */
716 if ((sp
= metasetname(sname
, ep
)) == NULL
) {
722 if (cmd
== infoshort
|| cmd
== infolong
) {
725 "too many arguments"));
727 if (info(sp
, cmd
, 1, 1, ep
)) {
732 if (meta_smf_isonline(meta_smf_getmask(), ep
) == 0) {
740 if (meta_check_root(ep
) != 0) {
745 if (! metaislocalset(sp
)) {
746 if ((sd
= metaget_setdesc(sp
, ep
)) == NULL
) {
750 if (MD_MNSET_DESC(sd
)) {
756 * Adjust lock for traditional and local diskset.
758 * A MN diskset does not use the set meta_lock but instead
759 * uses the clnt_lock of rpc.metad and the suspend/resume
760 * feature of the rpc.mdcommd. Can't use set meta_lock since
761 * class 1 messages are grabbing this lock and if this thread
762 * is holding the set meta_lock then no rpc.mdcommd suspend
765 if ((!multi_node
) && (meta_lock(sp
, TRUE
, ep
) != 0)) {
770 /* check for ownership */
771 if (meta_check_ownership(sp
, ep
) != 0) {
776 /* snarf MDDB locations */
778 if (meta_setup_db_locations(ep
) != 0) {
779 if (! mdismddberror(ep
, MDE_DB_STALE
)) {
780 if (forceflg
== FALSE
) {
784 options
= MDCHK_ALLOW_NODBS
;
790 /* patch MDDB locations */
792 if (optind
< (argc
- 1)) {
794 "too many arguments to -p"));
797 if (optind
== (argc
- 1))
798 cffilename
= argv
[optind
];
800 if (metaislocalset(sp
)) {
801 if (meta_db_patch(sysfilename
, cffilename
, 1, ep
)) {
808 /* add/delete replicas */
809 if (cmd
== attach
|| cmd
== detach
) {
810 if (chngdb(sp
, cmd
, argc
, argv
, options
, ep
)) {