xref: /onnv-gate/usr/src/lib/lvm/libmeta/common/meta_smf.c (revision 2150:e99313126b1a)
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