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 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate /* 300Sstevel@tonic-gate * Service Management Facility (SMF) interfaces. 310Sstevel@tonic-gate */ 320Sstevel@tonic-gate 330Sstevel@tonic-gate #include <stdio.h> 340Sstevel@tonic-gate #include <libscf.h> 350Sstevel@tonic-gate #include <meta.h> 360Sstevel@tonic-gate 370Sstevel@tonic-gate static void enable(char *svc_names[], md_error_t *ep); 380Sstevel@tonic-gate static void disable(char *svc_names[], md_error_t *ep); 390Sstevel@tonic-gate static int enabled(char *svc_name); 400Sstevel@tonic-gate static int online(char *svc_names[], char **names); 410Sstevel@tonic-gate static void wait_online(char *svc_names[]); 420Sstevel@tonic-gate static int is_online(char *svc_name); 430Sstevel@tonic-gate 440Sstevel@tonic-gate static char 450Sstevel@tonic-gate *svm_core_svcs[] = { 460Sstevel@tonic-gate "system/metainit: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 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 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 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 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 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 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 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 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 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]); 326*113Sgjelinek 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 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