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
5*2150Sjeanm * Common Development and Distribution License (the "License").
6*2150Sjeanm * 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*2150Sjeanm * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate * Service Management Facility (SMF) interfaces.
300Sstevel@tonic-gate */
310Sstevel@tonic-gate
320Sstevel@tonic-gate #include <stdio.h>
330Sstevel@tonic-gate #include <libscf.h>
340Sstevel@tonic-gate #include <meta.h>
350Sstevel@tonic-gate
360Sstevel@tonic-gate static void enable(char *svc_names[], md_error_t *ep);
370Sstevel@tonic-gate static void disable(char *svc_names[], md_error_t *ep);
380Sstevel@tonic-gate static int enabled(char *svc_name);
390Sstevel@tonic-gate static int online(char *svc_names[], char **names);
400Sstevel@tonic-gate static void wait_online(char *svc_names[]);
410Sstevel@tonic-gate static int is_online(char *svc_name);
420Sstevel@tonic-gate
430Sstevel@tonic-gate static char
440Sstevel@tonic-gate *svm_core_svcs[] = {
450Sstevel@tonic-gate "system/metainit:default",
46*2150Sjeanm "system/metasync:default",
470Sstevel@tonic-gate "system/mdmonitor:default",
480Sstevel@tonic-gate "network/rpc/meta:default",
490Sstevel@tonic-gate NULL
500Sstevel@tonic-gate };
510Sstevel@tonic-gate
520Sstevel@tonic-gate static char
530Sstevel@tonic-gate *svm_diskset_svcs[] = {
540Sstevel@tonic-gate "network/rpc/metamed:default",
550Sstevel@tonic-gate "network/rpc/metamh:default",
560Sstevel@tonic-gate NULL
570Sstevel@tonic-gate };
580Sstevel@tonic-gate
590Sstevel@tonic-gate static char
600Sstevel@tonic-gate *svm_mn_diskset_svcs[] = {
610Sstevel@tonic-gate "network/rpc/mdcomm:default",
620Sstevel@tonic-gate NULL
630Sstevel@tonic-gate };
640Sstevel@tonic-gate
650Sstevel@tonic-gate /*
660Sstevel@tonic-gate * Enable the specified SVM services through the SMF.
670Sstevel@tonic-gate */
680Sstevel@tonic-gate int
meta_smf_enable(uint_t flags,md_error_t * ep)690Sstevel@tonic-gate meta_smf_enable(uint_t flags, md_error_t *ep)
700Sstevel@tonic-gate {
710Sstevel@tonic-gate if (flags & META_SMF_CORE) {
720Sstevel@tonic-gate enable(svm_core_svcs, ep);
730Sstevel@tonic-gate wait_online(svm_core_svcs);
740Sstevel@tonic-gate }
750Sstevel@tonic-gate
760Sstevel@tonic-gate if (flags & META_SMF_DISKSET) {
770Sstevel@tonic-gate enable(svm_diskset_svcs, ep);
780Sstevel@tonic-gate wait_online(svm_diskset_svcs);
790Sstevel@tonic-gate }
800Sstevel@tonic-gate
810Sstevel@tonic-gate if (flags & META_SMF_MN_DISKSET) {
820Sstevel@tonic-gate enable(svm_mn_diskset_svcs, ep);
830Sstevel@tonic-gate wait_online(svm_mn_diskset_svcs);
840Sstevel@tonic-gate }
850Sstevel@tonic-gate
860Sstevel@tonic-gate if (ep != NULL)
870Sstevel@tonic-gate return ((mdisok(ep)) ? 0 : -1);
880Sstevel@tonic-gate else
890Sstevel@tonic-gate return (0);
900Sstevel@tonic-gate }
910Sstevel@tonic-gate
920Sstevel@tonic-gate /*
930Sstevel@tonic-gate * Disable the specified SVM services through the SMF.
940Sstevel@tonic-gate */
950Sstevel@tonic-gate int
meta_smf_disable(uint_t flags,md_error_t * ep)960Sstevel@tonic-gate meta_smf_disable(uint_t flags, md_error_t *ep)
970Sstevel@tonic-gate {
980Sstevel@tonic-gate if (flags & META_SMF_CORE) {
990Sstevel@tonic-gate disable(svm_core_svcs, ep);
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate if (flags & META_SMF_DISKSET) {
1030Sstevel@tonic-gate disable(svm_diskset_svcs, ep);
1040Sstevel@tonic-gate }
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate if (flags & META_SMF_MN_DISKSET) {
1070Sstevel@tonic-gate disable(svm_mn_diskset_svcs, ep);
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate if (ep != NULL)
1110Sstevel@tonic-gate return ((mdisok(ep)) ? 0 : -1);
1120Sstevel@tonic-gate else
1130Sstevel@tonic-gate return (0);
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate /*
1170Sstevel@tonic-gate * Determine if desired services are online. If all services in the
1180Sstevel@tonic-gate * classes specified by flags are online, 1 is returned. Otherwise
1190Sstevel@tonic-gate * 0 is returned.
1200Sstevel@tonic-gate */
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate int
meta_smf_isonline(uint_t flags,md_error_t * ep)1230Sstevel@tonic-gate meta_smf_isonline(uint_t flags, md_error_t *ep)
1240Sstevel@tonic-gate {
1250Sstevel@tonic-gate int ret = 1;
1260Sstevel@tonic-gate char *names = NULL;
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate if (flags & META_SMF_CORE) {
1290Sstevel@tonic-gate if (online(svm_core_svcs, &names) == 0)
1300Sstevel@tonic-gate ret = 0;
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate if (flags & META_SMF_DISKSET) {
1330Sstevel@tonic-gate if (online(svm_diskset_svcs, &names) == 0)
1340Sstevel@tonic-gate ret = 0;
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate if (flags & META_SMF_MN_DISKSET) {
1370Sstevel@tonic-gate if (online(svm_mn_diskset_svcs, &names) == 0)
1380Sstevel@tonic-gate ret = 0;
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate if (ret == 0) {
1420Sstevel@tonic-gate (void) mderror(ep, MDE_SMF_NO_SERVICE, names);
1430Sstevel@tonic-gate Free(names);
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate return (ret);
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate /*
1500Sstevel@tonic-gate * Return a bitmask of the META_SMF_* flags indicating which services should be
1510Sstevel@tonic-gate * online given the current SVM configuration.
1520Sstevel@tonic-gate */
1530Sstevel@tonic-gate int
meta_smf_getmask()1540Sstevel@tonic-gate meta_smf_getmask()
1550Sstevel@tonic-gate {
1560Sstevel@tonic-gate int mask = 0;
1570Sstevel@tonic-gate mdsetname_t *sp = NULL;
1580Sstevel@tonic-gate mddb_config_t c;
1590Sstevel@tonic-gate md_error_t status = mdnullerror;
1600Sstevel@tonic-gate md_error_t *ep = &status;
1610Sstevel@tonic-gate int max_sets;
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate /*
1640Sstevel@tonic-gate * If there are any local metadbs configured then the core services
1650Sstevel@tonic-gate * are needed.
1660Sstevel@tonic-gate */
1670Sstevel@tonic-gate (void) memset(&c, 0, sizeof (c));
1680Sstevel@tonic-gate c.c_setno = MD_LOCAL_SET;
1690Sstevel@tonic-gate if (metaioctl(MD_DB_GETDEV, &c, &c.c_mde, NULL) != 0 || c.c_dbcnt == 0)
1700Sstevel@tonic-gate return (mask);
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate mask |= META_SMF_CORE;
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate /*
1750Sstevel@tonic-gate * If any disksets configured then the diskset services are needed.
1760Sstevel@tonic-gate * Also check for multi-node sets.
1770Sstevel@tonic-gate */
1780Sstevel@tonic-gate if ((max_sets = get_max_sets(ep)) > 0) {
1790Sstevel@tonic-gate int i;
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate mdclrerror(ep);
1820Sstevel@tonic-gate for (i = 1; i < max_sets; i++) {
1830Sstevel@tonic-gate md_set_desc *sd;
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate if ((sp = metasetnosetname(i, ep)) == NULL) {
1860Sstevel@tonic-gate if (!mdisok(ep) && !mdiserror(ep, MDE_NO_SET) &&
1870Sstevel@tonic-gate !mdismddberror(ep, MDE_NOTENOUGH_DB) &&
1880Sstevel@tonic-gate !mdiserror(ep, MDE_SMF_NO_SERVICE) &&
1890Sstevel@tonic-gate ep->info.errclass != MDEC_RPC) {
1900Sstevel@tonic-gate /*
1910Sstevel@tonic-gate * metad rpc program not registered
1920Sstevel@tonic-gate * can't get diskset info
1930Sstevel@tonic-gate */
1940Sstevel@tonic-gate break;
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate } else {
1980Sstevel@tonic-gate mask |= META_SMF_DISKSET;
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) != NULL) {
2010Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
2020Sstevel@tonic-gate mask |= META_SMF_MN_DISKSET;
2030Sstevel@tonic-gate
2040Sstevel@tonic-gate /*
2050Sstevel@tonic-gate * we don't have to check the
2060Sstevel@tonic-gate * rest of the disksets at this
2070Sstevel@tonic-gate * point
2080Sstevel@tonic-gate */
2090Sstevel@tonic-gate break;
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate }
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate mdclrerror(ep);
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate return (mask);
2190Sstevel@tonic-gate }
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate static void
enable(char * svc_names[],md_error_t * ep)2220Sstevel@tonic-gate enable(char *svc_names[], md_error_t *ep)
2230Sstevel@tonic-gate {
2240Sstevel@tonic-gate int i;
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate for (i = 0; svc_names[i]; i++) {
2270Sstevel@tonic-gate if (!enabled(svc_names[i]))
2280Sstevel@tonic-gate if (smf_enable_instance(svc_names[i], 0) != 0) {
2290Sstevel@tonic-gate if (ep != NULL) {
2300Sstevel@tonic-gate (void) mderror(ep, MDE_SMF_FAIL,
2310Sstevel@tonic-gate svc_names[i]);
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate }
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate static void
disable(char * svc_names[],md_error_t * ep)2380Sstevel@tonic-gate disable(char *svc_names[], md_error_t *ep)
2390Sstevel@tonic-gate {
2400Sstevel@tonic-gate int i;
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate for (i = 0; svc_names[i]; i++) {
2430Sstevel@tonic-gate if (enabled(svc_names[i]))
2440Sstevel@tonic-gate if (smf_disable_instance(svc_names[i], 0) != 0) {
2450Sstevel@tonic-gate if (ep != NULL) {
2460Sstevel@tonic-gate (void) mderror(ep, MDE_SMF_FAIL,
2470Sstevel@tonic-gate svc_names[i]);
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate static int
enabled(char * svc_name)2540Sstevel@tonic-gate enabled(char *svc_name)
2550Sstevel@tonic-gate {
2560Sstevel@tonic-gate scf_simple_prop_t *prop;
2570Sstevel@tonic-gate int rval = 0;
2580Sstevel@tonic-gate
2590Sstevel@tonic-gate prop = scf_simple_prop_get(NULL, svc_name, SCF_PG_GENERAL,
2600Sstevel@tonic-gate SCF_PROPERTY_ENABLED);
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate if (scf_simple_prop_numvalues(prop) == 1) {
2630Sstevel@tonic-gate if (*scf_simple_prop_next_boolean(prop) != 0)
2640Sstevel@tonic-gate rval = 1;
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate scf_simple_prop_free(prop);
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate return (rval);
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate /*
2730Sstevel@tonic-gate * There can be a delay while the RPC services get going. Try to
2740Sstevel@tonic-gate * make sure the RPC daemons are ready to run before we return.
2750Sstevel@tonic-gate * Check 15 times (15 seconds total wait time) and then just
2760Sstevel@tonic-gate * return.
2770Sstevel@tonic-gate */
2780Sstevel@tonic-gate static void
wait_online(char * svc_names[])2790Sstevel@tonic-gate wait_online(char *svc_names[])
2800Sstevel@tonic-gate {
2810Sstevel@tonic-gate int i;
2820Sstevel@tonic-gate char *names = NULL;
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate for (i = 0; i < 15; i++) {
2850Sstevel@tonic-gate if (online(svc_names, &names))
2860Sstevel@tonic-gate break;
2870Sstevel@tonic-gate (void) sleep(1);
2880Sstevel@tonic-gate }
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate if (names != NULL)
2910Sstevel@tonic-gate Free(names);
2920Sstevel@tonic-gate }
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate /*
2950Sstevel@tonic-gate * Check to see if all services in the svc_names are online. If they are
2960Sstevel@tonic-gate * all online 1 is returned, otherwise 0 is returned.
2970Sstevel@tonic-gate */
2980Sstevel@tonic-gate
2990Sstevel@tonic-gate static int
online(char * svc_names[],char ** names)3000Sstevel@tonic-gate online(char *svc_names[], char **names)
3010Sstevel@tonic-gate {
3020Sstevel@tonic-gate int i;
3030Sstevel@tonic-gate int rv = 1;
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate for (i = 0; svc_names[i]; i++) {
3060Sstevel@tonic-gate if (is_online(svc_names[i]) == 0) {
3070Sstevel@tonic-gate int sz;
3080Sstevel@tonic-gate char *p;
3090Sstevel@tonic-gate
3100Sstevel@tonic-gate /*
3110Sstevel@tonic-gate * Need space for the name, the new line, the
3120Sstevel@tonic-gate * tab and the null terminator.
3130Sstevel@tonic-gate */
3140Sstevel@tonic-gate sz = strlen(svc_names[i]) + 3;
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate if (*names == NULL) {
3170Sstevel@tonic-gate p = Malloc(sz);
3180Sstevel@tonic-gate (void) snprintf(p, sz, "\n\t%s", svc_names[i]);
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate } else {
3210Sstevel@tonic-gate /* Add space for existing names */
3220Sstevel@tonic-gate sz += strlen(*names);
3230Sstevel@tonic-gate p = Malloc(sz);
3240Sstevel@tonic-gate (void) snprintf(p, sz, "%s\n\t%s", *names,
3250Sstevel@tonic-gate svc_names[i]);
326113Sgjelinek Free(*names);
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate *names = p;
3300Sstevel@tonic-gate rv = 0;
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate }
3330Sstevel@tonic-gate return (rv);
3340Sstevel@tonic-gate }
3350Sstevel@tonic-gate
3360Sstevel@tonic-gate /*
3370Sstevel@tonic-gate * Return 1 if the specified service is online. Otherwise, return 0.
3380Sstevel@tonic-gate */
3390Sstevel@tonic-gate static int
is_online(char * svc_name)3400Sstevel@tonic-gate is_online(char *svc_name)
3410Sstevel@tonic-gate {
3420Sstevel@tonic-gate int rval = 0;
3430Sstevel@tonic-gate char *s;
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate if ((s = smf_get_state(svc_name)) != NULL) {
3460Sstevel@tonic-gate if (strcmp(s, "online") == 0)
3470Sstevel@tonic-gate rval = 1;
3480Sstevel@tonic-gate free(s);
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate return (rval);
3510Sstevel@tonic-gate }
352