diff options
Diffstat (limited to 'usr/src/lib/libdscfg/common/cfg_vols.c')
-rw-r--r-- | usr/src/lib/libdscfg/common/cfg_vols.c | 1286 |
1 files changed, 0 insertions, 1286 deletions
diff --git a/usr/src/lib/libdscfg/common/cfg_vols.c b/usr/src/lib/libdscfg/common/cfg_vols.c deleted file mode 100644 index 6f0f8bb447..0000000000 --- a/usr/src/lib/libdscfg/common/cfg_vols.c +++ /dev/null @@ -1,1286 +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 <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/stat.h> -#include <sys/mkdev.h> -#include <strings.h> -#include <stdarg.h> -#include <stdlib.h> -#include <locale.h> -#include <errno.h> - -#include <sys/nsctl/cfg.h> - -#include <sys/unistat/spcs_s.h> -#include <sys/unistat/spcs_s_u.h> -#include <sys/unistat/spcs_errors.h> -#include <sys/unistat/spcs_s_impl.h> - -#include <sys/nsctl/sv.h> -#include <sys/nsctl/nsc_hash.h> - -#define DEV_EXPAND 32 - -#define DO_DISABLE 0 -#define DO_ENABLE 1 - -/* - * Utility functions for iiadm and rdcadm/sndradm. - */ - -typedef struct hash_data_s { - union { - char *users; - char *mode; - } u; - char *path; - char *node; - int setno; -} hash_data_t; - -typedef struct { - dev_t rdev; - mode_t mode; - char *path; -} device_t; - -static hash_data_t *make_svol_data(char *, char *, char *, int); -static hash_data_t *make_dsvol_data(char *, char *, char *, int); -static void delete_svol_data(void *); -static void delete_dsvol_data(void *); -static int sv_action(char *, CFGFILE *, char *, int); - -static int add_dev_entry(const char *); -static int compare(const void *, const void *); -static char *find_devid(const char *); -static void free_dev_entries(); -static void rebuild_devhash(); - -static hash_node_t **dsvol; -static int dsvol_loaded = 0; - -static hash_node_t **svol; -static int svol_loaded = 0; - -static hash_node_t **shadowvol; - -static hash_node_t **devhash; -static device_t *devlist; -static int devcount = 0; -static int devalloc = 0; - -/* - * cfg_add_user - * - * Description: - * Adds the calling tool as a user of the volume. - * - * Inputs: - * char *path: The pathname of the volume to be enabled. - * char *cnode: The device group name, or NULL if -C local or not cluster - * CFGFILE *cfg: A pointer to the current config file, or NULL if this - * function is to open/write/commit/close the change itself. - * - * Return values: - * CFG_USER_FIRST: Indicates that this is the first user of this - * particular volume. - * CFG_USER_OK: Indicates that the volume has already been entered into - * the config file. - * CFG_USER_ERR: Indicates that some failure has occurred and no changes - * to the config file have been made. - * CFG_USER_REPEAT: Indicates that this user has already registered for - * the volume. - */ -int -cfg_add_user(CFGFILE* cfg, char *path, char *cnode, char *user) -{ - int self_open, self_loaded, change_made; - char *ctag, search_key[ CFG_MAX_KEY ], buf[ CFG_MAX_BUF ]; - int retval, rc; - hash_data_t *data; - - self_open = (cfg == NULL); - self_loaded = 0; - change_made = 0; - - if (self_open) { - cfg = cfg_open(NULL); - if (cfg == NULL) { - return (CFG_USER_ERR); - } - - if (!cfg_lock(cfg, CFG_WRLOCK)) { - /* oops */ - cfg_close(cfg); - return (CFG_USER_ERR); - } - } - - /* Check cnode */ - ctag = cfg_get_resource(cfg); - if (cnode) { - if (ctag) { - if (strcmp(cnode, ctag)) - return (CFG_USER_ERR); - } else - cfg_resource(cfg, cnode); - } else - cnode = ctag; - - if (!dsvol_loaded) { - if (cfg_load_dsvols(cfg) < 0) { - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - self_loaded = 1; - } - - /* find the volume */ - (void) snprintf(search_key, CFG_MAX_KEY, "%s:%s", path, cnode); - data = nsc_lookup(dsvol, search_key); - - if (!data) { - /* whoops, not found. Add as new user */ - cfg_rewind(cfg, CFG_SEC_CONF); - (void) snprintf(buf, CFG_MAX_BUF, "%s %s %s", path, cnode, - user); - rc = cfg_put_cstring(cfg, "dsvol", buf, strlen(buf)); - if (rc < 0) { - if (self_loaded) { - cfg_unload_dsvols(); - } - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - /* reload hash, if we need to */ - if (!self_loaded) { - cfg_unload_dsvols(); - if (cfg_load_dsvols(cfg) < 0) { - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - } - retval = CFG_USER_FIRST; - change_made = 1; - } else { - /* Check to ensure we're not already listed */ - char *p = strdup(data->u.users); - char *q = strtok(p, ","); - while (q && (strcmp(q, user) != 0)) { - q = strtok(0, ","); - } - free(p); /* not using data; only testing 'q' ptr */ - - if (!q) { - /* not listed as a user */ - cfg_rewind(cfg, CFG_SEC_CONF); - (void) snprintf(buf, CFG_MAX_BUF, "%s %s %s,%s", - data->path, data->node, data->u.users, user); - (void) snprintf(search_key, CFG_MAX_KEY, "dsvol.set%d", - data->setno); - if (cfg_put_cstring(cfg, search_key, buf, - strlen(buf)) < 0) { - if (self_loaded) { - cfg_unload_dsvols(); - } - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - - /* - * Since we deleted an entry from the config - * file, we don't know what all the new - * set numbers are. We need to reload - * everything - */ - if (!self_loaded) { - cfg_unload_dsvols(); - if (cfg_load_dsvols(cfg) < 0) { - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - } - change_made = 1; - retval = CFG_USER_OK; - } else { - retval = CFG_USER_REPEAT; - } - } - - if (self_loaded) { - cfg_unload_dsvols(); - } - - if (self_open) { - if (change_made) - (void) cfg_commit(cfg); - cfg_close(cfg); - } - - return (retval); -} - -/* - * cfg_rem_user - * - * Description: - * Removes a user from the config file. - * - * Inputs: - * char *path: The pathname of the volume to be enabled. - * char *cnode: The device group name, or NULL if -C local or not cluster - * char *user: The subsystem that is adding this tag (sv, ii, sndr) - * CFGFILE *cfg: A pointer to the current config file, or NULL if this - * function is to open/write/commit/close the change itself. - * Return values: - * CFG_USER_ERR: An error occurred during the processing of this - * directive. - * CFG_USER_OK: User successfully removed; volume in use by other(s). - * CFG_USER_LAST: User successfuly removed; no other users registered - * CFG_USER_GONE: The volume is no longer listed in the dsvol section, - * indicating some sort of application-level error. - * - */ -int -cfg_rem_user(CFGFILE *cfg, char *path, char *cnode, char *user) -{ - int self_open, self_loaded, change_made; - char *ctag, search_key[ CFG_MAX_KEY ], buf[ CFG_MAX_BUF ]; - char cfg_key[ CFG_MAX_KEY ]; - hash_data_t *data; - int retval; - int force_remove; - - self_open = (cfg == NULL); - self_loaded = 0; - change_made = 0; - force_remove = (strcmp(user, "sv") == 0); - - if ('-' == *user) { - ++user; - } - - /* Check cnode */ - ctag = cfg_get_resource(cfg); - if (cnode) { - if (ctag) { - if (strcmp(cnode, ctag)) - return (CFG_USER_ERR); - } else - cfg_resource(cfg, cnode); - } else - cnode = ctag; - - if (self_open) { - cfg = cfg_open(NULL); - if (cfg == NULL) { - return (CFG_USER_ERR); - } - - if (!cfg_lock(cfg, CFG_WRLOCK)) { - /* oops */ - cfg_close(cfg); - return (CFG_USER_ERR); - } - } - - - change_made = 0; - if (!dsvol_loaded) { - if (cfg_load_dsvols(cfg) < 0) { - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - self_loaded = 1; - } - - /* find the volume */ - (void) snprintf(search_key, CFG_MAX_KEY, "%s:%s", path, cnode); - data = nsc_lookup(dsvol, search_key); - - if (!data) { - /* yipes */ - retval = CFG_USER_GONE; - } else if (force_remove) { - retval = CFG_USER_LAST; - cfg_rewind(cfg, CFG_SEC_CONF); - (void) snprintf(cfg_key, CFG_MAX_KEY, "dsvol.set%d", - data->setno); - if (cfg_put_cstring(cfg, cfg_key, NULL, 0) < 0) { - if (self_loaded) { - cfg_unload_dsvols(); - } - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - if (!self_loaded) { - cfg_unload_dsvols(); - if (cfg_load_dsvols(cfg) < 0) { - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - } - } else { - char *p = strdup(data->u.users); - char *q = strtok(p, ","); - int appended = 0; - - (void) snprintf(buf, CFG_MAX_BUF, "%s %s ", data->path, - data->node); - while (q && (strcmp(q, user) != 0)) { - if (appended) { - strcat(buf, ","); - strcat(buf, q); - } else { - strcat(buf, q); - appended = 1; - } - q = strtok(0, ","); - } - - if (!q) { - /* uh-oh */ - retval = CFG_USER_GONE; - } else { - /* old user skipped; add in remaining users */ - while (q = strtok(0, ", ")) { - if (appended) { - strcat(buf, ","); - strcat(buf, q); - } else { - strcat(buf, q); - appended = 1; - } - } - - if (appended) { - retval = CFG_USER_OK; - cfg_rewind(cfg, CFG_SEC_CONF); - (void) snprintf(cfg_key, CFG_MAX_KEY, - "dsvol.set%d", data->setno); - if (cfg_put_cstring(cfg, cfg_key, buf, - strlen(buf)) < 0) { - if (self_loaded) { - cfg_unload_dsvols(); - } - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - if (!self_loaded) { - cfg_unload_dsvols(); - if (cfg_load_dsvols(cfg) < 0) { - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - } - } else { - retval = CFG_USER_LAST; - cfg_rewind(cfg, CFG_SEC_CONF); - (void) snprintf(cfg_key, CFG_MAX_KEY, - "dsvol.set%d", data->setno); - if (cfg_put_cstring(cfg, cfg_key, NULL, - 0) < 0) { - if (self_loaded) { - cfg_unload_dsvols(); - } - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - /* - * Since we deleted an entry from the config - * file, we don't know what all the new - * set numbers are. We need to reload - * everything - */ - if (!self_loaded) { - cfg_unload_dsvols(); - if (cfg_load_dsvols(cfg) < 0) { - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - } - } - change_made = 1; - } - } - - if (self_loaded) { - cfg_unload_dsvols(); - } - - if (self_open) { - if (change_made) - (void) cfg_commit(cfg); - cfg_close(cfg); - } - - return (retval); -} - -/* - * Enable a volume under SV control (or add this char *user to the list - * of users of that volume). - * - * Parameters: - * cfg - The config file to use. - * path - The pathname of the volume - * ctag - The cluster tag for this volume (if any) - * user - The user (sv, ii, sndr) of the volume. - */ -int -cfg_vol_enable(CFGFILE *cfg, char *path, char *ctag, char *user) -{ - int rc; - int retval; - - if (!ctag || *ctag == '\0') { - ctag = "-"; - } - - retval = -1; - rc = cfg_add_user(cfg, path, ctag, user); - switch (rc) { - case CFG_USER_ERR: - spcs_log("dsvol", NULL, - gettext("unable to set up dsvol section of config for %s"), - path); - break; - case CFG_USER_OK: - retval = 0; - break; - case CFG_USER_FIRST: - /* enable sv! */ - retval = sv_action(path, cfg, ctag, DO_ENABLE); - if (retval < 0) { - (void) cfg_rem_user(cfg, path, ctag, user); - } - break; - default: - spcs_log("dsvol", NULL, - gettext("unexpected return from cfg_add_user(%d)"), rc); - break; - } - - return (retval); -} - -/* - * Disable a volume from SV control (or remove this char *user from the list - * of users of that volume). - * - * Parameters: - * cfg - The config file to use. - * path - The pathname of the volume - * ctag - The cluster tag for this volume (if any) - * user - The user (sv, ii, sndr) of the volume. - */ -int -cfg_vol_disable(CFGFILE *cfg, char *path, char *ctag, char *user) -{ - int rc; - int retval; - - if (!ctag || *ctag == '\0') { - ctag = "-"; - } - - retval = -1; - rc = cfg_rem_user(cfg, path, ctag, user); - switch (rc) { - case CFG_USER_ERR: - spcs_log("dsvol", NULL, - gettext("unable to set up dsvol section of config for %s"), - path); - break; - case CFG_USER_OK: - retval = 0; - break; - case CFG_USER_GONE: - spcs_log("dsvol", NULL, - gettext("%s tried to remove non-existent tag for %s"), - user, path); - break; - case CFG_USER_LAST: - /* diable sv! */ - retval = sv_action(path, cfg, ctag, DO_DISABLE); - break; - default: - spcs_log("dsvol", NULL, - gettext("unexpected return from cfg_rem_user(%d)"), rc); - break; - } - - return (retval); -} - -/* - * cfg_load_dsvols - * - * Description: - * Loads the dsvol section of the config file into a giant hash, to - * make searching faster. The important bit to remember is to not - * release the write lock between calling cfg_load_dsvols() and the - * cfg_*_user() functions. - * - * Assumptions: - * 1/ cfg file is open - * 2/ cfg file has been write-locked - * 3/ user of this routine may already be using hcreate/hsearch - * - * Return value: - * -1 if error, or total number of sets found - */ -int -cfg_load_dsvols(CFGFILE *cfg) -{ - int set, rc, entries; - char search_key[ CFG_MAX_KEY ]; - char *buf; - char **entry, *path, *cnode, *users; - hash_data_t *data; - int devs_added = 0; - int offset = 0; - char *ctag = cfg_get_resource(cfg); - if (!ctag || *ctag == '\0') { - ctag = "-"; - } - - dsvol = nsc_create_hash(); - if (!dsvol) { - return (-1); - } - - rc = 0; - cfg_rewind(cfg, CFG_SEC_CONF); - entries = cfg_get_section(cfg, &entry, "dsvol"); - for (set = 1; set <= entries; set++) { - buf = entry[set - 1]; - - /* split up the line */ - if (!(path = strtok(buf, " "))) { - /* oops, now what? */ - free(buf); - break; - } - if (!(cnode = strtok(0, " "))) { - free(buf); - break; - } - if (ctag && (strcmp(cnode, ctag) != 0)) { - ++offset; - free(buf); - continue; - } - - if (!(users = strtok(0, " "))) { - free(buf); - break; - } - - data = make_dsvol_data(path, cnode, users, set - offset); - if (!data) { - free(buf); - break; - } - (void) snprintf(search_key, CFG_MAX_KEY, "%s:%s", path, cnode); - rc = nsc_insert_node(dsvol, data, search_key); - if (rc < 0) { - free(buf); - break; - } - - /* we also need to keep track of node information */ - rc = add_dev_entry(path); - if (rc < 0) { - free(buf); - break; - } else if (rc) - ++devs_added; - - free(buf); - rc = 0; - } - - while (set < entries) - free(entry[set++]); - if (entries) - free(entry); - - if (devs_added) { - qsort(devlist, devcount, sizeof (device_t), compare); - rebuild_devhash(); - } - - dsvol_loaded = 1; - return (rc < 0? rc : entries); -} - -/* - * cfg_unload_dsvols - * - * Description: - * Free all memory allocated with cfg_load_dsvols. - */ -void -cfg_unload_dsvols() -{ - if (dsvol) { - nsc_remove_all(dsvol, delete_dsvol_data); - dsvol = 0; - dsvol_loaded = 0; - } -} - -/* - * cfg_load_svols - * - * Description: - * Loads the sv section of the config file into a giant hash, to make - * searching faster. The important bit to remember is to not release - * the write lock between calling cfg_load_svols() and the cfg_*_user() - * functions. - * - * Assumptions: - * 1/ cfg file is open - * 2/ cfg file has been write-locked - * 3/ user of this routine may already be using builtin hcreate/hsearch - */ -int -cfg_load_svols(CFGFILE *cfg) -{ - int set, entries, offset = 0; - char *buf, **entry; - char *path, *mode, *cnode; - hash_data_t *data; - char *ctag = cfg_get_resource(cfg); - if (!ctag || *ctag == '\0') { - ctag = "-"; - } - - svol = nsc_create_hash(); - if (!svol) { - return (-1); - } - - cfg_rewind(cfg, CFG_SEC_CONF); - entries = cfg_get_section(cfg, &entry, "sv"); - for (set = 1; set <= entries; set++) { - buf = entry[set - 1]; - - /* split up the line */ - if (!(path = strtok(buf, " "))) { - free(buf); - break; - } - if (!(mode = strtok(0, " "))) { - free(buf); - break; - } - if (!(cnode = strtok(0, " "))) { - cnode = ""; - } - - if (ctag && (strcmp(cnode, ctag) != 0)) { - ++offset; - free(buf); - continue; - } - - data = make_svol_data(path, mode, cnode, set - offset); - if (!data) { - free(buf); - break; - } - if (nsc_insert_node(svol, data, path) < 0) { - free(buf); - break; - } - free(buf); - } - while (set < entries) - free(entry[set++]); - if (entries) - free(entry); - - svol_loaded = 1; - return (0); -} - -/* - * cfg_unload_svols - * - * Description: - * Frees all memory allocated with cfg_load_dsvols - */ -void -cfg_unload_svols() -{ - if (svol) { - nsc_remove_all(svol, delete_svol_data); - svol = 0; - svol_loaded = 0; - } -} - -/* - * cfg_get_canonical_name - * - * Description: - * Find out whether a device is already known by another name in - * the config file. - * - * Parameters: - * cfg - The config file to use - * path - The pathname of the device - * result - (output) The name it is otherwise known as. This parameter - * must be freed by the caller. - * - * Return values: - * -1: error - * 0: name is as expected, or is not known - * 1: Name is known by different name (stored in 'result') - */ -int -cfg_get_canonical_name(CFGFILE *cfg, const char *path, char **result) -{ - int self_loaded; - char *alt_path; - int retval; - - if (devlist) { - self_loaded = 0; - } else { - if (cfg_load_shadows(cfg) < 0) { - return (-1); - } - self_loaded = 1; - } - - /* see if it exists under a different name */ - alt_path = find_devid(path); - if (!alt_path || strcmp(path, alt_path) == 0) { - *result = NULL; - retval = 0; - } else { - /* a-ha */ - *result = strdup(alt_path); - retval = 1; - } - - if (self_loaded) { - free_dev_entries(); - } - - return (retval); -} - -/* - * cfg_load_shadows - * - * Description: - * Load in shadow and bitmap volumes from the II section of the - * config file. SNDR's volumes are handled already by cfg_load_dsvols. - * Not all shadow volumes are listed under dsvol: they can be exported. - * - * Parameters: - * cfg - The config file to use - * - * Return values: - * -1: error - * 0: success - */ -int -cfg_load_shadows(CFGFILE *cfg) -{ - int set, self_loaded, rc, entries; - char *buf, **entry, *ptr; - int devs_added = 0; - - if (dsvol_loaded) { - self_loaded = 0; - } else { - if (cfg_load_dsvols(cfg) < 0) { - return (-1); - } - self_loaded = 1; - } - - shadowvol = nsc_create_hash(); - if (!shadowvol) { - return (-1); - } - - rc = 0; - cfg_rewind(cfg, CFG_SEC_CONF); - entries = cfg_get_section(cfg, &entry, "ii"); - for (set = 1; set <= entries; set++) { - buf = entry[set - 1]; - - /* skip the master vol */ - ptr = strtok(buf, " "); - - /* shadow is next */ - ptr = strtok(NULL, " "); - - rc = add_dev_entry(ptr); - if (rc < 0) { - free(buf); - break; - } else if (rc) - ++devs_added; - - /* and next is bitmap */ - ptr = strtok(NULL, " "); - - rc = add_dev_entry(ptr); - if (rc < 0) { - free(buf); - break; - } else if (rc) - ++devs_added; - rc = 0; - free(buf); - } - while (set < entries) - free(entry[set++]); - if (entries) - free(entry); - - if (self_loaded) { - cfg_unload_dsvols(); - } - - if (devs_added) { - /* sort it, in preparation for lookups */ - qsort(devlist, devcount, sizeof (device_t), compare); - rebuild_devhash(); - } - - return (rc); -} - -void -cfg_unload_shadows() -{ - /* do nothing */ -} - -/* ---------------------------------------------------------------------- */ - -static hash_data_t * -make_dsvol_data(char *path, char *cnode, char *users, int set) -{ - hash_data_t *data; - - data = (hash_data_t *)malloc(sizeof (hash_data_t)); - if (!data) { - return (0); - } - - data->u.users = strdup(users); - data->path = strdup(path); - data->node = strdup(cnode); - data->setno = set; - - return (data); -} - -static void -delete_dsvol_data(void *data) -{ - hash_data_t *p = (hash_data_t *)data; - - free(p->u.users); - free(p->path); - free(p->node); - free(p); -} - -static hash_data_t * -make_svol_data(char *path, char *mode, char *cnode, int set) -{ - hash_data_t *data; - - data = (hash_data_t *)malloc(sizeof (hash_data_t)); - if (!data) { - return (0); - } - - data->u.mode = strdup(mode); - data->path = strdup(path); - data->node = strdup(cnode); - data->setno = set; - - return (data); -} - - -static void -delete_svol_data(void *data) -{ - hash_data_t *p = (hash_data_t *)data; - - free(p->u.mode); - free(p->path); - free(p->node); - free(p); -} - -static int -sv_action(char *path, CFGFILE *caller_cfg, char *ctag, int enable) -{ - struct stat stb; - sv_conf_t svc; - int fd = -1; - int cfg_changed = 0; - CFGFILE *cfg; - int print_log = 0; - int err = 0, rc; - int sv_ioctl, spcs_err, self_loaded; - char *log_str1, *log_str2; - char key[ CFG_MAX_KEY ]; - char buf[ CFG_MAX_BUF ]; - hash_data_t *node; - device_t *statinfo = 0; - - if (caller_cfg == NULL) { - cfg = cfg_open(NULL); - if (cfg == NULL) - return (-1); - - if (ctag) - cfg_resource(cfg, ctag); - } else - cfg = caller_cfg; - - - self_loaded = 0; - sv_ioctl = (enable? SVIOC_ENABLE : SVIOC_DISABLE); - log_str1 = (enable? gettext("enabled %s") : gettext("disabled %s")); - log_str2 = (enable? gettext("unable to enable %s") : - gettext("unable to disable %s")); - spcs_err = (enable? SV_EENABLED : SV_EDISABLED); - bzero(&svc, sizeof (svc)); - - if (devhash) - statinfo = nsc_lookup(devhash, path); - - if (statinfo) { - if (!S_ISCHR(statinfo->mode)) - goto error; - svc.svc_major = major(statinfo->rdev); - svc.svc_minor = minor(statinfo->rdev); - } else { - if (stat(path, &stb) != 0) - goto error; - - if (!S_ISCHR(stb.st_mode)) - goto error; - svc.svc_major = major(stb.st_rdev); - svc.svc_minor = minor(stb.st_rdev); - } - - strncpy(svc.svc_path, path, sizeof (svc.svc_path)); - - fd = open(SV_DEVICE, O_RDONLY); - if (fd < 0) - goto error; - - svc.svc_flag = (NSC_DEVICE | NSC_CACHE); - svc.svc_error = spcs_s_ucreate(); - - do { - rc = ioctl(fd, sv_ioctl, &svc); - } while (rc < 0 && errno == EINTR); - - if (rc < 0) { - if (errno != spcs_err) { - spcs_log("sv", &svc.svc_error, log_str2, svc.svc_path); - if (enable) - goto error; - else - err = errno; - } else - err = spcs_err; - } - - spcs_log("sv", NULL, log_str1, svc.svc_path); - - /* SV enable succeeded */ - if (caller_cfg == NULL) /* was not previously locked */ - if (!cfg_lock(cfg, CFG_WRLOCK)) - goto error; - - if (err != spcs_err) { /* already enabled, already in config */ - if (enable) { - cfg_rewind(cfg, CFG_SEC_CONF); - (void) snprintf(buf, CFG_MAX_BUF, "%s - %s", path, - ctag? ctag : "-"); - if (cfg_put_cstring(cfg, "sv", buf, CFG_MAX_BUF) < 0) { - /* SV config not updated, so SV disable again */ - (void) ioctl(fd, SVIOC_DISABLE, &svc); - print_log++; - } else - cfg_changed = 1; - } else { - /* pull it out of the config */ - if (!svol_loaded) { - if (cfg_load_svols(cfg) < 0) { - if (NULL == caller_cfg) { - cfg_close(cfg); - } - return (-1); - } - self_loaded = 1; - } - node = nsc_lookup(svol, svc.svc_path); - if (node) { - cfg_rewind(cfg, CFG_SEC_CONF); - (void) snprintf(key, CFG_MAX_KEY, "sv.set%d", - node->setno); - if (cfg_put_cstring(cfg, key, NULL, NULL) < 0) { - spcs_log("sv", NULL, - gettext("failed to remove %s from " - "sv config"), svc.svc_path); - } - /* - * Since we deleted an entry from the config - * file, we don't know what all the new - * set numbers are. We need to reload - * everything - */ - if (!self_loaded) { - cfg_unload_svols(); - if (cfg_load_svols(cfg) < 0) { - if (NULL == caller_cfg) { - cfg_close(cfg); - } - return (-1); - } - } - cfg_changed = 1; - } - if (self_loaded) { - cfg_unload_svols(); - self_loaded = 0; - } - } - } - -#ifdef lint - (void) printf("extra line to shut lint up %s\n", module_names[0]); -#endif - -error: - if (fd >= 0) - (void) close(fd); - - if (cfg == NULL) - return (-1); - - if (cfg_changed) - if (caller_cfg == NULL) /* we opened config */ - (void) cfg_commit(cfg); - - if (caller_cfg == NULL) - cfg_close(cfg); - if ((cfg_changed) || (err == spcs_err)) - return (1); - if (print_log) - spcs_log("sv", NULL, - gettext("unable to add to configuration, disabled %s"), - svc.svc_path); - spcs_s_ufree(&svc.svc_error); - - return (-1); -} - -/* - * add_dev_entry - * - * Add an entry into the devlist and the devhash for future lookups. - * - * Return values: - * -1 An error occurred. - * 0 Entry added - * 1 Entry already exists. - */ -static int -add_dev_entry(const char *path) -{ - struct stat buf; - device_t *newmem; - hash_data_t *data; - - if (!devhash) { - devhash = nsc_create_hash(); - if (!devhash) { - return (-1); - } - } else { - data = nsc_lookup(devhash, path); - if (data) { - return (1); - } - } - - if (stat(path, &buf) < 0) { - /* ignore error, we are most likely deleting entry anyway */ - buf.st_rdev = 0; - } - - if (devcount >= devalloc) { - /* make some room */ - devalloc += DEV_EXPAND; - newmem = (device_t *)realloc(devlist, devalloc * - sizeof (device_t)); - if (!newmem) { - free_dev_entries(); - return (-1); - } else { - devlist = newmem; - } - } - - devlist[ devcount ].path = strdup(path); - devlist[ devcount ].rdev = buf.st_rdev; - devlist[ devcount ].mode = buf.st_mode; - - if (nsc_insert_node(devhash, &devlist[devcount], path) < 0) { - return (-1); - } - - ++devcount; - return (0); -} - -static void -rebuild_devhash() -{ - int i; - - if (!devhash) - nsc_remove_all(devhash, 0); - - devhash = nsc_create_hash(); - if (!devhash) - return; - - for (i = 0; i < devcount; i++) { - nsc_insert_node(devhash, &devlist[i], devlist[i].path); - } -} - -static int -compare(const void *va, const void *vb) -{ - device_t *a = (device_t *)va; - device_t *b = (device_t *)vb; - - return (b->rdev - a->rdev); -} - -static char * -find_devid(const char *path) -{ - device_t key; - device_t *result; - struct stat buf; - - if (!devlist || !devhash) - return (NULL); - - /* See if we already know the device id by this name */ - result = (device_t *)nsc_lookup(devhash, path); - if (result) { - return (NULL); - } - - /* try to find it by another name */ - if (stat(path, &buf) < 0) - return (NULL); - - key.rdev = buf.st_rdev; - - /* it's storted, so we use the binary-chop method to find it */ - result = bsearch(&key, devlist, devcount, sizeof (device_t), compare); - - if (result) { - return (result->path); - } - - return (NULL); -} - -static void -free_dev_entries() -{ - int i; - device_t *p; - - if (!devlist) { - return; - } - for (i = 0, p = devlist; i < devcount; i++, p++) { - free(p->path); - } - free(devlist); - devlist = NULL; - devcount = 0; - devalloc = 0; - - if (devhash) { - nsc_remove_all(devhash, 0); - devhash = NULL; - } -} |