2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A/*
2N/A * Service Management Facility (SMF) interfaces.
2N/A */
2N/A
2N/A#include <stdio.h>
2N/A#include <libscf.h>
2N/A#include <meta.h>
2N/A
2N/Astatic void enable(char *svc_names[], md_error_t *ep);
2N/Astatic void disable(char *svc_names[], md_error_t *ep);
2N/Astatic int enabled(char *svc_name);
2N/Astatic int online(char *svc_names[], char **names);
2N/Astatic void wait_online(char *svc_names[]);
2N/Astatic int is_online(char *svc_name);
2N/A
2N/Astatic char
2N/A*svm_core_svcs[] = {
2N/A "system/metainit:default",
2N/A "system/metasync:default",
2N/A "system/mdmonitor:default",
2N/A "network/rpc/meta:default",
2N/A NULL
2N/A};
2N/A
2N/Astatic char
2N/A*svm_diskset_svcs[] = {
2N/A "network/rpc/metamed:default",
2N/A "network/rpc/metamh:default",
2N/A NULL
2N/A};
2N/A
2N/Astatic char
2N/A*svm_mn_diskset_svcs[] = {
2N/A "network/rpc/mdcomm:default",
2N/A NULL
2N/A};
2N/A
2N/A/*
2N/A * Enable the specified SVM services through the SMF.
2N/A */
2N/Aint
2N/Ameta_smf_enable(uint_t flags, md_error_t *ep)
2N/A{
2N/A if (flags & META_SMF_CORE) {
2N/A enable(svm_core_svcs, ep);
2N/A wait_online(svm_core_svcs);
2N/A }
2N/A
2N/A if (flags & META_SMF_DISKSET) {
2N/A enable(svm_diskset_svcs, ep);
2N/A wait_online(svm_diskset_svcs);
2N/A }
2N/A
2N/A if (flags & META_SMF_MN_DISKSET) {
2N/A enable(svm_mn_diskset_svcs, ep);
2N/A wait_online(svm_mn_diskset_svcs);
2N/A }
2N/A
2N/A if (ep != NULL)
2N/A return ((mdisok(ep)) ? 0 : -1);
2N/A else
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Disable the specified SVM services through the SMF.
2N/A */
2N/Aint
2N/Ameta_smf_disable(uint_t flags, md_error_t *ep)
2N/A{
2N/A if (flags & META_SMF_CORE) {
2N/A disable(svm_core_svcs, ep);
2N/A }
2N/A
2N/A if (flags & META_SMF_DISKSET) {
2N/A disable(svm_diskset_svcs, ep);
2N/A }
2N/A
2N/A if (flags & META_SMF_MN_DISKSET) {
2N/A disable(svm_mn_diskset_svcs, ep);
2N/A }
2N/A
2N/A if (ep != NULL)
2N/A return ((mdisok(ep)) ? 0 : -1);
2N/A else
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Determine if desired services are online. If all services in the
2N/A * classes specified by flags are online, 1 is returned. Otherwise
2N/A * 0 is returned.
2N/A */
2N/A
2N/Aint
2N/Ameta_smf_isonline(uint_t flags, md_error_t *ep)
2N/A{
2N/A int ret = 1;
2N/A char *names = NULL;
2N/A
2N/A if (flags & META_SMF_CORE) {
2N/A if (online(svm_core_svcs, &names) == 0)
2N/A ret = 0;
2N/A }
2N/A if (flags & META_SMF_DISKSET) {
2N/A if (online(svm_diskset_svcs, &names) == 0)
2N/A ret = 0;
2N/A }
2N/A if (flags & META_SMF_MN_DISKSET) {
2N/A if (online(svm_mn_diskset_svcs, &names) == 0)
2N/A ret = 0;
2N/A }
2N/A
2N/A if (ret == 0) {
2N/A (void) mderror(ep, MDE_SMF_NO_SERVICE, names);
2N/A Free(names);
2N/A }
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/A/*
2N/A * Return a bitmask of the META_SMF_* flags indicating which services should be
2N/A * online given the current SVM configuration.
2N/A */
2N/Aint
2N/Ameta_smf_getmask()
2N/A{
2N/A int mask = 0;
2N/A mdsetname_t *sp = NULL;
2N/A mddb_config_t c;
2N/A md_error_t status = mdnullerror;
2N/A md_error_t *ep = &status;
2N/A int max_sets;
2N/A
2N/A /*
2N/A * If there are any local metadbs configured then the core services
2N/A * are needed.
2N/A */
2N/A (void) memset(&c, 0, sizeof (c));
2N/A c.c_setno = MD_LOCAL_SET;
2N/A if (metaioctl(MD_DB_GETDEV, &c, &c.c_mde, NULL) != 0 || c.c_dbcnt == 0)
2N/A return (mask);
2N/A
2N/A mask |= META_SMF_CORE;
2N/A
2N/A /*
2N/A * If any disksets configured then the diskset services are needed.
2N/A * Also check for multi-node sets.
2N/A */
2N/A if ((max_sets = get_max_sets(ep)) > 0) {
2N/A int i;
2N/A
2N/A mdclrerror(ep);
2N/A for (i = 1; i < max_sets; i++) {
2N/A md_set_desc *sd;
2N/A
2N/A if ((sp = metasetnosetname(i, ep)) == NULL) {
2N/A if (!mdisok(ep) && !mdiserror(ep, MDE_NO_SET) &&
2N/A !mdismddberror(ep, MDE_NOTENOUGH_DB) &&
2N/A !mdiserror(ep, MDE_SMF_NO_SERVICE) &&
2N/A ep->info.errclass != MDEC_RPC) {
2N/A /*
2N/A * metad rpc program not registered
2N/A * can't get diskset info
2N/A */
2N/A break;
2N/A }
2N/A
2N/A } else {
2N/A mask |= META_SMF_DISKSET;
2N/A
2N/A if ((sd = metaget_setdesc(sp, ep)) != NULL) {
2N/A if (MD_MNSET_DESC(sd)) {
2N/A mask |= META_SMF_MN_DISKSET;
2N/A
2N/A /*
2N/A * we don't have to check the
2N/A * rest of the disksets at this
2N/A * point
2N/A */
2N/A break;
2N/A }
2N/A }
2N/A }
2N/A
2N/A mdclrerror(ep);
2N/A }
2N/A }
2N/A
2N/A return (mask);
2N/A}
2N/A
2N/Astatic void
2N/Aenable(char *svc_names[], md_error_t *ep)
2N/A{
2N/A int i;
2N/A
2N/A for (i = 0; svc_names[i]; i++) {
2N/A if (!enabled(svc_names[i]))
2N/A if (smf_enable_instance(svc_names[i], 0) != 0) {
2N/A if (ep != NULL) {
2N/A (void) mderror(ep, MDE_SMF_FAIL,
2N/A svc_names[i]);
2N/A }
2N/A }
2N/A }
2N/A}
2N/A
2N/Astatic void
2N/Adisable(char *svc_names[], md_error_t *ep)
2N/A{
2N/A int i;
2N/A
2N/A for (i = 0; svc_names[i]; i++) {
2N/A if (enabled(svc_names[i]))
2N/A if (smf_disable_instance(svc_names[i], 0) != 0) {
2N/A if (ep != NULL) {
2N/A (void) mderror(ep, MDE_SMF_FAIL,
2N/A svc_names[i]);
2N/A }
2N/A }
2N/A }
2N/A}
2N/A
2N/Astatic int
2N/Aenabled(char *svc_name)
2N/A{
2N/A scf_simple_prop_t *prop;
2N/A int rval = 0;
2N/A
2N/A prop = scf_simple_prop_get(NULL, svc_name, SCF_PG_GENERAL,
2N/A SCF_PROPERTY_ENABLED);
2N/A
2N/A if (scf_simple_prop_numvalues(prop) == 1) {
2N/A if (*scf_simple_prop_next_boolean(prop) != 0)
2N/A rval = 1;
2N/A }
2N/A
2N/A scf_simple_prop_free(prop);
2N/A
2N/A return (rval);
2N/A}
2N/A
2N/A/*
2N/A * There can be a delay while the RPC services get going. Try to
2N/A * make sure the RPC daemons are ready to run before we return.
2N/A * Check 15 times (15 seconds total wait time) and then just
2N/A * return.
2N/A */
2N/Astatic void
2N/Await_online(char *svc_names[])
2N/A{
2N/A int i;
2N/A char *names = NULL;
2N/A
2N/A for (i = 0; i < 15; i++) {
2N/A if (online(svc_names, &names))
2N/A break;
2N/A (void) sleep(1);
2N/A }
2N/A
2N/A if (names != NULL)
2N/A Free(names);
2N/A}
2N/A
2N/A/*
2N/A * Check to see if all services in the svc_names are online. If they are
2N/A * all online 1 is returned, otherwise 0 is returned.
2N/A */
2N/A
2N/Astatic int
2N/Aonline(char *svc_names[], char **names)
2N/A{
2N/A int i;
2N/A int rv = 1;
2N/A
2N/A for (i = 0; svc_names[i]; i++) {
2N/A if (is_online(svc_names[i]) == 0) {
2N/A int sz;
2N/A char *p;
2N/A
2N/A /*
2N/A * Need space for the name, the new line, the
2N/A * tab and the null terminator.
2N/A */
2N/A sz = strlen(svc_names[i]) + 3;
2N/A
2N/A if (*names == NULL) {
2N/A p = Malloc(sz);
2N/A (void) snprintf(p, sz, "\n\t%s", svc_names[i]);
2N/A
2N/A } else {
2N/A /* Add space for existing names */
2N/A sz += strlen(*names);
2N/A p = Malloc(sz);
2N/A (void) snprintf(p, sz, "%s\n\t%s", *names,
2N/A svc_names[i]);
2N/A Free(*names);
2N/A }
2N/A
2N/A *names = p;
2N/A rv = 0;
2N/A }
2N/A }
2N/A return (rv);
2N/A}
2N/A
2N/A/*
2N/A * Return 1 if the specified service is online. Otherwise, return 0.
2N/A */
2N/Astatic int
2N/Ais_online(char *svc_name)
2N/A{
2N/A int rval = 0;
2N/A char *s;
2N/A
2N/A if ((s = smf_get_state(svc_name)) != NULL) {
2N/A if (strcmp(s, "online") == 0)
2N/A rval = 1;
2N/A free(s);
2N/A }
2N/A return (rval);
2N/A}
2N/A
2N/A/*
2N/A * Determine if desired service is disabled. If so, 1 is returned.
2N/A * Otherwise 0 is returned.
2N/A */
2N/Aint
2N/Ameta_smf_isdisabled(char *svc_name)
2N/A{
2N/A int rval = 0;
2N/A char *s;
2N/A
2N/A if ((s = smf_get_state(svc_name)) != NULL) {
2N/A if (strcmp(s, "disabled") == 0)
2N/A rval = 1;
2N/A free(s);
2N/A }
2N/A return (rval);
2N/A}