diff options
Diffstat (limited to 'usr/src/cmd/avs/rdc/sndradm.c')
-rw-r--r-- | usr/src/cmd/avs/rdc/sndradm.c | 5715 |
1 files changed, 0 insertions, 5715 deletions
diff --git a/usr/src/cmd/avs/rdc/sndradm.c b/usr/src/cmd/avs/rdc/sndradm.c deleted file mode 100644 index 4bcb3008dd..0000000000 --- a/usr/src/cmd/avs/rdc/sndradm.c +++ /dev/null @@ -1,5715 +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 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <sys/types.h> -#include <sys/utsname.h> -#include <sys/wait.h> -#include <stdio.h> -#include <errno.h> -#include <values.h> -#include <limits.h> -#include <fcntl.h> -#include <strings.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/stat.h> - -#include <locale.h> -#include <langinfo.h> -#include <libintl.h> -#include <stdarg.h> -#include <netdb.h> -#include <ctype.h> - -#include <sys/nsctl/rdc_io.h> -#include <sys/nsctl/rdc_ioctl.h> -#include <sys/nsctl/rdc_prot.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/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netinet/tcp.h> -#include <rpc/rpc_com.h> -#include <rpc/rpc.h> - -#include <sys/nsctl/librdc.h> -#include <sys/nsctl/nsc_hash.h> - -#include "rdcadm.h" - -/* - * support for the special cluster tag "local" to be used with -C in a - * cluster for local volumes. - */ - -#define RDC_LOCAL_TAG "local" - -typedef struct volcount_s { - int count; -} volcount_t; -hash_node_t **volhash = NULL; - -/* - * rdc_islocal is only pertinent while creating the pairs array. - * after all the pairs are set, its value is useless, retaining - * the last value it was set to. - * its only reason in life is to suppress an error message in 2 - * places where the inappropriate becomes appropriate (a supplied - * ctag which does not match an implied one cfg_dgame()). This - * happens when C "local" is supplied. It is then used to make an - * error message clearer. A - * gettext("set %s does not match", rdc_islocal < 1?dga:dgb) situation - */ -static int rdc_islocal = 0; - -char *program; - -#define min(a, b) ((a) > (b) ? (b) : (a)) - -static char place_holder[] = "-"; /* cfg place holder value */ - -/* - * config file user level Dual copy pair structure - */ -typedef struct _sd_dual_pair { - char fhost[MAX_RDC_HOST_SIZE]; /* Hostname for primary device */ - char fnetaddr[RDC_MAXADDR]; /* Host netaddr for primary device */ - char ffile[NSC_MAXPATH]; /* Primary device */ - char fbitmap[NSC_MAXPATH]; /* Primary bitmap device */ - char thost[MAX_RDC_HOST_SIZE]; /* Hostname for secondary device */ - char tnetaddr[RDC_MAXADDR]; /* Host netaddr for secondary device */ - char tfile[NSC_MAXPATH]; /* Secondary device */ - char tbitmap[NSC_MAXPATH]; /* Secondary bitmap device */ - char directfile[NSC_MAXPATH]; /* Local FCAL direct IO volume */ - char group[NSC_MAXPATH]; /* Group name */ - char ctag[MAX_RDC_HOST_SIZE]; /* Cluster resource name tag */ - char diskqueue[NSC_MAXPATH]; /* Disk Queue volume */ - int doasync; /* Device is in sync/async mode */ -} _sd_dual_pair_t; - -#define EXTRA_ARGS 6 /* g grp C ctag q diskqueue */ - -static int rdc_operation( - CFGFILE *, char *, char *, char *, char *, char *, char *, - int, int, char *, char *, char *, char *, int *, int); -int read_config(int, char *, char *, char *); -static int read_libcfg(int, char *, char *); -int prompt_user(int, int); -static void rdc_check_dgislocal(char *); -void process_clocal(char *); -static void usage(void); -void q_usage(int); -static void load_rdc_vols(CFGFILE *); -static void unload_rdc_vols(); -static int perform_autosv(); -static void different_devs(char *, char *); -static void validate_name(CFGFILE *, char *); -static void set_autosync(int, char *, char *, char *); -static int autosync_is_on(char *tohost, char *tofile); -static void enable_autosync(char *fhost, char *ffile, char *thost, char *tfile); -static void checkgfields(CFGFILE *, int, char *, char *, char *, char *, - char *, char *, char *, char *, char *); -static void checkgfield(CFGFILE *, int, char *, char *, char *); -static int rdc_bitmapset(char *, char *, char *, int, nsc_off_t); -static int parse_cfg_buf(char *, _sd_dual_pair_t *, char *); -static void verify_groupname(char *grp); -extern char *basename(char *); - -int rdc_maxsets; -static _sd_dual_pair_t *pair_list; - -struct netbuf svaddr; -struct netbuf *svp; -struct netconfig nconf; -struct netconfig *conf; -struct knetconfig knconf; - -static char *reconfig_pbitmap = NULL; -static char *reconfig_sbitmap = NULL; -#ifdef _RDC_CAMPUS -static char *reconfig_direct = NULL; -#endif -static char *reconfig_group = NULL; -static char reconfig_ctag[MAX_RDC_HOST_SIZE]; -static int reconfig_doasync = -1; - -static int clustered = 0; -static int proto_test = 0; -int allow_role = 0; - - -static char * -rdc_print_state(rdc_set_t *urdc) -{ - if (!urdc) - return (""); - - if (urdc->sync_flags & RDC_VOL_FAILED) - return (gettext("volume failed")); - else if (urdc->sync_flags & RDC_FCAL_FAILED) - return (gettext("fcal failed")); - else if (urdc->bmap_flags & RDC_BMP_FAILED) - return (gettext("bitmap failed")); - else if (urdc->flags & RDC_DISKQ_FAILED) - return (gettext("disk queue failed")); - else if (urdc->flags & RDC_LOGGING) { - if (urdc->sync_flags & RDC_SYNC_NEEDED) - return (gettext("need sync")); - else if (urdc->sync_flags & RDC_RSYNC_NEEDED) - return (gettext("need reverse sync")); - else if (urdc->flags & RDC_QUEUING) - return (gettext("queuing")); - else - return (gettext("logging")); - } else if ((urdc->flags & RDC_SLAVE) && (urdc->flags & RDC_SYNCING)) { - if (urdc->flags & RDC_PRIMARY) - return (gettext("reverse syncing")); - else - return (gettext("syncing")); - } else if (urdc->flags & RDC_SYNCING) { - if (urdc->flags & RDC_PRIMARY) - return (gettext("syncing")); - else - return (gettext("reverse syncing")); - } - - return (gettext("replicating")); -} - - -static int -rdc_print(int file_format, int verbose, char *group_arg, char *ctag_arg, - char *user_shost, char *user_sdev, CFGFILE *cfgp) -{ - rdc_status_t *rdc_status; - spcs_s_info_t ustatus; - rdc_set_t *urdc; - size_t size; - int i, rc, max; - char *tohost, *tofile; - _sd_dual_pair_t pair; - char *tmptohost = pair.thost; - char *tmptofile = pair.tfile; - char *fromhost = pair.fhost; - char *fromfile = pair.ffile; - char *frombitmap = pair.fbitmap; - char *tobitmap = pair.tbitmap; - char *directfile = pair.directfile; - char *group = pair.group; - char *diskqueue = pair.diskqueue; - char *ctag = pair.ctag; - CFGFILE *cfg; - int j; - int setnumber; - char key[CFG_MAX_KEY]; - char buf[CFG_MAX_BUF]; - char sync[16]; - int match, found; - - size = sizeof (rdc_status_t) + (sizeof (rdc_set_t) * (rdc_maxsets - 1)); - match = (user_shost != NULL || user_sdev != NULL); - found = 0; - - if (user_shost == NULL && user_sdev != NULL) - user_shost = ""; - else if (user_shost != NULL && user_sdev == NULL) - user_sdev = ""; - - rdc_status = malloc(size); - if (!rdc_status) { - rdc_err(NULL, - gettext("unable to allocate %ld bytes"), size); - } - - rdc_status->nset = rdc_maxsets; - ustatus = spcs_s_ucreate(); - - rc = RDC_IOCTL(RDC_STATUS, rdc_status, 0, 0, 0, 0, ustatus); - if (rc == SPCS_S_ERROR) { - rdc_err(&ustatus, gettext("statistics error")); - } - - spcs_s_ufree(&ustatus); - - max = min(rdc_status->nset, rdc_maxsets); - - if (cfgp != NULL) { - cfg = cfgp; - cfg_rewind(cfg, CFG_SEC_CONF); - } else { - if ((cfg = cfg_open(NULL)) == NULL) - rdc_err(NULL, - gettext("unable to access configuration")); - - if (!cfg_lock(cfg, CFG_RDLOCK)) - rdc_err(NULL, gettext("unable to lock configuration")); - } - - for (i = 0; i < max; i++) { - urdc = &rdc_status->rdc_set[i]; - - if (!(urdc->flags & RDC_ENABLED)) - continue; - - if (match && - (strcmp(user_shost, urdc->secondary.intf) != 0 || - strcmp(user_sdev, urdc->secondary.file) != 0)) - continue; - - tohost = urdc->secondary.intf; - tofile = urdc->secondary.file; - found = 1; - - /* get sndr entries until shost, sfile match */ - for (j = 0; j < rdc_maxsets; j++) { - setnumber = j + 1; - (void) snprintf(key, sizeof (key), - "sndr.set%d", setnumber); - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) { - break; - } - - if (parse_cfg_buf(buf, &pair, NULL)) - rdc_err(NULL, gettext("cfg input error")); - - if (strcmp(tmptofile, tofile) != 0) - continue; - if (strcmp(tmptohost, tohost) != 0) - continue; - - if (pair.doasync == 0) - (void) strcpy(sync, "sync"); - else - (void) strcpy(sync, "async"); - - /* Got the matching entry */ - - break; - } - - if (j == rdc_maxsets) - continue; /* not found in config */ - - if (strcmp(group_arg, "") != 0 && - strncmp(group_arg, group, NSC_MAXPATH) != 0) - continue; - - if (strcmp(ctag_arg, "") != 0 && - strncmp(ctag_arg, ctag, MAX_RDC_HOST_SIZE) != 0) - continue; - - if (file_format) { - (void) printf("%s %s %s %s %s %s %s %s", - fromhost, fromfile, frombitmap, - tohost, tofile, tobitmap, - directfile, sync); - if (strlen(group) != 0) - (void) printf(" g %s", group); - if ((strlen(ctag) != 0) && (ctag[0] != '-')) - (void) printf(" C %s", ctag); - if (strlen(diskqueue) != 0) - (void) printf(" q %s", diskqueue); - (void) printf("\n"); - continue; - } - - if (strcmp(group_arg, "") != 0 && - strncmp(group_arg, urdc->group_name, NSC_MAXPATH) != 0) - continue; - - if (!(urdc->flags & RDC_PRIMARY)) { - (void) printf(gettext("%s\t<-\t%s:%s\n"), - urdc->secondary.file, urdc->primary.intf, - urdc->primary.file); - } else { - (void) printf(gettext("%s\t->\t%s:%s\n"), - urdc->primary.file, urdc->secondary.intf, - urdc->secondary.file); - } - if (!verbose) - continue; - - if (urdc->autosync) - (void) printf(gettext("autosync: on")); - else - (void) printf(gettext("autosync: off")); - - (void) printf(gettext(", max q writes: %lld"), urdc->maxqitems); - (void) printf(gettext(", max q fbas: %lld"), urdc->maxqfbas); - (void) printf(gettext(", async threads: %d"), - urdc->asyncthr); - (void) printf(gettext(", mode: %s"), - pair.doasync ? "async" : "sync"); - - if (strlen(urdc->group_name) != 0) - (void) printf(gettext(", group: %s"), urdc->group_name); - if ((strlen(ctag) != 0) && (ctag[0] != '-')) - (void) printf(gettext(", ctag: %s"), ctag); - if (strlen(urdc->disk_queue) != 0) { - (void) printf(gettext(", %s diskqueue: %s"), - (urdc->flags & RDC_QNOBLOCK) ? gettext("non blocking") : - gettext("blocking"), urdc->disk_queue); - } - - (void) printf(gettext(", state: %s"), rdc_print_state(urdc)); - (void) printf(gettext("\n")); - - } - - if (!cfgp) - cfg_close(cfg); - - free(rdc_status); - - if (match && !found) { - rdc_warn(NULL, gettext("unable to find set %s:%s"), - user_shost, user_sdev); - } - - return (0); -} - - -int -parse_extras(int argc, char *args[], int i) -{ - int gflag = 0; - int Cflag = 0; - int qflag = 0; - int j; - - (void) strcpy(pair_list[i].ctag, ""); - (void) strcpy(pair_list[i].group, ""); - (void) strcpy(pair_list[i].diskqueue, ""); - - if (argc == 0) - return (0); - - if (argc != 2 && argc != 4 && argc != 6) - return (-1); - - for (j = 0; j < argc; j += 2) { - if (strcmp(args[j], "g") == 0) { - if (gflag) - return (-1); - (void) strncpy(pair_list[i].group, args[j + 1], - NSC_MAXPATH); - gflag = 1; - } - if (strcmp(args[j], "C") == 0) { - if (!clustered) - return (-1); - if (Cflag) - return (-1); - (void) strncpy(pair_list[i].ctag, args[j + 1], - MAX_RDC_HOST_SIZE); - process_clocal(pair_list[i].ctag); - Cflag = 1; - } - if (strcmp(args[j], "q") == 0) { - if (qflag) - return (-1); - (void) strncpy(pair_list[i].diskqueue, args[j + 1], - NSC_MAXPATH); - qflag = 1; - } - } - - return (0); -} - -static int -parse_cfg_buf(char *buf, _sd_dual_pair_t *pair, char *lghn) -{ - int rc = 0; - char sync[16]; - char options[64], *p, *q; - int len; - - rc = sscanf(buf, "%s %s %s %s %s %s %s %s %s %s %s %s", pair->fhost, - pair->ffile, pair->fbitmap, pair->thost, pair->tfile, - pair->tbitmap, pair->directfile, sync, pair->group, - pair->ctag, options, pair->diskqueue); - - if (rc != 12) - rdc_err(NULL, gettext("cfg input error")); - - if (strcmp(pair->diskqueue, place_holder) == 0) - (void) strcpy(pair->diskqueue, ""); - - if (strcmp(pair->group, place_holder) == 0) - (void) strcpy(pair->group, ""); - - if (strcmp(sync, "sync") == 0) - pair->doasync = 0; - else if (strcmp(sync, "async") == 0) - pair->doasync = 1; - else { - rdc_err(NULL, - gettext("set %s:%s neither sync nor async"), - pair->thost, pair->tfile); - } - - if (lghn && (p = strstr(options, "lghn="))) { - p += 5; - q = strchr(p, ';'); - if (q) { - /* LINTED p & q limited to options[64] */ - len = q - p; - } else { - len = strlen(p); - } - (void) strncpy(lghn, p, len); - lghn[len] = '\0'; - } else if (lghn) { - *lghn = '\0'; - } - - return (0); -} - -static int -ctag_check(char *fromhost, char *fromfile, char *frombitmap, char *tohost, - char *tofile, char *tobitmap, char *ctag, char *diskq) -{ - char *file_dgname; - char *bmp_dgname; - char *que_dgname; - char *localfile; - char file_buf[MAX_RDC_HOST_SIZE]; - char bmp_buf[MAX_RDC_HOST_SIZE]; - char que_buf[NSC_MAXPATH]; - int is_primary; - struct hostent *hp; - char fromname[MAXHOSTNAMELEN], toname[MAXHOSTNAMELEN]; - - if (!clustered) - return (0); - - hp = gethost_byname(fromhost); - (void) strncpy(fromname, hp->h_name, MAXHOSTNAMELEN); - hp = gethost_byname(tohost); - (void) strncpy(toname, hp->h_name, MAXHOSTNAMELEN); - if (!self_check(fromname) && !self_check(toname)) { - /* - * If we could get a list of logical hosts on this cluster - * then we could print something intelligent about where - * the volume is mastered. For now, just print some babble - * about the fact that we have no idea. - */ - rdc_err(NULL, - gettext("either %s:%s or %s:%s is not local"), - fromhost, fromfile, tohost, tofile); - } - - is_primary = self_check(fromname); - - /* - * If implicit disk group name and no ctag specified by user, - * we set the ctag to it. - * If implicit disk group name, it must match any supplied ctag. - */ - localfile = is_primary ? fromfile : tofile; - file_dgname = cfg_dgname(localfile, file_buf, sizeof (file_buf)); - if (file_dgname && strlen(file_dgname)) - rdc_check_dgislocal(file_dgname); - - /* - * Autogenerate a ctag, if not "-C local" or no "-C " specified - */ - if (!rdc_islocal && !strlen(ctag) && file_dgname && strlen(file_dgname)) - (void) strncpy(ctag, file_dgname, MAX_RDC_HOST_SIZE); - - /* - * making an exception here for users giving the "local"tag - * this overrides this error message. (rdc_islocal ! = 1) - */ - if (!rdc_islocal && strlen(ctag) && - file_dgname && strlen(file_dgname) && - strncmp(ctag, file_dgname, MAX_RDC_HOST_SIZE)) { - rdc_warn(NULL, gettext("ctag \"%s\" does not " - "match disk group name \"%s\" of volume %s"), ctag, - file_dgname, localfile); - return (-1); - } - - /* - * Do we have a non-volume managed disk without -C local specified? - */ - if (!rdc_islocal && (!file_dgname || !strlen(file_dgname))) { - rdc_err(NULL, gettext("volume \"%s\" is not part" - " of a disk group,\nplease specify resource ctag\n"), - localfile); - } - - /* - * Do we have a volume managed disk with -C local? - */ - if (rdc_islocal && file_dgname && (strlen(file_dgname) > 0)) { - rdc_err(NULL, gettext( - "volume \"%s\" is part of a disk group\n"), localfile); - } - - /* - * Local bitmap must also have same ctag. - */ - localfile = is_primary ? frombitmap : tobitmap; - bmp_dgname = cfg_dgname(localfile, bmp_buf, sizeof (bmp_buf)); - if (bmp_dgname && strlen(bmp_dgname)) - rdc_check_dgislocal(bmp_dgname); - - /* - * Assure that if the primary has a device group, so must the bitmap - */ - if ((file_dgname && strlen(file_dgname)) && - (!bmp_dgname || !strlen(bmp_dgname))) { - rdc_warn(NULL, gettext("bitmap %s is not in disk group \"%s\""), - localfile, rdc_islocal < 1?file_dgname:ctag); - return (-1); - } - - /* - * Assure that if the if there is a ctag, it must match the bitmap - */ - if (!rdc_islocal && strlen(ctag) && - bmp_dgname && strlen(bmp_dgname) && - strncmp(ctag, bmp_dgname, MAX_RDC_HOST_SIZE)) { - rdc_warn(NULL, gettext("ctag \"%s\" does not " - "match disk group name \"%s\" of bitmap %s"), ctag, - bmp_dgname, localfile); - return (-1); - } - - /* - * If this is the SNDR primary and there is a local disk queue - */ - if (is_primary && diskq[0]) { - - /* - * Local disk queue must also have same ctag. - */ - que_dgname = cfg_dgname(diskq, que_buf, sizeof (que_buf)); - if (que_dgname && strlen(que_dgname)) - rdc_check_dgislocal(que_dgname); - - /* - * Assure that if the primary has a device group, so must - * the disk queue - */ - if ((file_dgname && strlen(file_dgname)) && - (!que_dgname || !strlen(que_dgname))) { - rdc_warn(NULL, gettext("disk queue %s is not in disk " - "group \"%s\""), diskq, - rdc_islocal < 1?file_dgname:ctag); - return (-1); - } - - /* - * Assure that if the if there is a ctag, it must match - * the disk queue - */ - if (!rdc_islocal && strlen(ctag) && - que_dgname && strlen(que_dgname) && - strncmp(ctag, que_dgname, MAX_RDC_HOST_SIZE)) { - rdc_warn(NULL, gettext("ctag \"%s\" does not " - "match disk group name \"%s\" of disk queue %s"), - ctag, que_dgname, diskq); - return (-1); - } - } - - return (0); -} - -#define DISKQ_OKAY 0 -#define DISKQ_FAIL 1 -#define DISKQ_REWRITEG 2 -/* - * check that newq is compatable with the groups current disk queue. - * Newq is incompatable if it is set and the groups queue is set and the queues - * are different. - * - * if newq is not set but should be, it will be set to the correct value. - * returns: - * DISK_REWRITEG entire group needs to take new value of disk_queue - * DISKQ_OKAY newq contains a value that matches the group. - * DISKQ_FAIL disk queues are incompatible. - */ -static int -check_diskqueue(CFGFILE *cfg, char *newq, char *newgroup) -{ - int i, setnumber; - _sd_dual_pair_t pair; - char *group = pair.group; - char *diskqueue = pair.diskqueue; - char buf[CFG_MAX_BUF]; - char key[CFG_MAX_KEY]; - int open_cfg = cfg == NULL ? 1 : 0; - - - if (newgroup == NULL || *newgroup == '\0') { - if (*newq == '\0') - return (DISKQ_OKAY); /* okay, */ - newgroup = "--nomatch--"; - } - - if (open_cfg) { - if ((cfg = cfg_open(NULL)) == NULL) - rdc_err(NULL, - gettext("unable to access configuration")); - if (!cfg_lock(cfg, CFG_RDLOCK)) - rdc_err(NULL, gettext("unable to lock configuration")); - } - - /*CSTYLED*/ - for (i = 0; ; i++) { - setnumber = i + 1; - (void) snprintf(key, sizeof (key), "sndr.set%d", setnumber); - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) - break; - /* - * I think this is quicker than - * having to double dip into the config - */ - if (parse_cfg_buf(buf, &pair, NULL)) - rdc_err(NULL, gettext("cfg input error")); - - if (strncmp(group, newgroup, NSC_MAXPATH) != 0) { - if (((strncmp(diskqueue, newq, NSC_MAXPATH) == 0)) && - (diskqueue[0] != '\0')) { - if (open_cfg) - cfg_close(cfg); - return (DISKQ_FAIL); - } - continue; - } - if (*newq == '\0') { - if (diskqueue[0] != '\0') - (void) strncpy(newq, diskqueue, NSC_MAXPATH); - if (open_cfg) - cfg_close(cfg); - return (DISKQ_OKAY); /* okay, */ - } - - if (open_cfg) - cfg_close(cfg); - if (diskqueue[0] == '\0') /* no queue here */ - return (DISKQ_REWRITEG); - return (strncmp(diskqueue, newq, NSC_MAXPATH) - == 0 ? DISKQ_OKAY : DISKQ_FAIL); - } - if (open_cfg) - cfg_close(cfg); - return (DISKQ_OKAY); -} - - -int -pair_diskqueue_check(int newpair) -{ - int i, j; - int rc; - - for (i = 0; i < newpair; i++) { - if (strcmp(pair_list[i].group, pair_list[newpair].group) != 0) - continue; - if (strcmp(pair_list[i].diskqueue, pair_list[newpair].diskqueue) - == 0) - return (DISKQ_OKAY); /* matches existing group */ - if ((pair_list[newpair].group[0] != '\0') && - (pair_list[newpair].diskqueue[0] != '\0') && - (pair_list[i].diskqueue[0] != '\0')) { - rdc_warn(NULL, - gettext("disk queue %s does not match %s " - "skipping set"), pair_list[newpair].diskqueue, - pair_list[i].diskqueue); - return (DISKQ_FAIL); - } - - if ((strcmp(pair_list[newpair].diskqueue, "") == 0) && - pair_list[newpair].group[0] != '\0') { - (void) strncpy(pair_list[newpair].diskqueue, - pair_list[i].diskqueue, NSC_MAXPATH); - return (DISKQ_OKAY); /* changed to existing group que */ - } - if (strcmp(pair_list[i].diskqueue, "") == 0) { - for (j = 0; j < newpair; j++) { - if ((pair_list[j].group[0] != '\0') && - (strncmp(pair_list[j].group, - pair_list[newpair].group, - NSC_MAXPATH) == 0)) { - (void) strncpy(pair_list[j].diskqueue, - pair_list[newpair].diskqueue, - NSC_MAXPATH); - } - } - return (DISKQ_OKAY); - } - break; /* no problem with pair_list sets */ - - } - - /* now check with already configured sets */ - rc = check_diskqueue(NULL, pair_list[newpair].diskqueue, - pair_list[newpair].group); - if (rc == DISKQ_REWRITEG) { - for (i = 0; i < newpair; i++) { - if (strcmp(pair_list[i].group, - pair_list[newpair].group) != 0) - continue; - - (void) strncpy(pair_list[i].diskqueue, - pair_list[newpair].diskqueue, NSC_MAXPATH); - } - } - return (rc); -} - -int -ii_set_exists(CFGFILE *cfg, char *ma, char *sh, char *bm) -{ - char buf[CFG_MAX_BUF]; - char key[CFG_MAX_KEY]; - char master[NSC_MAXPATH]; - char shadow[NSC_MAXPATH]; - char bitmap[NSC_MAXPATH]; - int i; - - for (i = 1; ; i++) { - (void) snprintf(key, sizeof (key), "ii.set%d", i); - bzero(&master, sizeof (master)); - bzero(&shadow, sizeof (shadow)); - bzero(&bitmap, sizeof (bitmap)); - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) - break; - (void) sscanf(buf, "%s %s %s", master, shadow, bitmap); - if (strcmp(master, ma) != 0) - continue; - if (strcmp(shadow, sh) != 0) - continue; - if (strcmp(bitmap, bm) != 0) - continue; - return (1); - } - return (0); -} - -void -rdc_ii_config(int argc, char **argv) -{ - char *master; - char *shadow; - char *bitmap; - char c; - CFGFILE *cfg; - int i; - int setnumber; - char key[CFG_MAX_KEY]; - char buf[CFG_MAX_BUF]; - int found; - int sev; - - /* Parse the rest of the arguments to see what to do */ - - if (argc - optind != 4) { - usage(); - exit(1); - } - - c = *argv[optind]; - switch (c) { - case 'd': - /* Delete an ndr_ii entry */ - - master = argv[++optind]; - shadow = argv[++optind]; - bitmap = argv[++optind]; - - if ((cfg = cfg_open(NULL)) == NULL) - rdc_err(NULL, - gettext("unable to access configuration")); - if (!cfg_lock(cfg, CFG_WRLOCK)) - rdc_err(NULL, gettext("unable to lock configuration")); - - found = 0; - /* get ndr_ii entries until a match is found */ - /*CSTYLED*/ - for (i = 0; ; i++) { - setnumber = i + 1; - - (void) snprintf(key, sizeof (key), - "ndr_ii.set%d.secondary", - setnumber); - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) - break; - if (strcmp(buf, master) != 0) - continue; - - /* Got a matching entry */ - - (void) snprintf(key, sizeof (key), - "ndr_ii.set%d.shadow", - setnumber); - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) - break; - if (strcmp(buf, shadow) != 0) - continue; - - (void) snprintf(key, sizeof (key), - "ndr_ii.set%d.bitmap", - setnumber); - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) - break; - if (strcmp(buf, bitmap) != 0) - continue; - - (void) snprintf(key, sizeof (key), - "ndr_ii.set%d", setnumber); - if (cfg_put_cstring(cfg, key, NULL, 0) < 0) { - rdc_warn(NULL, - gettext("unable to remove \"%s\" " - "from configuration storage: %s"), - key, cfg_error(&sev)); - } else { - if (cfg_commit(cfg) < 0) - rdc_err(NULL, - gettext("ndr_ii set %s %s %s " - "not deconfigured."), - master, shadow, bitmap); - else - spcs_log("sndr", NULL, - gettext("ndr_ii set %s %s %s " - "has been deconfigured."), - master, shadow, bitmap); - } - found = 1; - break; - } - - if (!found) { - rdc_err(NULL, - gettext("did not find matching ndr_ii " - "entry for %s %s %s"), master, shadow, bitmap); - } - - cfg_close(cfg); - - break; - - case 'a': - /* Add an ndr_ii entry */ - - master = argv[++optind]; - shadow = argv[++optind]; - bitmap = argv[++optind]; - - if ((cfg = cfg_open(NULL)) == NULL) - rdc_err(NULL, - gettext("unable to access configuration")); - if (!cfg_lock(cfg, CFG_WRLOCK)) - rdc_err(NULL, gettext("unable to lock configuration")); - - found = 0; - /* get ndr_ii entries in case a match is found */ - /*CSTYLED*/ - for (i = 0; ; i++) { - setnumber = i + 1; - - (void) snprintf(key, sizeof (key), - "ndr_ii.set%d.secondary", - setnumber); - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) - break; - if (strcmp(buf, master) == 0) { - rdc_err(NULL, - gettext("found matching ndr_ii " - "entry for %s"), master); - } - } - /* - * check to see if this is using a sndr bitmap. - * kind of a courtesy check, as the ii copy would fail anyway - * excepting the case where they had actually configured - * ii/sndr that way, in which case they are broken - * before we get here - */ - /*CSTYLED*/ - for (i = 0; ; i++) { - setnumber = i + 1; - - /* - * Checking local bitmaps - */ - (void) snprintf(key, sizeof (key), "sndr.set%d.phost", - setnumber); - - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) - break; - if (self_check(buf)) { - (void) snprintf(key, sizeof (key), - "sndr.set%d.pbitmap", - setnumber); - } else { - (void) snprintf(key, sizeof (key), - "sndr.set%d.sbitmap", - setnumber); - } - - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) - break; - - if ((strcmp(buf, bitmap) == 0) || - (strcmp(buf, master) == 0) || - (strcmp(buf, shadow) == 0)) { - rdc_err(NULL, - gettext("%s is already configured " - "as a Remote Mirror bitmap"), buf); - } - } - if (!ii_set_exists(cfg, master, shadow, bitmap)) { - rdc_warn(NULL, gettext("Point-in-Time Copy set " - "%s %s %s is not already configured. Remote " - "Mirror will attempt to configure this set when " - "a sync is issued to it. The results of that " - "operation will be in /var/adm/ds.log"), - master, shadow, bitmap); - spcs_log("sndr", NULL, gettext("Point-in-Time Copy set " - "%s %s %s is not already configured. Remote " - "Mirror will attempt to configure this set when " - "a sync is issued to it. The results of that " - "operation will be in /var/adm/ds.log"), - master, shadow, bitmap); - } else { - spcs_log("sndr", NULL, gettext("ndr_ii set " - "%s %s %s has been configured."), - master, shadow, bitmap); - } - - /* - * Prior to insertion in ndr_ii entry, if in a Sun Cluster - * assure device groups are the same and cluster tag is set - */ - if (clustered && !rdc_islocal) { - char mst_dg[NSC_MAXPATH] = {0}; - char shd_dg[NSC_MAXPATH] = {0}; - char bmp_dg[NSC_MAXPATH] = {0}; - - if (!(cfg_dgname(master, mst_dg, sizeof (mst_dg)) && - cfg_dgname(shadow, shd_dg, sizeof (shd_dg)) && - cfg_dgname(bitmap, bmp_dg, sizeof (bmp_dg)))) - rdc_warn(NULL, gettext("ndr_ii: %s %s %s are " - "not in a device group"), - master, shadow, bitmap); - else if (strcmp(mst_dg, bmp_dg) || - strcmp(mst_dg, shd_dg)) - rdc_warn(NULL, gettext("ndr_ii: %s %s %s are " - "not in different device groups"), - master, shadow, bitmap); - else { - cfg_resource(cfg, shd_dg); - (void) snprintf(buf, sizeof (buf), - "%s %s %s update %s", - master, shadow, bitmap, shd_dg); - } - } else { - (void) snprintf(buf, sizeof (buf), "%s %s %s update", - master, shadow, bitmap); - } - - if ((cfg_put_cstring(cfg, "ndr_ii", buf, strlen(buf)) < 0) || - (cfg_commit(cfg) < 0)) - rdc_warn(NULL, gettext("unable to add \"%s\" to " - "configuration storage: %s"), - buf, cfg_error(&sev)); - - cfg_close(cfg); - - break; - - default: - usage(); - exit(1); - } -} - -void -check_rdcbitmap(int cmd, char *hostp, char *bmp) -{ - int i; - CFGFILE *cfg; - int entries; - char **entry; - char *host, *pri, *sec, *sbm, *bit, *mas, *sha, *ovr; - char *shost, *buf, *que; - - if ((cfg = cfg_open(NULL)) == NULL) - rdc_err(NULL, - gettext("unable to access configuration")); - if (!cfg_lock(cfg, CFG_RDLOCK)) - rdc_err(NULL, gettext("unable to lock configuration")); - - /* - * look into II config to see if this is being used elsewhere - */ - entry = NULL; - entries = cfg_get_section(cfg, &entry, "ii"); - for (i = 0; i < entries; i++) { - buf = entry[i]; - - mas = strtok(buf, " "); /* master */ - sha = strtok(NULL, " "); /* shadow */ - bit = strtok(NULL, " "); /* bitmap */ - (void) strtok(NULL, " "); /* mode */ - ovr = strtok(NULL, " "); /* overflow */ - - /* - * got master, shadow, overflow, and bitmap, now compare - */ - if ((strcmp(bmp, mas) == 0) || - (strcmp(bmp, sha) == 0) || - (strcmp(bmp, ovr) == 0) || - (strcmp(bmp, bit) == 0)) { - rdc_err(NULL, - gettext("bitmap %s is in use by" - " Point-in-Time Copy"), bmp); - } - free(buf); - } - if (entries) - free(entry); - - - /* - * and last but not least, make sure sndr is not using vol for anything - */ - entry = NULL; - entries = cfg_get_section(cfg, &entry, "sndr"); - for (i = 0; i < entries; i++) { - buf = entry[i]; - - /* - * I think this is quicker than - * having to double dip into the config - */ - host = strtok(buf, " "); /* phost */ - pri = strtok(NULL, " "); /* primary */ - bit = strtok(NULL, " "); /* pbitmap */ - shost = strtok(NULL, " "); /* shost */ - sec = strtok(NULL, " "); /* secondary */ - sbm = strtok(NULL, " "); /* sbitmap */ - (void) strtok(NULL, " "); /* type */ - (void) strtok(NULL, " "); /* mode */ - (void) strtok(NULL, " "); /* group */ - (void) strtok(NULL, " "); /* cnode */ - (void) strtok(NULL, " "); /* options */ - que = strtok(NULL, " "); /* diskq */ - - if (cmd == RDC_CMD_ENABLE) { - if (self_check(host)) { - if ((strcmp(bmp, pri) == 0) || - (strcmp(bmp, que) == 0) || - (strcmp(bmp, bit) == 0)) { - rdc_err(NULL, - gettext("bitmap %s is already " - "in use by StorEdge Network Data " - "Replicator"), bmp); - } - } else { - if ((strcmp(bmp, sec) == 0) || - (strcmp(bmp, sbm) == 0)) { - rdc_err(NULL, - gettext("bitmap %s is already " - "in use by StorEdge Network Data " - "Replicator"), bmp); - } - } - } else if (cmd == RDC_CMD_RECONFIG) { - - /* - * read this logic 1000 times and consider - * multi homed, one to many, many to one (marketing) - * etc, etc, before changing - */ - if (self_check(hostp)) { - if (self_check(host)) { - if ((strcmp(bmp, pri) == 0) || - (strcmp(bmp, que) == 0) || - (strcmp(bmp, bit) == 0)) { - rdc_err(NULL, - gettext("bitmap %s is already " - "in use by StorEdge Network " - "Data Replicator"), bmp); - } - } else { - if ((strcmp(hostp, shost) == 0) && - (strcmp(bmp, sec) == 0) || - (strcmp(bmp, sbm) == 0)) { - rdc_err(NULL, - gettext("bitmap %s is already " - "in use by StorEdge Network " - "Data Replicator"), bmp); - - } - } - } else { /* self_check(hostp) failed */ - if (self_check(host)) { - if ((strcmp(shost, hostp) == 0) && - (strcmp(bmp, sec) == 0) || - (strcmp(bmp, sbm) == 0)) { - rdc_err(NULL, - gettext("bitmap %s is already " - "in use by StorEdge Network " - "Data Replicator"), bmp); - } - } else { - if ((strcmp(host, hostp) == 0) && - (strcmp(bmp, pri) == 0) || - (strcmp(bmp, que) == 0) || - (strcmp(bmp, bit) == 0)) { - rdc_err(NULL, - gettext("bitmap %s is already " - "in use by StorEdge Network " - "Data Replicator"), bmp); - } - } - } - - } - - free(buf); - } - cfg_close(cfg); - - if (entries) - free(entry); -} -int -check_intrange(char *arg) { - int i; - - for (i = 0; i < strlen(arg); i++) { - if (arg[i] < '0' || arg[i] > '9') { - rdc_warn(NULL, "not a valid number, must be a " - "decimal between 1 and %d", MAXINT); - return (0); - } - } - errno = 0; - i = (int)strtol(arg, NULL, 10); - if ((errno) || (i < 1) || (i > MAXINT)) { - rdc_warn(NULL, "not a valid number, must be a decimal " - "between 1 and %d", MAXINT); - return (0); - } - return (1); -} - -void -rewrite_group_diskqueue(CFGFILE *cfg, _sd_dual_pair_t *pair, char *diskqueue) -{ - int set; - char buf[CFG_MAX_BUF]; - char key[CFG_MAX_KEY]; - _sd_dual_pair_t tmpair; - - for (set = 1; /*CSTYLED*/; set++) { - bzero(buf, CFG_MAX_BUF); - bzero(&tmpair, sizeof (tmpair)); - - (void) snprintf(key, sizeof (key), "sndr.set%d", set); - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) { - break; - } - if (parse_cfg_buf(buf, &tmpair, NULL)) - continue; - if (pair->group && pair->group[0]) { - if (strcmp(pair->group, tmpair.group) != 0) - continue; /* not the group we want */ - - } else { /* no group specified */ - if (strcmp(pair->thost, tmpair.thost) != 0) - continue; - if (strcmp(pair->tfile, tmpair.tfile) != 0) - continue; - } - - (void) sprintf(key, "sndr.set%d.diskq", set); - - if (cfg_put_cstring(cfg, key, diskqueue, - strlen(diskqueue)) < 0) { - perror(cfg_error(NULL)); - } - } -} - -void -diskq_subcmd(int subcmd, char *qvol, char *group_arg, char *ctag_arg, - char *tohost_arg, char *tofile_arg) -{ - int found = 0; - int setnumber = 0; - char key[CFG_MAX_KEY]; - char buf[CFG_MAX_BUF]; - int i; - int rc; - int option = 0; - _sd_dual_pair_t pair; - CFGFILE *cfg; - char *ctag = NULL; - int resourced = 0; - - if ((cfg = cfg_open(NULL)) == NULL) - rdc_err(NULL, - gettext("unable to access configuration")); - - if (!cfg_lock(cfg, CFG_WRLOCK)) - rdc_err(NULL, - gettext("unable to lock configuration")); - -redo: - if (cfg_load_svols(cfg) < 0 || - cfg_load_dsvols(cfg) < 0 || - cfg_load_shadows(cfg) < 0) - rdc_err(NULL, - gettext("Unable to parse config filer")); - load_rdc_vols(cfg); - - /*CSTYLED*/ - for (i = 0; i < rdc_maxsets;) { - setnumber++; - - bzero(buf, CFG_MAX_BUF); - (void) snprintf(key, sizeof (key), - "sndr.set%d", setnumber); - rc = cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF); - if (rc < 0) - break; - if (parse_cfg_buf(buf, &pair, NULL)) - continue; - - if (strlen(group_arg) == 0) { - if (strcmp(tohost_arg, pair.thost) == 0 && - strcmp(tofile_arg, pair.tfile) == 0) { - (void) strcpy(group_arg, pair.group); - found = 1; - break; - } - - } else { - if (strcmp(group_arg, pair.group) == 0) { - found = 1; - break; - } - } - } - - if (!found) { - if (strlen(group_arg) == 0) { - rdc_err(NULL, - gettext("Unable to find %s:%s in " - "configuration storage"), - tohost_arg, tofile_arg); - } else { - rdc_err(NULL, - gettext("Unable to find group %s in " - "configuration storage"), group_arg); - } - } - if (!resourced && strlen(pair.ctag)) { /* uh-oh... */ - cfg_unload_svols(cfg); - cfg_unload_dsvols(cfg); - cfg_unload_shadows(cfg); - unload_rdc_vols(); - cfg_resource(cfg, pair.ctag); - ctag = strdup(pair.ctag); - resourced = 1; - setnumber = 0; - goto redo; - } - - if (clustered && !rdc_islocal) { - if (strcmp(ctag_arg, "") && - strncmp(ctag_arg, pair.ctag, MAX_RDC_HOST_SIZE)) - rdc_warn(NULL, gettext("ctags %s and %s " - "do not match, proceeding with operation based " - "on existing set information"), ctag_arg, ctag); - } - switch (subcmd) { - case RDC_CMD_ADDQ: - if (clustered && (ctag_check(pair.fhost, pair.ffile, - pair.fbitmap, pair.thost, pair.tfile, pair.tbitmap, - pair.ctag, qvol) < 0)) - exit(1); - - if (strlen(pair.diskqueue) > 0) { - rdc_err(NULL, gettext("Remote Mirror set already " - "has a disk queue")); - } - if (check_diskqueue(cfg, qvol, group_arg) == DISKQ_FAIL) { - rdc_err(NULL, - gettext("diskqueue %s is incompatible"), qvol); - } - if (rdc_operation(cfg, pair.fhost, pair.ffile, pair.fbitmap, - pair.thost, pair.tfile, pair.tbitmap, subcmd, 0, - pair.directfile, pair.group, pair.ctag, qvol, &pair.doasync, - 0) < 0) { - if (cfg_vol_disable(cfg, qvol, ctag, "sndr") < 0) - rdc_warn(NULL, gettext("Failed to remove disk " - "queue [%s] from configuration"), qvol); - rdc_err(NULL, gettext("Add disk queue operation " - "failed")); - } - if (nsc_lookup(volhash, qvol) == NULL) { - if (cfg_vol_enable(cfg, qvol, ctag, "sndr") < 0) { - rdc_err(NULL, gettext("Add disk queue " - "operation failed")); - } - } - rewrite_group_diskqueue(cfg, &pair, qvol); - - spcs_log("sndr", NULL, gettext("Remote Mirror: added " - "diskqueue %s to set %s:%s and its group"), qvol, - pair.thost, pair.tfile); - break; - case RDC_OPT_FORCE_QINIT: - if (strlen(pair.diskqueue) == 0) { - rdc_err(NULL, gettext("Remote Mirror set does not " - "have a disk queue")); - } - subcmd = RDC_CMD_INITQ; - option = RDC_OPT_FORCE_QINIT; - if (rdc_operation(cfg, pair.fhost, pair.ffile, pair.fbitmap, - pair.thost, pair.tfile, pair.tbitmap, subcmd, option, - pair.directfile, pair.group, pair.ctag, qvol, &pair.doasync, - 0) < 0) { - exit(1); - } - break; - case RDC_CMD_INITQ: - if (strlen(pair.diskqueue) == 0) { - rdc_err(NULL, gettext("Remote Mirror set does not " - "have a disk queue")); - } - if (rdc_operation(cfg, pair.fhost, pair.ffile, pair.fbitmap, - pair.thost, pair.tfile, pair.tbitmap, subcmd, 0, - pair.directfile, pair.group, pair.ctag, qvol, &pair.doasync, - 0) < 0) { - exit(1); - } - break; - case RDC_CMD_REMQ: - if (strlen(pair.diskqueue) == 0) { - rdc_err(NULL, gettext("Remote Mirror set does not " - "have a disk queue")); - } - if (rdc_operation(cfg, pair.fhost, pair.ffile, pair.fbitmap, - pair.thost, pair.tfile, pair.tbitmap, subcmd, 0, - pair.directfile, pair.group, pair.ctag, qvol, &pair.doasync, - 0) < 0) { - exit(1); - } - if (cfg_vol_disable(cfg, pair.diskqueue, ctag, "sndr") < 0) - rdc_warn(NULL, gettext("Failed to remove disk queue " - "[%s] from configuration"), pair.diskqueue); - rewrite_group_diskqueue(cfg, &pair, place_holder); - - spcs_log("sndr", NULL, gettext("Remote Mirror: removed " - "diskqueue from set %s:%s and its group"), pair.thost, - pair.tfile); - break; - case RDC_CMD_KILLQ: - if (strlen(pair.diskqueue) == 0) { - rdc_err(NULL, gettext("Remote Mirror set does not " - "have a disk queue")); - } - if (rdc_operation(cfg, pair.fhost, pair.ffile, pair.fbitmap, - pair.thost, pair.tfile, pair.tbitmap, subcmd, 0, - pair.directfile, pair.group, pair.ctag, qvol, &pair.doasync, - 0) < 0) { - rdc_err(NULL, gettext("Failed to remove disk queue")); - } - if (cfg_vol_disable(cfg, pair.diskqueue, ctag, "sndr") < 0) - rdc_warn(NULL, gettext("Failed to remove disk queue " - "[%s] from configuration"), pair.diskqueue); - - rewrite_group_diskqueue(cfg, &pair, place_holder); - - spcs_log("sndr", NULL, gettext("Remote Mirror: forcibly " - "removed diskqueue from set %s:%s and its group "), - pair.thost, pair.tfile); - break; - case RDC_CMD_REPQ: - if (clustered && (ctag_check(pair.fhost, pair.ffile, - pair.fbitmap, pair.thost, pair.tfile, pair.tbitmap, - pair.ctag, qvol) < 0)) - exit(1); - - if (strlen(pair.diskqueue) == 0) { - rdc_err(NULL, gettext("Remote Mirror set does not " - "have a disk queue")); - } - if (rdc_operation(cfg, pair.fhost, pair.ffile, pair.fbitmap, - pair.thost, pair.tfile, pair.tbitmap, RDC_CMD_REMQ, 0, - pair.directfile, pair.group, pair.ctag, qvol, &pair.doasync, - 0) < 0) { - rdc_err(NULL, gettext("Failed to remove disk queue")); - } - if (cfg_vol_disable(cfg, pair.diskqueue, ctag, "sndr") < 0) - rdc_warn(NULL, gettext("Failed to remove disk queue " - "[%s] from configuration"), pair.diskqueue); - - rewrite_group_diskqueue(cfg, &pair, place_holder); - - /* commit here, enable may fail */ - if (cfg_commit(cfg) < 0) { - rdc_err(NULL, gettext("commit replace disk queue %s " - "with %s failed"), pair.diskqueue, qvol); - } - - if (check_diskqueue(cfg, qvol, group_arg) == DISKQ_FAIL) { - rdc_err(NULL, - gettext("cannot replace disk queue %s with %s"), - pair.diskqueue, qvol); - } - if (rdc_operation(cfg, pair.fhost, pair.ffile, pair.fbitmap, - pair.thost, pair.tfile, pair.tbitmap, RDC_CMD_ADDQ, 0, - pair.directfile, pair.group, pair.ctag, qvol, &pair.doasync, - 0) < 0) { - if (cfg_vol_disable(cfg, qvol, ctag, "sndr") < 0) - rdc_warn(NULL, gettext("Failed to remove disk " - "queue [%s] from configuration"), qvol); - rdc_err(NULL, gettext("Failed to add new disk queue")); - } - if (nsc_lookup(volhash, qvol) == NULL) - if (cfg_vol_enable(cfg, qvol, ctag, "sndr") < 0) { - rdc_err(NULL, gettext("Replace disk queue " - "operation failed")); - } - - rewrite_group_diskqueue(cfg, &pair, qvol); - - spcs_log("sndr", NULL, gettext("Remote Mirror: replaced " - "diskqueue for set %s:%s and its group with %s"), - pair.thost, pair.tfile, qvol); - break; - } - - cfg_unload_svols(cfg); - cfg_unload_dsvols(cfg); - cfg_unload_shadows(cfg); - unload_rdc_vols(); - - if (cfg_commit(cfg) < 0) - rdc_err(NULL, gettext("commit failed on disk queue operation")); - - cfg_close(cfg); - if (ctag) - free(ctag); -} -void -spcslog_sync(rdcconfig_t *sets, int start, int type) -{ - rdcconfig_t *setp = sets; - - while (setp) { - if (start) { - spcs_log("sndr", NULL, - gettext("%s %s %s %s %s %s %s %s\nSync Started"), - program, rdc_decode_flag(RDC_CMD_COPY, type), - setp->phost, setp->pfile, setp->pbmp, - setp->shost, setp->sfile, setp->sbmp); - } else { - spcs_log("sndr", NULL, - gettext("%s %s %s %s %s %s %s %s\nSync Ended"), - program, rdc_decode_flag(RDC_CMD_COPY, type), - setp->phost, setp->pfile, setp->pbmp, - setp->shost, setp->sfile, setp->sbmp); - } - setp = setp->next; - } -} - -void -spcslog_tunable(char *shost, char *svol) -{ - if (qblock == RDC_OPT_SET_QNOBLOCK) - spcs_log("sndr", NULL, gettext("diskqueue " - "set to non blocking for %s:%s and any members " - "of it's group"), shost, svol); - else if (qblock == RDC_OPT_CLR_QNOBLOCK) - spcs_log("sndr", NULL, gettext("diskqueue " - "set to blocking for %s:%s and any members " - "of it's group"), shost, svol); - - if (maxqfbas) - spcs_log("sndr", NULL, gettext("maxqfbas set to %d for %s:%s"), - maxqfbas, shost, svol); - if (maxqitems) - spcs_log("sndr", NULL, gettext("maxwrites set to %d for %s:%s"), - maxqitems, shost, svol); - if (asyncthr) - spcs_log("sndr", NULL, gettext("%d async threads configured " - "for %s:%s"), asyncthr, shost, svol); -} - -int -set_qblock(char *blockarg) -{ - if (strcmp(blockarg, "block") == 0) - qblock = RDC_OPT_CLR_QNOBLOCK; - else if (strcmp(blockarg, "noblock") == 0) - qblock = RDC_OPT_SET_QNOBLOCK; - else - return (1); - - return (0); -} - -static void -rdc_force_disable(CFGFILE *cfg, char *phost, char *pvol, char *pbmp, - char *shost, char *svol, char *sbmp, char *ctag, char *lhname) -{ - rdc_config_t parms; - spcs_s_info_t ustatus; - volcount_t *vc; - char *datavol = NULL; - char *bmpvol = NULL; - int on_pri = 0; - int on_sec = 0; - - /* are we on the primary or secondary host? */ - if (ctag && *ctag && *lhname) { - if (strcmp(phost, lhname) == 0) { - on_pri = 1; - } else if (strcmp(shost, lhname) == 0) { - on_sec = 1; - } - } else if (self_check(phost)) { - on_pri = 1; - } else if (self_check(shost)) { - on_sec = 1; - } - - if (on_pri) { - datavol = pvol; - bmpvol = pbmp; - } else if (on_sec) { - datavol = svol; - bmpvol = sbmp; - } else { - rdc_err(NULL, gettext("Unable to determine whether current " - "node is primary or secondary")); - } - - /* set up parms structure */ - parms.command = RDC_CMD_DISABLE; - (void) strncpy(parms.rdc_set->primary.intf, phost, MAX_RDC_HOST_SIZE); - (void) strncpy(parms.rdc_set->primary.file, pvol, NSC_MAXPATH); - (void) strncpy(parms.rdc_set->secondary.intf, shost, MAX_RDC_HOST_SIZE); - (void) strncpy(parms.rdc_set->secondary.file, svol, NSC_MAXPATH); - ustatus = spcs_s_ucreate(); - parms.options = RDC_OPT_FORCE_DISABLE; - - /* - * We are now going to 'force' the kernel to disable the set. By - * setting the RDC_OPT_FORCE_DISABLE flag, the kernel will bypass some - * of the checks that are normally done when attempting to disable - * a set. We need to do this force option in a cluster environment - * when the logical hostname for the primary or secondary volume - * is no longer available. - */ - spcs_log("sndr", NULL, "%s sndradm -d %s %s %s %s %s %s", - gettext("FORCE DISABLE"), phost, pvol, pbmp, shost, svol, sbmp); - rdc_warn(NULL, gettext("Forcing set disable")); - if (RDC_IOCTL(RDC_CONFIG, &parms, 0, 0, 0, 0, ustatus) != SPCS_S_OK) - rdc_warn(&ustatus, gettext("set %s:%s not enabled in kernel"), - shost, svol); - - /* if we get to this point, then a set was disabled. try sv-disable */ - vc = nsc_lookup(volhash, datavol); - if (vc && (1 == vc->count)) - if (cfg_vol_disable(cfg, datavol, ctag, "sndr") < 0) - rdc_warn(NULL, gettext("Failed to remove data volume " - "[%s] from configuration"), datavol); - vc = nsc_lookup(volhash, bmpvol); - if (vc && (1 == vc->count)) - if (cfg_vol_disable(cfg, bmpvol, ctag, "sndr") < 0) - rdc_warn(NULL, gettext("Failed to remove bitmap " - "[%s] from configuration"), bmpvol); -} - -void -check_rdcsecondary(char *secondary) -{ - int i; - CFGFILE *cfg; - int entries; - char **entry; - char *sha; - char *buf; - - if ((cfg = cfg_open(NULL)) == NULL) - rdc_err(NULL, - gettext("error opening config")); - if (!cfg_lock(cfg, CFG_RDLOCK)) - rdc_err(NULL, gettext("error locking config")); - - entry = NULL; - entries = cfg_get_section(cfg, &entry, "ii"); - for (i = 0; i < entries; i++) { - buf = entry[i]; - - (void) strtok(buf, " "); /* master */ - sha = strtok(NULL, " "); /* shadow */ - if (strcmp(secondary, sha) == 0) { - rdc_err(NULL, - gettext("secondary %s is in use by" - " Point-in-Time Copy"), secondary); - } - free(buf); - } - if (entries) - free(entry); - cfg_close(cfg); -} - -int -main(int argc, char *argv[]) -{ - char config_file[FILENAME_MAX]; - char fromhost[MAX_RDC_HOST_SIZE]; - char tohost[MAX_RDC_HOST_SIZE]; - char fromfile[NSC_MAXPATH]; - char tofile[NSC_MAXPATH]; - char frombitmap[NSC_MAXPATH]; - char tobitmap[NSC_MAXPATH]; - char directfile[NSC_MAXPATH]; - char group[NSC_MAXPATH]; - char ctag[MAX_RDC_HOST_SIZE]; - char options_cfg[CFG_MAX_BUF]; - char fromnetaddr[RDC_MAXADDR]; - char tonetaddr[RDC_MAXADDR]; - char tmphost[MAX_RDC_HOST_SIZE]; - char tmpfile[NSC_MAXPATH]; - char tmpbitmap[NSC_MAXPATH]; - char diskqueue[NSC_MAXPATH]; - char lhname[MAX_RDC_HOST_SIZE]; - char mode[16]; - rdc_version_t rdc_version; - int pairs; - int pid; - int flag = 0; - int fflag = 0; - int reverse = 0; - int nflag = 0; - int iflag = 0; - int doasync; - int pflag = 0; - int vflag = 0; - int verbose = 0; - int errflag = 0; - int cfgflag = 0; - int cfg_success; - int Iflag = 0; - char c; - char inval = 0; - int found; - int rc; - int geflag = 0; - int qflag = 0; - char *qarg; - int Bflag = 0; - char *bitfile; - CFGFILE *cfg = NULL; - int i; - int setnumber; - char key[CFG_MAX_KEY]; - char buf[CFG_MAX_BUF]; - char ctag_arg[MAX_RDC_HOST_SIZE]; - char group_arg[NSC_MAXPATH]; - int file_format = 0; - int sev; - int diskq_group = DISKQ_OKAY; - int extra_argc; - char *ctag_p, *group_p, *diskqueue_p; - char *required; - char *role_env; - int checksetfields = -1; - nsc_off_t boffset = 0; - int oflag = 0; - rdcconfig_t *sets = NULL; - rdcconfig_t *sets_p = NULL; - rdc_rc_t *rclist = NULL; - rdc_rc_t *rcp = NULL; - int host_not_found = 0; - - (void) setlocale(LC_ALL, ""); - (void) textdomain("rdc"); - role_env = getenv("SNDR_ROLE_REVERSE"); - if (role_env && strcmp(role_env, "sndr_allow_reverse") == 0) - allow_role = 1; - - program = basename(argv[0]); - - rc = rdc_check_release(&required); - if (rc < 0) { - rdc_err(NULL, - gettext("unable to determine the current " - "Solaris release: %s\n"), strerror(errno)); - } else if (rc == FALSE) { - rdc_err(NULL, - gettext("incorrect Solaris release (requires %s)\n"), - required); - } - - if ((clustered = cfg_iscluster()) < 0) { - rdc_err(NULL, gettext("unable to ascertain environment")); - } - - (void) strcpy(ctag_arg, ""); - (void) strcpy(group_arg, ""); - bzero(ctag, MAX_RDC_HOST_SIZE); - bzero(reconfig_ctag, MAX_RDC_HOST_SIZE); - bzero(diskqueue, NSC_MAXPATH); - - rdc_maxsets = rdc_get_maxsets(); - if (rdc_maxsets == -1) { - rdc_err(NULL, - gettext("unable to get maxsets value from kernel")); - } - - pair_list = calloc(rdc_maxsets, sizeof (*pair_list)); - if (pair_list == NULL) { - rdc_err(NULL, - gettext("unable to allocate pair_list array for %d sets"), - rdc_maxsets); - } - - bzero(group, sizeof (group)); - bzero(diskqueue, sizeof (diskqueue)); - qblock = 0; - - while ((c = -#ifdef DEBUG - getopt(argc, argv, "A:B:C:D:EF:HIO:PRUW:a:bdef:g:hilmno:pq:rsuvw")) -#else - getopt(argc, argv, "A:B:C:D:EF:HIO:PRUW:a:bdef:g:hilmno:pq:rsuvw")) -#endif - != -1) { - switch (c) { - case 'B': - if (!allow_role || flag) { - inval = 1; - break; - } - bitfile = optarg; - Bflag = 1; - flag = RDC_BITMAPOP; - break; - case 'H': - /* 'h' was already assigned */ - if (flag) - inval = 1; - flag = RDC_CMD_HEALTH; - break; - case 'I': - /* List or edit ndr_ii configuration entries */ - Iflag = 1; - break; - case 'R': - if (flag) - inval = 1; - flag = RDC_CMD_RECONFIG; - break; -#ifdef DEBUG - case 'U': /* UDP support */ - proto_test = 1; - break; -#endif - case 'F': - if (flag && flag != RDC_CMD_TUNABLE) - inval = 1; - flag = RDC_CMD_TUNABLE; - - if (check_intrange(optarg)) - maxqfbas = atoi(optarg); - else - exit(1); - - break; - case 'W': - if (flag && flag != RDC_CMD_TUNABLE) - inval = 1; - flag = RDC_CMD_TUNABLE; - - if (check_intrange(optarg)) - maxqitems = atoi(optarg); - else - exit(1); - - break; - case 'A': - if (flag && flag != RDC_CMD_TUNABLE) - inval = 1; - flag = RDC_CMD_TUNABLE; - - if (check_intrange(optarg)) - asyncthr = atoi(optarg); - else - exit(1); - - break; - case 'D': - if (flag && flag != RDC_CMD_TUNABLE) - inval = 1; - flag = RDC_CMD_TUNABLE; - - if (set_qblock(optarg)) { - usage(); - exit(1); - } - iflag |= qblock; - break; - case 'a': - if (flag && flag != RDC_CMD_TUNABLE) - inval = 1; - flag = RDC_CMD_TUNABLE; - if (strcmp(optarg, "off") == 0) - autosync = AUTOSYNC_OFF; - else if (strcmp(optarg, "on") == 0) - autosync = AUTOSYNC_ON; - else - inval = 1; - break; - case 'C': - if (clustered) { - (void) strncpy(ctag_arg, optarg, - MAX_RDC_HOST_SIZE); - process_clocal(ctag_arg); - } else - inval = 1; - break; - case 'g': - if (flag == RDC_CMD_ENABLE) - inval = 1; - geflag = 1; - (void) strncpy(group_arg, optarg, NSC_MAXPATH); - verify_groupname(group_arg); - break; - case 'b': - /* ignore */ - break; - case 'n': - nflag = 1; - break; - case 'd': - if (flag) - inval = 1; - flag = RDC_CMD_DISABLE; - break; - case 'e': - if (flag || geflag) - inval = 1; - flag = RDC_CMD_ENABLE; - iflag |= RDC_OPT_SETBMP; - break; - case 'E': - if (flag) - inval = 1; - flag = RDC_CMD_ENABLE; - iflag |= RDC_OPT_CLRBMP; - break; - case 'f': - fflag = 1; - (void) strcpy(config_file, optarg); - break; - case 'h': - usage(); - exit(0); - break; - case 'l': - if (flag) - inval = 1; - flag = RDC_CMD_LOG; - break; - case 'm': - if (flag) - inval = 1; - flag = RDC_CMD_COPY; - iflag |= RDC_OPT_FULL; - break; - case 'O': - case 'o': - - if (!allow_role || oflag) { - inval = 1; - break; - } - if (c == 'o') { - oflag = RDC_BITMAPOR; - } else { - oflag = RDC_BITMAPSET; - } - boffset = strtoull(optarg, NULL, 0); - break; - case 'P': - if (flag) - inval = 1; - pflag = 1; - verbose = 1; - break; - case 'p': - if (flag) - inval = 1; - pflag = 1; - break; - case 'q': - if (flag) - inval = 1; - flag = RDC_CMD_INITQ; - qflag = optind; - qarg = optarg; - break; - case 'i': - if (flag) - inval = 1; - pflag = 1; - file_format = 1; - break; - case 'r': - reverse = 1; - iflag |= RDC_OPT_REVERSE; - break; - case 's': - if (flag) - inval = 1; - flag = RDC_CMD_STATUS; - nflag = 1; /* No prompt for a status */ - break; - case 'u': - if (flag) - inval = 1; - flag = RDC_CMD_COPY; - iflag |= RDC_OPT_UPDATE; - break; - case 'v': - if (flag) - inval = 1; - pflag = 1; - vflag = 1; - break; - case 'w': - if (flag) - inval = 1; - flag = RDC_CMD_WAIT; - break; - case '?': - errflag++; - } - } - - if (inval || ((flag != RDC_BITMAPOP) && oflag)) { - rdc_warn(NULL, gettext("invalid argument combination")); - errflag = 1; - } - - if (flag && Iflag) { - /* Mutually incompatible */ - usage(); - exit(1); - } - - if (Iflag) { - rdc_ii_config(argc, argv); - exit(0); - } - - if (vflag) { - spcs_s_info_t ustatus; - - ustatus = spcs_s_ucreate(); - rc = RDC_IOCTL(RDC_VERSION, &rdc_version, 0, 0, 0, 0, ustatus); - if (rc == SPCS_S_ERROR) { - rdc_err(&ustatus, gettext("statistics error")); - } - spcs_s_ufree(&ustatus); -#ifdef DEBUG - (void) printf(gettext("Remote Mirror version %d.%d.%d.%d\n"), - rdc_version.major, rdc_version.minor, - rdc_version.micro, rdc_version.baseline); -#else - if (rdc_version.micro) { - (void) printf(gettext( - "Remote Mirror version %d.%d.%d\n"), - rdc_version.major, - rdc_version.minor, - rdc_version.micro); - } else { - (void) printf(gettext("Remote Mirror version %d.%d\n"), - rdc_version.major, rdc_version.minor); - } -#endif - exit(0); - } - - if (!(flag || pflag) || errflag) { - usage(); - exit(1); - } - - if (pflag && !fflag && (argc - optind) == 0) { - /* print with no set specified */ - exit(rdc_print(file_format, verbose, - group_arg, ctag_arg, NULL, NULL, NULL)); - } - - if (qflag) { /* change disk queue setting */ - int subcmd = 0; - int offset = 0; - char *ptr; - char *qvol; - char tohost_arg[MAX_RDC_HOST_SIZE]; - char tofile_arg[NSC_MAXPATH]; - - if (strcmp("a", qarg) == 0) { - subcmd = RDC_CMD_ADDQ; - offset = 1; - } else if (strcmp("d", qarg) == 0) { - subcmd = RDC_CMD_REMQ; - offset = 0; - } else if (strcmp("r", qarg) == 0) { - subcmd = RDC_CMD_REPQ; - offset = 1; - } else { - rdc_warn(NULL, " %s Invalid qopt", qarg); - q_usage(1); - exit(1); - } - if (strlen(group_arg) == 0) { - /* pick out single set as shost:svol */ - ptr = strtok(argv[qflag + offset], ":"); - if (ptr) - (void) strncpy(tohost_arg, ptr, - MAX_RDC_HOST_SIZE); - else { - rdc_warn(NULL, gettext("Bad host specified")); - q_usage(1); - exit(1); - } - ptr = strtok(NULL, ":"); - if (ptr) - (void) strncpy(tofile_arg, ptr, NSC_MAXPATH); - else { - rdc_warn(NULL, gettext("Bad set specified")); - q_usage(1); - exit(1); - } - } - - qvol = argv[qflag]; - if ((qvol == NULL) && (subcmd != RDC_CMD_REMQ)) { - rdc_warn(NULL, gettext("missing queue volume")); - q_usage(1); - exit(1); - } - diskq_subcmd(subcmd, qvol, group_arg, ctag_arg, - tohost_arg, tofile_arg); - exit(0); - } - - if (flag == RDC_CMD_RECONFIG && !fflag) { - /* See what is to be reconfigured */ - if (argc - optind == 0) - flag = RDC_CMD_RESET; - else { - if (argc - optind < 2) { - usage(); - exit(1); - } - c = *argv[optind++]; - if (argv[optind -1][1] != '\0') { - usage(); - exit(2); - } - switch (c) { - case 'b': - if (argc - optind < 2) { - usage(); - exit(1); - } - if (*argv[optind] == 'p') - reconfig_pbitmap = argv[++optind]; - else if (*argv[optind] == 's') - reconfig_sbitmap = argv[++optind]; - else { - usage(); - exit(1); - } - optind++; - break; -#ifdef _RDC_CAMPUS - case 'd': - reconfig_direct = argv[optind++]; - break; -#endif - case 'g': - reconfig_group = argv[optind++]; - verify_groupname(reconfig_group); - break; - case 'C': - if (clustered) { - (void) strncpy(reconfig_ctag, - argv[optind++], MAX_RDC_HOST_SIZE); - process_clocal(reconfig_ctag); - } else { - usage(); - exit(1); - } - break; - case 'm': - if (strcmp(argv[optind], "sync") == 0) - reconfig_doasync = 0; - else if (strcmp(argv[optind], "async") == 0) - reconfig_doasync = 1; - else { - usage(); - exit(1); - } - optind++; - break; - case 'r': - if (allow_role) { - iflag |= RDC_OPT_REVERSE_ROLE; - break; - } - /* FALLTHROUGH */ - default: - usage(); - exit(1); - } - } - } - if (fflag) { - checksetfields = 1; - if ((argc - optind) != 0) { - usage(); - exit(1); - } - } else { - if ((argc - optind) == 0) { - /* Use libcfg to figure out what to operate on */ - cfgflag = 1; -#ifdef DEBUG - rdc_warn(NULL, gettext("using current config")); -#endif - checksetfields = 0; - } else { - if ((argc - optind) < 8 && (argc - optind) != 1) { - usage(); - exit(1); - } - } - } - - if (cfgflag) { - if (flag == RDC_CMD_ADDQ || - flag == RDC_CMD_REMQ || - flag == RDC_CMD_KILLQ || - flag == RDC_CMD_INITQ) { - rdc_err(NULL, gettext("can not use current config " - "for disk queue operations")); - } - } else if (fflag) { - if (flag == RDC_CMD_ADDQ || - flag == RDC_CMD_REMQ || - flag == RDC_CMD_KILLQ || - flag == RDC_CMD_INITQ) { - rdc_err(NULL, gettext("can not use a config file " - "for disk queue operations")); - } - } - if (cfgflag) { - if (flag == RDC_CMD_ENABLE) { - rdc_err(NULL, gettext("can not use current config " - "for enable command")); - } - if ((flag == RDC_CMD_RECONFIG) && (reconfig_pbitmap || - reconfig_sbitmap)) { - rdc_err(NULL, gettext("can not use current config " - "for bitmap reconfiguration")); - } - if (flag == RDC_BITMAPOP) { - rdc_err(NULL, gettext("can not use current config " - "for bitmap set command")); - } - pairs = read_libcfg(flag, group_arg, ctag_arg); - if (pairs == 0) { - (void) fprintf(stderr, - gettext("no matching Remote Mirror sets found " - "in config\n")); - exit(1); - } - } else if (!fflag) { - /* - * Format is either: - * - * tohost:tofile - * - * or something like this for example: - * - * fromhost fromfile frombitmap tohost tofile tobitmap ip sync - * g group C ctag - */ - - if (argc - optind == 1) { - char tohost_arg[MAX_RDC_HOST_SIZE]; - char tofile_arg[NSC_MAXPATH]; - char *ptr; - - checksetfields = 0; - if (flag == RDC_CMD_ENABLE) { - rdc_err(NULL, - gettext("must specify full set details for " - "enable command")); - } - ptr = strtok(argv[optind], ":"); - if (ptr) - (void) strncpy(tohost_arg, ptr, - MAX_RDC_HOST_SIZE); - else { - rdc_err(NULL, gettext("Bad host specified")); - } - ptr = strtok(NULL, ":"); - if (ptr) - (void) strncpy(tofile_arg, ptr, NSC_MAXPATH); - else { - rdc_err(NULL, gettext("Bad set specified")); - } - - /* Now look up tohost:tofile via libcfg */ - - if ((cfg = cfg_open(NULL)) == NULL) - rdc_err(NULL, - gettext("unable to access configuration")); - - if (!cfg_lock(cfg, CFG_RDLOCK)) - rdc_err(NULL, - gettext("unable to lock configuration")); - - setnumber = 0; - found = 0; - /*CSTYLED*/ - for (i = 0; i < rdc_maxsets;) { - setnumber++; - - bzero(buf, CFG_MAX_BUF); - (void) snprintf(key, sizeof (key), - "sndr.set%d", setnumber); - rc = cfg_get_cstring(cfg, key, buf, - CFG_MAX_BUF); - if (rc < 0) - break; - - (void) snprintf(key, sizeof (key), - "sndr.set%d.shost", setnumber); - (void) cfg_get_cstring(cfg, key, tohost, - sizeof (tohost)); - if (strncmp(tohost, tohost_arg, NSC_MAXPATH)) - continue; - - (void) snprintf(key, sizeof (key), - "sndr.set%d.secondary", setnumber); - (void) cfg_get_cstring(cfg, key, tofile, - sizeof (tofile)); - if (strncmp(tofile, tofile_arg, NSC_MAXPATH)) - continue; - - found = 1; - - (void) snprintf(key, sizeof (key), - "sndr.set%d.phost", setnumber); - (void) cfg_get_cstring(cfg, key, fromhost, - sizeof (fromhost)); - - (void) snprintf(key, sizeof (key), - "sndr.set%d.primary", setnumber); - (void) cfg_get_cstring(cfg, key, fromfile, - sizeof (fromfile)); - - (void) snprintf(key, sizeof (key), - "sndr.set%d.pbitmap", setnumber); - (void) cfg_get_cstring(cfg, key, frombitmap, - sizeof (frombitmap)); - - (void) snprintf(key, sizeof (key), - "sndr.set%d.sbitmap", setnumber); - (void) cfg_get_cstring(cfg, key, tobitmap, - sizeof (tobitmap)); - - (void) snprintf(key, sizeof (key), - "sndr.set%d.type", setnumber); - (void) cfg_get_cstring(cfg, key, directfile, - sizeof (directfile)); - if (strcmp(directfile, "ip") == 0) - (void) strcpy(directfile, ""); - - (void) snprintf(key, sizeof (key), - "sndr.set%d.mode", setnumber); - (void) cfg_get_cstring( - cfg, key, mode, sizeof (mode)); - - (void) snprintf(key, sizeof (key), - "sndr.set%d.group", setnumber); - (void) cfg_get_cstring(cfg, key, group, - sizeof (group)); - if (strcmp(group_arg, "") && - strncmp(group_arg, group, NSC_MAXPATH)) - continue; - (void) snprintf(key, sizeof (key), - "sndr.set%d.cnode", setnumber); - (void) cfg_get_cstring( - cfg, key, ctag, sizeof (ctag)); - if ((strlen(ctag_arg) > 0) && - (strcmp(ctag_arg, ctag) != 0)) - rdc_err(NULL, - gettext("ctags %s and %s " - "do not match"), ctag_arg, ctag); - - if (strcmp(mode, "sync") == 0) - doasync = 0; - else if (strcmp(mode, "async") == 0) - doasync = 1; - else { - rdc_err(NULL, - gettext("set %s:%s neither sync " - "nor async"), tohost, tofile); - } - break; - } - cfg_close(cfg); - if (!found) { - rdc_err(NULL, - gettext("set %s:%s not found in config"), - tohost_arg, tofile_arg); - } - } else { - checksetfields = 1; - (void) strncpy(fromhost, argv[optind], - MAX_RDC_HOST_SIZE); - (void) strncpy(fromfile, argv[optind+1], NSC_MAXPATH); - (void) strncpy(frombitmap, argv[optind+2], NSC_MAXPATH); - (void) strncpy(tohost, argv[optind+3], - MAX_RDC_HOST_SIZE); - (void) strncpy(tofile, argv[optind+4], NSC_MAXPATH); - (void) strncpy(tobitmap, argv[optind+5], NSC_MAXPATH); - - /* Check the length of entries from the command line */ - if ((fromhost[MAX_RDC_HOST_SIZE - 1] != '\0') || - (tohost[MAX_RDC_HOST_SIZE - 1] != '\0')) { - rdc_err(NULL, - gettext("hostname is longer than %d " - "characters\n"), (MAX_RDC_HOST_SIZE - 1)); - } - - /* Check if it's ip address -- not allowed */ - if ((inet_addr(fromhost) != (in_addr_t)(-1)) || - (inet_addr(tohost) != (in_addr_t)(-1))) { - rdc_err(NULL, gettext( - "The hostname specified is invalid.\n" - "See 'man inet(3SOCKET)'")); - } - - if ((fromfile[NSC_MAXPATH - 1] != '\0') || - (tofile[NSC_MAXPATH - 1] != '\0') || - (frombitmap[NSC_MAXPATH - 1] != '\0') || - (tobitmap[NSC_MAXPATH - 1] != '\0')) { - rdc_err(NULL, gettext("device name is longer " - "than %d characters\n"), (NSC_MAXPATH - 1)); - } -#ifdef _RDC_CAMPUS - if (argv[optind+6][0] == '/') { - /* FCAL directio */ - (void) strncpy(directfile, argv[optind+6], - NSC_MAXPATH); - } else if (strcmp(argv[optind+6], "ip") != 0) { -#else - if (strcmp(argv[optind+6], "ip") != 0) { -#endif - usage(); - exit(1); - } else - (void) strcpy(directfile, "ip"); - - if (strcmp(argv[optind+7], "sync") == 0) - doasync = 0; - else if (strcmp(argv[optind+7], "async") == 0) - doasync = 1; - else { - usage(); - exit(1); - } - - /* - * At this point, we could have a set which is - * clustered, but neither a 'C ctag' or '-C ctag' has - * been specified. To avoid clobbering the ctag if a - * dscfg operation is done in the future, we should get - * the ctag out of the config at this point. To do this, - * set the cluster resource filter to NULL to look at - * all sets in the config, pulling out the ctag for the - * set matching shost:svol. If the set is not found, - * fail here. Note, we skip this set on an enable as the - * set is not yet in the config, so no need to waste - * time. - */ - if ((argc - optind == 8) && clustered && - (flag != RDC_CMD_ENABLE)) { - int setnumber; - char key[CFG_MAX_KEY]; - - if ((cfg = cfg_open(NULL)) == NULL) { - rdc_err(NULL, - gettext("unable to access configuration")); - } - if (!cfg_lock(cfg, CFG_RDLOCK)) { - rdc_err(NULL, - gettext("unable to lock configuration")); - } - - cfg_resource(cfg, NULL); - - if ((setnumber = - find_setnumber_in_libcfg(cfg, NULL, tohost, - tofile)) < 0) { - cfg_close(cfg); - rdc_err(NULL, - gettext("unable to find Remote " - "Mirror set " - "%s:%s in config"), - tohost, tofile); - } - - (void) snprintf(key, sizeof (key), - "sndr.set%d.cnode", setnumber); - if (cfg_get_cstring(cfg, key, ctag_arg, - MAX_RDC_HOST_SIZE) < 0) { - cfg_close(cfg); - rdc_err(NULL, - gettext("unable to determine ctag " - "for Remote Mirror set %s:%s"), - tohost, tofile); - } - - rdc_islocal = strcmp(ctag_arg, "-") ? 0 : 1; - - cfg_close(cfg); - } - - extra_argc = argc - optind; - if (extra_argc < 8 || extra_argc > 14 || - extra_argc % 2 != 0) { - usage(); - exit(1); - } - - /* - * Loop through all of the extra arguments specified - * on the command line, setting the appropriate values - * for valid entries. If an unrecognized argument is - * detected, abort with error. Note: This hack should be - * removed and we should not accept these entries as - * arguments, they should be passed in as switches. - */ - for (i = (8 + optind); i < argc; i += 2) { - /* string case statement */ - if (strcmp(argv[i], "g") == 0) { - (void) strncpy(group, argv[i + 1], - NSC_MAXPATH); - if (group[NSC_MAXPATH - 1] != '\0') { - rdc_err(NULL, gettext("group name is " - "longer than %d characters\n"), - (NSC_MAXPATH - 1)); - } - } else if (strcmp(argv[i], "C") == 0) { - if (!clustered) { - usage(); - exit(1); - } - (void) strncpy(ctag, argv[i + 1], - MAX_RDC_HOST_SIZE); - - if (ctag[MAX_RDC_HOST_SIZE - 1] != '\0') { - rdc_err(NULL, gettext("cluster name " - "is longer than %d characters\n"), - (MAX_RDC_HOST_SIZE - 1)); - } - process_clocal(ctag); - - /* - * well here is something. - * what if they went sndradm -C local - * host a b host a b ip sync C foobar? - * they might be confused - * lets stop them if ctag_arg and ctag - * don't match and forgive if they are - * the same, below also. - */ - if ((strlen(ctag_arg) > 0) && - (strcmp(ctag_arg, ctag) != 0)) { - rdc_err(NULL, gettext("ctags " - "%s and %s do not match "), - ctag_arg, ctag); - - } - } else if (strcmp(argv[i], "q") == 0) { - (void) strncpy(diskqueue, argv[i + 1], - NSC_MAXPATH); - if (diskqueue[NSC_MAXPATH - 1] != '\0') { - rdc_err(NULL, gettext("diskq name is " - "longer than %d characters\n"), - (NSC_MAXPATH - 1)); - } - } else { - /* Unrecognized argument */ - usage(); - exit(1); - } - } - } - - /* - * Are we able to determine the existance of either - * of these host addresses? - */ - if (gethost_netaddrs(fromhost, tohost, - (char *)&fromnetaddr, (char *)&tonetaddr) < 0) { - (void) fprintf(stderr, "\n"); - rdc_warn(NULL, gettext("unable to determine IP " - "addresses for either host %s or host %s"), - fromhost, tohost); - - if (flag != RDC_CMD_DISABLE) - exit(1); - else - host_not_found = 1; - } - - /* - * Are we running on neither host? - */ - if (!self_check(fromhost) && !self_check(tohost)) { - if (flag == RDC_CMD_DISABLE) { - (void) fprintf(stderr, "\n"); - rdc_warn(NULL, gettext("Not running on either host " - "%s or host %s"), fromhost, tohost); - host_not_found = 1; - } - } - - /* - * at this point, hopfully it is safe to say that - * if a ctag was supplied via -C tag it is safe to - * move it from ctag_arg to ctag. If it was passed in - * at the end and the beginning of the cli, it must - * match, as per checks above. if it was not passed - * in at the end, but at the beginning, we can deal. - * this should handle the case of shost:svol. - * which is the main reason for this. - * - * there are 3 cases: passed in by cli, checked just above. - * using libdscfg, you must pass in -C tag to have - * ctag_check pass. - * finally a file. same rules as libdscfg. - */ - if ((strlen(ctag) == 0) && (strlen(ctag_arg) > 0)) - (void) strcpy(ctag, ctag_arg); - - if (flag == RDC_CMD_RECONFIG) { - if (reconfig_pbitmap) { - (void) strncpy(frombitmap, reconfig_pbitmap, - NSC_MAXPATH); - check_rdcbitmap(flag, fromhost, frombitmap); - } - if (reconfig_sbitmap) { - (void) strncpy(tobitmap, reconfig_sbitmap, - NSC_MAXPATH); - check_rdcbitmap(flag, tohost, tobitmap); - } -#ifdef _RDC_CAMPUS - if (reconfig_direct) - (void) strncpy(directfile, reconfig_direct, - NSC_MAXPATH); -#endif - if (reconfig_group) - (void) strncpy(group, reconfig_group, - NSC_MAXPATH); - - if (strlen(reconfig_ctag) > 0) - (void) strncpy(ctag, reconfig_ctag, - MAX_RDC_HOST_SIZE); - if (reconfig_doasync != -1) - doasync = reconfig_doasync; - } - - if (flag == RDC_CMD_ENABLE || flag == RDC_CMD_RECONFIG) { - if (ctag_check(fromhost, fromfile, frombitmap, - tohost, tofile, tobitmap, ctag, diskqueue) < 0) - exit(1); - if ((diskq_group = check_diskqueue(NULL, diskqueue, - group)) == DISKQ_FAIL) { - rdc_err(NULL, gettext("disk queue %s is " - "incompatible with existing queue"), - diskqueue); - } - - } - pairs = 1; - } else { - pairs = read_config(flag, config_file, group_arg, ctag_arg); - if (pairs == 0) { - rdc_err(NULL, gettext("%s contains no " - "matching Remote Mirror sets"), config_file); - } - } - - if (!nflag && !pflag && prompt_user(flag, iflag) == -1) - exit(1); - - while (pairs--) { - - if (cfgflag || fflag) { - (void) strncpy(fromfile, pair_list[pairs].ffile, - NSC_MAXPATH); - (void) strncpy(tofile, pair_list[pairs].tfile, - NSC_MAXPATH); - (void) strncpy(frombitmap, pair_list[pairs].fbitmap, - NSC_MAXPATH); - (void) strncpy(fromhost, - pair_list[pairs].fhost, MAX_RDC_HOST_SIZE); - (void) strncpy(tohost, pair_list[pairs].thost, - MAX_RDC_HOST_SIZE); - (void) strncpy(tobitmap, pair_list[pairs].tbitmap, - NSC_MAXPATH); - (void) strncpy(directfile, pair_list[pairs].directfile, - NSC_MAXPATH); - (void) strncpy(group, pair_list[pairs].group, - NSC_MAXPATH); - (void) strncpy(ctag, pair_list[pairs].ctag, - MAX_RDC_HOST_SIZE); - (void) strncpy(diskqueue, pair_list[pairs].diskqueue, - NSC_MAXPATH); - - bcopy(pair_list[pairs].fnetaddr, fromnetaddr, - RDC_MAXADDR); - bcopy(pair_list[pairs].tnetaddr, tonetaddr, - RDC_MAXADDR); - - doasync = pair_list[pairs].doasync; - } - - if (pflag) { - static int first = 1; - - if (first) { - if ((cfg = cfg_open(NULL)) == NULL) - rdc_err(NULL, - gettext("unable to access configuration")); - - if (!cfg_lock(cfg, CFG_RDLOCK)) - rdc_err(NULL, - gettext("unable to lock configuration")); - - first = 0; - } - - (void) rdc_print(file_format, verbose, - group_arg, ctag_arg, tohost, tofile, cfg); - - if (pairs == 0) { - cfg_close(cfg); - exit(0); - } - - /* short circuit the rest of the command loop */ - continue; - } - if (Bflag) { - int ret; - ret = rdc_bitmapset(tohost, tofile, bitfile, oflag, - boffset); - exit(ret); - } - if ((fflag || cfgflag) && flag == RDC_CMD_RECONFIG) { - char orig_fbmp[MAXHOSTNAMELEN]; - char orig_tbmp[MAXHOSTNAMELEN]; - int ret; - rdc_config_t parms; - spcs_s_info_t ustatus; - - parms.command = RDC_CMD_STATUS; - parms.rdc_set->netconfig = NULL; - (void) strncpy(parms.rdc_set->primary.intf, fromhost, - MAX_RDC_HOST_SIZE); - (void) strncpy(parms.rdc_set->secondary.intf, tohost, - MAX_RDC_HOST_SIZE); - (void) strncpy(parms.rdc_set->primary.file, fromfile, - NSC_MAXPATH); - (void) strncpy(parms.rdc_set->secondary.file, tofile, - NSC_MAXPATH); - ustatus = spcs_s_ucreate(); - ret = RDC_IOCTL(RDC_CONFIG, &parms, - NULL, 0, 0, 0, ustatus); - if (ret != SPCS_S_OK) { - rdc_err(NULL, gettext("unable to get set status" - " before reconfig operation")); - } - (void) strncpy(orig_fbmp, parms.rdc_set->primary.bitmap, - NSC_MAXPATH); - (void) strncpy(orig_tbmp, - parms.rdc_set->secondary.bitmap, NSC_MAXPATH); - - if (strncmp(orig_fbmp, frombitmap, NSC_MAXPATH) != 0) - check_rdcbitmap(flag, fromhost, frombitmap); - if (strncmp(orig_tbmp, tobitmap, NSC_MAXPATH) != 0) - check_rdcbitmap(flag, tohost, tobitmap); - spcs_s_ufree(&ustatus); - - } - /* - * take a peek in the config to see if - * the bitmap is being used elsewhere - */ - if (flag == RDC_CMD_ENABLE) { - struct stat stb; - /* - * just for fun, lets see if some silly person - * specified the same vol and bitmap - */ - if ((strcmp(fromfile, frombitmap) == 0) || - (strcmp(tofile, tobitmap) == 0)) - rdc_err(NULL, gettext("volumes and bitmaps" - " must not match")); - if (self_check(fromhost)) { - check_rdcbitmap(flag, fromhost, frombitmap); - if (stat(fromfile, &stb) != 0) { - rdc_err(NULL, - gettext("unable to access %s: %s"), - fromfile, strerror(errno)); - } - if (!S_ISCHR(stb.st_mode)) { - rdc_err(NULL, - gettext("%s is not a character device"), - fromfile); - } - } else { /* on the secondary */ - check_rdcbitmap(flag, tohost, tobitmap); - /* extra check for secondary vol */ - check_rdcsecondary(tofile); - if (stat(tofile, &stb) != 0) { - rdc_err(NULL, - gettext("unable to access %s: %s"), - tofile, strerror(errno)); - } - if (!S_ISCHR(stb.st_mode)) { - rdc_err(NULL, - gettext("%s is not a character device"), - tofile); - } - } - - } - - if (flag == RDC_CMD_ENABLE || flag == RDC_CMD_DISABLE || - flag == RDC_CMD_RECONFIG) { - if ((cfg = cfg_open(NULL)) == NULL) - rdc_err(NULL, - gettext("unable to access configuration")); - - if (!cfg_lock(cfg, CFG_WRLOCK)) - rdc_err(NULL, - gettext("unable to lock configuration")); - - cfg_resource(cfg, clustered ? ctag : NULL); - } else - cfg = NULL; - - if (cfg && perform_autosv() && - (flag == RDC_CMD_ENABLE || flag == RDC_CMD_DISABLE || - flag == RDC_CMD_RECONFIG)) { - if (cfg_load_svols(cfg) < 0 || - cfg_load_dsvols(cfg) < 0 || - cfg_load_shadows(cfg) < 0) - rdc_err(NULL, - gettext("Unable to parse config filer")); - load_rdc_vols(cfg); - } - cfg_success = (cfg == NULL); - if (cfg && flag == RDC_CMD_ENABLE) { - /* Enabled, so add the set via libcfg */ - - /* Build a new sndr entry and put it */ - group_p = *group? group : place_holder; - diskqueue_p = *diskqueue? diskqueue : place_holder; - - if ((diskqueue_p == place_holder) && - (group_p != place_holder)) { - get_group_diskq(cfg, group_p, diskqueue); - if (*diskqueue) - diskqueue_p = diskqueue; - } - - /* - * format in pconfig is: - * phost.primary.pbitmap.shost.secondary. - * sbitmap.type.mode.group.cnode.options.diskq - */ - (void) snprintf(buf, sizeof (buf), - "%s %s %s %s %s %s %s %s %s %s - %s", - fromhost, fromfile, frombitmap, tohost, tofile, - tobitmap, directfile, - doasync? "async" : "sync", group_p, - clustered? ctag : "-", diskqueue_p); - - if (cfg_put_cstring(cfg, "sndr", buf, strlen(buf)) < 0) - rdc_warn(NULL, - gettext("unable to add \"%s\" to " - "configuration storage: %s"), - buf, cfg_error(&sev)); - setnumber = find_setnumber_in_libcfg(cfg, clustered? - ctag : NULL, tohost, tofile); - if (setnumber < 0) - rdc_warn(NULL, - gettext("unable to add \"%s\" to " - "configuration storage: %s"), - diskqueue_p, cfg_error(&sev)); - - else - cfg_success = 1; - - /* Add cluster aware info */ - if (clustered && !rdc_islocal) { - (void) snprintf(key, sizeof (key), - "sndr.set%d.options", setnumber); - if (self_check(fromhost)) { - if (cfg_put_options(cfg, CFG_SEC_CONF, - key, "lghn", fromhost) < 0) { - rdc_err(NULL, - gettext("unable to add " - "\"%s\" to configuration " - "storage: %s"), - fromhost, cfg_error(&sev)); - } - } else if (self_check(tohost)) { - if (cfg_put_options(cfg, CFG_SEC_CONF, - key, "lghn", tohost) < 0) { - rdc_err(NULL, - gettext("unable to add " - "\"%s\" to configuration " - "storage: %s"), - fromhost, cfg_error(&sev)); - } - } - } - } else if (cfg && flag == RDC_CMD_DISABLE) { - found = 0; - /* Disabled, so delete the set via libcfg */ - - /* get sndr entries until shost, sfile match */ - for (i = 0; i < rdc_maxsets; i++) { - setnumber = i + 1; - (void) snprintf(key, sizeof (key), "sndr.set%d", - setnumber); - if (cfg_get_cstring(cfg, key, buf, - CFG_MAX_BUF) < 0) { - break; - } - (void) snprintf(key, sizeof (key), - "sndr.set%d.secondary", setnumber); - if (cfg_get_cstring(cfg, key, buf, - CFG_MAX_BUF) < 0) - break; - if (strcmp(buf, tofile) != 0) - continue; - (void) snprintf(key, sizeof (key), - "sndr.set%d.shost", - setnumber); - if (cfg_get_cstring(cfg, key, buf, - CFG_MAX_BUF) < 0) - break; - if (strcmp(buf, tohost) != 0) - continue; - found = 1; -#ifdef DEBUG - if (checksetfields == -1) { - rdc_err(NULL, - gettext("checksetfields not set")); - } -#endif - if (checksetfields) { - checkgfields(cfg, setnumber, fromhost, - fromfile, frombitmap, tobitmap, - directfile, (doasync == 1) - ? "async" : "sync", group, ctag, - diskqueue); - } - - /* perform cluster specific options */ - if (clustered) { - /* get the logical host, if set */ - (void) snprintf(key, sizeof (key), - "sndr.set%d.options", setnumber); - (void) cfg_get_single_option(cfg, - CFG_SEC_CONF, key, "lghn", - lhname, MAX_RDC_HOST_SIZE); - - /* figure out the cluster tag, if any */ - (void) snprintf(key, sizeof (key), - "sndr.set%d.cnode", setnumber); - if (cfg_get_cstring(cfg, key, buf, - CFG_MAX_BUF) < 0) - break; - if (strcmp(buf, ctag)) - rdc_err(NULL, gettext("ctags %s" - " and %s do not match"), - buf, ctag); - } else { - *lhname = '\0'; - *ctag = '\0'; - } - - /* figure out the disk queue, if any */ - (void) snprintf(key, sizeof (key), - "sndr.set%d.diskq", - setnumber); - if (cfg_get_cstring(cfg, key, buf, - CFG_MAX_BUF) < 0) - break; - if (strlen(buf) > 0) { - (void) strncpy(diskqueue, buf, - NSC_MAXPATH); - } else { - *diskqueue = '\0'; - } - (void) snprintf(key, sizeof (key), "sndr.set%d", - setnumber); - if (cfg_put_cstring(cfg, key, NULL, 0) < 0) - rdc_warn(NULL, - gettext("unable to remove \"%s\" " - "from configuration storage: %s"), - buf, cfg_error(&sev)); - else - cfg_success = 1; - break; - } - if (found == 0) { - rdc_err(NULL, - gettext("Unable to find %s:%s in " - "configuration storage"), - tohost, tofile); - } - if (host_not_found) { - rdc_force_disable(cfg, fromhost, fromfile, - frombitmap, tohost, tofile, tobitmap, ctag, - lhname); - if (cfg_commit(cfg) < 0) - rdc_err(NULL, gettext("commit on " - "force disable failed")); - cfg_close(cfg); - return (0); - } - } else if (cfg && flag == RDC_CMD_RECONFIG) { - /* Update relevant cfg record */ - - cfg_resource(cfg, NULL); - - /* get sndr entries until shost, sfile match */ - for (i = 0; i < rdc_maxsets; i++) { - setnumber = i + 1; - (void) snprintf(key, sizeof (key), "sndr.set%d", - setnumber); - if (cfg_get_cstring(cfg, key, buf, - CFG_MAX_BUF) < 0) { - break; - } - (void) snprintf(key, sizeof (key), - "sndr.set%d.secondary", setnumber); - if (cfg_get_cstring(cfg, key, buf, - CFG_MAX_BUF) < 0) - break; - if (strcmp(buf, tofile) != 0) - continue; - (void) snprintf(key, sizeof (key), - "sndr.set%d.shost", - setnumber); - if (cfg_get_cstring(cfg, key, buf, - CFG_MAX_BUF) < 0) - break; - if (strcmp(buf, tohost) != 0) - continue; - (void) snprintf(key, sizeof (key), - "sndr.set%d.cnode", - setnumber); - if (cfg_get_cstring(cfg, key, buf, - CFG_MAX_BUF) < 0) - break; - if (reconfig_ctag[0] == '\0') - (void) strncpy(ctag, buf, - sizeof (ctag)); - if (doasync) - (void) strcpy(mode, "async"); - else - (void) strcpy(mode, "sync"); - if (strcmp(directfile, "") == 0) - (void) strcpy(directfile, "ip"); - - group_p = strlen(group) > 0 ? group : - place_holder; - - /* - * if we are reconfigging out altogether, - * get rid of the diskqueue - */ - if (group_p == place_holder) - diskqueue_p = place_holder; - else - diskqueue_p = strlen(diskqueue) > 0 ? - diskqueue : place_holder; - - /* - * do a little diskq dance here for reconfigs - * that did not specify the diskqueue whilst - * reconfigging ... - */ - if ((diskqueue_p == place_holder) && - (group_p != place_holder)) { - get_group_diskq(cfg, group_p, - diskqueue); - diskqueue_p = strlen(diskqueue) > 0 ? - diskqueue : place_holder; - } - - (void) snprintf(key, sizeof (key), - "sndr.set%d.options", setnumber); - if (cfg_get_cstring(cfg, key, options_cfg, - CFG_MAX_BUF) < 0) { - break; - } - - ctag_p = strlen(ctag) > 0 ? - ctag : place_holder; - (void) snprintf(buf, sizeof (buf), - "%s %s %s %s %s %s %s %s %s %s %s %s", - fromhost, fromfile, frombitmap, - tohost, tofile, tobitmap, - directfile, mode, group_p, - ctag_p, options_cfg, diskqueue_p); - - (void) snprintf(key, sizeof (key), "sndr.set%d", - setnumber); - if (cfg_put_cstring(cfg, key, buf, - strlen(buf)) < 0) - rdc_warn(NULL, - gettext("unable to update \"%s\" " - "in configuration storage: %s"), - buf, cfg_error(&sev)); - else - cfg_success = 1; - break; - } - } - - if (cfg_success) { - if (cfg && perform_autosv()) { - if (self_check(fromhost)) { - if (diskqueue[0] && - (strcmp(diskqueue, fromfile) == 0) || - (strcmp(diskqueue, frombitmap) == 0)) { - rdc_err(NULL, gettext("disk " - "queue volume %s must not " - "match any primary Remote " - "Mirror volume or bitmap"), - diskqueue); - } - - if (diskqueue[0]) { - different_devs(fromfile, diskqueue); - different_devs(frombitmap, diskqueue); - validate_name(cfg, diskqueue); - } - different_devs(fromfile, frombitmap); - validate_name(cfg, fromfile); - validate_name(cfg, frombitmap); - } else { - different_devs(tofile, tobitmap); - validate_name(cfg, tofile); - validate_name(cfg, tobitmap); - } - } - /* - * okay, if the command is sync, just build - * a list of rdcconfig_t's after the pairs-- - * loop is done, we will pass this list to - * librdc to multithread the syncs (after - * forking off a daemonish type process - * that waits for the libcall to complete - * ints of interest: - * flag ie RDC_CMD_COPY, iflag RDC_OPT_UPDATE, - * reverse RDC_OPT_REVERSE, RDC_OPT_FORWARD - * if necessary, turn autosync back on - */ - if (flag == RDC_CMD_COPY) { - if (autosync_is_on(tohost, tofile) == - AUTOSYNC_ON) - enable_autosync(fromhost, fromfile, - tohost, tofile); - - if (sets == NULL) { - sets_p = sets = - rdc_alloc_config(fromhost, fromfile, - frombitmap, tohost, tofile, - tobitmap, "mode", "group", "ctag", - "options", 0); - - if (sets_p == NULL) { - rdc_err(NULL, - gettext("rdc config alloc" - "failed %s"), rdc_error(NULL)); - } - continue; - } - - sets_p = sets_p->next = - rdc_alloc_config(fromhost, fromfile, - frombitmap, tohost, tofile, tobitmap, - "mode", "group", "ctag", "options", 0); - - if (sets_p == NULL) { - rdc_err(NULL, gettext("rdc config alloc" - "failed %s"), rdc_error(NULL)); - } - continue; - } - - /* - * block incoming signals until after the possible - * cfg_commit is done - */ - block_sigs(); - if (rdc_operation(cfg, fromhost, fromfile, frombitmap, - tohost, tofile, tobitmap, flag, iflag, directfile, - group, ctag, diskqueue, &doasync, reverse) < 0) { - ; - /*EMPTY*/ - } else if (cfg) { - if (diskq_group == DISKQ_REWRITEG) { - rewrite_group_diskqueue(cfg, - &pair_list[pairs], diskqueue); - } - if (perform_autosv() && - (flag == RDC_CMD_ENABLE || - flag == RDC_CMD_DISABLE || - flag == RDC_CMD_RECONFIG)) { - unload_rdc_vols(); - cfg_unload_shadows(); - cfg_unload_dsvols(); - cfg_unload_svols(); - } - if ((iflag & RDC_OPT_REVERSE_ROLE) != 0 && - allow_role) { - bzero(tmphost, MAX_RDC_HOST_SIZE); - bzero(tmpfile, NSC_MAXPATH); - bzero(tmpbitmap, NSC_MAXPATH); - (void) strncpy(tmphost, fromhost, - MAX_RDC_HOST_SIZE); - (void) strncpy(tmpfile, fromfile, - NSC_MAXPATH); - (void) strncpy(tmpbitmap, frombitmap, - NSC_MAXPATH); - - (void) strncpy(fromhost, tohost, - MAX_RDC_HOST_SIZE); - (void) strncpy(fromfile, tofile, - NSC_MAXPATH); - (void) strncpy(frombitmap, tobitmap, - NSC_MAXPATH); - - (void) strncpy(tohost, tmphost, - MAX_RDC_HOST_SIZE); - (void) strncpy(tofile, tmpfile, - NSC_MAXPATH); - (void) strncpy(tobitmap, tmpbitmap, - NSC_MAXPATH); - group_p = strlen(group) > 0 ? group : - place_holder; - diskqueue_p = strlen(diskqueue) > 0 ? - diskqueue : place_holder; - ctag_p = strlen(ctag) > 0 ? - ctag : place_holder; - (void) snprintf(buf, sizeof (buf), "%s " - "%s %s %s %s %s %s %s %s %s %s %s", - fromhost, fromfile, frombitmap, - tohost, tofile, tobitmap, - directfile, mode, group_p, - ctag_p, options_cfg, diskqueue_p); - - (void) snprintf(key, sizeof (key), - "sndr.set%d", setnumber); - if (cfg_put_cstring(cfg, key, buf, - strlen(buf)) < 0) - rdc_err(NULL, - gettext("unable to update \"%s\" " - "in configuration storage: %s"), - buf, cfg_error(&sev)); - } - if (cfg_commit(cfg) < 0) { - rdc_err(NULL, gettext("commit on role " - "reversal failed")); - } - } - unblock_sigs(); - } - - if (cfg) { - cfg_close(cfg); - } - - } - if (flag == RDC_CMD_COPY) { - pid = fork(); - if (pid == -1) { /* error forking */ - perror("fork"); - exit(1); - } - } else { - exit(0); - } - if (pid > 0) /* parent process */ - exit(0); - - spcslog_sync(sets, 1, iflag); - if (iflag & RDC_OPT_REVERSE) { - if (iflag & RDC_OPT_UPDATE) - rclist = rdc_ursync(sets); - else - rclist = rdc_rsync(sets); - } else if (iflag & RDC_OPT_UPDATE) { - rclist = rdc_usync(sets); - } else - rclist = rdc_fsync(sets); - - rcp = rclist; - while (rcp) { - if (rcp->rc < 0) { - /* rclist->msg has already been gettext'd */ - (void) fprintf(stderr, - gettext("Remote Mirror: %s %s %s %s %s %s\n"), - rcp->set.phost, rcp->set.pfile, rcp->set.pbmp, - rcp->set.shost, rcp->set.sfile, rcp->set.sbmp); - rdc_warn(NULL, "%s", rcp->msg); - spcs_log("sndr", NULL, "%s", rcp->msg); - } - rcp = rcp->next; - } - - spcslog_sync(sets, 0, iflag); - - if (sets) - rdc_free_config(sets, RDC_FREEALL); - if (rclist) - rdc_free_rclist(rclist); - - return (0); -} -/* - * process_clocal() - * pre: a non null string - * post: if the string is "local" - * then it is converted to "-" - * and rdc_islocal is set to 1 - * if not rdc_islocal set to 0 - */ -void -process_clocal(char *ctag) -{ - /* - * Check for the special cluster tag and convert into the - * internal representation. - */ - - if (ctag != NULL && strcmp(ctag, RDC_LOCAL_TAG) == 0) { - (void) strcpy(ctag, "-"); - rdc_islocal = 1; - } else { - rdc_islocal = 0; - } -} - -static void -rdc_check_dgislocal(char *dgname) -{ - char *othernode; - int rc; - - /* - * check where this disk service is mastered - */ - - rc = cfg_dgname_islocal(dgname, &othernode); - if (rc < 0) { - rdc_err(NULL, gettext("unable to find " - "disk service, %s: %s"), dgname, strerror(errno)); - } - - if (rc == 0) { - rdc_err(NULL, gettext("disk service, %s, is " - "active on node \"%s\"\nPlease re-issue " - "the command on that node"), dgname, othernode); - } -} - -static void -different_devs(char *dev1, char *dev2) -{ - struct stat buf1, buf2; - - if (stat(dev1, &buf1) < 0) { - spcs_log("sndr", NULL, gettext("Remote Mirror: can't stat %s"), - dev1); - rdc_err(NULL, gettext("Remote Mirror: can't stat %s"), dev1); - } - if (stat(dev2, &buf2) < 0) { - spcs_log("sndr", NULL, gettext("Remote Mirror: can't stat %s"), - dev2); - rdc_err(NULL, gettext("Remote Mirror: can't stat %s"), dev2); - } - if (buf1.st_rdev == buf2.st_rdev) { - spcs_log("sndr", NULL, gettext("Remote Mirror: '%s' and '%s' " - "refer to the same device"), dev1, dev2); - rdc_err(NULL, gettext("Remote Mirror: '%s' and '%s' refer to " - "the same device"), dev1, dev2); - } -} - -static void -validate_name(CFGFILE *cfg, char *vol) -{ - char *altname; - int rc; - - if (!cfg) { - rdc_err(NULL, gettext("Remote Mirror: null cfg ptr in " - "validate_name")); - } - - rc = cfg_get_canonical_name(cfg, vol, &altname); - if (rc < 0) { - spcs_log("sndr", NULL, gettext("Remote Mirror: unable to parse " - "config file\n")); - rdc_err(NULL, gettext("Remote Mirror: unable to parse config " - "file\n")); - } - if (rc) { - spcs_log("sndr", NULL, gettext("Remote Mirror: '%s': already " - "configured as '%s'"), vol, altname); - rdc_err(NULL, gettext("Remote Mirror: The volume '%s' has been " - "configured previously as '%s'. Re-enter command with " - "the latter name."), vol, altname); - } -} - -/* - * Add the autosync value to the option field for the sndr set specified by - * tohost:tofile. - * - * ASSUMPTIONS: - * - cfg file is available to take a write lock. - * - set is already configured in dscfg - * - * INPUTS: - * autosync_val - value to set autosync to - * tohost - secondary host - * tofile - secondary volume - * - * OUTPUTS: - * none. - * - */ -static void -set_autosync(int autosync_val, char *tohost, char *tofile, char *ctag) -{ - CFGFILE *cfg; - char key[CFG_MAX_KEY], buf[CFG_MAX_BUF]; - char tag[CFG_MAX_BUF], val[CFG_MAX_BUF]; - char auto_tag[CFG_MAX_BUF]; - _sd_dual_pair_t pair; - _sd_dual_pair_t tmpair; - int setnumber, options = 0, already_set = 0, cfg_success = 0; - int set; - - /* verify valid autosync request */ - if ((autosync_val != AUTOSYNC_ON) && (autosync_val != AUTOSYNC_OFF)) { -#ifdef DEBUG - rdc_warn(NULL, - gettext("set_autosync called with improper value")); -#endif - return; - } - - if ((cfg = cfg_open(NULL)) == NULL) { - rdc_err(NULL, gettext("unable to access configuration")); - } - if (!cfg_lock(cfg, CFG_WRLOCK)) { - rdc_err(NULL, gettext("unable to lock configuration")); - } - - if (clustered) { - cfg_resource(cfg, ctag); - } else { - cfg_resource(cfg, NULL); - } - - /* find set number in config */ - if ((setnumber = find_setnumber_in_libcfg(cfg, clustered? ctag : NULL, - tohost, tofile)) < 0) { - cfg_close(cfg); - rdc_err(NULL, gettext("unable to find Remote Mirror set %s:%s: " - "in config"), tohost, tofile); - } - (void) snprintf(key, sizeof (key), "sndr.set%d.options", setnumber); - (void) snprintf(auto_tag, sizeof (auto_tag), "auto"); - - /* Check if there are any options already set, including ours */ - if (cfg_get_options(cfg, CFG_SEC_CONF, key, tag, CFG_MAX_BUF, val, - CFG_MAX_BUF) >= 0) { - options = 1; - - do { - if (strcmp(tag, auto_tag) == 0) { - already_set = 1; - } - } while (cfg_get_options(cfg, CFG_SEC_CONF, NULL, tag, - CFG_MAX_BUF, val, CFG_MAX_BUF) >= 0); - } - - /* options already exist, edit ours out */ - if (options && already_set) { - char *p, *q; - int need_to_clear_buf = 1; - - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) { - rdc_err(NULL, gettext("unable to get options field " - "for Remote Mirror set %s:%s"), tohost, tofile); - } - - /* parse out our options, all of the form "auto=" */ - p = strdup(buf); - bzero(buf, sizeof (buf)); - - q = strtok(p, ";"); - do { - /* if another tag/value exists, keep it */ - if (strncmp(auto_tag, q, 4) != 0) { - (void) strcat(buf, q); - (void) strcat(buf, ";"); - need_to_clear_buf = 0; - } - } while (q = strtok(NULL, ";")); - free(p); - - /* if we were the only option, clear the field */ - if (need_to_clear_buf) { - (void) strcat(buf, "-"); - } - - if (cfg_put_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) { - rdc_err(NULL, gettext("unable to clear autosync value " - "in config for Remote Mirror set %s:%s"), tohost, - tofile); - } else { - cfg_success = 1; - } - } - - /* autosync is not present in options field, add if on is requested */ - if (autosync_val == AUTOSYNC_ON) { - if (cfg_put_options(cfg, CFG_SEC_CONF, key, auto_tag, "on") - < 0) { - rdc_err(NULL, gettext("unable to update autosync value " - "in config for Remote Mirror set %s:%s"), tohost, - tofile); - } else { - cfg_success = 1; - } - } - /* if we are in a group, update any other sets in the same group */ - do { - bzero(&pair, sizeof (pair)); - bzero(buf, CFG_MAX_BUF); - - (void) snprintf(key, sizeof (key), "sndr.set%d", setnumber); - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) { - break; - } - if (parse_cfg_buf(buf, &pair, NULL)) - break; - if (pair.group == NULL) /* not in a group */ - break; - if (!pair.group[0]) - break; /* not in a group */ - for (set = 1; /*CSTYLED*/; set++) { - if (set == setnumber) - continue; - bzero(buf, CFG_MAX_BUF); - options = 0; - already_set = 0; - - (void) snprintf(key, sizeof (key), "sndr.set%d", set); - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) { - break; /* last set processed */ - } - bzero(&tmpair, sizeof (tmpair)); - if (parse_cfg_buf(buf, &tmpair, NULL)) - break; - if (strcmp(pair.group, tmpair.group) != 0) - continue; /* not the group we want */ - - (void) snprintf(key, sizeof (key), "sndr.set%d.options", - set); - /* - * Check if there are any options already set, - * including ours - */ - if (cfg_get_options(cfg, CFG_SEC_CONF, key, tag, - CFG_MAX_BUF, val, CFG_MAX_BUF) >= 0) { - options = 1; - - do { - if (strcmp(tag, auto_tag) == 0) { - already_set = 1; - } - } while (cfg_get_options(cfg, CFG_SEC_CONF, - NULL, tag, CFG_MAX_BUF, val, - CFG_MAX_BUF) >= 0); - } - - /* options already exist, edit ours out */ - if (options && already_set) { - char *p, *q; - int need_to_clear_buf = 1; - - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) - < 0) { - rdc_err(NULL, gettext("unable to get " - "options field for Remote Mirror set " - "%s:%s"), tmpair.thost, tmpair.tfile); - } - - /* - * parse out our options, all of the - * form "auto=" - */ - p = strdup(buf); - bzero(buf, sizeof (buf)); - - q = strtok(p, ";"); - do { - /* - * if another tag/value exists, - * keep it - */ - if (strncmp(auto_tag, q, 4) != 0) { - (void) strcat(buf, q); - (void) strcat(buf, ";"); - need_to_clear_buf = 0; - } - } while (q = strtok(NULL, ";")); - free(p); - - /* - * if we were the only option, - * clear the field - */ - if (need_to_clear_buf) { - (void) strcat(buf, "-"); - } - - if (cfg_put_cstring(cfg, key, buf, CFG_MAX_BUF) - < 0) { - rdc_err(NULL, gettext("unable to clear " - "autosync value in config for " - "Remote Mirror set %s:%s"), - tmpair.thost, tmpair.tfile); - cfg_success = 0; - } - } - - /* - * autosync is not present in options field, - * add if on is requested - */ - if (autosync_val == AUTOSYNC_ON) { - if (cfg_put_options(cfg, CFG_SEC_CONF, key, - auto_tag, "on") < 0) { - rdc_err(NULL, gettext("unable to update" - " autosync value in config for " - "Remote Mirror set %s:%s"), - tmpair.thost, - tmpair.tfile); - cfg_success = 0; - } - } - } - - /* CONSTCOND */ - } while (0); - if (cfg_success) { - if (cfg_commit(cfg) < 0) { - rdc_err(NULL, gettext("commit on role reversal failed")); - } - } - - cfg_close(cfg); -} - -/* - * Check to see if autosync is on for set specified by tohost:tofile. - * - * ASSUMPTIONS: - * config is available to take a read lock against it. - * - * INPUTS: - * tohost - secondary host - * tofile - secondary volume - * - * OUTPUTS: - * -1 error - * AUTOSYNC_ON if autosync is on - * AUTOSYNC_OFF if autosync is off - */ -static int -autosync_is_on(char *tohost, char *tofile) -{ - CFGFILE *cfg; - int setnumber, autosync_val = AUTOSYNC_OFF; - char key[CFG_MAX_KEY]; - char tag[CFG_MAX_BUF], val[CFG_MAX_BUF]; - - if ((cfg = cfg_open(NULL)) == NULL) { - rdc_err(NULL, gettext("unable to access configuration")); - } - - if (!cfg_lock(cfg, CFG_RDLOCK)) { - cfg_close(cfg); - rdc_err(NULL, gettext("unable to lock configuration")); - } - - if ((setnumber = find_setnumber_in_libcfg(cfg, NULL, tohost, tofile)) < - 0) { - cfg_close(cfg); - rdc_err(NULL, gettext("cannot find Remote Mirror set %s:%s in " - "config"), tohost, tofile); - } - - (void) snprintf(key, CFG_MAX_KEY, "sndr.set%d.options", setnumber); - if (cfg_get_options(cfg, CFG_SEC_CONF, key, tag, CFG_MAX_BUF, val, - CFG_MAX_BUF) >= 0) { - do { - if (strcmp(tag, "auto") == 0) { - if (strcmp(val, "on") == 0) { - autosync_val = AUTOSYNC_ON; - } - break; - } - } while (cfg_get_options(cfg, CFG_SEC_CONF, NULL, tag, - CFG_MAX_BUF, val, CFG_MAX_BUF) >= 0); - } - - cfg_close(cfg); - return (autosync_val); -} - -void -enable_autosync(char *fhost, char *ffile, char *thost, char *tfile) -{ - rdc_config_t parms; - spcs_s_info_t ustat; - rdc_addr_t *p; - - ustat = spcs_s_ucreate(); - parms.command = RDC_CMD_TUNABLE; - - p = &parms.rdc_set[0].primary; - (void) strncpy(p->intf, fhost, MAX_RDC_HOST_SIZE); - (void) strncpy(p->file, ffile, MAX_RDC_HOST_SIZE); - - p = &parms.rdc_set[0].secondary; - (void) strncpy(p->intf, thost, NSC_MAXPATH); - (void) strncpy(p->file, tfile, NSC_MAXPATH); - - parms.rdc_set[0].autosync = 1; - parms.rdc_set[0].maxqfbas = -1; - parms.rdc_set[0].maxqitems = -1; - parms.rdc_set[0].asyncthr = -1; - parms.rdc_set[0].netconfig = NULL; - - if ((RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustat)) != - SPCS_S_OK) { - rdc_warn(&ustat, gettext("failed to update autosync for" - " Remote Mirror set %s:%s"), thost, tfile); - spcs_log("sndr", &ustat, gettext("failed to update autosync for" - " Remote Mirror set %s:%s"), thost, tfile); - } - spcs_s_ufree(&ustat); -} - -static int -rdc_operation(CFGFILE *cfg, char *fromhost, char *fromfile, char *frombitmap, - char *tohost, char *tofile, char *tobitmap, - int flag, int iflag, - char *directfile, char *group, char *ctag, char *diskqueue, - int *doasync, int reverse) -{ - const int getaddr = (flag == RDC_CMD_ENABLE); - const int rpcbind = !getaddr; - rdc_config_t parms; - int ret; - spcs_s_info_t ustatus; - struct hostent *hp; - char fromname[MAXHOSTNAMELEN], toname[MAXHOSTNAMELEN]; - char orig_fbmp[MAXHOSTNAMELEN], orig_tbmp[MAXHOSTNAMELEN]; - char orig_diskq[NSC_MAXPATH]; - struct t_info tinfo; - int success = 1; - int autosync_toggle_needed = 0; - char *vol1, *vol2, *vol3; - - conf = &nconf; - - hp = gethost_byname(fromhost); - (void) strncpy(fromname, hp->h_name, MAXHOSTNAMELEN); - hp = gethost_byname(tohost); - (void) strncpy(toname, hp->h_name, MAXHOSTNAMELEN); - - if (self_check(fromname) && self_check(toname)) { - rdc_err(NULL, gettext("both %s and %s are local"), - fromhost, tohost); - } - - /* we have to find out what to sv disable after reconfig */ - if (flag == RDC_CMD_RECONFIG) { - - parms.command = RDC_CMD_STATUS; - parms.rdc_set->netconfig = NULL; - (void) strncpy(parms.rdc_set->primary.intf, fromhost, - MAX_RDC_HOST_SIZE); - (void) strncpy(parms.rdc_set->secondary.intf, tohost, - MAX_RDC_HOST_SIZE); - (void) strncpy(parms.rdc_set->primary.file, fromfile, - NSC_MAXPATH); - (void) strncpy(parms.rdc_set->secondary.file, tofile, - NSC_MAXPATH); - ustatus = spcs_s_ucreate(); - ret = RDC_IOCTL(RDC_CONFIG, &parms, - NULL, 0, 0, 0, ustatus); - if (ret != SPCS_S_OK) { - rdc_err(NULL, gettext("unable to get set status" - " before reconfig operation")); - } - (void) strncpy(orig_fbmp, parms.rdc_set->primary.bitmap, - NSC_MAXPATH); - (void) strncpy(orig_tbmp, parms.rdc_set->secondary.bitmap, - NSC_MAXPATH); - (void) strncpy(orig_diskq, parms.rdc_set->disk_queue, - NSC_MAXPATH); - } - - /* - * another terrible addition, if we are reconfigging mode - * and not logging, just give up. - */ - if ((reconfig_doasync != -1) && - (!(parms.rdc_set->flags & RDC_LOGGING))) { - rdc_err(NULL, gettext("cannot reconfigure sync/async, " - "Remote Mirror set not logging")); - spcs_log("sndr", NULL, gettext("cannot reconfigure sync/async, " - "Remote Mirror set not logging")); - } - - /* - * Now build up the address for each host including port and transport - */ - if (getaddr) { - svp = get_addr(toname, RDC_PROGRAM, RDC_VERS_MIN, - &conf, proto_test ? NC_UDP:NULL, "rdc", &tinfo, - rpcbind); - - if (svp == NULL) { - rdc_warn(NULL, gettext("unable to determine network " - "information for %s"), toname); -#ifdef DEBUG - (void) printf("get_addr failed for Ver 4 %s\n", toname); -#endif - return (-1); - } - svaddr = *svp; - } else { - bzero(&svaddr, sizeof (svaddr)); - } - - parms.rdc_set->secondary.addr.len = svaddr.len; - parms.rdc_set->secondary.addr.maxlen = - svaddr.maxlen; - parms.rdc_set->secondary.addr.buf = - (void *)svaddr.buf; - -#ifdef DEBUG_ADDR - (void) fprintf(stderr, "secondary buf %x len %d\n", - svaddr.buf, svaddr.len); - - for (i = 0; i < svaddr.len; i++) - (void) printf("%u ", svaddr.buf[i]); - (void) printf("\n"); -#endif - - if (getaddr) { - svp = get_addr(fromname, RDC_PROGRAM, RDC_VERS_MIN, - &conf, proto_test ? NC_UDP: NULL, "rdc", &tinfo, - rpcbind); - if (svp == NULL) { -#ifdef DEBUG - (void) printf("get_addr failed for Ver 4 %s\n", - fromname); -#endif - return (-1); - } - svaddr = *svp; - } - - parms.rdc_set->primary.addr.len = svaddr.len; - parms.rdc_set->primary.addr.maxlen = svaddr.maxlen; - parms.rdc_set->primary.addr.buf = (void *)svaddr.buf; - -#ifdef DEBUG_ADDR - (void) fprintf(stderr, "primary buf %x len %d\n", - svaddr.buf, svaddr.len); - for (i = 0; i < svaddr.len; i++) - (void) printf("%u ", svaddr.buf[i]); - (void) printf("\n"); -#endif - - if (getaddr) { - (void) convert_nconf_to_knconf(conf, &knconf); -#ifdef DEBUG_ADDR - (void) printf("knconf %x %s %s %x\n", knconf.knc_semantics, - knconf.knc_protofmly, knconf.knc_proto, knconf.knc_rdev); -#endif - parms.rdc_set->netconfig = &knconf; - } else { - parms.rdc_set->netconfig = NULL; - } - - if (!self_check(fromname) && !self_check(toname)) { - if (!clustered) - rdc_err(NULL, gettext("neither %s nor %s is local"), - fromhost, tohost); - else { - /* - * IF we could get a list of logical hosts on this cluster - * Then we could print something intelligent about where - * the volume is mastered. For now, just print some babble - * about the fact that we have no idea. - */ - rdc_err(NULL, - gettext("either %s:%s or %s:%s is not local"), - fromhost, fromfile, tohost, tofile); - } - } - - (void) strncpy(parms.rdc_set->primary.intf, fromhost, - MAX_RDC_HOST_SIZE); - (void) strncpy(parms.rdc_set->primary.file, fromfile, NSC_MAXPATH); - (void) strncpy(parms.rdc_set->primary.bitmap, frombitmap, NSC_MAXPATH); - - (void) strncpy(parms.rdc_set->secondary.intf, tohost, - MAX_RDC_HOST_SIZE); - (void) strncpy(parms.rdc_set->secondary.file, tofile, NSC_MAXPATH); - (void) strncpy(parms.rdc_set->secondary.bitmap, tobitmap, NSC_MAXPATH); - - if ((group == NULL) || ((strcmp(group, "-")) == 0)) - parms.rdc_set->group_name[0] = 0; - else - (void) strncpy(parms.rdc_set->group_name, group, NSC_MAXPATH); - - if (self_check(tohost) && - (strlen(diskqueue) > 0) && (diskqueue[0] != '-')) - if ((flag == RDC_CMD_ENABLE) || (flag == RDC_CMD_ADDQ)) - rdc_err(NULL, gettext("enabling disk queue on a Remote" - " Mirror secondary is not allowed (%s)"), - diskqueue); - - if ((diskqueue == NULL) || ((strcmp(diskqueue, "-")) == 0)) - parms.rdc_set->disk_queue[0] = 0; - else - (void) strncpy(parms.rdc_set->disk_queue, diskqueue, - NSC_MAXPATH); - - parms.rdc_set->maxqfbas = maxqfbas; - parms.rdc_set->maxqitems = maxqitems; - parms.rdc_set->asyncthr = asyncthr; - /* set up the permanent set id for this set */ - if (flag == RDC_CMD_ENABLE) { - char key[CFG_MAX_KEY]; - char setid[64]; - int set; - parms.rdc_set->setid = get_new_cfg_setid(cfg); - if (parms.rdc_set->setid <= 0) { - rdc_err(NULL, gettext("unable to obtain unique set id " - "for %s:%s"), tohost, tofile); - } - if ((set = find_setnumber_in_libcfg(cfg, clustered? ctag : NULL, - tohost, tofile)) < 0) { - rdc_err(NULL, gettext("unable to store unique set id" - " for %s:%s"), tohost, tofile); - } - (void) snprintf(key, sizeof (key), "sndr.set%d.options", set); - (void) snprintf(setid, sizeof (setid), "%d", - parms.rdc_set->setid); - - if (cfg_put_options(cfg, CFG_SEC_CONF, key, "setid", - setid) < 0) { - rdc_err(NULL, gettext("unable to store unique set " - "id for %s:%s: %s"), tohost, tofile, - gettext(cfg_error(NULL))); - } - } else if (flag != RDC_CMD_DISABLE) { /* set already gone from cfg */ - parms.rdc_set->setid = get_cfg_setid(cfg, ctag, tohost, tofile); - if (parms.rdc_set->setid <= 0) { - rdc_err(NULL, gettext("unable to obtain unique set id " - "for %s:%s"), tohost, tofile); - } - } - - /* - * Always set autosync flag to default so nothing gets messed up. If - * we are doing an autosync operation, it'll all get taken care of - * then. - */ - parms.rdc_set->autosync = AUTOSYNC; - - - /* gethostid(3c) is defined to return a 32bit value */ - parms.rdc_set->syshostid = (int32_t)gethostid(); - - parms.command = 0; - parms.options = iflag; - parms.command = flag; - if (flag == RDC_CMD_ENABLE || flag == RDC_CMD_RECONFIG) { - if (*doasync) - parms.options |= RDC_OPT_ASYNC; - else - parms.options |= RDC_OPT_SYNC; - } else if (flag == RDC_CMD_COPY) { - if (reverse) - parms.options |= RDC_OPT_REVERSE; - else - parms.options |= RDC_OPT_FORWARD; - } - - if (self_check(fromname)) { - if (flag == RDC_CMD_COPY && reverse && mounted(fromfile)) - rdc_err(NULL, gettext("can not start reverse sync" - " as a file system is mounted on %s"), - fromfile); - parms.options |= RDC_OPT_PRIMARY; - if (strcmp(directfile, "ip") == 0) - parms.rdc_set->direct_file[0] = 0; /* no directfile */ - else - (void) strncpy(parms.rdc_set->direct_file, directfile, - NSC_MAXPATH); - } else { - parms.options |= RDC_OPT_SECONDARY; - parms.rdc_set->direct_file[0] = 0; /* no fcal directio */ - } - - if ((asyncthr || maxqitems || maxqfbas || qblock) && - (parms.options & RDC_OPT_SECONDARY)) { - rdc_err(NULL, gettext("changing queue parameters may " - " only be done on a primary Remote Mirror host")); - spcs_log("sndr", NULL, gettext("changing queue parameters may " - " only be done on a primary Remote Mirror host")); - - } - - ustatus = spcs_s_ucreate(); - - if (flag == RDC_CMD_COPY) { - parms.command = RDC_CMD_STATUS; - ret = RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus); - if ((ret != SPCS_S_OK) || - !(parms.rdc_set->flags & RDC_LOGGING)) { - rdc_err(NULL, gettext("can not start sync" - " as Remote Mirror set %s:%s is not logging"), - tohost, tofile); - } - spcs_log("sndr", NULL, - gettext("%s %s %s %s %s %s %s %s\nStarting"), - program, rdc_decode_flag(flag, parms.options), - fromhost, fromfile, frombitmap, - tohost, tofile, tobitmap); - parms.command = RDC_CMD_COPY; - } - - if ((flag == RDC_CMD_COPY) && - (autosync_is_on(tohost, tofile) == AUTOSYNC_ON)) { - /* check if autosync needs to be turned on when doing a copy/update */ - parms.rdc_set->autosync = AUTOSYNC_ON; - autosync_toggle_needed = 1; - } else if ((flag == RDC_CMD_LOG) && - (autosync_is_on(tohost, tofile) == AUTOSYNC_ON)) { - /* check if autosync needs to be turned off when going to logging */ - parms.rdc_set->autosync = AUTOSYNC_OFF; - autosync_toggle_needed = 1; - } else if (((autosync == AUTOSYNC_ON) || (autosync == AUTOSYNC_OFF)) && - (flag == RDC_CMD_TUNABLE)) { - /* - * Request to change the autosync value. cfg file will be - * available at this point. If autosync request is to turn off, - * mark off in both the config and the kernel regardless of - * the state of the set. If the request is to turn autosync on, - * set in the kernel if the set is not in logging mode. - * - * XXX - * If the set is in logging mode because of a network - * failure, we will not know. Therefore, a manual update - * will have to be issued to enable autosync in the - * kernel. - * XXX - */ - set_autosync(autosync, tohost, tofile, ctag); - - if (autosync == AUTOSYNC_OFF) { - parms.rdc_set->autosync = AUTOSYNC_OFF; - } else if (autosync == AUTOSYNC_ON) { - parms.command = RDC_CMD_STATUS; - ret = RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, - ustatus); - if (ret != SPCS_S_OK) { - rdc_err(NULL, gettext("can not determine " - "status of Remote Mirror set %s:%s"), - tohost, tofile); - } - - /* need to reset the tunables after a status ioctl */ - parms.rdc_set->autosync = autosync; - parms.rdc_set->maxqfbas = maxqfbas; - parms.rdc_set->maxqitems = maxqitems; - parms.rdc_set->asyncthr = asyncthr; - - /* - * if in logging mode, just update config, kernel will - * be updated with the next copy/update request. - */ - if (parms.rdc_set->flags & RDC_LOGGING) { - parms.rdc_set->autosync = AUTOSYNC; - } else { - parms.rdc_set->autosync = AUTOSYNC_ON; - } - - parms.command = flag; - } - } - - if (autosync_toggle_needed) { - parms.command = RDC_CMD_TUNABLE; - ret = RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus); - if (ret != SPCS_S_OK) { - spcs_log("sndr", NULL, gettext("failed to update " - "autosync for Remote Mirror set %s:%s"), tohost, - tofile); - rdc_err(NULL, gettext("failed to update autosync for " - "Remote Mirror set %s:%s"), tohost, tofile); - } - /* reset command and default autosync flags */ - parms.rdc_set->autosync = AUTOSYNC; - parms.command = flag; - } - - errno = 0; - ret = RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus); - if ((ret != SPCS_S_OK) && (flag != RDC_CMD_HEALTH)) { - (void) fprintf(stderr, - gettext("Remote Mirror: %s %s %s %s %s %s\n"), - fromhost, fromfile, - frombitmap, tohost, tofile, tobitmap); - - if (errno == RDC_EEINVAL) { - spcs_log("sndr", NULL, - "%s %s %s %s %s %s %s %s\n%s", - program, rdc_decode_flag(flag, parms.options), - fromhost, fromfile, frombitmap, - tohost, tofile, tobitmap, - gettext("invalid command option")); - rdc_err(&ustatus, - gettext("Remote Mirror: invalid command option " - "'%s'"), rdc_decode_flag(flag, - parms.options)); - } else { - spcs_log("sndr", &ustatus, - "%s %s %s %s %s %s %s %s", - program, rdc_decode_flag(flag, parms.options), - fromhost, fromfile, frombitmap, - tohost, tofile, tobitmap); - if ((flag == RDC_CMD_RECONFIG) && - (!(iflag & RDC_OPT_REVERSE_ROLE))) { - success = 0; - rdc_warn(&ustatus, 0); - } else - rdc_err(&ustatus, 0); - } - } - if ((flag == RDC_CMD_RECONFIG) && (iflag & RDC_OPT_REVERSE_ROLE) == 0) { - parms.command = RDC_CMD_STATUS; - if (RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus) == - SPCS_S_OK) { - char shostbuf[CFG_MAX_BUF]; - char svolbuf[CFG_MAX_BUF]; - char key[CFG_MAX_KEY]; - int i, numels; - int cfgsuccess = 1; - - /* - * okeydoke, at this point we could have a reconfig - * gone bad. libdscfg does not know about this. - * parms contains the kernel picture, and we know - * what we tried to reconfig. find out where it went - * wrong, find the set in libdscfg, update it. We'll - * issue a warning, then return 0 (eventually). - * this will allow libdscfg to be committed with the - * good info. got it? - * BTW: the only time we can run into this multiple - * reconfig attempt failure is IF we reconfig from file - * and some thing goes wrong with one of the reconfigs - */ - - /* find the set in libdscfg */ - - numels = cfg_get_num_entries(cfg, "sndr"); - /* yes, numels could be -1 */ - for (i = 1; i < numels; i++) { - bzero(shostbuf, sizeof (shostbuf)); - bzero(svolbuf, sizeof (svolbuf)); - bzero(key, sizeof (key)); - - (void) snprintf(key, sizeof (key), - "sndr.set%d.shost", i); - - (void) cfg_get_cstring(cfg, key, &shostbuf, - sizeof (shostbuf)); - if (strncmp(shostbuf, tohost, sizeof (tohost))) - continue; - - bzero(key, sizeof (key)); - (void) snprintf(key, sizeof (key), - "sndr.set%d.secondary", i); - (void) cfg_get_cstring(cfg, key, &svolbuf, - sizeof (svolbuf)); - if (strncmp(svolbuf, tofile, NSC_MAXPATH)) - continue; - break; - - /* - * found it, now i contains the set offset. - * i, being the variable, not bad english. - */ - - } - /* shouldn't happen */ - if ((numels < 1) || (i > numels)) { - rdc_warn(NULL, gettext("unable to retrieve " - "set from configuration database")); - /* - * yuck. but indents are pushing the envelope - * we should not be updating config - * if we did not find the entry - * the error will have to do - */ - cfgsuccess = 0; - goto notfound; - } - - /* - * now, put all the correct names back for errors etc. - * also, sock them into dscfg, if the the config was a - * success for one, it will be a redundant but harmless - */ - - /* - * we could not have reconfigged mode if we - * are not logging, AND the kernel CAN return - * sync as the status of an async set if it is - * currently syncing.. Hence the flags & RDC_LOGGING - */ - if (parms.rdc_set->flags & RDC_LOGGING) { - bzero(key, sizeof (key)); - (void) snprintf(key, sizeof (key), - "sndr.set%d.mode", i); - if (parms.rdc_set->flags & RDC_ASYNC) { - *doasync = 1; - if (cfg_put_cstring(cfg, key, "async", - strlen("async")) < 0) { - cfgsuccess = 0; - } - - } else { - *doasync = 0; - if (cfg_put_cstring(cfg, key, "sync", - strlen("sync")) < 0) { - cfgsuccess = 0; - } - } - } -#ifdef _RDC_CAMPUS - if (*parms.rdc_set->direct_file) { - (void) strncpy(directfile, - parms.rdc_set->direct_file, NSC_MAXPATH); - bzero(key, sizeof (key)); - (void) snprintf(key, sizeof (key), - "sndr.set%d.type", i); - if (cfg_put_cstring(cfg, key, directfile, - strlen(directfile)) < 0) - cfgsuccess = 0; - } else { - (void) strncpy(directfile, "-", NSC_MAXPATH); - bzero(key, sizeof (key)); - (void) snprintf(key, sizeof (key), - "sndr.set%d.type", i); - if (cfg_put_cstring(cfg, key, directfile, - strlen(directfile)) < 0) - cfgsuccess = 0; - } -#endif - - if (*parms.rdc_set->group_name) { - (void) strncpy(group, parms.rdc_set->group_name, - NSC_MAXPATH); - bzero(key, sizeof (key)); - (void) snprintf(key, sizeof (key), - "sndr.set%d.group", i); - if (cfg_put_cstring(cfg, key, group, - strlen(group)) < 0) - cfgsuccess = 0; - - } else { - (void) strncpy(group, "-", NSC_MAXPATH); - bzero(key, sizeof (key)); - (void) snprintf(key, sizeof (key), - "sndr.set%d.group", i); - if (cfg_put_cstring(cfg, key, group, - strlen(group)) < 0) - cfgsuccess = 0; - } - - if (*parms.rdc_set->disk_queue) { - (void) strncpy(diskqueue, - parms.rdc_set->disk_queue, NSC_MAXPATH); - } else { - (void) strncpy(diskqueue, "-", NSC_MAXPATH); - } - bzero(key, sizeof (key)); - (void) snprintf(key, sizeof (key), - "sndr.set%d.diskq", i); - if (cfg_put_cstring(cfg, key, diskqueue, - strlen(diskqueue)) < 0) - cfgsuccess = 0; - - (void) strncpy(frombitmap, - parms.rdc_set->primary.bitmap, NSC_MAXPATH); - bzero(key, sizeof (key)); - (void) snprintf(key, sizeof (key), - "sndr.set%d.pbitmap", i); - if (cfg_put_cstring(cfg, key, frombitmap, - strlen(frombitmap)) < 0) - cfgsuccess = 0; - - (void) strncpy(tobitmap, - parms.rdc_set->secondary.bitmap, NSC_MAXPATH); - bzero(key, sizeof (key)); - (void) snprintf(key, sizeof (key), - "sndr.set%d.sbitmap", i); - if (cfg_put_cstring(cfg, key, tobitmap, - strlen(tobitmap)) < 0) - cfgsuccess = 0; - - bzero(key, sizeof (key)); - (void) snprintf(key, sizeof (key), - "sndr.set%d.cnode", i); - if (clustered) - if (cfg_put_cstring(cfg, key, ctag, - strlen(ctag)) < 0) - cfgsuccess = 0; -notfound: - if (cfgsuccess == 0) { - rdc_warn(NULL, gettext("unable to update " - "configuration storage")); - } - } else { - spcs_log("sndr", NULL, - "%s %s %s %s %s %s %s %s\n%s", - program, rdc_decode_flag(flag, parms.options), - fromhost, fromfile, frombitmap, - tohost, tofile, tobitmap, - gettext("unable to update config file")); - rdc_err(&ustatus, - gettext("Remote Mirror: unable to update " - "config file")); - - } - } - - if (flag == RDC_CMD_HEALTH && errno == 0) { - (void) fprintf(stderr, - gettext("Remote Mirror: %s %s %s %s %s %s\n"), - fromhost, fromfile, - frombitmap, tohost, tofile, tobitmap); - - if (ret == RDC_ACTIVE) - (void) fprintf(stderr, "Active\n"); - else if (ret == RDC_INACTIVE) - (void) fprintf(stderr, "Inactive\n"); - else - (void) fprintf(stderr, "Unknown\n"); - } else if (ret != SPCS_S_OK) { - if (errno == RDC_EEINVAL) { - spcs_log("sndr", NULL, - "%s %s %s %s %s %s %s %s\n%s", - program, rdc_decode_flag(flag, parms.options), - fromhost, fromfile, frombitmap, - tohost, tofile, tobitmap, - gettext("invalid command option")); - rdc_err(&ustatus, - gettext("Remote Mirror: invalid command option " - "'%s'"), - rdc_decode_flag(flag, parms.options)); - } - } - if (flag == RDC_CMD_STATUS) { - (void) fprintf(stderr, - gettext("Remote Mirror: %s %s %s %s %s %s\n"), - fromhost, fromfile, - frombitmap, tohost, tofile, tobitmap); - (void) fprintf(stderr, "flags 0x%x\n", parms.rdc_set->flags | - parms.rdc_set->sync_flags | parms.rdc_set->bmap_flags); - } else if (success) { - spcs_log("sndr", NULL, - gettext("%s %s %s %s %s %s %s %s\nSuccessful"), - program, rdc_decode_flag(flag, parms.options), - fromhost, fromfile, frombitmap, - tohost, tofile, tobitmap); - if (flag == RDC_CMD_TUNABLE) - spcslog_tunable(tohost, tofile); - } - - if (cfg && perform_autosv()) { - spcs_s_ufree(&ustatus); - /* figure out which are the local volumes */ - if (parms.options & RDC_OPT_PRIMARY) { - vol1 = fromfile; - vol2 = frombitmap; - if ((diskqueue && diskqueue[0]) && - (strncmp(diskqueue, "-", 1) != 0)) - vol3 = diskqueue; - else - vol3 = NULL; - } else { - vol1 = tofile; - vol2 = tobitmap; - vol3 = NULL; - if ((flag == RDC_CMD_ENABLE) && - (strlen(diskqueue) > 0) && - (strncmp(diskqueue, "-", 1)) != 0) { - rdc_warn(NULL, - gettext("enabling a disk queue on a " - "Remote Mirror secondary is not allowed. " - "(%s) ignored"), diskqueue); - } - } - - if (flag == RDC_CMD_ENABLE) { - ustatus = spcs_s_ucreate(); - /* - * SV-enable all local volumes - * if the sv_enables fail, disable the sndr vols - * that we just enabled - * and return -1 so the cfg_commit() won't happen - */ - - if (nsc_lookup(volhash, vol1) == NULL) { - if (cfg_vol_enable(cfg, vol1, ctag, "sndr") - < 0) { - spcs_log("sndr", NULL, - "sv enable failed for %s, " - "disabling Remote Mirror set %s:%s", - vol1, tohost, tofile); - /* - * warn here, but we are going to exit - * we want to catch any errors on the - * way down, then exit - */ - - rdc_warn(NULL, - "unable to sv enable %s\n" - "disabling Remote Mirror set %s:%s", - vol1, tohost, tofile); - - parms.command = RDC_CMD_DISABLE; - ret = RDC_IOCTL(RDC_CONFIG, &parms, - NULL, 0, 0, 0, ustatus); - if (ret != SPCS_S_OK) { - (void) fprintf(stderr, - gettext("Remote Mirror:" - " %s %s %s %s %s %s\n"), - fromhost, fromfile, - frombitmap, tohost, tofile, - tobitmap); - spcs_log("sndr", &ustatus, - "%s %s %s %s %s %s %s %s", - program, - rdc_decode_flag(parms.command, - parms.options), - fromhost, - fromfile, frombitmap, - tohost, tofile, tobitmap); - rdc_err(&ustatus, 0); - } - /* - * ok, we should've reported any errs - * exit explictly - */ - exit(1); - - } - } - if (vol2 && nsc_lookup(volhash, vol2) == NULL) { - if (cfg_vol_enable(cfg, vol2, ctag, "sndr") - < 0) { - spcs_log("sndr", NULL, - "sv enable failed for %s, " - "disabling Remote Mirror set %s:%s", - vol1, tohost, tofile); - /* - * warn here, but we are going to exit - * we want to catch any errors on the - * way down, then exit - */ - - rdc_warn(NULL, - "unable to sv enable %s\n" - "disabling Remote Mirror set %s:%s", - vol2, tohost, tofile); - - parms.command = RDC_CMD_DISABLE; - ret = RDC_IOCTL(RDC_CONFIG, &parms, - NULL, 0, 0, 0, ustatus); - if (ret != SPCS_S_OK) { - (void) fprintf(stderr, - gettext("Remote Mirror:" - " %s %s %s %s %s %s\n"), - fromhost, fromfile, - frombitmap, tohost, tofile, - tobitmap); - spcs_log("sndr", &ustatus, - "%s %s %s %s %s %s %s %s", - program, - rdc_decode_flag(parms.command, - parms.options), - fromhost, - fromfile, frombitmap, - tohost, tofile, tobitmap); - rdc_err(&ustatus, 0); - } - /* - * ok, we should've reported any errs - * exit explictly - */ - exit(1); - - } - } - - if (vol3 && nsc_lookup(volhash, diskqueue) == NULL) { - if (cfg_vol_enable(cfg, diskqueue, ctag, "sndr") - < 0) { - spcs_log("sndr", NULL, - "sv enable failed for %s, " - "disabling Remote Mirror set %s:%s", - diskqueue, tohost, tofile); - if (cfg_vol_disable(cfg, vol1, ctag, - "sndr") < 0) - rdc_warn(NULL, gettext("Failed to " - "remove volume [%s] from " - "configuration"), vol1); - if (cfg_vol_disable(cfg, vol2, ctag, - "sndr") < 0) - rdc_warn(NULL, gettext("Failed to " - "remove volume [%s] from " - "configuration"), vol2); - - /* - * warn here, but we are going to exit - * we want to catch any errors on the - * way down, then exit - */ - - rdc_warn(NULL, - "unable to sv enable %s\n" - "disabling Remote Mirror set %s:%s", - diskqueue, tohost, tofile); - - parms.command = RDC_CMD_DISABLE; - ret = RDC_IOCTL(RDC_CONFIG, &parms, - NULL, 0, 0, 0, ustatus); - if (ret != SPCS_S_OK) { - (void) fprintf(stderr, - gettext("Remote Mirror:" - " %s %s %s %s %s %s\n"), - fromhost, fromfile, - frombitmap, tohost, tofile, - tobitmap); - spcs_log("sndr", &ustatus, - "%s %s %s %s %s %s %s %s", - program, - rdc_decode_flag(parms.command, - parms.options), - fromhost, - fromfile, frombitmap, - tohost, tofile, tobitmap); - rdc_err(&ustatus, 0); - } - /* - * ok, we should've reported any errs - * exit explictly - */ - exit(1); - - } - } - } else if (flag == RDC_CMD_DISABLE) { - /* - * If we're no longer using a volume, SV-disable it - */ - volcount_t *vc; - - vc = nsc_lookup(volhash, vol1); - if (vc && (1 == vc->count)) { - if (cfg_vol_disable(cfg, vol1, ctag, "sndr") - < 0) - rdc_warn(NULL, gettext("Failed to " - "remove volume [%s] from " - "configuration"), vol1); - - } else if (!vc) { - rdc_warn(NULL, - gettext("Unable to find %s in config"), - vol1); - } - - if (vol2) { - vc = nsc_lookup(volhash, vol2); - if (vc && (1 == vc->count)) { - if (cfg_vol_disable(cfg, vol2, ctag, - "sndr") < 0) - rdc_warn(NULL, gettext("Failed to " - "remove volume [%s] from " - "configuration"), vol2); - } else if (!vc) { - rdc_warn(NULL, gettext("Unable to find" - " %s in config"), vol2); - } - } - - if (diskqueue != NULL && strlen(diskqueue) > 0) { - vc = nsc_lookup(volhash, diskqueue); - if (vc && (1 == vc->count)) { - if (cfg_vol_disable(cfg, diskqueue, ctag, - "sndr") < 0) - rdc_warn(NULL, gettext("Failed to " - "remove disk queue [%s] from " - "configuration"), diskqueue); - } else if (!vc) { - rdc_warn(NULL, gettext("Unable to find" - " %s in config"), diskqueue); - } - } - /* WARNING about to go to 4 space indenting */ - } else if (flag == RDC_CMD_RECONFIG) { - volcount_t *vc; - /* disable ex-bitmaps, enable new bitmaps */ - if (parms.options & RDC_OPT_PRIMARY) { - if (strcmp(orig_fbmp, frombitmap) != 0) { - vc = nsc_lookup(volhash, orig_fbmp); - if (vc && (vc->count == 1)) { - if (cfg_vol_disable(cfg, orig_fbmp, ctag, - "sndr") < 0) - rdc_warn(NULL, gettext("Failed to " - "remove bitmap [%s] from " - "configuration"), orig_fbmp); - } else if (!vc) { - rdc_warn(NULL, gettext("Unable to find " - "%s in config"), orig_fbmp); - } - if (nsc_lookup(volhash, frombitmap) == NULL) { - if (cfg_vol_enable(cfg, frombitmap, ctag, - "sndr") < 0) { - spcs_log("sndr", NULL, - "reconfig sv enable failed for %s, " - "disabling Remote Mirror set %s:%s", - frombitmap, tohost, tofile); - rdc_warn(NULL, - "unable to sv enable %s\n" - "disabling Remote Mirror set %s:%s", - frombitmap, tohost, tofile); - parms.command = RDC_CMD_DISABLE; - ret = RDC_IOCTL(RDC_CONFIG, &parms, - NULL, 0, 0, 0, ustatus); - if (ret != SPCS_S_OK) { - (void) fprintf(stderr, - gettext("Remote Mirror:" - " %s %s %s %s %s %s\n"), - fromhost, fromfile, - frombitmap, tohost, tofile, - tobitmap); - spcs_log("sndr", &ustatus, - "%s %s %s %s %s %s %s %s", - program, - rdc_decode_flag(parms.command, - parms.options), - fromhost, - fromfile, frombitmap, - tohost, tofile, tobitmap); - rdc_warn(&ustatus, 0); - } - exit(1); - } - } - } else if ((orig_diskq[0] != '\0') && - (strcmp(orig_diskq, diskqueue) != 0)) { - vc = nsc_lookup(volhash, orig_diskq); - if (vc && (vc->count == 1)) { - if (cfg_vol_disable(cfg, orig_diskq, ctag, - "sndr") < 0) - rdc_warn(NULL, gettext("Failed to " - "remove disk queue [%s] from " - "configuration"), orig_diskq); - } else if (!vc) { - rdc_warn(NULL, gettext("Unable to find " - "%s in config"), orig_diskq); - } - if (vol3 && - (nsc_lookup(volhash, diskqueue) == NULL)) { - if (cfg_vol_enable(cfg, diskqueue, ctag, - "sndr") < 0) { - spcs_log("sndr", NULL, "reconfig sv " - "enable of diskqueue %s failed, " - "disabling Remote Mirror set %s:%s", - diskqueue, tohost, tofile); - rdc_warn(NULL, "reconfig sv " - "enable of diskqueue %s failed." - "disabling Remote Mirror set %s:%s", - diskqueue, tohost, tofile); - parms.command = RDC_CMD_DISABLE; - ret = RDC_IOCTL(RDC_CONFIG, &parms, - NULL, 0, 0, 0, ustatus); - if (ret != SPCS_S_OK) { - (void) fprintf(stderr, - gettext("Remote Mirror:" - " %s %s %s %s %s %s\n"), - fromhost, fromfile, - frombitmap, tohost, tofile, - tobitmap); - spcs_log("sndr", &ustatus, - "%s %s %s %s %s %s %s %s", - program, - rdc_decode_flag(parms.command, - parms.options), - fromhost, - fromfile, frombitmap, - tohost, tofile, tobitmap); - rdc_warn(&ustatus, 0); - } - exit(1); - } - } - } - } else if (flag != RDC_OPT_PRIMARY) { - if (strcmp(orig_tbmp, tobitmap) != 0) { - vc = nsc_lookup(volhash, orig_tbmp); - if (vc && (vc->count == 1)) { - if (cfg_vol_disable(cfg, orig_tbmp, ctag, - "sndr") < 0) - rdc_warn(NULL, gettext("Failed to " - "remove bitmap [%s] from " - "configuration"), orig_tbmp); - } else if (!vc) { - rdc_warn(NULL, - gettext("Unable to find %s in config"), - orig_tbmp); - } - if (nsc_lookup(volhash, tobitmap) == NULL) { - if (cfg_vol_enable(cfg, tobitmap, ctag, - "sndr") < 0) { - spcs_log("sndr", NULL, - "reconfig sv enable failed for %s, " - "disabling Remote Mirror set %s:%s", - tobitmap, tohost, tofile); - rdc_warn(NULL, - "unable to sv enable %s\n" - "disabling Remote Mirror set %s:%s", - tobitmap, tohost, tofile); - parms.command = RDC_CMD_DISABLE; - ret = RDC_IOCTL(RDC_CONFIG, &parms, - NULL, 0, 0, 0, ustatus); - if (ret != SPCS_S_OK) { - (void) fprintf(stderr, - gettext("Remote Mirror:" - " %s %s %s %s %s %s\n"), - fromhost, fromfile, - frombitmap, tohost, tofile, - tobitmap); - spcs_log("sndr", &ustatus, - "%s %s %s %s %s %s %s %s", - program, - rdc_decode_flag(parms.command, - parms.options), - fromhost, fromfile, frombitmap, - tohost, tofile, tobitmap); - rdc_warn(&ustatus, 0); - } - exit(1); - } - } - } - } - /* END 4 space indenting */ - } - } - spcs_s_ufree(&ustatus); - - return (0); -} - - -/* - * read_config() - * - * DESCRIPTION: Read the lines in a configuration file and return the - * pairs of devices to be mirrored/enabled/disabled/updated. - * The format for the configuration file is as follows: - * - * fromhost fromfile frombitmap tohost tofile tobitmap - * - * where fromfile is the primary device which is local to the - * fromhost subsystem, tofile is the secondary device which is - * local to the tohost subsystem, and type is 1 if the device - * a simckd device or 0 otherwise. Any line preceeded by a '#' - * is considered to be a comment. - * - * Inputs: - * char *config_file Name of configuration file for rdcadm - * - * Outputs: - * int i Number of pairs of devices - * - * Side Effects: The 0 to i-1 entries in the pair_list are filled. - * - */ - -int -read_config(int flag, char *config_file, char *group_arg, char *ctag_arg) -{ - int ret; - char dsk_flagstr[NSC_MAXPATH]; - char line[1024], tmp_line[1024]; - char fromhost[MAX_RDC_HOST_SIZE]; - char fromfile[NSC_MAXPATH]; - char frombitmap[NSC_MAXPATH]; - char tohost[MAX_RDC_HOST_SIZE]; - char tofile[NSC_MAXPATH]; - char tobitmap[NSC_MAXPATH]; - char directfile[NSC_MAXPATH]; - char sync[16]; - int doasync; - FILE *fp; - int i, j; - char *extra_args[EXTRA_ARGS]; - char *tmp, *split_str = " \t\n"; - - for (j = 0; j < EXTRA_ARGS; j++) - extra_args[j] = malloc(NSC_MAXPATH); - - if (!(fp = fopen(config_file, "r"))) { - rdc_err(NULL, gettext("error opening %s"), config_file); - } - - i = 0; - while (fgets(line, sizeof (line), fp)) { - if (line[0] == '#') /* this is a comment */ - continue; - - ret = 0; - (void) strcpy(tmp_line, line); - - if ((tmp = strtok(tmp_line, split_str)) != NULL) { - if (strlen(tmp) >= MAX_RDC_HOST_SIZE) { - (void) printf(gettext("hostname is longer than %d " - "characters\n"), (MAX_RDC_HOST_SIZE - 1)); - continue; - } - (void) strncpy(fromhost, tmp, (MAX_RDC_HOST_SIZE - 1)); - fromhost[(MAX_RDC_HOST_SIZE - 1)] = '\0'; - ret++; - } - if ((tmp = strtok(NULL, split_str)) != NULL) { - if (strlen(tmp) >= NSC_MAXPATH) { - (void) printf(gettext( - "device name is longer than %d " - "characters\n"), (NSC_MAXPATH - 1)); - continue; - } - (void) strncpy(fromfile, tmp, (NSC_MAXPATH - 1)); - fromfile[(NSC_MAXPATH - 1)] = '\0'; - ret++; - } - if ((tmp = strtok(NULL, split_str)) != NULL) { - if (strlen(tmp) >= NSC_MAXPATH) { - (void) printf(gettext( - "device name is longer than %d " - "characters\n"), (NSC_MAXPATH - 1)); - continue; - } - (void) strncpy(frombitmap, tmp, (NSC_MAXPATH - 1)); - frombitmap[(NSC_MAXPATH - 1)] = '\0'; - ret++; - } - if ((tmp = strtok(NULL, split_str)) != NULL) { - if (strlen(tmp) >= MAX_RDC_HOST_SIZE) { - (void) printf(gettext( - "hostname is longer than %d " - "characters\n"), (MAX_RDC_HOST_SIZE - 1)); - continue; - } - (void) strncpy(tohost, tmp, (MAX_RDC_HOST_SIZE - 1)); - tohost[(MAX_RDC_HOST_SIZE - 1)] = '\0'; - ret++; - } - if ((tmp = strtok(NULL, split_str)) != NULL) { - if (strlen(tmp) >= NSC_MAXPATH) { - (void) printf(gettext( - "device name is longer than %d " - "characters\n"), (NSC_MAXPATH - 1)); - continue; - } - (void) strncpy(tofile, tmp, (NSC_MAXPATH - 1)); - tofile[(NSC_MAXPATH - 1)] = '\0'; - ret++; - } - if ((tmp = strtok(NULL, split_str)) != NULL) { - if (strlen(tmp) >= NSC_MAXPATH) { - (void) printf(gettext( - "device name is longer than %d " - "characters\n"), (NSC_MAXPATH - 1)); - continue; - } - (void) strncpy(tobitmap, tmp, (NSC_MAXPATH - 1)); - tobitmap[(NSC_MAXPATH - 1)] = '\0'; - ret++; - } - if ((tmp = strtok(NULL, split_str)) != NULL) { - (void) strncpy(dsk_flagstr, tmp, 15); - dsk_flagstr[15] = '\0'; - ret++; - } - if ((tmp = strtok(NULL, split_str)) != NULL) { - (void) strncpy(sync, tmp, 15); - sync[15] = '\0'; - ret++; - } - for (j = 0; j < EXTRA_ARGS; j++) { - if ((tmp = strtok(NULL, split_str)) != NULL) { - (void) strncpy(extra_args[j], tmp, - (NSC_MAXPATH - 1)); - extra_args[j][(NSC_MAXPATH - 1)] = '\0'; - ret++; - } - } - - if (ret == 0) /* this is a blank line */ - continue; - - if (ret < 8) { - (void) fclose(fp); - rdc_warn(NULL, - gettext("invalid format in %s"), config_file); - rdc_err(NULL, "%s", line); - } - - if (i >= rdc_maxsets) { - (void) fclose(fp); - rdc_err(NULL, - gettext("number of Remote Mirror sets exceeds %d"), - rdc_maxsets); - } - -#ifdef _RDC_CAMPUS - if (dsk_flagstr[0] == '/') { - /* fcal directio */ - (void) strncpy(directfile, dsk_flagstr, NSC_MAXPATH); - } else if (strcmp(dsk_flagstr, "ip") != 0) { -#else - if (strcmp(dsk_flagstr, "ip") != 0) { -#endif - (void) fclose(fp); - rdc_err(NULL, -#ifdef _RDC_CAMPUS - gettext("ip/fcal specification missing")); -#else - gettext("ip specification missing")); -#endif - } else - (void) strcpy(directfile, "ip"); - - if (strcmp(sync, "sync") == 0) - doasync = 0; - else if (strcmp(sync, "async") == 0) - doasync = 1; - else { - (void) fclose(fp); - rdc_err(NULL, - gettext("sync/async specification missing")); - } - (void) strncpy(pair_list[i].fhost, fromhost, MAX_RDC_HOST_SIZE); - (void) strncpy(pair_list[i].ffile, fromfile, NSC_MAXPATH); - (void) strncpy(pair_list[i].fbitmap, frombitmap, NSC_MAXPATH); - (void) strncpy(pair_list[i].thost, tohost, MAX_RDC_HOST_SIZE); - (void) strncpy(pair_list[i].tfile, tofile, NSC_MAXPATH); - (void) strncpy(pair_list[i].tbitmap, tobitmap, NSC_MAXPATH); - (void) strncpy(pair_list[i].directfile, directfile, - NSC_MAXPATH); - pair_list[i].doasync = doasync; - - if (gethost_netaddrs(fromhost, tohost, - (char *)pair_list[i].fnetaddr, - (char *)pair_list[i].tnetaddr) < 0) { - (void) fclose(fp); - rdc_err(NULL, gettext("unable to determine IP " - "addresses for hosts %s, %s"), fromhost, tohost); - } - - if (parse_extras(ret - 8, extra_args, i) < 0) { - (void) fclose(fp); - rdc_err(NULL, gettext("illegal option in:\n%s"), - line); - } - - if (flag == RDC_CMD_ENABLE || flag == RDC_CMD_RECONFIG) { - if (ctag_check(fromhost, fromfile, frombitmap, - tohost, tofile, tobitmap, pair_list[i].ctag, - pair_list[i].diskqueue) < 0) - continue; /* Ignore illegal sets */ - if (pair_diskqueue_check(i)) - continue; /* ignore sets with incorrect diskq */ - } - - /* Filter according to ctag and group arguments */ - if (strcmp(ctag_arg, "") && - strncmp(ctag_arg, pair_list[i].ctag, - MAX_RDC_HOST_SIZE)) - continue; - if (strcmp(group_arg, "") && - strncmp(group_arg, pair_list[i].group, NSC_MAXPATH)) - continue; - - i++; - } - (void) fclose(fp); - for (j = 0; j < EXTRA_ARGS; j++) - free(extra_args[j]); - return (i); -} - - -/* - * read_libcfg() - * - * DESCRIPTION: Read the relevant config info via libcfg - * - * Outputs: - * int i Number of pairs of devices - * - * Side Effects: The 0 to i-1 entries in the pair_list are filled. - * - */ -static int -read_libcfg(int flag, char *group_arg, char *ctag_arg) -{ - int rc; - CFGFILE *cfg; - int i; - _sd_dual_pair_t *pairp; - char buf[CFG_MAX_BUF]; - char key[CFG_MAX_KEY]; - int setnumber; - - if ((cfg = cfg_open(NULL)) == NULL) - rdc_err(NULL, gettext("unable to access configuration")); - - if (!cfg_lock(cfg, CFG_RDLOCK)) - rdc_err(NULL, gettext("unable to lock configuration")); - - if (strcmp(ctag_arg, "")) - cfg_resource(cfg, ctag_arg); - else { - cfg_resource(cfg, NULL); - } - - setnumber = 0; - /*CSTYLED*/ - for (i = 0; i < rdc_maxsets;) { - setnumber++; - - bzero(buf, CFG_MAX_BUF); - (void) snprintf(key, sizeof (key), "sndr.set%d", setnumber); - rc = cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF); - if (rc < 0) - break; - - pairp = &pair_list[i]; - if (parse_cfg_buf(buf, pairp, NULL)) - continue; - - if (strcmp(group_arg, "") && - strncmp(group_arg, pairp->group, NSC_MAXPATH)) - continue; - - if (flag == RDC_CMD_RECONFIG) { - if (reconfig_pbitmap) - (void) strncpy(pairp->fbitmap, reconfig_pbitmap, - NSC_MAXPATH); - if (reconfig_sbitmap) - (void) strncpy(pairp->tbitmap, reconfig_sbitmap, - NSC_MAXPATH); -#ifdef _RDC_CAMPUS - if (reconfig_direct) - (void) strncpy(directfile, reconfig_direct, - NSC_MAXPATH); -#endif - if (reconfig_group) - (void) strncpy(pairp->group, reconfig_group, - NSC_MAXPATH); - - if (strlen(reconfig_ctag) > 0) - (void) strncpy(pairp->ctag, reconfig_ctag, - MAX_RDC_HOST_SIZE); - - if (reconfig_doasync != -1) - pairp->doasync = reconfig_doasync; - } - - - if (ctag_check(pairp->fhost, pairp->ffile, - pairp->fbitmap, pairp->thost, pairp->tfile, - pairp->tbitmap, pairp->ctag, pairp->diskqueue) < 0) - continue; /* Ignore illegal sets */ - - if (gethost_netaddrs(pairp->fhost, pairp->thost, - (char *)pairp->fnetaddr, - (char *)pairp->tnetaddr) < 0) { - rdc_err(NULL, gettext("unable to determine IP " - "addresses for hosts %s, %s"), pairp->fhost, - pairp->thost); - } - - i++; - } - - cfg_close(cfg); - return (i); -} - -void -q_usage(int prhdr) -{ - if (prhdr) - (void) fprintf(stderr, gettext("disk queue usage:\n")); - - (void) fprintf(stderr, - gettext("\t%s -g <group> -q a <vol>\t\tadd disk queue to " - "group\n"), program); - (void) fprintf(stderr, - gettext("\t%s -g <group> -q d \t\tremove disk queue from" - " group\n"), program); - (void) fprintf(stderr, - gettext("\t%s -g <group> -q r <newvol>\treplace disk queue for a" - " group\n"), program); - - (void) fprintf(stderr, - gettext("\t%s -q a <vol> <shost>:<sdev>\tadd disk queue to " - "a set\n"), program); - (void) fprintf(stderr, - gettext("\t%s -q d <shost>:<sdev>\t\tremove disk queue from " - "a set\n"), program); - (void) fprintf(stderr, - gettext("\t%s -q r <newvol> <shost>:<sdev>\treplace disk queue for " - "a set\n"), program); - -} - -static void -usage() -{ - (void) fprintf(stderr, gettext("usage:\n")); - - (void) fprintf(stderr, - gettext("\t%s [opts] -a {on | off} [set]\t" - "set autosync\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -A <asyncthr> [set]\t" - "set the number of asynchronous\n\t\t\t\t\t\tthreads\n"), - program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -d [set]\t\t\t" - "disable\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -e [set]\t\t\t" - "enable with bits in bitmap set\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -E [set]\t\t\t" - "enable with bits in bitmap clear\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -F <maxqfbas> [set]\t" - "set maximum fbas to queue\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -D {block | noblock} [set]\t" - "set disk queue blocking mode\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -H [set]\t\t\t" - "report link health\n"), program); - - (void) fprintf(stderr, - gettext("\t%s -h\t\t\t\tusage message\n"), program); - - (void) fprintf(stderr, - gettext("\t%s -I a <master> <shadow> <bitmap>\t" - "add ndr_ii config entry\n"), program); - - (void) fprintf(stderr, - gettext("\t%s -I d <master> <shadow> <bitmap>\t" - "delete ndr_ii config entry\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -i [set]\t\t\t" - "print sets in config file format\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -l [set]\t\t\t" - "enter logging mode\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -m [set]\t\t\t" - "full sync\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -m -r [set]\t\t" - "full reverse sync\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -P [set]\t\t\t" - "print sets verbose\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -p [set]\t\t\t" - "print sets\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -R\t\t\t" - "reset error conditions\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -R b p <bitmap> [set]\t" - "reconfig primary bitmap\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -R b s <bitmap> [set]\t" - "reconfig secondary bitmap\n"), program); - - if (clustered) - (void) fprintf(stderr, - gettext("\t%s [opts] -R C <ctag> [set]\t" - "reconfig cluster tag\n"), program); - -#ifdef _RDC_CAMPUS - (void) fprintf(stderr, - gettext("\t%s [opts] -R d <pathname> [set]\t" - "reconfig campus direct file\n"), program); -#endif - - (void) fprintf(stderr, - gettext("\t%s [opts] -R -f <volset-file> \t" - "reconfig from file\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -R g <group> [set]\t" - "reconfig group\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -R m {sync|async} [set]\t" - "reconfig mode\n"), program); - - if (allow_role) - (void) fprintf(stderr, - gettext("\t%s [opts] -R r [set]\t\t" - "reverse roles\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -u [set]\t\t\t" - "update sync\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -u -r [set]\t\t" - "update reverse sync\n"), program); - - (void) fprintf(stderr, - gettext("\t%s -v\t\t\t\tdisplay version\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -W <maxwrites> [set]\t" - "set maximum writes to queue\n"), program); - - (void) fprintf(stderr, - gettext("\t%s [opts] -w [set]\t\t\t" - "wait\n"), program); - q_usage(0); - - (void) fprintf(stderr, gettext("\nopts:\n")); - (void) fprintf(stderr, gettext("\t-n\t\tnon-interactive mode " - "(not valid for print operations)\n")); - (void) fprintf(stderr, gettext( - "\t-g <group>\toperate on sets in group only " - "(not valid for enable\n\t\t\toperations)\n")); - if (clustered) - (void) fprintf(stderr, - gettext("\t-C <ctag>\tignore sets not in cluster ctag " - "(not valid for enable\n\t\t\toperations)\n")); - - (void) fprintf(stderr, gettext("\nset:\n")); - if (clustered) - (void) fprintf(stderr, - gettext("\t<phost> <pdev> <pbmp> " -#ifdef _RDC_CAMPUS - "<shost> <sdev> <sbmp> {ip | <directfile>} " -#else - "<shost> <sdev> <sbmp> ip " -#endif - "\\\n\t\t{sync | async} [g <group>] [q <qdev>] " - "[C <ctag>]\n")); - else - (void) fprintf(stderr, - gettext("\t<phost> <pdev> <pbmp> " -#ifdef _RDC_CAMPUS - "<shost> <sdev> <sbmp> {ip | <directfile>} " -#else - "<shost> <sdev> <sbmp> ip " -#endif - "\\\n\t\t{sync | async} [g <group>] [q <qdev>]\n")); - (void) fprintf(stderr, - gettext("\t<shost>:<sdev>\t\t" - "operate on set matching shost and sdev\n")); - (void) fprintf(stderr, - gettext("\t-f volset-file\t\t" - "operate on all sets specified in config file\n" - "\t\t\t\tnote: not valid for single set operations. See\n" - "\t\t\t\t%s(1RDC).\n"), program); - (void) fprintf(stderr, - gettext("\t<no arg>\t\toperate on all configured sets\n")); -} - -int -prompt_user(int flag, int options) -{ - int c; - - switch (flag) { - case RDC_CMD_DISABLE: - (void) printf(gettext("Disable Remote Mirror? (Y/N) [N]: ")); - break; - case RDC_CMD_ENABLE: - (void) printf(gettext("Enable Remote Mirror? (Y/N) [N]: ")); - break; - case RDC_CMD_HEALTH: - (void) printf(gettext("Report Remote Mirror link health? (Y/N)" - "[N]: ")); - break; - case RDC_CMD_COPY: - if (options & RDC_OPT_FULL) { - if (options & RDC_OPT_REVERSE) - (void) printf(gettext("Overwrite primary with" - " secondary? (Y/N) [N]: ")); - else - (void) printf(gettext("Overwrite secondary with" - " primary? (Y/N) [N]: ")); - } else { - if (options & RDC_OPT_REVERSE) - (void) printf(gettext("Refresh primary with" - " secondary? (Y/N) [N]: ")); - else - (void) printf(gettext("Refresh secondary with" - " primary? (Y/N) [N]: ")); - } - break; - case RDC_CMD_RECONFIG: - (void) printf(gettext( - "Perform Remote Mirror reconfiguration? (Y/N) [N]: ")); - break; - case RDC_CMD_RESET: - (void) printf(gettext("Perform Remote Mirror reset? (Y/N) " - "[N]: ")); - break; - case RDC_CMD_TUNABLE: - (void) printf(gettext("Change Remote Mirror tunable? (Y/N) " - "[N]: ")); - break; - case RDC_CMD_LOG: - (void) printf(gettext( - "Put Remote Mirror into logging mode? (Y/N) [N]: ")); - break; - case RDC_CMD_WAIT: - (void) printf(gettext( - "Wait for Remote Mirror sync completion? (Y/N) [N]: ")); - break; - default: - (void) printf(gettext("Perform Remote Mirror operation? (Y/N) " - "[N]: ")); - } - - c = getchar(); - if ((c != 'y') && (c != 'Y')) { - (void) printf("\n"); - return (-1); - } - return (0); -} - -static void -load_rdc_vols(CFGFILE *cfg) -{ - int set; - char key[ CFG_MAX_KEY ]; - char buf[ CFG_MAX_BUF ]; - _sd_dual_pair_t pair; - char *vol, *bmp; - char *host1 = pair.fhost, *host2 = pair.thost; - char *diskqueue = pair.diskqueue; - volcount_t *volcount; - char lghn[ MAX_RDC_HOST_SIZE ]; - - if (volhash) { - return; - } - - cfg_rewind(cfg, CFG_SEC_CONF); - volhash = nsc_create_hash(); - for (set = 1; /*CSTYLED*/; set++) { - (void) snprintf(key, CFG_MAX_KEY, "sndr.set%d", set); - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF)) { - break; - } - - if (parse_cfg_buf(buf, &pair, lghn)) - continue; - vol = pair.ffile; - bmp = pair.fbitmap; - - /* use lghn if possible */ - if (*lghn) { - if (strcmp(host2, lghn) == 0) { - vol = pair.tfile; - bmp = pair.tbitmap; - } - } else if (!self_check(host1)) { - /* next one had better be ours */ - vol = pair.tfile; - bmp = pair.tbitmap; - - if (!self_check(host2)) { - rdc_warn(NULL, - gettext("config error: neither %s nor %s" - " is localhost"), host1, 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; - (void) 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; - (void) nsc_insert_node(volhash, volcount, bmp); - } - - if (strcmp(diskqueue, place_holder) == 0) - continue; - /* diskqueue vol may be used more than once */ - volcount = (volcount_t *)nsc_lookup(volhash, diskqueue); - if (volcount) { - volcount->count++; - } else { - volcount = (volcount_t *)malloc(sizeof (volcount_t)); - volcount->count = 1; - (void) nsc_insert_node(volhash, volcount, diskqueue); - } - } -} - -static void -unload_rdc_vols() -{ - nsc_remove_all(volhash, free); - volhash = 0; -} - -static int -perform_autosv() -{ - if (!clustered) { - return (1); - } else { - return (cfg_issuncluster()); - } -} - -/* - * Check the user supplied fields against those in the dscfg for - * this set. - * Never returns on an error. - */ -static void -checkgfields(CFGFILE *cfg, int setnumber, char *fromhost, char *fromfile, - char *frombitmap, char *tobitmap, char *type, char *mode, char *group, - char *ctag, char *diskq) -{ - if (fromhost[0]) - checkgfield(cfg, setnumber, "phost", - gettext("primary host"), fromhost); - if (fromfile[0]) - checkgfield(cfg, setnumber, "primary", - gettext("primary volume"), fromfile); - if (frombitmap[0]) - checkgfield(cfg, setnumber, "pbitmap", - gettext("primary bitmap"), frombitmap); - if (tobitmap[0]) - checkgfield(cfg, setnumber, "sbitmap", - gettext("secondary bitmap"), tobitmap); - if (type[0]) - checkgfield(cfg, setnumber, "type", - gettext("type of connection"), type); - if (mode[0]) - checkgfield(cfg, setnumber, "mode", - gettext("mode of connection"), mode); - if (group[0]) - checkgfield(cfg, setnumber, "group", - gettext("group"), group); - if (ctag[0]) - checkgfield(cfg, setnumber, "cnode", - gettext("cluster tag"), ctag); - if (diskq[0]) - checkgfield(cfg, setnumber, "diskq", - gettext("disk queue volume"), diskq); -} - -/* - * Check the 'fname' field in the dscfg file for set number 'setnumber' - * If it does not match the user's data, 'data', then print the error - * message using the friendly field name 'ufield'. - * Never returns on an error. - */ -static void -checkgfield(CFGFILE *cfg, int setnumber, char *fname, char *ufield, char *data) -{ - char buf[CFG_MAX_BUF]; - char key[CFG_MAX_KEY]; - - (void) snprintf(key, sizeof (key), "sndr.set%d.%s", setnumber, fname); - if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) { - rdc_err(NULL, gettext("unable to fetch data for key %s"), - key); - } - if (strcmp(buf, data) != 0) { - rdc_err(NULL, - gettext("the value specified for the %s field is not\nthe " - "same as that contained within the configuration storage " - "file for this set.\nYou specified \"%s\" " - "expected \"%s\"."), - ufield, data, buf); - } -} - -/* - * load and send the contents of the bitmap file to the kernel. - */ -static int -rdc_bitmapset(char *tohost, char *tofile, char *bitmap, int op, - nsc_off_t offset) -{ - rdc_bitmap_op_t bmop; - int fd; - void *buffer; - int buffersz; - struct stat s; - int n; - int ret; - /* - * open bitmap file for reading. - */ - if ((fd = open(bitmap, O_RDONLY)) < 0) { - rdc_warn(NULL, gettext("Unable to open bitmap file %s"), - bitmap); - return (1); - } - (void) fstat(fd, &s); - - if (S_ISREG(s.st_mode) == 0) { - rdc_warn(NULL, gettext("Bitmap %s is not a regular file"), - bitmap); - (void) close(fd); - return (1); - } - - if (op == 0) { - op = RDC_BITMAPOR; - } - /* - * use the file size to allocate buffer. This - * size should be a multiple of FBA, but don't check - * it here. - */ - buffersz = s.st_size; - buffer = malloc(buffersz); - if (buffer == NULL) { - rdc_warn(NULL, gettext("Unable to allocate %d bytes " - "for bitmap file %s"), buffersz, bitmap); - (void) close(fd); - return (1); - } - n = read(fd, buffer, buffersz); - (void) close(fd); - if (n != buffersz) { - rdc_warn(NULL, gettext("Unable to read the bitmap file, " - "read returned %d instead of %d"), - n, buffersz); - free(buffer); - return (1); - } - bmop.offset = offset; - bmop.op = op; - (void) strncpy(bmop.sechost, tohost, MAX_RDC_HOST_SIZE); - (void) strncpy(bmop.secfile, tofile, NSC_MAXPATH); - bmop.len = buffersz; - bmop.addr = (unsigned long)buffer; - ret = rdc_ioctl_simple(RDC_BITMAPOP, &bmop); - free(buffer); - if (ret < 0) { - rdc_warn(NULL, gettext("Setting bitmap ioctl failed for set " - "%s:%s"), tohost, tofile); - - switch (errno) { - case EIO: - rdc_warn(NULL, gettext("One of the sets is not " - "enabled")); - break; - case ENXIO: - rdc_warn(NULL, gettext("One of the sets is not " - "logging")); - break; - default: - break; - } - } else { - ret = 0; - } - if (ret) - ret = 1; - return (ret); -} - -/* - * verify_groupname: Check the group name for the following rules: - * 1. The name does not start with a '-' - * 2. The name does not contain any space characters as defined by - * isspace(3C). - * - * If either of these rules are broken, error immediately. - */ -static void -verify_groupname(char *grp) -{ - int i; - - if (grp[0] == '-') { - rdc_err(NULL, gettext("group name cannot start with a '-'")); - } - - for (i = 0; grp[i] != '\0'; i++) { - if (isspace(grp[i])) { - rdc_err(NULL, gettext("group name cannot contain a " - "space")); - } - } -} |