diff options
Diffstat (limited to 'usr/src/cmd/avs/sv/svadm.c')
-rw-r--r-- | usr/src/cmd/avs/sv/svadm.c | 1515 |
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; - } -} |