summaryrefslogtreecommitdiff
path: root/usr/src/cmd/avs/sv/svadm.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/avs/sv/svadm.c')
-rw-r--r--usr/src/cmd/avs/sv/svadm.c1515
1 files changed, 0 insertions, 1515 deletions
diff --git a/usr/src/cmd/avs/sv/svadm.c b/usr/src/cmd/avs/sv/svadm.c
deleted file mode 100644
index 4fee03b277..0000000000
--- a/usr/src/cmd/avs/sv/svadm.c
+++ /dev/null
@@ -1,1515 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mkdev.h>
-#include <sys/param.h>
-#include <sys/wait.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <errno.h>
-#include <stdio.h>
-#include <locale.h>
-#include <unistd.h>
-#include <search.h>
-#include <libgen.h>
-#include <nsctl.h>
-
-#include <sys/unistat/spcs_s.h>
-#include <sys/unistat/spcs_s_u.h>
-#include <sys/unistat/spcs_errors.h>
-
-#include <sys/nsctl/sv.h>
-#include <sys/nsctl/sv_impl.h>
-
-#include <sys/nsctl/cfg.h>
-#include <sys/nsctl/nsc_hash.h>
-
-#include "../sv/svadm.h"
-
-
-static int sv_max_devices;
-
-
-/*
- * support for the special cluster tag "local" to be used with -C in a
- * cluster for local volumes.
- */
-
-#define SV_LOCAL_TAG "local"
-
-static int sv_islocal;
-
-/*
- * libcfg access.
- */
-
-static CFGFILE *cfg; /* libcfg file pointer */
-static int cfg_changed; /* set to 1 if we need to commit changes */
-
-static char *cfg_cluster_tag; /* local cluster tag */
-
-static char *implicit_tag; /* implicit cluster tag */
-
-
-/*
- * Print width for print_sv() output.
- */
-
-#define STATWIDTH (SV_MAXPATH / 2)
-
-/*
- * Pathnames.
- */
-
-static const caddr_t sv_rpath = SV_DEVICE;
-
-/*
- * Functions.
- */
-
-static int read_config_file(const caddr_t, sv_name_t []);
-static int enable_dev(sv_name_t *);
-static int disable_dev(const caddr_t);
-static void error(spcs_s_info_t *, caddr_t, ...);
-static void create_cfg_hash();
-static int find_in_hash(char *path);
-static void destroy_hashtable();
-static void remove_from_cfgfile(char *path, int setnumber);
-
-static caddr_t program;
-
-static void
-sv_cfg_open(CFGLOCK mode)
-{
- if (cfg != NULL)
- return;
-
- cfg = cfg_open(NULL);
- if (cfg == NULL) {
- error(NULL, gettext("unable to access the configuration"));
- /* NOTREACHED */
- }
-
- if (cfg_cluster_tag && *cfg_cluster_tag) {
- cfg_resource(cfg, cfg_cluster_tag);
- } else {
- cfg_resource(cfg, NULL);
- }
- if (!cfg_lock(cfg, mode)) {
- error(NULL, gettext("unable to lock the configuration"));
- /* NOTREACHED */
- }
-}
-
-
-static void
-sv_cfg_close(void)
-{
- if (cfg == NULL)
- return;
-
- if (cfg_changed) {
- (void) cfg_commit(cfg);
- cfg_changed = 0;
- }
-
- cfg_close(cfg);
- cfg = NULL;
-}
-
-
-
-static void
-usage(void)
-{
- (void) fprintf(stderr, gettext("usage:\n"));
-
- (void) fprintf(stderr, gettext(
- "\t%s -h help\n"), program);
-
- (void) fprintf(stderr, gettext(
- "\t%s [-C tag] display status\n"),
- program);
-
- (void) fprintf(stderr, gettext(
- "\t%s [-C tag] -i display "
- "extended status\n"), program);
-
- (void) fprintf(stderr, gettext(
- "\t%s [-C tag] -v display "
- "version number\n"), program);
-
- (void) fprintf(stderr, gettext(
- "\t%s [-C tag] -e { -f file | volume } enable\n"), program);
-
- (void) fprintf(stderr, gettext(
- "\t%s [-C tag] -d { -f file | volume } disable\n"), program);
-
- (void) fprintf(stderr, gettext(
- "\t%s [-C tag] -r { -f file | volume } reconfigure\n"), program);
-
- sv_cfg_close();
-}
-
-static void
-message(caddr_t prefix, spcs_s_info_t *status, caddr_t string, va_list ap)
-{
- (void) fprintf(stderr, "%s: %s: ", program, prefix);
- (void) vfprintf(stderr, string, ap);
- (void) fprintf(stderr, "\n");
-
- if (status) {
- spcs_s_report(*status, stderr);
- spcs_s_ufree(status);
- }
-}
-
-
-static void
-error(spcs_s_info_t *status, caddr_t string, ...)
-{
- va_list ap;
- va_start(ap, string);
-
- message(gettext("error"), status, string, ap);
-
- va_end(ap);
-
- sv_cfg_close();
- exit(1);
-}
-
-
-static void
-warn(spcs_s_info_t *status, caddr_t string, ...)
-{
- va_list ap;
- va_start(ap, string);
-
- message(gettext("warning"), status, string, ap);
-
- va_end(ap);
-}
-
-
-static void
-sv_get_maxdevs(void)
-{
- sv_name_t svn[1];
- sv_list_t svl;
- int fd;
-
- if (sv_max_devices > 0)
- return;
-
- fd = open(sv_rpath, O_RDONLY);
- if (fd < 0)
- error(NULL, gettext("unable to open %s: %s"),
- sv_rpath, strerror(errno));
-
- bzero(&svl, sizeof (svl));
- bzero(&svn[0], sizeof (svn));
-
- svl.svl_names = &svn[0];
- svl.svl_error = spcs_s_ucreate();
-
- if (ioctl(fd, SVIOC_LIST, &svl) < 0) {
- (void) close(fd);
- error(&svl.svl_error, gettext("unable to get max devs"));
- }
-
- spcs_s_ufree(&svl.svl_error);
- sv_max_devices = svl.svl_maxdevs;
-
- (void) close(fd);
-}
-
-
-static sv_name_t *
-sv_alloc_svnames(void)
-{
- sv_name_t *svn = NULL;
-
- sv_get_maxdevs();
-
- svn = calloc(sv_max_devices, sizeof (*svn));
- if (svn == NULL) {
- error(NULL, "unable to allocate %ld bytes of memory",
- sv_max_devices * sizeof (*svn));
- }
-
- return (svn);
-}
-
-
-static void
-sv_check_dgislocal(char *dgname)
-{
- char *othernode;
- int rc;
-
- /*
- * check where this disk service is mastered
- */
-
- rc = cfg_dgname_islocal(dgname, &othernode);
- if (rc < 0) {
- error(NULL, gettext("unable to find "
- "disk service, %s: %s"), dgname, strerror(errno));
- }
-
- if (rc == 0) {
- error(NULL, gettext("disk service, %s, is "
- "active on node \"%s\"\nPlease re-issue "
- "the command on that node"), dgname, othernode);
- }
-}
-
-
-/*
- * Carry out cluster based checks for a specified volume, or just
- * global options.
- */
-static void
-sv_check_cluster(char *path)
-{
- char dgname[CFG_MAX_BUF];
- static int sv_iscluster = -1; /* set to 1 if running in a cluster */
-
- /*
- * Find out if we are running in a cluster
- */
- if (sv_iscluster == -1) {
- if ((sv_iscluster = cfg_iscluster()) < 0) {
- error(NULL, gettext("unable to ascertain environment"));
- }
- }
-
- if (!sv_iscluster && cfg_cluster_tag != NULL) {
- error(NULL, gettext("-C is not valid when not in a cluster"));
- }
-
- if (!sv_iscluster || sv_islocal || path == NULL) {
- return;
- }
-
-
- /*
- * Cluster-only checks on pathname
- */
- if (cfg_dgname(path, dgname, sizeof (dgname)) == NULL) {
- error(NULL, gettext("unable to determine "
- "disk group name for %s"), path);
- return;
- }
-
- if (cfg_cluster_tag != NULL) {
- /*
- * Do dgislocal check now in case path did not contain
- * a dgname.
- *
- * E.g. adding a /dev/did/ device to a disk service.
- */
-
- sv_check_dgislocal(cfg_cluster_tag);
- }
-
- if (strcmp(dgname, "") == 0)
- return; /* NULL dgname is valid */
-
- if (cfg_cluster_tag == NULL) {
- /*
- * Implicitly set the cluster tag to dgname
- */
-
- sv_check_dgislocal(dgname);
-
- if (implicit_tag) {
- free(implicit_tag);
- implicit_tag = NULL;
- }
-
- implicit_tag = strdup(dgname);
- if (implicit_tag == NULL) {
- error(NULL,
- gettext("unable to allocate memory "
- "for cluster tag"));
- }
- } else {
- /*
- * Check dgname and cluster tag from -C are the same.
- */
-
- if (strcmp(dgname, cfg_cluster_tag) != 0) {
- error(NULL,
- gettext("-C (%s) does not match disk group "
- "name (%s) for %s"), cfg_cluster_tag,
- dgname, path);
- }
-
- /*
- * sv_check_dgislocal(cfg_cluster_tag) was called above.
- */
- }
-}
-
-
-static void
-print_version(void)
-{
- sv_version_t svv;
- int fd;
-
- bzero(&svv, sizeof (svv));
- svv.svv_error = spcs_s_ucreate();
-
- fd = open(sv_rpath, O_RDONLY);
- if (fd < 0) {
- warn(NULL, gettext("unable to open %s: %s"),
- sv_rpath, strerror(errno));
- return;
- }
-
- if (ioctl(fd, SVIOC_VERSION, &svv) != 0) {
- error(&svv.svv_error,
- gettext("unable to read the version number"));
- /* NOTREACHED */
- }
-
- spcs_s_ufree(&svv.svv_error);
-#ifdef DEBUG
- (void) printf(gettext("Storage Volume version %d.%d.%d.%d\n"),
- svv.svv_major_rev, svv.svv_minor_rev,
- svv.svv_micro_rev, svv.svv_baseline_rev);
-#else
- if (svv.svv_micro_rev) {
- (void) printf(gettext("Storage Volume version %d.%d.%d\n"),
- svv.svv_major_rev, svv.svv_minor_rev, svv.svv_micro_rev);
- } else {
- (void) printf(gettext("Storage Volume version %d.%d\n"),
- svv.svv_major_rev, svv.svv_minor_rev);
- }
-#endif
-
- (void) close(fd);
-}
-
-int
-main(int argc, char *argv[])
-{
- extern int optind;
- extern char *optarg;
- char *conf_file = NULL;
- int enable, disable, compare, print, version;
- int opt, Cflag, fflag, iflag;
- int rc;
-
- (void) setlocale(LC_ALL, "");
- (void) textdomain("svadm");
-
- program = strdup(basename(argv[0]));
-
- Cflag = fflag = iflag = 0;
- compare = enable = disable = version = 0;
-
- print = 1;
-
- while ((opt = getopt(argc, argv, "C:def:hirv")) != EOF) {
- switch (opt) {
-
- case 'C':
- if (Cflag) {
- warn(NULL,
- gettext("-C specified multiple times"));
- usage();
- exit(2);
- /* NOTREACHED */
- }
-
- Cflag++;
- cfg_cluster_tag = optarg;
- break;
-
- case 'e':
- print = 0;
- enable++;
- break;
-
- case 'd':
- print = 0;
- disable++;
- break;
-
- case 'f':
- fflag++;
- conf_file = optarg;
- break;
-
- case 'i':
- iflag++;
- break;
-
- case 'r':
- /* Compare running system with sv.cf */
- print = 0;
- compare++;
- break;
-
- case 'v':
- print = 0;
- version++;
- break;
-
- case 'h':
- usage();
- exit(0);
-
- default:
- usage();
- exit(2);
- /* NOTREACHED */
- }
- }
-
-
- /*
- * Usage checks
- */
-
- if ((enable + disable + compare) > 1) {
- warn(NULL, gettext("-d, -e and -r are mutually exclusive"));
- usage();
- exit(2);
- }
-
- if (fflag && (print || version)) {
- warn(NULL, gettext("-f is only valid with -d, -e or -r"));
- usage();
- exit(2);
- }
-
- if (fflag && optind != argc) {
- usage();
- exit(2);
- }
-
- if (print || version) {
- /* check for no more args */
-
- if (optind != argc) {
- usage();
- exit(2);
- }
- } else {
- /* check for inline args */
-
- if (!fflag && (argc - optind) != 1) {
- usage();
- exit(2);
- }
- }
-
- if (!print && iflag) {
- usage();
- exit(2);
- }
-
-
- /*
- * Check for the special cluster tag and convert into the
- * internal representation.
- */
-
- if (cfg_cluster_tag != NULL &&
- strcmp(cfg_cluster_tag, SV_LOCAL_TAG) == 0) {
- cfg_cluster_tag = "-";
- sv_islocal = 1;
- }
-
-
- /*
- * Process commands
- */
-
- if (optind != argc) {
- /* deal with inline volume argument */
-
- rc = 0;
- if (enable)
- rc = enable_one_sv(argv[optind]);
- else if (disable)
- rc = disable_one_sv(argv[optind]);
- else /* if (compare) */
- compare_one_sv(argv[optind]);
-
- if (rc != 0)
- return (1);
-
- return (0);
- }
-
- rc = 0;
- if (enable)
- rc = enable_sv(conf_file);
- else if (disable)
- rc = disable_sv(conf_file);
- else if (compare)
- compare_sv(conf_file);
- else if (print)
- print_sv(iflag);
- else /* if (version) */
- print_version();
-
- if (rc != 0)
- return (1);
-
- return (0);
-}
-
-
-
-/* LINT - not static as fwcadm uses it */
-static int
-enable_sv(char *conf_file)
-{
- int index;
- sv_name_t *svn;
- int cnt;
- int rc, ret;
-
- svn = sv_alloc_svnames();
-
- index = read_config_file(conf_file, svn);
-
- rc = ret = 0;
-
- for (cnt = 0; cnt < index; cnt++) {
-
- /*
- * Check for more data.
- */
- if (svn[cnt].svn_path[0] == '\0') {
- /*
- * This was set when reading sv.conf. After the last
- * line svn_path was set to \0, so we are finished.
- * We shouldn't get here, but put this in just in
- * case.
- */
- break;
- }
- rc = enable_dev(&svn[cnt]);
- if (rc && !ret)
- ret = rc;
- }
-
- sv_cfg_close();
-
- return (ret);
-}
-
-
-/* LINT - not static as fwcadm uses it */
-static int
-enable_one_sv(caddr_t path)
-{
- sv_name_t svn;
- int rc;
-
- sv_get_maxdevs();
-
- bzero(&svn, sizeof (svn));
- (void) strncpy(svn.svn_path, path, sizeof (svn.svn_path));
- svn.svn_mode = (NSC_DEVICE | NSC_CACHE);
-
- /* force NULL termination */
- svn.svn_path[sizeof (svn.svn_path) - 1] = '\0';
-
- rc = enable_dev(&svn);
- sv_cfg_close();
-
- return (rc);
-}
-
-
-static int
-enable_dev(sv_name_t *svn)
-{
- char buf[CFG_MAX_BUF];
- struct stat stb;
- sv_conf_t svc;
- int fd;
- int sev;
- int rc;
- char *lcltag;
- char *altname;
-
- sv_check_cluster(svn->svn_path);
- sv_cfg_open(CFG_WRLOCK);
-
- bzero(&svc, sizeof (svc));
-
- if (stat(svn->svn_path, &stb) != 0) {
- warn(NULL, gettext("unable to access %s: %s"),
- svn->svn_path, strerror(errno));
- return (1);
- }
-
- if (!S_ISCHR(stb.st_mode)) {
- warn(NULL, gettext("%s is not a character device - ignored"),
- svn->svn_path);
- return (1);
- }
-
- svc.svc_major = major(stb.st_rdev);
- svc.svc_minor = minor(stb.st_rdev);
- (void) strncpy(svc.svc_path, svn->svn_path, sizeof (svc.svc_path));
-
- fd = open(sv_rpath, O_RDONLY);
- if (fd < 0) {
- warn(NULL, gettext("unable to open %s: %s"),
- svn->svn_path, strerror(errno));
- return (1);
- }
-
- svc.svc_flag = svn->svn_mode;
- svc.svc_error = spcs_s_ucreate();
-
- /* first, check for duplicates */
- rc = cfg_get_canonical_name(cfg, svn->svn_path, &altname);
- if (rc < 0) {
- spcs_log("sv", NULL, gettext("Unable to parse config file"));
- warn(NULL, gettext("Unable to parse config file"));
- (void) close(fd);
- return (1);
- }
- if (rc) {
- error(NULL, gettext("'%s' has already been configured as "
- "'%s'. Re-enter command with the latter name."),
- svn->svn_path, altname);
- }
-
- /* secondly, try to insert it into the dsvol config */
- if (implicit_tag && *implicit_tag) {
- lcltag = implicit_tag;
- } else if (cfg_cluster_tag && *cfg_cluster_tag) {
- lcltag = cfg_cluster_tag;
- } else {
- lcltag = "-";
- }
- rc = cfg_add_user(cfg, svn->svn_path, lcltag, "sv");
- if (CFG_USER_ERR == rc) {
- spcs_log("sv", NULL,
- gettext("%s: unable to put %s into dsvol cfg"),
- program, svn->svn_path);
- warn(NULL, gettext("unable to put %s into dsvol cfg"),
- svn->svn_path);
- (void) close(fd);
- return (1);
- }
- cfg_changed = 1;
-
- if (CFG_USER_OK == rc) {
- /* success */
- (void) close(fd);
- return (0);
- }
-
- if (ioctl(fd, SVIOC_ENABLE, &svc) < 0) {
- if ((CFG_USER_REPEAT == rc) && (SV_EENABLED == errno)) {
- /* it's ok -- we were just double-checking */
- (void) close(fd);
- return (0);
- }
-
- spcs_log("sv", &svc.svc_error,
- gettext("%s: unable to enable %s"),
- program, svn->svn_path);
-
- warn(&svc.svc_error, gettext("unable to enable %s"),
- svn->svn_path);
-
- /* remove it from dsvol, if we're the ones who put it in */
- if (CFG_USER_FIRST == rc) {
- (void) cfg_rem_user(cfg, svn->svn_path, lcltag, "sv");
- }
- (void) close(fd);
- return (1);
- }
-
- spcs_log("sv", NULL, gettext("%s: enabled %s"),
- program, svn->svn_path);
-
- if (implicit_tag != NULL) {
-#ifdef DEBUG
- if (cfg_cluster_tag != NULL) {
- error(NULL,
- gettext("enable_dev: -C %s AND implicit_tag %s!"),
- cfg_cluster_tag, implicit_tag);
- }
-#endif
-
- (void) snprintf(buf, sizeof (buf), "%s - %s",
- svc.svc_path, implicit_tag);
- } else {
- (void) strcpy(buf, svc.svc_path);
- }
-
- rc = 0;
- if (cfg_put_cstring(cfg, "sv", buf, sizeof (buf)) < 0) {
- warn(NULL,
- gettext("unable to add %s to configuration storage: %s"),
- svc.svc_path, cfg_error(&sev));
- rc = 1;
- }
-
- cfg_changed = 1;
- spcs_s_ufree(&svc.svc_error);
- (void) close(fd);
-
- return (rc);
-}
-
-
-/*
- * This routine parses the config file passed in via conf_file and
- * stores the data in the svn array. The return value is the number
- * of entries read from conf_file. If an error occurs the error()
- * routine is called (which exits the program).
- */
-static int
-read_config_file(const caddr_t conf_file, sv_name_t svn[])
-{
- char line[1024], rdev[1024], junk[1024];
- struct stat stb;
- int lineno;
- int cnt, i;
- int index = 0; /* Current location in svn array */
- sv_name_t *cur_svn; /* Pointer to svn[index] */
- FILE *fp;
-
- if (access(conf_file, R_OK) != 0 ||
- stat(conf_file, &stb) != 0 ||
- !S_ISREG(stb.st_mode)) {
- error(NULL, gettext("cannot read config file %s"), conf_file);
- }
-
- if ((fp = fopen(conf_file, "r")) == NULL) {
- error(NULL, gettext("unable to open config file %s: %s"),
- conf_file, strerror(errno));
- }
-
- lineno = 0;
-
- while (fgets(line, sizeof (line), fp) != NULL) {
- lineno++;
-
- i = strlen(line);
-
- if (i < 1)
- continue;
-
- if (line[i-1] == '\n')
- line[i-1] = '\0';
- else if (i == (sizeof (line) - 1)) {
- warn(NULL, gettext(
- "line %d: line too long -- should be less than %d characters"),
- lineno, (sizeof (line) - 1));
- warn(NULL, gettext("line %d: ignored"), lineno);
- }
-
- /*
- * check for comment line.
- */
- if (line[0] == '#')
- continue;
-
- cnt = sscanf(line, "%s %s", rdev, junk);
-
- if (cnt != 1 && cnt != 2) {
- if (cnt > 0) {
- warn(NULL, gettext("line %d: invalid format"),
- lineno);
- warn(NULL, gettext("line %d: ignored"), lineno);
- }
- continue;
- }
-
- rdev[sizeof (rdev) - 1] = '\0';
-
- cur_svn = &svn[index]; /* For easier reading below */
-
- if (strlen(rdev) >= sizeof (cur_svn->svn_path)) {
- warn(NULL, gettext(
- "line %d: raw device name (%s) longer than %d characters"),
- lineno, rdev,
- (sizeof (cur_svn->svn_path) - 1));
- warn(NULL, gettext("line %d: ignored"), lineno);
- continue;
- }
-
- (void) strcpy(cur_svn->svn_path, rdev);
- cur_svn->svn_mode = (NSC_DEVICE | NSC_CACHE);
-
- index++;
- }
-
- /* Set the last path to NULL */
- svn[index].svn_path[0] = '\0';
-
- (void) fclose(fp);
-
- return (index);
-}
-
-
-/*
- * Disable the device from the kernel configuration.
- *
- * RETURN:
- * 0 on success
- * non-zero on failure.
- *
- * Failures are reported to the user.
- */
-static int
-disable_dev(const caddr_t path)
-{
- struct stat stb;
- sv_conf_t svc;
- int fd;
-
- sv_check_cluster(path);
-
- if (stat(path, &stb) < 0) {
- svc.svc_major = (major_t)-1;
- svc.svc_minor = (minor_t)-1;
- } else {
- svc.svc_major = major(stb.st_rdev);
- svc.svc_minor = minor(stb.st_rdev);
- }
-
- if ((fd = open(sv_rpath, O_RDONLY)) < 0) {
- warn(NULL, gettext("unable to open %s: %s"),
- sv_rpath, strerror(errno));
- return (-1);
- }
-
- (void) strcpy(svc.svc_path, path);
- svc.svc_error = spcs_s_ucreate();
-
- /*
- * Issue the ioctl to attempt to disable this device. Note that all
- * the libdscfg details are handled elsewhere.
- */
- if (ioctl(fd, SVIOC_DISABLE, &svc) < 0) {
- if (errno != SV_EDISABLED) {
- spcs_log("sv", &svc.svc_error,
- gettext("%s: unable to disable %s"),
- program, path);
-
- warn(&svc.svc_error,
- gettext("unable to disable %s"), path);
- (void) close(fd);
- return (-1);
- }
- }
-
- spcs_log("sv", NULL, gettext("%s: disabled %s"), program, path);
-
- spcs_s_ufree(&svc.svc_error);
- (void) close(fd);
-
- return (0);
-}
-
-
-static void
-print_cluster_tag(const int setnumber)
-{
- char buf[CFG_MAX_BUF];
- char key[CFG_MAX_KEY];
-
- bzero(buf, sizeof (buf));
- (void) snprintf(key, sizeof (key), "sv.set%d.cnode", setnumber);
-
- (void) cfg_get_cstring(cfg, key, buf, sizeof (buf));
-
- if (*buf != '\0') {
- if (strcmp(buf, "-") == 0) {
- (void) printf(" [%s]", gettext("local to node"));
- } else {
- (void) printf(" [%s: %s]", gettext("cluster"), buf);
- }
- }
-}
-
-
-/* LINT - not static as fwcadm uses it */
-static void
-print_sv(int verbose)
-{
- sv_name_t *svn, *svn_system; /* Devices in system */
- sv_list_t svl_system;
- int fd, i;
- int setnumber;
-
- sv_check_cluster(NULL);
- sv_cfg_open(CFG_RDLOCK);
-
- svn_system = sv_alloc_svnames();
-
- if ((fd = open(sv_rpath, O_RDONLY)) < 0) {
- (void) printf(gettext("unable to open %s: %s"),
- sv_rpath, strerror(errno));
- return;
- }
-
- /* Grab the system list from the driver */
- svl_system.svl_count = sv_max_devices;
- svl_system.svl_names = &svn_system[0];
- svl_system.svl_error = spcs_s_ucreate();
-
- if (ioctl(fd, SVIOC_LIST, &svl_system) < 0) {
- error(&svl_system.svl_error, gettext("unable to get list"));
- }
-
- spcs_s_ufree(&svl_system.svl_error);
- (void) close(fd);
-
- /*
- * We build a hashmap out of the entries from the config file to make
- * searching faster. We end up taking a performance hit when the # of
- * volumes is small, but for larger configurations it's a
- * HUGE improvement.
- */
-
- /* build the hashtable */
- cfg_rewind(cfg, CFG_SEC_CONF);
- create_cfg_hash();
-
- /*
- * For each volume found from the kernel, print out
- * info about it from the kernel.
- */
- for (i = 0; i < svl_system.svl_count; i++) {
- if (*svn_system[i].svn_path == '\0') {
- break;
- }
-
- svn = &svn_system[i];
- if (svn->svn_mode == 0) {
-#ifdef DEBUG
- (void) printf(gettext("%s [kernel guard]\n"),
- svn->svn_path);
-#endif
- continue;
- }
- /* get sv entry from the hashtable */
- if ((setnumber = find_in_hash(svn->svn_path)) != -1) {
- (void) printf("%-*s", STATWIDTH, svn->svn_path);
-
- if (verbose) {
- print_cluster_tag(setnumber);
- }
-
- (void) printf("\n");
-
- } else {
- /*
- * We didn't find the entry in the hashtable. Let
- * the user know that the persistent storage is
- * inconsistent with the kernel configuration.
- */
- if (cfg_cluster_tag == NULL)
- warn(NULL, gettext(
- "%s is configured, but not in the "
- "config storage"), svn->svn_path);
- }
- }
-
- /* free up the hashtable */
- destroy_hashtable();
-
- sv_cfg_close();
-}
-
-
-/* LINT - not static as fwcadm uses it */
-static int
-disable_sv(char *conf_file)
-{
- sv_name_t *svn, *svn_system; /* Devices in system */
- sv_list_t svl_system;
- int fd, i, setnumber;
- int rc, ret;
-
- svn_system = sv_alloc_svnames();
-
- rc = ret = 0;
-
- if (conf_file == NULL) {
- if ((fd = open(sv_rpath, O_RDONLY)) < 0) {
- (void) printf(gettext("unable to open %s: %s"),
- sv_rpath, strerror(errno));
- return (1);
- }
-
- /* Grab the system list from the driver */
- svl_system.svl_count = sv_max_devices;
- svl_system.svl_names = &svn_system[0];
- svl_system.svl_error = spcs_s_ucreate();
-
- if (ioctl(fd, SVIOC_LIST, &svl_system) < 0) {
- error(&(svl_system.svl_error),
- gettext("unable to get list"));
- }
-
- spcs_s_ufree(&(svl_system.svl_error));
- (void) close(fd);
- } else {
- svl_system.svl_count = read_config_file(conf_file, svn_system);
- }
-
-
- for (i = 0; i < svl_system.svl_count; i++) {
- if (*svn_system[i].svn_path == '\0')
- break;
-
- svn = &svn_system[i];
-
- sv_check_cluster(svn->svn_path);
- sv_cfg_open(CFG_WRLOCK);
- create_cfg_hash();
- rc = 0;
- if ((setnumber = find_in_hash(svn->svn_path)) != -1) {
- if ((rc = disable_dev(svn->svn_path)) != -1) {
- remove_from_cfgfile(svn->svn_path, setnumber);
- } else if (errno == SV_ENODEV) {
- remove_from_cfgfile(svn->svn_path, setnumber);
- }
- } else {
- /* warn the user that we didn't find it in cfg file */
- warn(NULL, gettext(
- "%s was not found in the config storage"),
- svn->svn_path);
- /* try to disable anyway */
- (void) disable_dev(svn->svn_path);
- rc = 1;
- }
-
- sv_cfg_close();
- destroy_hashtable();
-
- if (rc && !ret)
- ret = rc;
- }
-
- return (ret);
-}
-
-
-/* LINT - not static as fwcadm uses it */
-static int
-disable_one_sv(char *path)
-{
- int setnumber;
- int rc;
-
- sv_get_maxdevs();
- sv_check_cluster(path);
- sv_cfg_open(CFG_WRLOCK);
-
- create_cfg_hash();
- if ((setnumber = find_in_hash(path)) != -1) {
- /* remove from kernel */
- if ((rc = disable_dev(path)) == 0) {
- /* remove the cfgline */
- remove_from_cfgfile(path, setnumber);
- } else if (errno == SV_ENODEV) {
- remove_from_cfgfile(path, setnumber);
- }
- } else {
- /* warn the user that we didn't find it in cfg file */
- warn(NULL,
- gettext("%s was not found in the config storage"), path);
- /* still attempt to remove */
- (void) disable_dev(path);
- rc = 1;
- }
- destroy_hashtable();
-
- sv_cfg_close();
- return (rc);
-}
-
-
-static void
-compare_tag(char *path)
-{
- char buf[CFG_MAX_BUF], vol[CFG_MAX_BUF], cnode[CFG_MAX_BUF];
- char key[CFG_MAX_KEY];
- int found, setnumber, i;
- char *tag;
-
- sv_check_cluster(path);
- cfg_resource(cfg, (char *)NULL); /* reset */
- cfg_rewind(cfg, CFG_SEC_CONF);
-
-#ifdef DEBUG
- if (cfg_cluster_tag != NULL && implicit_tag != NULL) {
- error(NULL, gettext("compare_tag: -C %s AND implicit_tag %s!"),
- cfg_cluster_tag, implicit_tag);
- }
-#endif
-
- if (cfg_cluster_tag != NULL)
- tag = cfg_cluster_tag;
- else if (implicit_tag != NULL)
- tag = implicit_tag;
- else
- tag = "-";
-
- found = 0;
- for (i = 0; i < sv_max_devices; i++) {
- setnumber = i + 1;
- (void) snprintf(key, sizeof (key), "sv.set%d", setnumber);
- if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0) {
- break;
- }
-
- if (sscanf(buf, "%s - %s", vol, cnode) != 2) {
- continue;
- }
-
- if (strcmp(path, vol) == 0) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- warn(NULL, gettext("unable to find %s in the configuration"),
- path);
- return;
- }
-
- /* have name match, compare cnode to new tag */
-
- if (strcmp(tag, cnode) == 0) {
- /* cluster tags match */
- return;
- }
-
- /* need to change the cluster tag */
-
- (void) snprintf(key, sizeof (key), "sv.set%d.cnode", setnumber);
- if (cfg_put_cstring(cfg, key, tag, strlen(tag)) < 0) {
- warn(NULL,
- gettext("unable to change cluster tag for %s"), path);
- return;
- }
-
- cfg_changed = 1;
-
- /* change "-" tags to "" for display purposes */
-
- if (strcmp(tag, "-") == 0)
- tag = "";
-
- if (strcmp(cnode, "-") == 0)
- (void) strcpy(cnode, "");
-
- (void) printf(
- gettext("%s: changed cluster tag for %s from \"%s\" to \"%s\"\n"),
- program, path, cnode, tag);
-
- spcs_log("sv", NULL,
- gettext("%s: changed cluster tag for %s from \"%s\" to \"%s\""),
- program, path, cnode, tag);
-}
-
-
-/* LINT - not static as fwcadm uses it */
-static void
-compare_sv(char *conf_file)
-{
- sv_name_t *svn_config; /* Devices in config file */
- sv_name_t *svn_system; /* Devices in system */
- sv_name_t *enable; /* Devices that need enabled */
- sv_list_t svl_system;
- int config_cnt;
- int sys_cnt = 0;
- int setnumber, i, j;
- int index = 0; /* Index in enable[] */
- int found;
- int fd0;
-
- svn_config = sv_alloc_svnames();
- svn_system = sv_alloc_svnames();
- enable = sv_alloc_svnames();
-
- bzero(svn_system, sizeof (svn_system));
- bzero(&svl_system, sizeof (svl_system));
- bzero(enable, sizeof (enable));
-
- /*
- * Read the configuration file
- * The return value is the number of entries
- */
- config_cnt = read_config_file(conf_file, svn_config);
-
- if ((fd0 = open(sv_rpath, O_RDONLY)) < 0)
- error(NULL, gettext("unable to open %s: %s"),
- sv_rpath, strerror(errno));
-
- /* Grab the system list from the driver */
- svl_system.svl_count = sv_max_devices;
- svl_system.svl_names = &svn_system[0];
- svl_system.svl_error = spcs_s_ucreate();
-
- if (ioctl(fd0, SVIOC_LIST, &svl_system) < 0) {
- error(&svl_system.svl_error, gettext("unable to get list"));
- }
-
- spcs_s_ufree(&svl_system.svl_error);
- (void) close(fd0);
-
- /*
- * Count the number of devices in the system.
- * The last entry in the array has '\0' for a path name.
- */
- for (j = 0; j < sv_max_devices; j++) {
- if (svn_system[j].svn_path[0] != '\0') {
- sys_cnt++;
- } else {
- break;
- }
- }
- /*
- * Compare the configuration array with the system array.
- * Mark any differences and disable conflicting devices.
- */
- for (i = 0; i < config_cnt; i++) {
- found = 0;
- for (j = 0; j < sys_cnt; j++) {
- if (svn_system[j].svn_path[0] == '\0' ||
- svn_system[j].svn_mode == 0)
- continue;
-
- /* Check to see if path matches */
- if (strcmp(svn_system[j].svn_path,
- svn_config[i].svn_path) == 0) {
- /* Found a match */
- svn_system[j].svn_path[0] = '\0';
- found++;
- break;
- }
- }
-
- if (!found) {
- /* Minor number not in system = > enable device */
- enable[index].svn_mode = svn_config[i].svn_mode;
- (void) strcpy(enable[index].svn_path,
- svn_config[i].svn_path);
- index++;
- }
- }
-
- /* Disable any devices that weren't in the config file */
- for (j = 0; j < sys_cnt; j++) {
- sv_check_cluster(NULL);
- sv_cfg_open(CFG_WRLOCK);
- create_cfg_hash();
- if (svn_system[j].svn_path[0] != '\0' &&
- svn_system[j].svn_mode != 0) {
- (void) printf(gettext("%s: disabling sv: %s\n"),
- program, svn_system[j].svn_path);
- if (disable_dev(svn_system[j].svn_path) == 0) {
- setnumber =
- find_in_hash(svn_system[j].svn_path);
- if (setnumber != -1) {
- /* the volume was found in cfg store */
- remove_from_cfgfile(
- svn_system[j].svn_path, setnumber);
- }
- }
- }
- sv_cfg_close();
- destroy_hashtable();
- }
-
- while (index) {
- /*
- * Config file doesn't match system => enable the devices
- * in enable[]
- */
- index--;
- (void) printf(gettext("%s: enabling new sv: %s\n"),
- program, enable[index].svn_path);
- (void) enable_dev(&enable[index]);
- }
-
- /*
- * Search for entries where the cluster tag has changed.
- */
- sv_check_cluster(NULL);
- sv_cfg_open(CFG_WRLOCK);
-
- for (i = 0; i < sv_max_devices; i++) {
- if (svn_config[i].svn_path[0] == '\0')
- break;
-
- compare_tag(svn_config[i].svn_path);
- }
-
- sv_cfg_close();
-}
-
-
-/*
- * We assume that the volume is already enabled and we can only
- * be changing the cluster tag. Anything else is an error.
- */
-/* LINT - not static as fwcadm uses it */
-static void
-compare_one_sv(char *path)
-{
- sv_get_maxdevs();
- sv_check_cluster(NULL);
- sv_cfg_open(CFG_WRLOCK);
-
- compare_tag(path);
-
- sv_cfg_close();
-}
-
-/*
- * Read all sets from the libdscfg configuration file, and store everything in
- * the hashfile.
- *
- * We assume that the config file has been opened & rewound for us. We store
- * the volume name as the key, and the setnumber where we found it as the data.
- *
- * The caller can pass in a pointer to the maximum number of volumes, or
- * a pointer to NULL, specifying we want 'all' the volumes. The table is
- * searched using find_in_hash.
- */
-static void
-create_cfg_hash()
-{
- char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
- char vol[CFG_MAX_BUF], cnode[CFG_MAX_BUF];
- int setnumber;
- ENTRY item;
-
- if (hcreate((size_t)sv_max_devices) == 0)
- error(NULL, gettext("unable to create hash table"));
-
- for (setnumber = 1; /* CSTYLED */; setnumber++) {
- (void) snprintf(key, sizeof (key), "sv.set%d", setnumber);
- if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0)
- break;
-
- if (sscanf(buf, "%s - %s", vol, cnode) != 2) {
- continue;
- }
-
- item.key = strdup(vol);
- item.data = (void *)setnumber;
- if (hsearch(item, ENTER) == NULL) {
- error(NULL,
- gettext("unable to add entry to hash table"));
- }
- }
-}
-
-/*
- * Function to search the hash for a specific volume. If it is found,
- * we return the set number. If it isn't found, we return -1
- */
-static int
-find_in_hash(char *path)
-{
- ENTRY *found_entry, item;
- int retval = -1;
-
- item.key = path;
-
- if ((found_entry = hsearch(item, FIND)) != NULL) {
- retval = (int)found_entry->data;
- }
-
- return (retval);
-}
-
-/*
- * Just a wrapper to destory the hashtable. At some point in the future we
- * might want to do something more.... For instance, verify that the cfg
- * database and the kernel configuration match (?) Just an idea.
- */
-static void
-destroy_hashtable()
-{
- hdestroy();
-}
-
-/*
- * This function will remove a particular set from the config file.
- *
- * We make a whole host of assumptions:
- * o the hashfile is up to date;
- * o The config file has been opened with a WRLOCK for us.
- */
-static void
-remove_from_cfgfile(char *path, int setnumber)
-{
- char key[CFG_MAX_KEY];
- int sev;
- char *lcltag;
-
- /* attempt to remove the volume from config storage */
- (void) snprintf(key, sizeof (key), "sv.set%d", setnumber);
- if (cfg_put_cstring(cfg, key, NULL, 0) < 0) {
- warn(NULL, gettext("unable to remove %s from "
- "config storage: %s"), path, cfg_error(&sev));
- } else {
- if (implicit_tag && *implicit_tag) {
- lcltag = implicit_tag;
- } else if (cfg_cluster_tag && *cfg_cluster_tag) {
- lcltag = cfg_cluster_tag;
- } else {
- lcltag = "-";
- }
- if (cfg_rem_user(cfg, path, lcltag, "sv") != CFG_USER_LAST) {
- warn(NULL, gettext("unable to remove %s from dsvol"),
- path);
- }
- cfg_changed = 1;
- }
-}