summaryrefslogtreecommitdiff
path: root/usr/src/lib/librdc/common/rdcpersist.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/librdc/common/rdcpersist.c')
-rw-r--r--usr/src/lib/librdc/common/rdcpersist.c716
1 files changed, 716 insertions, 0 deletions
diff --git a/usr/src/lib/librdc/common/rdcpersist.c b/usr/src/lib/librdc/common/rdcpersist.c
new file mode 100644
index 0000000000..703c8eef11
--- /dev/null
+++ b/usr/src/lib/librdc/common/rdcpersist.c
@@ -0,0 +1,716 @@
+/*
+ * 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 <fcntl.h>
+#include <unistd.h>
+#include <stropts.h>
+#include <stdio.h>
+#include <errno.h>
+#include <libintl.h>
+#include <locale.h>
+#include <stdlib.h>
+
+#include <sys/nsctl/rdcerr.h>
+#include <sys/nsctl/rdc_ioctl.h>
+#include <sys/nsctl/librdc.h>
+#include <sys/nsctl/cfg.h>
+#include <sys/nsctl/nsc_hash.h>
+#include <sys/nsctl/sv.h>
+
+#include <sys/unistat/spcs_dtrinkets.h>
+#include <sys/unistat/spcs_etrinkets.h>
+#include <sys/unistat/spcs_s.h>
+#include <sys/unistat/spcs_s_u.h>
+#include <sys/unistat/spcs_s_impl.h>
+#include <sys/unistat/spcs_errors.h>
+
+typedef struct volcount_s {
+ int count;
+} volcount_t;
+
+hash_node_t **volhash = NULL;
+
+char *
+config2buf(char *buf, rdcconfig_t *rdc)
+{
+ snprintf(buf, CFG_MAX_BUF, "%s %s %s %s %s %s %s %s %s %s %s",
+ rdc->phost, rdc->pfile, rdc->pbmp, rdc->shost, rdc->sfile,
+ rdc->sbmp, rdc->direct, rdc->mode, rdc->group ? rdc->group : "",
+ rdc->ctag ? rdc->ctag : "", rdc->options ? rdc->options : "");
+ return (buf);
+
+}
+
+/*
+ * SV type functions.
+ */
+
+static void
+load_rdc_vols(CFGFILE *cfg)
+{
+ int set;
+ char key[ CFG_MAX_KEY ];
+ char buf[ CFG_MAX_BUF ];
+ char *vol, *bmp, *host1, *host2;
+ volcount_t *volcount;
+
+ if (volhash) {
+ return;
+ }
+
+ cfg_rewind(cfg, CFG_SEC_CONF);
+ volhash = nsc_create_hash();
+ for (set = 1; /*CSTYLED*/; set++) {
+ snprintf(key, CFG_MAX_KEY, "sndr.set%d", set);
+ if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF)) {
+ break;
+ }
+
+ host1 = strtok(buf, " ");
+ vol = strtok(NULL, " ");
+ bmp = strtok(NULL, " ");
+
+ if (!self_check(host1)) {
+ /* next one had better be ours */
+ host2 = strtok(NULL, " ");
+ vol = strtok(NULL, " ");
+ bmp = strtok(NULL, " ");
+
+ if (!self_check(host2)) {
+ continue;
+ }
+ }
+
+ /* primary vol may be used more than once */
+ volcount = (volcount_t *)nsc_lookup(volhash, vol);
+ if (volcount) {
+ volcount->count++;
+ } else {
+ volcount = (volcount_t *)malloc(sizeof (volcount_t));
+ volcount->count = 1;
+ nsc_insert_node(volhash, volcount, vol);
+ }
+
+ /* bitmap ought to be only used once */
+ volcount = (volcount_t *)nsc_lookup(volhash, bmp);
+ if (volcount) {
+ /* argh */
+ volcount->count++;
+ } else {
+ volcount = (volcount_t *)malloc(sizeof (volcount_t));
+ volcount->count = 1;
+ nsc_insert_node(volhash, volcount, bmp);
+ }
+ }
+}
+
+int
+sv_enable_one_nocfg(char *vol)
+{
+ struct stat sb;
+ sv_conf_t svc;
+ int fd;
+
+ bzero(&svc, sizeof (svc));
+ if (stat(vol, &sb) != 0) {
+ rdc_set_error(NULL, RDC_OS, 0, "unable to stat %s", vol);
+ return (-1);
+ }
+ if (!S_ISCHR(sb.st_mode)) {
+ rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL, "%s is not"
+ " a character device", vol);
+ return (-1);
+ }
+
+ svc.svc_major = major(sb.st_rdev);
+ svc.svc_minor = minor(sb.st_rdev);
+ strncpy(svc.svc_path, vol, sizeof (svc.svc_path));
+
+ fd = open(SV_DEVICE, O_RDONLY);
+ if (fd < 0) {
+ rdc_set_error(NULL, RDC_OS, 0, 0);
+ return (-1);
+ }
+
+ svc.svc_flag = (NSC_DEVICE | NSC_CACHE);
+ svc.svc_error = spcs_s_ucreate();
+
+ if (ioctl(fd, SVIOC_ENABLE, &svc) < 0) {
+ if (errno != SV_EENABLED) {
+ rdc_set_error(&svc.svc_error, RDC_INTERNAL,
+ RDC_NONFATAL, 0);
+ return (-1);
+ }
+ }
+
+ spcs_log("sv", NULL, gettext("enabled %s"), svc.svc_path);
+
+ close(fd);
+ return (1);
+}
+
+int
+sv_enable_nocfg(rdcconfig_t *rdc)
+{
+ struct stat stbv;
+ struct stat stbb;
+ sv_conf_t svcv;
+ sv_conf_t svcb;
+ char vol[NSC_MAXPATH];
+ char bmp[NSC_MAXPATH];
+ int fd = -1;
+
+
+ if (self_check(rdc->phost)) {
+ strncpy(vol, rdc->pfile, NSC_MAXPATH);
+ strncpy(bmp, rdc->pbmp, NSC_MAXPATH);
+ } else {
+ strncpy(vol, rdc->sfile, NSC_MAXPATH);
+ strncpy(bmp, rdc->sbmp, NSC_MAXPATH);
+ }
+
+ bzero(&svcv, sizeof (svcv));
+ bzero(&svcb, sizeof (svcb));
+
+ if ((stat(vol, &stbv) != 0) || (stat(bmp, &stbb) != 0))
+ return (-1);
+
+ if ((!S_ISCHR(stbv.st_mode)) || (!S_ISCHR(stbb.st_mode)))
+ return (-1);
+
+ svcv.svc_major = major(stbv.st_rdev);
+ svcb.svc_minor = minor(stbb.st_rdev);
+
+ strncpy(svcv.svc_path, vol, sizeof (svcv.svc_path));
+ strncpy(svcb.svc_path, bmp, sizeof (svcb.svc_path));
+
+ fd = open(SV_DEVICE, O_RDONLY);
+ if (fd < 0)
+ return (-1);
+
+ /* SV enable the volume */
+ svcv.svc_flag = (NSC_DEVICE | NSC_CACHE);
+ svcv.svc_error = spcs_s_ucreate();
+
+ if (ioctl(fd, SVIOC_ENABLE, &svcv) < 0) {
+ if (errno != SV_EENABLED) {
+ spcs_log("sv", &svcv.svc_error,
+ gettext("unable to enable %s"),
+ svcv.svc_path);
+ spcs_s_ufree(&svcv.svc_error);
+ return (-1);
+ }
+ }
+
+ /* SV enable the bitmap disable the vol on error */
+ svcb.svc_flag = (NSC_DEVICE | NSC_CACHE);
+ svcb.svc_error = spcs_s_ucreate();
+
+ if (ioctl(fd, SVIOC_ENABLE, &svcb) < 0) {
+ if (errno != SV_EENABLED) {
+ spcs_log("sv", &svcb.svc_error,
+ gettext("unable to enable %s"),
+ svcb.svc_path);
+ if (ioctl(fd, SVIOC_DISABLE, &svcv) < 0)
+ spcs_log("sv", &svcv.svc_error,
+ gettext("unable to disable %s"),
+ svcv.svc_path);
+
+ spcs_s_ufree(&svcv.svc_error);
+ spcs_s_ufree(&svcb.svc_error);
+ return (-1);
+ }
+ }
+
+
+ spcs_log("sv", NULL, gettext("enabled %s"), svcv.svc_path);
+ spcs_log("sv", NULL, gettext("enabled %s"), svcb.svc_path);
+ spcs_s_ufree(&svcv.svc_error);
+ spcs_s_ufree(&svcb.svc_error);
+
+
+ if (fd >= 0)
+ (void) close(fd);
+
+ return (1);
+}
+
+int
+do_autosv_enable(CFGFILE *cfg, rdcconfig_t *rdc)
+{
+ char vol[NSC_MAXPATH];
+ char bmp[NSC_MAXPATH];
+
+ cfg_load_svols(cfg);
+ cfg_load_dsvols(cfg);
+ cfg_load_shadows(cfg);
+ load_rdc_vols(cfg);
+
+ if (self_check(rdc->phost)) {
+ strncpy(vol, rdc->pfile, NSC_MAXPATH);
+ strncpy(bmp, rdc->pbmp, NSC_MAXPATH);
+ } else {
+ strncpy(vol, rdc->sfile, NSC_MAXPATH);
+ strncpy(bmp, rdc->sbmp, NSC_MAXPATH);
+ }
+ if (nsc_lookup(volhash, vol) == NULL) {
+ if (cfg_vol_enable(cfg, vol, rdc->ctag, "sndr") < 0) {
+ rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
+ "auto sv enable failed for %s", vol);
+ return (-1);
+ }
+ }
+ if (nsc_lookup(volhash, bmp) == NULL) {
+ if (cfg_vol_enable(cfg, bmp, rdc->ctag, "sndr") < 0) {
+ rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
+ "auto sv enable failed for %s", vol);
+ return (-1);
+ }
+ }
+
+ nsc_remove_all(volhash, free);
+ volhash = NULL;
+
+ cfg_unload_shadows();
+ cfg_unload_dsvols();
+ cfg_unload_svols();
+
+ return (1);
+}
+
+int
+do_autosv_disable(CFGFILE *cfg, rdcconfig_t *rdc)
+{
+ char vol[NSC_MAXPATH];
+ char bmp[NSC_MAXPATH];
+ volcount_t *vc;
+
+ cfg_load_svols(cfg);
+ cfg_load_dsvols(cfg);
+ cfg_load_shadows(cfg);
+ load_rdc_vols(cfg);
+
+ if (self_check(rdc->phost)) {
+ strncpy(vol, rdc->pfile, NSC_MAXPATH);
+ strncpy(bmp, rdc->pbmp, NSC_MAXPATH);
+ } else {
+ strncpy(vol, rdc->sfile, NSC_MAXPATH);
+ strncpy(bmp, rdc->sbmp, NSC_MAXPATH);
+ }
+
+ vc = nsc_lookup(volhash, vol);
+ if (vc && (vc->count == 1)) {
+ if (cfg_vol_disable(cfg, vol, rdc->ctag, "sndr") < 0)
+ rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
+ "auto sv disable failed for %s", vol);
+ } else if (!vc) {
+ rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
+ "Unable to find %s in config", vol);
+ }
+ vc = nsc_lookup(volhash, bmp);
+ if (vc && (vc->count == 1)) {
+ if (cfg_vol_disable(cfg, bmp, rdc->ctag, "sndr") < 0)
+ rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
+ "auto sv disable failed for %s", bmp);
+
+ } else if (!vc) {
+ rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
+ "Unable to find %s in config", bmp);
+ }
+
+ return (1);
+
+}
+
+/*
+ * do sv enables for the appropriate vol
+ * and bitmap. If called without persistance
+ * it will follow a chain and sv enable all
+ * otherwise, it will enable only the one
+ * set.
+ */
+int
+sv_enable(CFGFILE *cfg, rdcconfig_t *rdcs)
+{
+ rdcconfig_t *rdcp = NULL;
+
+ rdcp = rdcs;
+ if (!rdcp->persist) {
+
+ return (sv_enable_nocfg(rdcp));
+
+ } else if (cfg == NULL) {
+
+ return (-1);
+
+ }
+
+ do_autosv_enable(cfg, rdcp);
+
+ return (1);
+}
+
+int
+sv_disable(CFGFILE *cfg, rdcconfig_t *rdcs)
+{
+ rdcconfig_t *rdcp;
+
+ rdcp = rdcs;
+ if (!rdcp->persist) { /* don't disable */
+
+ return (1);
+
+ } else if (cfg == NULL) {
+
+ return (-1);
+
+ }
+
+ do_autosv_disable(cfg, rdcp);
+
+ return (1);
+
+}
+
+/*
+ * disable the appropriate bitmap in rdc
+ * and replace it with bitmap
+ */
+int
+sv_reconfig(CFGFILE *cfg, rdcconfig_t *rdc, char *oldbmp, char *newbmp)
+{
+ rdcconfig_t *rdcp;
+ int fail = 0;
+
+ rdcp = rdc;
+ if (!rdcp->persist) { /* just enable, don't disable */
+
+ sv_enable_one_nocfg(newbmp);
+
+ } else if (rdcp->persist) { /* do sv disable and enable */
+ volcount_t *vc;
+
+ cfg_load_svols(cfg);
+ cfg_load_dsvols(cfg);
+ cfg_load_shadows(cfg);
+ load_rdc_vols(cfg);
+
+ vc = (volcount_t *)nsc_lookup(volhash, oldbmp);
+ if (vc && (vc->count == 1)) {
+ if (cfg_vol_disable(cfg, oldbmp, rdc->ctag, "sndr") < 0)
+ rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
+ "auto sv disable failed for %s", oldbmp);
+
+ }
+ if (nsc_lookup(volhash, newbmp) == NULL) {
+ if (cfg_vol_enable(cfg,
+ newbmp, rdc->ctag, "sndr") < 0) {
+
+ rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
+ "auto sv enable failed for %s", newbmp);
+ fail++;
+ }
+ }
+ nsc_remove_all(volhash, free);
+ volhash = NULL;
+
+ cfg_unload_shadows();
+ cfg_unload_dsvols();
+ cfg_unload_svols();
+ if (fail)
+ return (-1);
+
+ }
+ return (1);
+
+}
+
+/*
+ * SNDR functions
+ */
+
+/*
+ * add_to_rdc_cfg
+ * this adds the successfully created rdc sets to libdscfg,
+ * also, as auto_sv stuff is part of libdscfg, it does the
+ * auto_sv stuff and enables the correct volumes
+ */
+int
+add_to_rdc_cfg(rdcconfig_t *rdcs)
+{
+ CFGFILE *cfg;
+ rdcconfig_t *rdcp;
+ char *buf;
+
+
+ buf = calloc(CFG_MAX_BUF, sizeof (char));
+ if (!buf) {
+ rdc_set_error(NULL, RDC_OS, RDC_FATAL, NULL);
+ return (NULL);
+ }
+
+ if ((cfg = cfg_open(NULL)) == NULL) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ return (-1);
+ }
+ if ((cfg_lock(cfg, CFG_WRLOCK)) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ return (-1);
+ }
+
+ rdcp = rdcs;
+ while (rdcp) {
+ buf = config2buf(buf, rdcp);
+ if ((sv_enable(cfg, rdcp) < 0) ||
+ (cfg_put_cstring(cfg, "sndr", buf, CFG_MAX_BUF) < 0)) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ free(buf);
+ return (-1);
+ }
+ rdcp = rdcp->next;
+ }
+ if (!cfg_commit(cfg)) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, NULL);
+ return (-1);
+ }
+
+ cfg_close(cfg);
+
+ return (0);
+}
+
+int
+cfg_lookup(CFGFILE *cfg, char *shost, char *sfile)
+{
+ char buf[CFG_MAX_BUF];
+ char key[CFG_MAX_KEY];
+ int setnum;
+ int numsets = 0;
+
+ numsets = cfg_get_num_entries(cfg, "sndr");
+ for (setnum = 1; setnum <= numsets; setnum++) {
+ bzero(key, CFG_MAX_KEY);
+ snprintf(key, CFG_MAX_KEY, "sndr.set%d.shost", setnum);
+ if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ return (-1);
+ }
+ if (strncmp(buf, shost, strlen(shost)))
+ continue;
+
+ bzero(key, CFG_MAX_KEY);
+ snprintf(key, CFG_MAX_KEY, "sndr.set%d.secondary", setnum);
+ if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ return (-1);
+ }
+ if (strncmp(buf, sfile, strlen(sfile)))
+ continue;
+ break;
+ }
+ return (setnum);
+}
+
+void
+remove_from_rdc_cfg(rdcconfig_t *rdcs)
+{
+ CFGFILE *cfg;
+ rdcconfig_t *rdcp;
+ char key[CFG_MAX_KEY];
+
+ rdcp = rdcs;
+ cfg = cfg_open(NULL);
+ cfg_lock(cfg, CFG_WRLOCK);
+
+ while (rdcp) {
+ snprintf(key, CFG_MAX_KEY, "sndr.set%d",
+ cfg_lookup(cfg, rdcp->shost, rdcp->sfile));
+ if ((sv_disable(cfg, rdcp) < 0) ||
+ (cfg_put_cstring(cfg, key, NULL, 0)) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ }
+
+ rdcp = rdcp->next;
+ }
+ cfg_commit(cfg);
+ cfg_close(cfg);
+}
+/*ARGSUSED*/
+int
+replace_entry(int offset, char *entry)
+{
+ return (1);
+}
+
+/*
+ * this will set the value at "field" in dscfg to the
+ * value contained in entry.
+ * for things like bitmap reconfigs, only pass one rdc
+ * not a chain
+ */
+int
+replace_cfgfield(rdcconfig_t *rdc, char *field, char *entry)
+{
+ CFGFILE *cfg;
+ rdcconfig_t *rdcp;
+ char key[CFG_MAX_KEY];
+ char newentry[CFG_MAX_BUF];
+ char oldbmp[CFG_MAX_BUF];
+ int setnum;
+ int ispbmp = 0;
+ int issbmp = 0;
+
+ if (strncmp(field, "pbitmap", NSC_MAXPATH) == 0)
+ ispbmp++;
+ if (strncmp(field, "sbitmap", NSC_MAXPATH) == 0)
+ issbmp++;
+
+ bzero(newentry, sizeof (newentry));
+ if (!entry || strlen(entry) == 0)
+ *newentry = '-';
+ else
+ strncpy(newentry, entry, CFG_MAX_BUF);
+
+
+ if ((cfg = cfg_open(NULL)) == NULL) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ return (-1);
+ }
+ if ((cfg_lock(cfg, CFG_WRLOCK)) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ return (-1);
+ }
+
+ rdcp = rdc;
+ while (rdcp) {
+ if ((setnum = cfg_lookup(cfg, rdcp->shost, rdcp->sfile)) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ return (-1);
+ }
+ snprintf(key, CFG_MAX_KEY, "sndr.set%d.%s", setnum, field);
+ if (!((ispbmp || issbmp) &&
+ (cfg_get_cstring(cfg, key, oldbmp, CFG_MAX_BUF)) == 0)) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, "unable to get %s",
+ key);
+ }
+ if (((ispbmp && self_check(rdcp->phost)) ||
+ (issbmp && self_check(rdcp->shost))) &&
+ (sv_reconfig(cfg, rdcp, oldbmp, newentry) < 0)) {
+ rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
+ "unable to sv reconfig %s to %s", oldbmp, newentry);
+ return (-1);
+ }
+
+ if ((cfg_put_cstring(cfg, key, newentry, CFG_MAX_BUF)) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ return (-1);
+ }
+ rdcp = rdcp->next;
+ }
+ cfg_commit(cfg);
+ cfg_close(cfg);
+ return (1);
+}
+
+/*
+ * reverse_in_cfg
+ * used by RDC_OPT_REVERSE_ROLE
+ * swaps primary info and secondary info
+ */
+int
+reverse_in_cfg(rdcconfig_t *rdc)
+{
+ CFGFILE *cfg;
+ rdcconfig_t *rdcp = NULL;
+ char key[CFG_MAX_KEY];
+ int setnum;
+
+ if ((cfg = cfg_open(NULL)) == NULL) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ return (-1);
+ }
+ if ((cfg_lock(cfg, CFG_WRLOCK)) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ return (-1);
+ }
+
+ rdcp = rdc;
+ while (rdcp) {
+ if ((setnum = cfg_lookup(cfg, rdcp->shost, rdcp->sfile)) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ goto badconfig;
+ }
+ bzero(key, CFG_MAX_KEY);
+ snprintf(key, CFG_MAX_KEY, "sndr.set%d.phost", setnum);
+ if ((cfg_put_cstring(cfg, key, rdcp->shost, CFG_MAX_BUF)) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ goto badconfig;
+ }
+ bzero(key, CFG_MAX_KEY);
+ snprintf(key, CFG_MAX_KEY, "sndr.set%d.primary", setnum);
+ if ((cfg_put_cstring(cfg, key, rdcp->sfile, CFG_MAX_BUF)) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ goto badconfig;
+ }
+ bzero(key, CFG_MAX_KEY);
+ snprintf(key, CFG_MAX_KEY, "sndr.set%d.pbitmap", setnum);
+ if ((cfg_put_cstring(cfg, key, rdcp->sbmp, CFG_MAX_BUF)) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ goto badconfig;
+ }
+ bzero(key, CFG_MAX_KEY);
+ snprintf(key, CFG_MAX_KEY, "sndr.set%d.shost", setnum);
+ if ((cfg_put_cstring(cfg, key, rdcp->phost, CFG_MAX_BUF)) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ goto badconfig;
+ }
+ bzero(key, CFG_MAX_KEY);
+ snprintf(key, CFG_MAX_KEY, "sndr.set%d.secondary", setnum);
+ if ((cfg_put_cstring(cfg, key, rdcp->pfile, CFG_MAX_BUF)) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ goto badconfig;
+ }
+ bzero(key, CFG_MAX_KEY);
+ snprintf(key, CFG_MAX_KEY, "sndr.set%d.sbitmap", setnum);
+ if ((cfg_put_cstring(cfg, key, rdcp->pbmp, CFG_MAX_BUF)) < 0) {
+ rdc_set_error(NULL, RDC_DSCFG, 0, 0);
+ goto badconfig;
+ }
+ rdcp = rdcp->next;
+ }
+ if (!cfg_commit(cfg)) {
+ cfg_close(cfg);
+ return (-1);
+ }
+ cfg_close(cfg);
+ return (0);
+
+badconfig:
+ cfg_close(cfg);
+ return (-1);
+}