summaryrefslogtreecommitdiff
path: root/usr/src/cmd/avs/rdc/sndradm.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/avs/rdc/sndradm.c')
-rw-r--r--usr/src/cmd/avs/rdc/sndradm.c5715
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"));
- }
- }
-}