summaryrefslogtreecommitdiff
path: root/usr/src/cmd/avs/rdc
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/avs/rdc')
-rw-r--r--usr/src/cmd/avs/rdc/Makefile118
-rw-r--r--usr/src/cmd/avs/rdc/etc/Makefile71
-rw-r--r--usr/src/cmd/avs/rdc/etc/rdc.cluster.sh74
-rw-r--r--usr/src/cmd/avs/rdc/etc/rdc.sh186
-rw-r--r--usr/src/cmd/avs/rdc/etc/rdcfinish.sh90
-rw-r--r--usr/src/cmd/avs/rdc/rdc_ioctl.c87
-rw-r--r--usr/src/cmd/avs/rdc/rdcadm.h67
-rw-r--r--usr/src/cmd/avs/rdc/sndradm.c5715
-rw-r--r--usr/src/cmd/avs/rdc/sndrboot.c881
-rw-r--r--usr/src/cmd/avs/rdc/sndrd.c2013
-rw-r--r--usr/src/cmd/avs/rdc/sndrsubr.c463
-rw-r--r--usr/src/cmd/avs/rdc/sndrsyncd.c1695
12 files changed, 0 insertions, 11460 deletions
diff --git a/usr/src/cmd/avs/rdc/Makefile b/usr/src/cmd/avs/rdc/Makefile
deleted file mode 100644
index 1148884422..0000000000
--- a/usr/src/cmd/avs/rdc/Makefile
+++ /dev/null
@@ -1,118 +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 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-#
-
-DYNPROG = sndrd sndradm sndrboot sndrsyncd
-
-include ../../Makefile.cmd
-include ../Makefile.com
-
-PROG = $(DYNPROG)
-
-SUBDIRS= etc
-
-sndradm := POBJS = sndradm.o rdc_ioctl.o sndrsubr.o
-sndrboot := POBJS = sndrboot.o rdc_ioctl.o sndrsubr.o
-sndrd := POBJS = sndrd.o
-sndrsyncd := POBJS = sndrsyncd.o rdc_ioctl.o sndrsubr.o
-
-OBJS= \
- sndrboot.o \
- sndradm.o \
- sndrd.o \
- sndrsyncd.o \
- rdc_ioctl.o \
- sndrsubr.o
-
-XTRA_OBJS= \
- sdbc_ioctl.o
-
-SRCS= $(OBJS:%.o=%.c) ../sdbc/sdbc_ioctl.c
-
-sndradm := LDLIBS += -lrdc -lunistat -ldscfg -lnsctl -lnsl
-sndrboot := LDLIBS += -lrdc -lunistat -ldscfg
-sndrd := LDLIBS += -lrdc -lnsl
-sndrsyncd := LDLIBS += -lrdc -ldscfg -lunistat
-
-CFLAGS += $(CCVERBOSE) -D_RDC_ -D_SYSCALL32
-LINTFLAGS += -Xa -n -s -x -m -u -Dlint -errhdr=%user -D_RDC_ -D_SYSCALL32
-LINTFLAGS += -DDEBUG
-LINTFLAGS += -erroff=E_SEC_SPRINTF_UNBOUNDED_COPY
-LINTFLAGS += -erroff=E_SEC_SCANF_UNBOUNDED_COPY
-LINTFLAGS += -erroff=E_SEC_PRINTF_VAR_FMT
-LINTFLAGS += -erroff=E_FUNC_SET_NOT_USED
-CERRWARN += -_gcc=-Wno-unused-label
-CERRWARN += -_gcc=-Wno-parentheses
-CERRWARN += -_gcc=-Wno-uninitialized
-POFILE = rdc_all.po
-POFILES = sndradm.po sndrboot.po
-ROOTLIBLINKS = $(ROOTLIB)/sndrd $(ROOTLIB)/sndrsyncd
-ROOTUSRSBINLINKS = $(ROOTUSRSBIN)/sndradm $(ROOTUSRSBIN)/sndrboot
-
-all := TARGET= all
-install := TARGET= install
-clean := TARGET= clean
-clobber := TARGET= clobber
-lint := TARGET= lint
-
-.KEEP_STATE:
-
-.PARALLEL: $(OBJS) $(XTRA_OBJS)
-
-all: $(SUBDIRS) $(PROG) $(POFILES)
-
-install: $(SUBDIRS) all $(ROOTPROG) $(ROOTLIBLINKS) $(ROOTUSRSBINLINKS)
-
-lint: $(SUBDIRS) lint_SRCS
-
-clean: $(SUBDIRS)
- $(RM) *.o $(POFILES)
-
-$(PROG): $$(POBJS)
- $(LINK.c) $(POBJS) -o $@ $(LDLIBS)
- $(POST_PROCESS)
-
-$(POFILE): $(POFILES)
- $(RM) $@
- $(CAT) $(POFILES) > $@
-
-sdbc_ioctl.o: ../sdbc/sdbc_ioctl.c
- $(COMPILE.c) ../sdbc/sdbc_ioctl.c
-
-$(SUBDIRS): FRC
- @cd $@; pwd; $(MAKE) $(TARGET)
-
-$(ROOTLIBLINKS): $(ROOTLIB) $(ROOTPROG)
- -$(RM) $(ROOTLIBLINKS);
- $(LN) $(ROOTBIN)/sndrd $(ROOTLIB)/sndrd;
- $(LN) $(ROOTBIN)/sndrsyncd $(ROOTLIB)/sndrsyncd
-
-$(ROOTUSRSBINLINKS): $(ROOTUSRSBIN) $(ROOTPROG)
- -$(RM) $(ROOTUSRSBINLINKS);
- $(LN) $(ROOTBIN)/sndradm $(ROOTUSRSBIN)/sndradm;
- $(LN) $(ROOTBIN)/sndrboot $(ROOTUSRSBIN)/sndrboot
-
-FRC:
-
-include ../../Makefile.targ
diff --git a/usr/src/cmd/avs/rdc/etc/Makefile b/usr/src/cmd/avs/rdc/etc/Makefile
deleted file mode 100644
index cbe78b12a2..0000000000
--- a/usr/src/cmd/avs/rdc/etc/Makefile
+++ /dev/null
@@ -1,71 +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 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-include ../../../Makefile.cmd
-include ../../Makefile.com
-
-PROG1 = rdc
-PROG2 = rdcfinish
-PROG3 = rdc.cluster
-SHFILES = $(PROG1) $(PROG2) $(PROG3)
-ROOTINIT_D = $(ROOTETC)/init.d
-
-FILEMODE = 0744
-
-ROOTETCFILES= $(ETCFILES:%=$(ROOTETC)/%)
-
-ROOTINIT_DPROG1 = $(ROOTINIT_D)/$(PROG1)
-ROOTINIT_DPROG2 = $(ROOTINIT_D)/$(PROG2)
-ROOTINIT_DPROG3 = $(ROOTINIT_D)/$(PROG3)
-
-.KEEP_STATE:
-
-all: $(SHFILES) $(ETCFILES) $(INITFILES)
-
-install: $(ROOTINIT_DPROG1) $(ROOTINIT_DPROG2) $(ROOTINIT_DPROG3) $(ROOTLIBSVCMETHOD) $(CLUSTERSBINDIR)
- -$(RM) $(CLUSTERLIBDSCFGSTOPDIR)/15rdc
- -$(RM) $(CLUSTERLIBDSCFGSTARTDIR)/10rdc
- -$(RM) $(ROOTLIBSVCMETHOD)/svc-rdc
- -$(RM) $(ROOTLIBSVCMETHOD)/svc-rdcsyncd
- -$(RM) $(CLUSTERSBINDIR)/rdc
- -$(SYMLINK) ../../../sbin/rdc $(CLUSTERLIBDSCFGSTOPDIR)/15rdc
- -$(SYMLINK) ../../../sbin/rdc $(CLUSTERLIBDSCFGSTARTDIR)/10rdc
- $(LN) $(ROOTINIT_D)/rdc $(ROOTLIBSVCMETHOD)/svc-rdc
- $(LN) $(ROOTINIT_D)/rdcfinish $(ROOTLIBSVCMETHOD)/svc-rdcsyncd
- $(CP) $(ROOTINIT_D)/rdc.cluster $(CLUSTERSBINDIR)/rdc
-
-$(ROOTINIT_DPROG1): $(PROG1)
- $(INS.file) $(PROG1)
-
-$(ROOTINIT_DPROG2): $(PROG2)
- $(INS.file) $(PROG2)
-
-$(ROOTINIT_DPROG3): $(PROG3)
- $(INS.file) $(PROG3)
-
-clean:
- $(RM) $(SHFILES)
-
-clobber: clean
-
-lint:
diff --git a/usr/src/cmd/avs/rdc/etc/rdc.cluster.sh b/usr/src/cmd/avs/rdc/etc/rdc.cluster.sh
deleted file mode 100644
index 2d6d0621df..0000000000
--- a/usr/src/cmd/avs/rdc/etc/rdc.cluster.sh
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/ksh
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-# SNDR start script
-#
-# Description: This is the SNDR switchover script.
-# It is used to start or stop a specified cluster
-# resource group when invoked from the data service cluster
-# failover script.
-#
-
-PATH=/etc:/bin
-RDCBOOT="/usr/sbin/sndrboot"
-RDCSYNCD="/usr/lib/sndrsyncd"
-USAGE="Usage: $0 {start|stop} cluster_resource"
-
-SVCS=/usr/bin/svcs
-SVCS_NAME=system/nws_rdc
-
-# Determine if SMF service is online
-#
-ONLINE=`$SVCS -D $SVCS_NAME 2>>/dev/null | grep "^online"`
-if [ -z $ONLINE ]
-then
- echo "$SVCS_NAME not online"
- exit 1
-fi
-
-if [[ -z "$2" ]]
-then
- echo "$USAGE"
- exit 1
-fi
-
-case "$1" in
-'start')
- if [[ -x $RDCBOOT ]]
- then
- $RDCBOOT -r -C "$2"
- fi
- ;;
-
-'stop')
- if [[ -x $RDCBOOT ]]
- then
- $RDCBOOT -s -C "$2"
- fi
- ;;
-
-*)
- echo $USAGE
- exit 1
- ;;
-esac
diff --git a/usr/src/cmd/avs/rdc/etc/rdc.sh b/usr/src/cmd/avs/rdc/etc/rdc.sh
deleted file mode 100644
index 198d1186b2..0000000000
--- a/usr/src/cmd/avs/rdc/etc/rdc.sh
+++ /dev/null
@@ -1,186 +0,0 @@
-#!/bin/sh
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# SNDR start script
-#
-# Description: This is the SNDR start script. It must be located
-# in /etc/init.d with links to the appropriate rc2.d and
-# rc0.d files.
-# It can also be used to start or stop a specified cluster
-# resource group when invoked from the data service cluster
-# failover script.
-#
-#
-#
-PATH=/etc:/bin
-RDCBOOT="/usr/sbin/sndrboot"
-USAGE="Usage: $0 {start|stop} [cluster_resource]"
-SVCS=/usr/bin/svcs
-DSCFG_DEPEND_NOCHK="/tmp/.dscfgadm_pid"
-OS_MINOR=`/usr/bin/uname -r | /usr/bin/cut -d '.' -f2`
-
-. /lib/svc/share/smf_include.sh
-
-# Make sure prior SMF dependents are not 'online'
-# $1 = name of SMF service to validate dependents
-#
-do_smf_depends ()
-{
- times=0
- count=1
-
- if [ $OS_MINOR -ge 11 ]
- then
- return 0
- elif [ -f $DSCFG_DEPEND_NOCHK ]
- then
- for pid in `pgrep dscfgadm`
- do
- if [ `grep -c $pid $DSCFG_DEPEND_NOCHK` -gt 0 ]
- then
- return 0
- fi
- done
- elif [ `ps -ef | grep preremove | grep -c SUNWrdcu` -gt 0 ]
- then
- return 0
-
- fi
-
- while [ $count -ne 0 ]
- do
- count=`$SVCS -o STATE -D $1 2>>/dev/null | grep "^online" | wc -l`
- if [ $count -ne 0 ]
- then
- # Output banner after waiting first 5 seconds
- #
- if [ $times -eq 1 ]
- then
- echo "Waiting for $1 dependents to be 'offline'"
- $SVCS -D $1 2>>/dev/null | grep "^online"
- fi
-
- # Has it been longer then 5 minutes? (60 * 5 secs.)
- #
- if [ $times -eq 60 ]
- then
- echo "Error: Failed waiting for $1 dependents to be 'offline'"
- $SVCS -D $1 2>>/dev/null | grep "^online"
- exit $SMF_EXIT_ERR_FATAL
- fi
-
- # Now sleep, giving other services time to stop
- #
- sleep 5
- times=`expr $times + 1`
- fi
- done
- return 0
-}
-
-CLINFO=/usr/sbin/clinfo
-
-killproc() { # kill the named process(es)
- pid=`/usr/bin/ps -e |
- /usr/bin/grep -w $1 |
- /usr/bin/sed -e 's/^ *//' -e 's/ .*//'`
- [ "$pid" != "" ] && kill $pid
-}
-
-
-case "$1" in
-'start')
- COPT=
-
- if [ -x ${RDCBOOT} ]
- then
- if ${CLINFO}
- then
- if [ "$2" != "" ]
- then
- ${RDCBOOT} -r -C $2
- else
- # SNDR 3.2 SetIDs fixup
- ${RDCBOOT} -C post-patch-setids -r -s
-
- COPT="-C -"
- ${RDCBOOT} ${COPT} -r
- fi
- else
- # non-clustered start
- ${RDCBOOT} -r
- fi
- fi
- ;;
-
-'stop')
- COPT=
-
- if [ ! -r /dev/rdc ]
- then
- RDCBOOT=/usr/bin/true
- fi
-
- do_smf_depends "system/nws_rdc"
-
- if [ -x ${RDCBOOT} ]
- then
- if ${CLINFO}
- then
- if [ "$2" != "" ]
- then
- ${RDCBOOT} -s -C $2
- else
- COPT="-C -"
- ${RDCBOOT} ${COPT} -s
-
- echo "killing SNDR daemons"
- killproc sndrd
- killproc sndrsync
- fi
- else
- # non-clustered stop
-
- ${RDCBOOT} -s
-
- echo "killing SNDR daemons"
- killproc sndrd
- killproc sndrsync
- fi
- else
- # no sndr boot command, kill daemon anyway
-
- echo "killing SNDR daemons"
- killproc sndrd
- killproc sndrsync
- fi
-
- ;;
-
-*)
- echo $USAGE
- exit 1
- ;;
-esac
-exit $SMF_EXIT_OK
diff --git a/usr/src/cmd/avs/rdc/etc/rdcfinish.sh b/usr/src/cmd/avs/rdc/etc/rdcfinish.sh
deleted file mode 100644
index f0cc2f1b8e..0000000000
--- a/usr/src/cmd/avs/rdc/etc/rdcfinish.sh
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/bin/sh
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# Second SNDR start script
-# - called after the TCP/IP stack has been initialised,
-# and networking enabled.
-#
-# - should be linked to /etc/rc2.d/S72rdcfinish as follows:
-#
-# ln /etc/init.d/rdc /etc/rc2.d/S72rdcfinish
-#
-PATH=/etc:/bin
-RDCD="/usr/lib/sndrd"
-RDCSYNCD="/usr/lib/sndrsyncd"
-USAGE="Usage: $0 start"
-
-. /lib/svc/share/smf_include.sh
-
-case "$1" in
-'start')
- echo "Completing SNDR startup:\c"
-
- ##
- ## Start sndrd
- ##
-
- if [ ! -f ${RDCD} ]
- then
- echo "Cannot find ${RDCD}.\nSNDR services unavailable." > /dev/console
- exit $SMF_EXIT_MON_OFFLINE
- fi
-
- ps -e | grep sndrd > /dev/null 2>&1
- if [ $? -ne 0 ]; then
- ${RDCD}
- echo " sndrd\c"
- else
- echo " sndrd already enabled\c"
- fi
-
- ##
- ## Start sndrsyncd
- ##
-
- if [ ! -f ${RDCSYNCD} ]
- then
- echo "\nCannot find ${RDCSYNCD}.\nSNDR start aborted." > /dev/console
- exit $SMF_EXIT_MON_OFFLINE
- fi
-
- ps -e | grep sndrsyn > /dev/null 2>&1
- if [ $? -ne 0 ]; then
- ${RDCSYNCD}
- echo " sndrsyncd\c"
- else
- echo " sndrsyncd already running\c"
- fi
-
- echo " done"
- ;;
-'stop')
- # Inserted for symmetry
- ;;
-*)
- echo $USAGE
- exit 1
- ;;
-esac
-exit $SMF_EXIT_OK
diff --git a/usr/src/cmd/avs/rdc/rdc_ioctl.c b/usr/src/cmd/avs/rdc/rdc_ioctl.c
deleted file mode 100644
index 1fcd85669d..0000000000
--- a/usr/src/cmd/avs/rdc/rdc_ioctl.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * RDC user level ioctl interface
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-
-#include <sys/nsctl/sd_cache.h>
-#include <sys/nsctl/sd_conf.h>
-#include <sys/nsctl/rdc_ioctl.h>
-#include <sys/unistat/spcs_s.h>
-#include <sys/unistat/spcs_s_u.h>
-
-const char *__rdc_dev = "/dev/rdc";
-static int __rdc_fd;
-
-
-static int
-__rdc_open(void)
-{
- int fd = open(__rdc_dev, O_RDONLY);
-
- if (fd < 0)
- return (-1);
-
- return (__rdc_fd = fd);
-}
-
-
-int
-rdc_ioctl(long cmd, long a0, long a1, long a2, long a3, long a4,
- spcs_s_info_t ustatus)
-{
- _rdc_ioctl_t args;
-
- if (!__rdc_fd && __rdc_open() < 0)
- return (-1);
-
- args.arg0 = a0;
- args.arg1 = a1;
- args.arg2 = a2;
- args.arg3 = a3;
- args.arg4 = a4;
- args.magic = RDC_MAGIC; /* for versioning */
- args.ustatus = ustatus;
-
- return (ioctl(__rdc_fd, cmd, &args));
-}
-
-/*
- * Simple form of the ioctl, just pass the command and buffer address
- * to the kernel.
- */
-int
-rdc_ioctl_simple(long cmd, void *addr)
-{
- if (!__rdc_fd && __rdc_open() < 0)
- return (-1);
- return (ioctl(__rdc_fd, cmd, addr));
-}
diff --git a/usr/src/cmd/avs/rdc/rdcadm.h b/usr/src/cmd/avs/rdc/rdcadm.h
deleted file mode 100644
index 6ad0c05731..0000000000
--- a/usr/src/cmd/avs/rdc/rdcadm.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _RDCADM_H
-#define _RDCADM_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define MAXQFBAS 0
-#define MAXQITEMS 0
-#define ASYNCTHR 0
-#define AUTOSYNC -1
-#define AUTOSYNC_OFF 0
-#define AUTOSYNC_ON 1
-#define QBLOCK 0
-
-extern int maxqfbas;
-extern int maxqitems;
-extern int autosync;
-extern int asyncthr;
-extern int qblock;
-
-extern char *rdc_decode_flag(int, int);
-extern void rdc_err(spcs_s_info_t *status, char *string, ...);
-extern void rdc_warn(spcs_s_info_t *status, char *string, ...);
-extern int rdc_get_maxsets();
-extern int mounted(char *device);
-extern int get_cfg_setid(CFGFILE *cfg, char *ctag, char *tohost, char *tofile);
-extern int get_new_cfg_setid(CFGFILE *cfg);
-extern void get_group_diskq(CFGFILE *cfg, char *group, char *diskq);
-extern int find_setnumber_in_libcfg(CFGFILE *, char *, char *, char *);
-extern int sv_enable(char *, CFGFILE *, char *);
-extern void block_sigs(void);
-extern void unblock_sigs(void);
-
-extern char *program;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _RDCADM_H */
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"));
- }
- }
-}
diff --git a/usr/src/cmd/avs/rdc/sndrboot.c b/usr/src/cmd/avs/rdc/sndrboot.c
deleted file mode 100644
index fcdb59899b..0000000000
--- a/usr/src/cmd/avs/rdc/sndrboot.c
+++ /dev/null
@@ -1,881 +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/wait.h>
-#include <stdio.h>
-#include <sys/mnttab.h>
-#include <errno.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <locale.h>
-#include <langinfo.h>
-#include <libintl.h>
-#include <stdarg.h>
-#include <netdb.h>
-#include <ctype.h>
-#include <sys/utsname.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/nsctl/cfg_cluster.h>
-
-#include <sys/unistat/spcs_s.h>
-#include <sys/unistat/spcs_s_u.h>
-#include <sys/unistat/spcs_errors.h>
-
-#include "rdcadm.h"
-
-/*
- * Special re-use of sndrboot to fix SNDR set IDs during post-patch processing
- */
-#define RDC_CMD_FIXSETIDS 0xFEEDFACE
-
-/*
- * 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 diskqueue[NSC_MAXPATH]; /* Disk Queue volume */
- char group[NSC_MAXPATH]; /* Group name */
- char lhost[MAX_RDC_HOST_SIZE]; /* Logical hostname for cluster */
- int doasync; /* Device is in sync/async mode */
- int setid; /* unique setid of this set */
-} _sd_dual_pair_t;
-
-#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>
-
-char *ctag = NULL;
-
-int parseopts(int, char **, int *);
-static int rdc_operation(char *, char *, char *, char *, char *, char *, int,
- char *, char *, char *, int, char *, int setid);
-static int read_libcfg(int);
-static void usage(void);
-
-extern char *basename(char *);
-
-int rdc_maxsets;
-static _sd_dual_pair_t *pair_list;
-char *program;
-
-struct netbuf svaddr;
-struct netbuf *svp;
-struct netconfig nconf;
-struct netconfig *conf;
-struct knetconfig knconf;
-static int clustered = 0;
-static int proto_test = 0;
-
-#ifdef lint
-int
-sndrboot_lintmain(int argc, char *argv[])
-#else
-int
-main(int argc, char *argv[])
-#endif
-{
- 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 diskqueue[NSC_MAXPATH];
- char group[NSC_MAXPATH];
- char lhost[MAX_RDC_HOST_SIZE];
- int pairs;
- int pid;
- int flag = 0;
- int doasync;
- int rc;
- char *required;
- int setid;
-
- (void) setlocale(LC_ALL, "");
- (void) textdomain("rdc");
-
- 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);
- }
-
- rdc_maxsets = rdc_get_maxsets();
- if (rdc_maxsets == -1) {
- spcs_log("sndr", NULL,
- gettext("%s unable to get maxsets value from kernel"),
- program);
-
- 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);
- }
-
- if (parseopts(argc, argv, &flag))
- return (1);
- pairs = read_libcfg(flag);
-
- if (flag == RDC_CMD_FIXSETIDS) {
- if (pairs) {
- spcs_log("sndr", NULL, gettext("Fixed %d Remote Mirror"
- " set IDs"), pairs);
-#ifdef DEBUG
- rdc_warn(NULL, gettext("Fixed %d Remote Mirror set "
- "IDs"), pairs);
-#endif
- }
- return (0);
- }
-
- if (pairs == 0) {
-#ifdef DEBUG
- rdc_err(NULL,
- gettext("Config contains no dual copy sets"));
-#else
- return (0);
-#endif
- }
-
- while (pairs--) {
- pid = fork();
- if (pid == -1) { /* error forking */
- perror("fork");
- continue;
- }
-
- if (pid > 0) /* this is parent process */
- continue;
-
-/*
- * At this point, this is the child process. Do the operation
- */
-
- (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(diskqueue,
- pair_list[pairs].diskqueue, NSC_MAXPATH);
- (void) strncpy(group,
- pair_list[pairs].group, NSC_MAXPATH);
- (void) strncpy(lhost,
- pair_list[pairs].lhost, MAX_RDC_HOST_SIZE);
-
- doasync = pair_list[pairs].doasync;
- setid = pair_list[pairs].setid;
- if (rdc_operation(fromhost, fromfile, frombitmap,
- tohost, tofile, tobitmap, flag, directfile, group,
- diskqueue, doasync, lhost, setid)
- < 0) {
- exit(255);
- }
-
- exit(0);
- }
-
- while ((wait((int *)0) > 0))
- ;
- return (0);
-}
-
-static int
-rdc_operation(fromhost, fromfile, frombitmap, tohost, tofile,
- tobitmap, flag, directfile, group, diskqueue, doasync,
- lhost, setid)
-char *fromhost, *fromfile, *frombitmap;
-char *tohost, *tofile, *tobitmap;
-int flag, doasync;
-char *directfile;
-char *group, *diskqueue;
-int setid;
-char *lhost;
-{
- const int getaddr = (flag == RDC_CMD_RESUME);
- const int rpcbind = !getaddr;
- rdc_config_t parms;
- int ret;
- spcs_s_info_t ustatus;
- struct hostent *hp;
- char fromname[MAXHOSTNAMELEN], toname[MAXHOSTNAMELEN];
- struct t_info tinfo;
- int i;
-
- conf = &nconf;
- bzero(&fromname, MAXHOSTNAMELEN);
- bzero(&toname, MAXHOSTNAMELEN);
-
- hp = gethost_byname(fromhost);
- if (hp == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s gethost_byname failed for %s"),
- program, fromhost);
- }
- if (strcmp(hp->h_name, fromhost) == 0)
- (void) strncpy(fromname, hp->h_name, MAXHOSTNAMELEN);
- else {
- for (i = 0; hp->h_aliases[i] != NULL; i++) {
- if (strcmp(hp->h_aliases[i], fromhost) == 0)
- (void) strncpy(fromname, hp->h_aliases[i],
- MAXHOSTNAMELEN);
- }
- }
- if (fromname[0] == '\0') {
- spcs_log("sndr", NULL,
- gettext("%s host %s is not local"),
- program, fromhost);
- rdc_err(NULL, gettext("Host %s is not local"),
- fromhost);
- }
- hp = gethost_byname(tohost);
- if (hp == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s gethost_byname failed for %s"),
- program, tohost);
- }
- if (strcmp(hp->h_name, tohost) == 0)
- (void) strncpy(toname, hp->h_name, MAXHOSTNAMELEN);
- else {
- for (i = 0; hp->h_aliases[i] != NULL; i++) {
- if (strcmp(hp->h_aliases[i], tohost) == 0)
- (void) strncpy(toname, hp->h_aliases[i],
- MAXHOSTNAMELEN);
- }
- }
- if (toname[0] == '\0') {
- spcs_log("sndr", NULL,
- gettext("%s host %s is not local"),
- program, tohost);
- rdc_err(NULL, gettext("Host %s is not local"),
- tohost);
- }
-
- if (self_check(fromname) && self_check(toname)) {
- spcs_log("sndr", NULL,
- gettext("%s Both %s and %s are local"),
- program, fromhost, tohost);
- rdc_err(NULL, gettext("Both %s and %s are local"),
- fromhost, tohost);
- }
-
- /*
- * 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) {
-#ifdef DEBUG
- (void) printf("get_addr failed for Ver 4 %s\n", toname);
-#endif
- spcs_log("sndr", NULL,
- gettext("%s get_addr failed for Ver 4"),
- program);
- 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;
- } else {
- ;
- /*EMPTY*/
- }
- 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 (!clustered && !self_check(fromname) && !self_check(toname)) {
- spcs_log("sndr", NULL,
- gettext("%s Neither %s nor %s is local"),
- program, fromhost, tohost);
- rdc_err(NULL, gettext("Neither %s nor %s is local"),
- fromhost, tohost);
- }
- (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);
-
- (void) strncpy(parms.rdc_set->group_name, group, NSC_MAXPATH);
- (void) strncpy(parms.rdc_set->disk_queue, diskqueue, NSC_MAXPATH);
-
- parms.rdc_set->maxqfbas = maxqfbas;
- parms.rdc_set->maxqitems = maxqitems;
- parms.rdc_set->autosync = autosync;
- parms.rdc_set->asyncthr = asyncthr;
- parms.rdc_set->setid = setid;
-
- /* gethostid(3c) is defined to return a 32bit value */
- parms.rdc_set->syshostid = (int32_t)gethostid();
-
- parms.command = 0;
- parms.options = 0;
- parms.command = flag;
-
- if (flag == RDC_CMD_RESUME) {
- if (doasync)
- parms.options |= RDC_OPT_ASYNC;
- else
- parms.options |= RDC_OPT_SYNC;
- }
- if (clustered) {
- if (!ctag)
- goto noconfig;
- if (strcmp(ctag, "-") == 0)
- goto noconfig;
-
-#ifdef DEBUG
- (void) fprintf(stderr, "logical hostname: %s\n", lhost);
-#endif
-
- if (strcmp(lhost, fromname) == 0) {
- parms.options |= RDC_OPT_PRIMARY;
- (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 direct */
- }
- } else {
-noconfig:
- /*
- * If not clustered, don't resume sndr sets with lhost
- */
- if ((flag == RDC_CMD_RESUME) && lhost && strlen(lhost))
- return (0);
-
- if (self_check(fromname)) {
- parms.options |= RDC_OPT_PRIMARY;
- (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 direct */
- }
- }
-
- ustatus = spcs_s_ucreate();
-
- errno = 0;
- ret = RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus);
- if (ret != SPCS_S_OK) {
-
- /* Surpress error messages for suspend on cluster elements */
- if ((flag == RDC_CMD_SUSPEND) && (errno == RDC_EALREADY) &&
- !clustered && lhost && strlen(lhost)) {
- spcs_s_ufree(&ustatus);
- return (0);
- }
-
- (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,
- gettext("%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,
- gettext("%s %s %s %s %s %s %s %s"),
- program, rdc_decode_flag(flag, parms.options),
- fromhost, fromfile, frombitmap,
- tohost, tofile, tobitmap);
- rdc_err(&ustatus, 0);
- }
- }
-
- 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);
-
- spcs_s_ufree(&ustatus);
- return (0);
-}
-/*
- * assign setid's to any existing
- * sets without setids, making sure of course NOT to re-use a setid
- */
-int
-update_setids(CFGFILE *cfg, int *no_id, int highest)
-{
- int setid;
- char buf[CFG_MAX_BUF];
- char key[CFG_MAX_KEY];
- char *ctag;
-
- /* If in a Sun Cluster, SetIDs need to have a ctag */
- if ((ctag = cfg_get_resource(cfg)) != NULL) {
- ctag = strdup(ctag);
- cfg_resource(cfg, "setid-ctag");
- }
-
- /*
- * Paranoia. IF there are any sets with setids, we don't
- * want to re-use their number.
- */
- if (highest > get_new_cfg_setid(cfg)) {
- bzero(&buf, sizeof (buf));
- (void) sprintf(buf, "%d", highest);
- if (cfg_put_cstring(cfg, "setid.set1.value", buf,
- sizeof (buf)) < 0)
- rdc_warn(NULL, gettext("sndrboot: Unable to store "
- "new setid"));
- }
-
- for (setid = 0; no_id[setid]; setid++) {
- bzero(&buf, sizeof (buf));
- bzero(&key, sizeof (key));
- (void) sprintf(buf, "%d", get_new_cfg_setid(cfg));
- (void) sprintf(key, "sndr.set%d.options", no_id[setid]);
- if (cfg_put_options(cfg, CFG_SEC_CONF, key, "setid", buf) < 0)
- rdc_warn(NULL, gettext("sndrboot: Unable to store "
- "unique setid"));
-
- pair_list[no_id[setid] - 1].setid = atoi(buf);
- }
-
- /* Restore old ctag if in a Sun Cluster */
- if (ctag) {
- cfg_resource(cfg, ctag);
- free(ctag);
- }
-
- if (cfg_commit(cfg) < 0)
- rdc_err(NULL, gettext("sndrboot: Failed to commit setids"));
-
- return (setid);
-}
-
-/*
- * this is called when the option lghn is no available in libdscfg
- * that should only happen on an upgrade.
- * cfg write lock must be held across this function
- */
-char *
-get_lghn(CFGFILE *cfg, char *ctag, int setnum, int flag)
-{
- FILE *pipe;
- char rsgrp[SCCONF_MAXSTRINGLEN];
- char cmd[SCCONF_MAXSTRINGLEN];
- static char lhostname[MAX_RDC_HOST_SIZE];
- char key[CFG_MAX_KEY];
- int rc;
-
- if (ctag == NULL)
- goto fail;
-
- bzero(&lhostname, sizeof (lhostname));
-
- (void) sprintf(rsgrp, "%s-stor-rg", ctag);
-/* BEGIN CSTYLED */
- rc = snprintf(cmd, SCCONF_MAXSTRINGLEN,
- "/usr/cluster/bin/scrgadm -pvv | fgrep HostnameList \
-| fgrep %s | fgrep value | awk -F: '{ print $4 }'", rsgrp);
-/* END CSTYLED */
-
- if (rc < 0) {
- rdc_err(NULL, gettext("Error getting scrgadm output"));
- }
-
- pipe = popen(cmd, "r");
-
- if (pipe == NULL) {
- rdc_err(NULL, gettext("Error opening pipe"));
- }
- rc = fscanf(pipe, "%s", lhostname);
- (void) pclose(pipe);
-
- if (rc != 1) {
- rdc_err(NULL, gettext("Unable to get logical host"));
- }
-
- /* not really failing, but suspend does not have the config lock */
- if (flag == RDC_CMD_SUSPEND)
- goto fail;
-
- bzero(&key, sizeof (key));
- (void) snprintf(key, sizeof (key), "sndr.set%d.options", setnum);
- if (cfg_put_options(cfg, CFG_SEC_CONF, key, "lghn", lhostname) < 0)
- rdc_warn(NULL, gettext("sndrboot: Unable to store logical "
- "host name in configuration database"));
-
- if (cfg_commit(cfg) < 0)
- rdc_err(NULL,
- gettext("sndrboot: Failed to commit logical host name"));
-
-fail:
- return (lhostname);
-
-}
-
-/*
- * 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 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 diskqueue[NSC_MAXPATH];
- char group[NSC_MAXPATH];
- char lhost[MAX_RDC_HOST_SIZE];
- char sync[16];
- char setid[64];
- int doasync;
- CFGFILE *cfg;
- int i, j = 0;
- int rc;
- char buf[CFG_MAX_BUF];
- char key[CFG_MAX_KEY];
- char dummy[NSC_MAXPATH];
- int setnumber;
- int numsets;
- int highest = 0;
- char lghn[5];
- int *no_id;
-
-
- if ((cfg = cfg_open("")) == NULL)
- rdc_err(NULL, gettext("Error opening config"));
-
- /*
- * If RDC_CMD_FIXSETIDS, we were called during post-patch install
- * Acquire a write-lock on the cfg_lock(), so the code can attempt
- * to fix setIDs
- */
- if (flag == RDC_CMD_FIXSETIDS) {
- if (!cfg_lock(cfg, CFG_WRLOCK))
- rdc_err(NULL, gettext("Error write locking config"));
- cfg_resource(cfg, NULL);
- } else {
- if (!cfg_lock(cfg, CFG_RDLOCK))
- rdc_err(NULL, gettext("Error locking config"));
- cfg_resource(cfg, ctag);
- }
-
- if ((numsets = cfg_get_num_entries(cfg, "sndr")) < 0)
- rdc_err(NULL, gettext("Unable to get set info from config"));
-
- no_id = (int *)calloc(numsets + 1, sizeof (int));
- if (!no_id)
- rdc_err(NULL, gettext("No memory"));
-
-
- (void) snprintf(lghn, sizeof (lghn), "lghn");
-
- for (i = 0; i < rdc_maxsets; i++) {
- setnumber = i + 1;
-
- 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;
-
- rc = sscanf(buf, "%s %s %s %s %s %s %s %s %s %s %s %s",
- fromhost, fromfile, frombitmap, tohost, tofile, tobitmap,
- directfile, sync, group, dummy, dummy, diskqueue);
- if (rc != 12)
- rdc_err(NULL, gettext("cfg input error (%d)"), rc);
-
- if (strcmp(directfile, "ip") == 0)
- (void) strcpy(directfile, "");
-
- if (strcmp(group, "-") == 0)
- (void) strcpy(group, "");
-
- if (strcmp(diskqueue, "-") == 0)
- (void) strcpy(diskqueue, "");
-
- (void) snprintf(key, sizeof (key),
- "sndr.set%d.options", setnumber);
-
- if (cfg_get_single_option(cfg, CFG_SEC_CONF, key,
- lghn, lhost, MAX_RDC_HOST_SIZE) < 0)
- (void) strcpy(lhost,
- get_lghn(cfg, ctag, setnumber, flag));
-
- if (strcmp(sync, "sync") == 0)
- doasync = 0;
- else if (strcmp(sync, "async") == 0)
- doasync = 1;
- else {
- cfg_close(cfg);
- rdc_err(NULL,
- gettext("Set %s:%s neither sync nor async"),
- tohost, tofile);
- }
-
- (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);
- (void) strncpy(pair_list[i].diskqueue, diskqueue,
- NSC_MAXPATH);
- (void) strncpy(pair_list[i].group, group, NSC_MAXPATH);
- (void) strncpy(pair_list[i].lhost, lhost, MAX_RDC_HOST_SIZE);
- pair_list[i].doasync = doasync;
-
- if (cfg_get_single_option(cfg, CFG_SEC_CONF, key, "setid",
- setid, sizeof (setid)) < 0) {
- no_id[j++] = setnumber;
- }
- pair_list[i].setid = atoi(setid);
-
- if (pair_list[i].setid > highest)
- highest = pair_list[i].setid;
-
- if (gethost_netaddrs(fromhost, tohost,
- (char *)pair_list[i].fnetaddr,
- (char *)pair_list[i].tnetaddr) < 0) {
- cfg_close(cfg);
- spcs_log("sndr", NULL,
- gettext("%s unable to determine IP addresses "
- "for hosts %s %s"), program, fromhost, tohost);
- rdc_err(NULL, gettext("unable to determine IP "
- "addresses for hosts %s, %s"), fromhost, tohost);
- }
- }
- /*
- * fix any lost set ids if possible, also deal with upgrade
- */
- if (j > 0 && flag == RDC_CMD_FIXSETIDS) {
- (void) update_setids(cfg, no_id, highest);
- i = j; /* Set number of fixups */
- }
- free(no_id);
- cfg_close(cfg);
- return (i);
-}
-
-
-int
-parseopts(argc, argv, flag)
-int argc;
-char **argv;
-int *flag;
-{
- int errflag = 0;
- char c;
- char inval = 0;
-#ifdef DEBUG
- while ((c = getopt(argc, argv, "C:Urs")) != -1) {
-#else
- while ((c = getopt(argc, argv, "C:rs")) != -1) {
-#endif
- switch (c) {
- case 'C':
- clustered = TRUE;
- ctag = optarg;
- break;
-#ifdef DEBUG
- case 'U':
- proto_test = 1;
- break;
-#endif
- case 'r':
- if (*flag)
- inval = 1;
- *flag = RDC_CMD_RESUME;
- break;
- case 's':
- if (*flag)
- inval = 1;
- *flag = RDC_CMD_SUSPEND;
- break;
- case '?':
- errflag++;
- }
- }
-
- /*
- * Special fix to address no SetIds in AVS 3.1 to 3.2 install + patch
- * Adjust set IDs, if someone invokes the following invalid command
- *
- * /use/sbin/sndrboot -C post-patch-setids -r -s
- *
- * Command will be called in post-install of the patch containing fix
- *
- */
- if (clustered && (strcmp(ctag, "post-patch-setids") == 0) &&
- *flag && inval) {
- *flag = RDC_CMD_FIXSETIDS;
- return (0);
- }
-
- if (inval) {
- rdc_warn(NULL, gettext("Invalid argument combination"));
- errflag = 1;
- }
-
- if (!*flag || errflag) {
- usage();
- return (-1);
- }
-
- return (0);
-}
-
-static void
-usage()
-{
- (void) fprintf(stderr, gettext("usage:\n"));
- (void) fprintf(stderr,
- gettext("\t%s -r [-C tag]\t\t"
- "resume\n"), program);
-
- (void) fprintf(stderr,
- gettext("\t%s -s [-C tag]\t\t"
- "suspend\n"), program);
-}
diff --git a/usr/src/cmd/avs/rdc/sndrd.c b/usr/src/cmd/avs/rdc/sndrd.c
deleted file mode 100644
index aa04f19127..0000000000
--- a/usr/src/cmd/avs/rdc/sndrd.c
+++ /dev/null
@@ -1,2013 +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.
- */
-/*
- * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
- * Copyright 2014 Gary Mills
- */
-
-/*
- * Network SNDR/ncall-ip server - based on nfsd
- */
-#include <sys/types.h>
-#include <rpc/types.h>
-#include <errno.h>
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netconfig.h>
-#include <stropts.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <strings.h>
-#include <signal.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <netdir.h>
-#include <rpc/rpc_com.h>
-#include <rpc/rpc.h>
-#include <tiuser.h>
-#include <netinet/tcp.h>
-#include <netinet/in.h>
-#include <syslog.h>
-#include <locale.h>
-#include <langinfo.h>
-#include <libintl.h>
-#include <libgen.h>
-#include <deflt.h>
-#include <sys/resource.h>
-
-#include <sys/nsctl/nsctl.h>
-
-#ifdef __NCALL__
-
-#include <sys/ncall/ncall.h>
-#include <sys/ncall/ncall_ip.h>
-#include <sys/nsctl/libncall.h>
-
-#define RDC_POOL_CREATE NC_IOC_POOL_CREATE
-#define RDC_POOL_RUN NC_IOC_POOL_RUN
-#define RDC_POOL_WAIT NC_IOC_POOL_WAIT
-#define RDC_PROGRAM NCALL_PROGRAM
-#define RDC_SERVICE "ncall"
-#undef RDC_SVCPOOL_ID /* We are overloading this value */
-#define RDC_SVCPOOL_ID NCALL_SVCPOOL_ID
-#define RDC_SVC_NAME "NCALL"
-#define RDC_VERS_MIN NCALL_VERS_MIN
-#define RDC_VERS_MAX NCALL_VERS_MAX
-
-#else /* !__NCALL__ */
-
-#include <sys/nsctl/rdc_ioctl.h>
-#include <sys/nsctl/rdc_io.h>
-#include <sys/nsctl/librdc.h>
-
-#define RDC_SERVICE "rdc"
-#define RDC_SVC_NAME "RDC"
-
-#endif /* __NCALL__ */
-
-#define RDCADMIN "/etc/default/sndr"
-
-#include <nsctl.h>
-
-struct conn_ind {
- struct conn_ind *conn_next;
- struct conn_ind *conn_prev;
- struct t_call *conn_call;
-};
-
-struct conn_entry {
- bool_t closing;
- struct netconfig nc;
-};
-
-static char *progname;
-static struct conn_entry *conn_polled;
-static int num_conns; /* Current number of connections */
-static struct pollfd *poll_array; /* array of poll descriptors for poll */
-static size_t num_fds = 0; /* number of transport fds opened */
-static void poll_for_action();
-static void remove_from_poll_list(int);
-static int do_poll_cots_action(int, int);
-static int do_poll_clts_action(int, int);
-static void add_to_poll_list(int, struct netconfig *);
-static int bind_to_provider(char *, char *, struct netbuf **,
- struct netconfig **);
-static int set_addrmask(int, struct netconfig *, struct netbuf *);
-static void conn_close_oldest(void);
-static boolean_t conn_get(int, struct netconfig *, struct conn_ind **);
-static void cots_listen_event(int, int);
-static int discon_get(int, struct netconfig *, struct conn_ind **);
-static int nofile_increase(int);
-static int is_listen_fd_index(int);
-#if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8)
-static int sndrsvcpool(int);
-static int svcwait(int id);
-#endif
-
-
-/*
- * RPC protocol block. Useful for passing registration information.
- */
-struct protob {
- char *serv; /* ASCII service name, e.g. "RDC" */
- int versmin; /* minimum version no. to be registered */
- int versmax; /* maximum version no. to be registered */
- int program; /* program no. to be registered */
- struct protob *next; /* next entry on list */
-};
-
-
-
-static size_t end_listen_fds;
-static int debugflg = 0;
-static int max_conns_allowed = -1;
-static int listen_backlog = 10;
-static char *trans_provider = (char *)NULL;
-static int rdcsvc(int, struct netbuf, struct netconfig *);
-
-/* used by cots_listen_event() */
-static int (*Mysvc)(int, struct netbuf, struct netconfig *) = rdcsvc;
-
-/*
- * Determine valid semantics for rdc.
- */
-#define OK_TPI_TYPE(_nconf) \
- (_nconf->nc_semantics == NC_TPI_CLTS || \
- _nconf->nc_semantics == NC_TPI_COTS || \
- _nconf->nc_semantics == NC_TPI_COTS_ORD)
-
-#define BE32_TO_U32(a) \
- ((((uint32_t)((uchar_t *)a)[0] & 0xFF) << (uint32_t)24) |\
- (((uint32_t)((uchar_t *)a)[1] & 0xFF) << (uint32_t)16) |\
- (((uint32_t)((uchar_t *)a)[2] & 0xFF) << (uint32_t)8) |\
- ((uint32_t)((uchar_t *)a)[3] & 0xFF))
-
-#ifdef DEBUG
-/*
- * Only support UDP in DEBUG mode for now
- */
-static char *defaultproviders[] = { "/dev/tcp", "/dev/tcp6", "/dev/udp",
- "/dev/udp6", NULL };
-#else
-static char *defaultproviders[] = { "/dev/tcp6", "/dev/tcp", NULL };
-#endif
-
-/*
- * Number of elements to add to the poll array on each allocation.
- */
-#define POLL_ARRAY_INC_SIZE 64
-#define NOFILE_INC_SIZE 64
-
-#ifdef __NCALL__
-const char *rdc_devr = "/dev/ncallip";
-#else
-const char *rdc_devr = "/dev/rdc";
-#endif
-
-static int rdc_fdr;
-static int
-
-open_rdc(void)
-{
- int fd = open(rdc_devr, O_RDONLY);
-
- if (fd < 0)
- return (-1);
-
- return (rdc_fdr = fd);
-}
-
-static int
-sndrsys(int type, void *arg)
-{
- int ret = -1;
- if (!rdc_fdr && open_rdc() < 0) { /* open failed */
- syslog(LOG_ERR, "open_rdc() failed: %m\n");
- } else {
- if ((ret = ioctl(rdc_fdr, type, arg)) < 0) {
- syslog(LOG_ERR, "ioctl(rdc_ioctl) failed: %m\n");
- }
- }
- return (ret);
-}
-
-int
-rdc_transport_open(struct netconfig *nconf)
-{
- int fd;
- struct strioctl strioc;
-
- if ((nconf == (struct netconfig *)NULL) ||
- (nconf->nc_device == (char *)NULL)) {
- syslog(LOG_ERR, "No netconfig device");
- return (-1);
- }
-
- /*
- * Open the transport device.
- */
- fd = t_open(nconf->nc_device, O_RDWR, (struct t_info *)NULL);
- if (fd == -1) {
- if (t_errno == TSYSERR && errno == EMFILE &&
- (nofile_increase(0) == 0)) {
- /* Try again with a higher NOFILE limit. */
- fd = t_open(nconf->nc_device, O_RDWR, NULL);
- }
- if (fd == -1) {
- if (t_errno == TSYSERR) {
- syslog(LOG_ERR, "t_open failed: %m");
- } else {
- syslog(LOG_ERR, "t_open failed: %s",
- t_errlist[t_errno]);
- }
- return (-1);
- }
- }
-
- /*
- * Pop timod because the RPC module must be as close as possible
- * to the transport.
- */
- if (ioctl(fd, I_POP, 0) < 0) {
- syslog(LOG_ERR, "I_POP of timod failed: %m");
- if (t_close(fd) == -1) {
- if (t_errno == TSYSERR) {
- syslog(LOG_ERR, "t_close failed on %d: %m", fd);
- } else {
- syslog(LOG_ERR, "t_close failed on %d: %s",
- fd, t_errlist[t_errno]);
- }
- }
- return (-1);
- }
-
- if (nconf->nc_semantics == NC_TPI_CLTS) {
- /*
- * Push rpcmod to filter data traffic to KRPC.
- */
- if (ioctl(fd, I_PUSH, "rpcmod") < 0) {
- syslog(LOG_ERR, "I_PUSH of rpcmod failed: %m");
- (void) t_close(fd);
- return (-1);
- }
- } else {
- if (ioctl(fd, I_PUSH, "rpcmod") < 0) {
- syslog(LOG_ERR, "I_PUSH of CONS rpcmod failed: %m");
- if (t_close(fd) == -1) {
- if (t_errno == TSYSERR) {
- syslog(LOG_ERR,
- "t_close failed on %d: %m", fd);
- } else {
- syslog(LOG_ERR,
- "t_close failed on %d: %s",
- fd, t_errlist[t_errno]);
- }
- }
- return (-1);
- }
-
- strioc.ic_cmd = RPC_SERVER;
- strioc.ic_dp = (char *)0;
- strioc.ic_len = 0;
- strioc.ic_timout = -1;
- /* Tell CONS rpcmod to act like a server stream. */
- if (ioctl(fd, I_STR, &strioc) < 0) {
- syslog(LOG_ERR, "CONS rpcmod set-up ioctl failed: %m");
- if (t_close(fd) == -1) {
- if (t_errno == TSYSERR) {
- syslog(LOG_ERR,
- "t_close failed on %d: %m", fd);
- } else {
- syslog(LOG_ERR,
- "t_close failed on %d: %s",
- fd, t_errlist[t_errno]);
- }
- }
- return (-1);
- }
- }
-
- /*
- * Re-push timod so that we will still be doing TLI
- * operations on the descriptor.
- */
- if (ioctl(fd, I_PUSH, "timod") < 0) {
- syslog(LOG_ERR, "I_PUSH of timod failed: %m");
- if (t_close(fd) == -1) {
- if (t_errno == TSYSERR) {
- syslog(LOG_ERR, "t_close failed on %d: %m", fd);
- } else {
- syslog(LOG_ERR, "t_close failed on %d: %s",
- fd, t_errlist[t_errno]);
- }
- }
- return (-1);
- }
-
- return (fd);
-}
-
-
-void
-rdcd_log_tli_error(char *tli_name, int fd, struct netconfig *nconf)
-{
- int error;
-
- /*
- * Save the error code across syslog(), just in case syslog()
- * gets its own error and, therefore, overwrites errno.
- */
- error = errno;
- if (t_errno == TSYSERR) {
- syslog(LOG_ERR, "%s(file descriptor %d/transport %s) %m",
- tli_name, fd, nconf->nc_proto);
- } else {
- syslog(LOG_ERR,
- "%s(file descriptor %d/transport %s) TLI error %d",
- tli_name, fd, nconf->nc_proto, t_errno);
- }
- errno = error;
-}
-
-/*
- * Called to set up service over a particular transport
- */
-void
-do_one(char *provider, char *proto, struct protob *protobp0,
- int (*svc)(int, struct netbuf, struct netconfig *))
-{
- struct netbuf *retaddr;
- struct netconfig *retnconf;
- struct netbuf addrmask;
- int vers;
- int sock;
-
- if (provider) {
- sock = bind_to_provider(provider, protobp0->serv, &retaddr,
- &retnconf);
- } else {
- (void) syslog(LOG_ERR,
- "Cannot establish %s service over %s: transport setup problem.",
- protobp0->serv, provider ? provider : proto);
- return;
- }
-
- if (sock == -1) {
- if ((Is_ipv6present() &&
- (strcmp(provider, "/dev/tcp6") == 0)) ||
- (!Is_ipv6present() && (strcmp(provider, "/dev/tcp") == 0)))
- (void) syslog(LOG_ERR,
- "Cannot establish %s service over %s: transport "
- "setup problem.",
- protobp0->serv, provider ? provider : proto);
- return;
- }
-
- if (set_addrmask(sock, retnconf, &addrmask) < 0) {
- (void) syslog(LOG_ERR,
- "Cannot set address mask for %s", retnconf->nc_netid);
- return;
- }
-
-
- /*
- * Register all versions of the programs in the protocol block list
- */
- for (vers = protobp0->versmin; vers <= protobp0->versmax; vers++) {
- (void) rpcb_unset(protobp0->program, vers, retnconf);
- (void) rpcb_set(protobp0->program, vers, retnconf, retaddr);
- }
-
- if (retnconf->nc_semantics == NC_TPI_CLTS) {
- /* Don't drop core if supporting module(s) aren't loaded. */
- (void) signal(SIGSYS, SIG_IGN);
-
- /*
- * svc() doesn't block, it returns success or failure.
- */
- if ((*svc)(sock, addrmask, retnconf) < 0) {
- (void) syslog(LOG_ERR, "Cannot establish %s service "
- "over <file desc. %d, protocol %s> : %m. Exiting",
- protobp0->serv, sock, retnconf->nc_proto);
- exit(1);
- }
- }
- /*
- * We successfully set up the server over this transport.
- * Add this descriptor to the one being polled on.
- */
- add_to_poll_list(sock, retnconf);
-}
-
-/*
- * Set up the SNDR/ncall-ip service over all the available transports.
- * Returns -1 for failure, 0 for success.
- */
-int
-do_all(struct protob *protobp,
- int (*svc)(int, struct netbuf, struct netconfig *))
-{
- struct netconfig *nconf;
- NCONF_HANDLE *nc;
-
- if ((nc = setnetconfig()) == (NCONF_HANDLE *)NULL) {
- syslog(LOG_ERR, "setnetconfig failed: %m");
- return (-1);
- }
- while (nconf = getnetconfig(nc)) {
- if ((nconf->nc_flag & NC_VISIBLE) &&
- strcmp(nconf->nc_protofmly, "loopback") != 0 &&
- OK_TPI_TYPE(nconf))
- do_one(nconf->nc_device, nconf->nc_proto, protobp, svc);
- }
- (void) endnetconfig(nc);
- return (0);
-}
-
-/*
- * Read the /etc/default/sndr configuration file to determine if the
- * client has been configured for number of threads, backlog or transport
- * provider.
- */
-
-static void
-read_default(void)
-{
- char *defval, *tmp_str;
- int errno;
- int tmp;
-
- /* Fail silently if error in opening the default rdc config file */
- if ((defopen(RDCADMIN)) == 0) {
- if ((defval = defread("SNDR_THREADS=")) != NULL) {
- errno = 0;
- tmp = strtol(defval, (char **)NULL, 10);
- if (errno == 0) {
- max_conns_allowed = tmp;
- }
- }
- if ((defval = defread("SNDR_LISTEN_BACKLOG=")) != NULL) {
- errno = 0;
- tmp = strtol(defval, (char **)NULL, 10);
- if (errno == 0) {
- listen_backlog = tmp;
- }
- }
- if ((defval = defread("SNDR_TRANSPORT=")) != NULL) {
- errno = 0;
- tmp_str = strdup(defval);
- if (errno == 0) {
- trans_provider = tmp_str;
- }
- }
- /* close defaults file */
- (void) defopen(NULL);
- }
-}
-#ifdef lint
-int
-sndrd_lintmain(int ac, char **av)
-#else
-int
-main(int ac, char **av)
-#endif
-{
- const char *dir = "/";
- int allflag = 0;
- int pid;
- int i, rc;
- struct protob *protobp0, *protobp;
- char **providerp;
- char *required;
-#if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8)
- int maxservers;
-#endif
-
- (void) setlocale(LC_ALL, "");
-#ifdef __NCALL__
- (void) textdomain("ncall");
-#else
- (void) textdomain("rdc");
-#endif
-
- progname = basename(av[0]);
-
-#ifdef __NCALL__
- rc = ncall_check_release(&required);
-#else
- rc = rdc_check_release(&required);
-#endif
- if (rc < 0) {
- (void) fprintf(stderr,
- gettext("%s: unable to determine the current "
- "Solaris release: %s\n"), progname, strerror(errno));
- exit(1);
- } else if (rc == FALSE) {
- (void) fprintf(stderr,
- gettext("%s: incorrect Solaris release (requires %s)\n"),
- progname, required);
- exit(1);
- }
-
- openlog(progname, LOG_PID|LOG_CONS, LOG_DAEMON);
- read_default();
-
- /*
- * Usage: <progname> [-c <number of threads>] [-t protocol] \
- * [-d] [-l <listen backlog>]
- */
- while ((i = getopt(ac, av, "ac:t:dl:")) != EOF) {
- switch (i) {
- case 'a':
- allflag = 1;
- break;
- case 'c':
- max_conns_allowed = atoi(optarg);
- if (max_conns_allowed <= 0)
- max_conns_allowed = 16;
- break;
-
- case 'd':
- debugflg++;
- break;
-
- case 't':
- trans_provider = optarg;
- break;
-
- case 'l':
- listen_backlog = atoi(optarg);
- if (listen_backlog < 0)
- listen_backlog = 32;
- break;
-
- default:
- syslog(LOG_ERR,
- "Usage: %s [-c <number of threads>] "
- "[-d] [-t protocol] "
- "[-l <listen backlog>]\n", progname);
- exit(1);
- break;
- }
- }
-
- if (chroot(dir) < 0) {
- syslog(LOG_ERR, "chroot failed: %m");
- exit(1);
- }
-
- if (chdir(dir) < 0) {
- syslog(LOG_ERR, "chdir failed: %m");
- exit(1);
- }
-
- if (!debugflg) {
- pid = fork();
- if (pid < 0) {
- syslog(LOG_ERR, "Fork failed\n");
- exit(1);
- }
- if (pid != 0)
- exit(0);
-
- /*
- * Close existing file descriptors, open "/dev/null" as
- * standard input, output, and error, and detach from
- * controlling terminal.
- */
-#if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8)
- /* use closefrom(3C) from PSARC/2000/193 when possible */
- closefrom(0);
-#else
- for (i = 0; i < _NFILE; i++)
- (void) close(i);
-#endif
- (void) open("/dev/null", O_RDONLY);
- (void) open("/dev/null", O_WRONLY);
- (void) dup(1);
- (void) setsid();
-
- /*
- * ignore all signals apart from SIGTERM.
- */
- for (i = 1; i < _sys_nsig; i++)
- (void) sigset(i, SIG_IGN);
-
- (void) sigset(SIGTERM, SIG_DFL);
- }
-
-#if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8)
- /*
- * Set up kernel RPC thread pool for the SNDR/ncall-ip server.
- */
- maxservers = (max_conns_allowed < 0 ? 16 : max_conns_allowed);
- if (sndrsvcpool(maxservers)) {
- (void) syslog(LOG_ERR,
- "Can't set up kernel %s service: %m. Exiting", progname);
- exit(1);
- }
-
- /*
- * Set up blocked thread to do LWP creation on behalf of the kernel.
- */
- if (svcwait(RDC_SVCPOOL_ID)) {
- (void) syslog(LOG_ERR,
- "Can't set up %s pool creator: %m, Exiting", progname);
- exit(1);
- }
-#endif
-
- /*
- * Build a protocol block list for registration.
- */
- protobp0 = protobp = (struct protob *)malloc(sizeof (struct protob));
- protobp->serv = RDC_SVC_NAME;
- protobp->versmin = RDC_VERS_MIN;
- protobp->versmax = RDC_VERS_MAX;
- protobp->program = RDC_PROGRAM;
- protobp->next = (struct protob *)NULL;
-
- if (allflag) {
- if (do_all(protobp0, rdcsvc) == -1)
- exit(1);
- } else if (trans_provider)
- do_one(trans_provider, NULL, protobp0, rdcsvc);
- else {
- for (providerp = defaultproviders;
- *providerp != NULL; providerp++) {
- trans_provider = *providerp;
- do_one(trans_provider, NULL, protobp0, rdcsvc);
- }
- }
-
-done:
- free(protobp);
-
- end_listen_fds = num_fds;
- /*
- * Poll for non-data control events on the transport descriptors.
- */
- poll_for_action();
-
- syslog(LOG_ERR, "%s fatal server error\n", progname);
-
- return (-1);
-}
-
-static int
-reuseaddr(int fd)
-{
- struct t_optmgmt req, resp;
- struct opthdr *opt;
- char reqbuf[128];
- int *ip;
-
- /* LINTED pointer alignment */
- opt = (struct opthdr *)reqbuf;
- opt->level = SOL_SOCKET;
- opt->name = SO_REUSEADDR;
- opt->len = sizeof (int);
-
- /* LINTED pointer alignment */
- ip = (int *)&reqbuf[sizeof (struct opthdr)];
- *ip = 1;
-
- req.flags = T_NEGOTIATE;
- req.opt.len = sizeof (struct opthdr) + opt->len;
- req.opt.buf = (char *)opt;
-
- resp.flags = 0;
- resp.opt.buf = reqbuf;
- resp.opt.maxlen = sizeof (reqbuf);
-
- if (t_optmgmt(fd, &req, &resp) < 0 || resp.flags != T_SUCCESS) {
- if (t_errno == TSYSERR) {
- syslog(LOG_ERR, "reuseaddr() t_optmgmt failed: %m\n");
- } else {
- syslog(LOG_ERR, "reuseaddr() t_optmgmt failed: %s\n",
- t_errlist[t_errno]);
- }
- return (-1);
- }
- return (0);
-}
-
-/*
- * poll on the open transport descriptors for events and errors.
- */
-void
-poll_for_action(void)
-{
- int nfds;
- int i;
-
- /*
- * Keep polling until all transports have been closed. When this
- * happens, we return.
- */
- while ((int)num_fds > 0) {
- nfds = poll(poll_array, num_fds, INFTIM);
- switch (nfds) {
- case 0:
- continue;
-
- case -1:
- /*
- * Some errors from poll could be
- * due to temporary conditions, and we try to
- * be robust in the face of them. Other
- * errors (should never happen in theory)
- * are fatal (eg. EINVAL, EFAULT).
- */
- switch (errno) {
- case EINTR:
- continue;
-
- case EAGAIN:
- case ENOMEM:
- (void) sleep(10);
- continue;
-
- default:
- (void) syslog(LOG_ERR,
- "poll failed: %m. Exiting");
- exit(1);
- }
- default:
- break;
- }
-
- /*
- * Go through the poll list looking for events.
- */
- for (i = 0; i < num_fds && nfds > 0; i++) {
- if (poll_array[i].revents) {
- nfds--;
- /*
- * We have a message, so try to read it.
- * Record the error return in errno,
- * so that syslog(LOG_ERR, "...%m")
- * dumps the corresponding error string.
- */
- if (conn_polled[i].nc.nc_semantics ==
- NC_TPI_CLTS) {
- errno = do_poll_clts_action(
- poll_array[i].fd, i);
- } else {
- errno = do_poll_cots_action(
- poll_array[i].fd, i);
- }
-
- if (errno == 0)
- continue;
- /*
- * Most returned error codes mean that there is
- * fatal condition which we can only deal with
- * by closing the transport.
- */
- if (errno != EAGAIN && errno != ENOMEM) {
- (void) syslog(LOG_ERR,
- "Error (%m) reading descriptor %d"
- "/transport %s. Closing it.",
- poll_array[i].fd,
- conn_polled[i].nc.nc_proto);
- (void) t_close(poll_array[i].fd);
- remove_from_poll_list(poll_array[i].fd);
- } else if (errno == ENOMEM)
- (void) sleep(5);
- }
- }
- }
-
- (void) syslog(LOG_ERR,
- "All transports have been closed with errors. Exiting.");
-}
-
-/*
- * Allocate poll/transport array entries for this descriptor.
- */
-static void
-add_to_poll_list(int fd, struct netconfig *nconf)
-{
- static int poll_array_size = 0;
-
- /*
- * If the arrays are full, allocate new ones.
- */
- if (num_fds == poll_array_size) {
- struct pollfd *tpa;
- struct conn_entry *tnp;
-
- if (poll_array_size != 0) {
- tpa = poll_array;
- tnp = conn_polled;
- } else
- tpa = (struct pollfd *)0;
-
- poll_array_size += POLL_ARRAY_INC_SIZE;
-
- /*
- * Allocate new arrays.
- */
- poll_array = (struct pollfd *)
- malloc(poll_array_size * sizeof (struct pollfd) + 256);
- conn_polled = (struct conn_entry *)
- malloc(poll_array_size * sizeof (struct conn_entry) + 256);
- if (poll_array == (struct pollfd *)NULL ||
- conn_polled == (struct conn_entry *)NULL) {
- syslog(LOG_ERR, "malloc failed for poll array");
- exit(1);
- }
-
- /*
- * Copy the data of the old ones into new arrays, and
- * free the old ones.
- * num_fds is guaranteed to be less than
- * poll_array_size, so this memcpy is safe.
- */
- if (tpa) {
- (void) memcpy((void *)poll_array, (void *)tpa,
- num_fds * sizeof (struct pollfd));
- (void) memcpy((void *)conn_polled, (void *)tnp,
- num_fds * sizeof (struct conn_entry));
- free((void *)tpa);
- free((void *)tnp);
- }
- }
-
- /*
- * Set the descriptor and event list. All possible events are
- * polled for.
- */
- poll_array[num_fds].fd = fd;
- poll_array[num_fds].events = POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI;
-
- /*
- * Copy the transport data over too.
- */
- conn_polled[num_fds].nc = *nconf; /* structure copy */
- conn_polled[num_fds].closing = 0;
-
- /*
- * Set the descriptor to non-blocking. Avoids a race
- * between data arriving on the stream and then having it
- * flushed before we can read it.
- */
- if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
- (void) syslog(LOG_ERR,
- "fcntl(file desc. %d/transport %s, F_SETFL, "
- "O_NONBLOCK): %m. Exiting",
- num_fds, nconf->nc_proto);
- exit(1);
- }
-
- /*
- * Count this descriptor.
- */
- ++num_fds;
-}
-
-static void
-remove_from_poll_list(int fd)
-{
- int i;
- int num_to_copy;
-
- for (i = 0; i < num_fds; i++) {
- if (poll_array[i].fd == fd) {
- --num_fds;
- num_to_copy = num_fds - i;
- (void) memcpy((void *)&poll_array[i],
- (void *)&poll_array[i+1],
- num_to_copy * sizeof (struct pollfd));
- (void) memset((void *)&poll_array[num_fds], 0,
- sizeof (struct pollfd));
- (void) memcpy((void *)&conn_polled[i],
- (void *)&conn_polled[i+1],
- num_to_copy * sizeof (struct conn_entry));
- (void) memset((void *)&conn_polled[num_fds], 0,
- sizeof (struct conn_entry));
- return;
- }
- }
- syslog(LOG_ERR, "attempt to remove nonexistent fd from poll list");
-
-}
-
-static void
-conn_close_oldest(void)
-{
- int fd;
- int i1;
-
- /*
- * Find the oldest connection that is not already in the
- * process of shutting down.
- */
- for (i1 = end_listen_fds; /* no conditional expression */; i1++) {
- if (i1 >= num_fds)
- return;
- if (conn_polled[i1].closing == 0)
- break;
- }
-#ifdef DEBUG
- (void) printf("too many connections (%d), releasing oldest (%d)\n",
- num_conns, poll_array[i1].fd);
-#else
- syslog(LOG_WARNING, "too many connections (%d), releasing oldest (%d)",
- num_conns, poll_array[i1].fd);
-#endif
- fd = poll_array[i1].fd;
- if (conn_polled[i1].nc.nc_semantics == NC_TPI_COTS) {
- /*
- * For politeness, send a T_DISCON_REQ to the transport
- * provider. We close the stream anyway.
- */
- (void) t_snddis(fd, (struct t_call *)0);
- num_conns--;
- remove_from_poll_list(fd);
- (void) t_close(fd);
- } else {
- /*
- * For orderly release, we do not close the stream
- * until the T_ORDREL_IND arrives to complete
- * the handshake.
- */
- if (t_sndrel(fd) == 0)
- conn_polled[i1].closing = 1;
- }
-}
-
-static boolean_t
-conn_get(int fd, struct netconfig *nconf, struct conn_ind **connp)
-{
- struct conn_ind *conn;
- struct conn_ind *next_conn;
-
- conn = (struct conn_ind *)malloc(sizeof (*conn));
- if (conn == NULL) {
- syslog(LOG_ERR, "malloc for listen indication failed");
- return (FALSE);
- }
-
- /* LINTED pointer alignment */
- conn->conn_call = (struct t_call *)t_alloc(fd, T_CALL, T_ALL);
- if (conn->conn_call == NULL) {
- free((char *)conn);
- rdcd_log_tli_error("t_alloc", fd, nconf);
- return (FALSE);
- }
-
- if (t_listen(fd, conn->conn_call) == -1) {
- rdcd_log_tli_error("t_listen", fd, nconf);
- (void) t_free((char *)conn->conn_call, T_CALL);
- free((char *)conn);
- return (FALSE);
- }
-
- if (conn->conn_call->udata.len > 0) {
- syslog(LOG_WARNING,
- "rejecting inbound connection(%s) with %d bytes "
- "of connect data",
- nconf->nc_proto, conn->conn_call->udata.len);
-
- conn->conn_call->udata.len = 0;
- (void) t_snddis(fd, conn->conn_call);
- (void) t_free((char *)conn->conn_call, T_CALL);
- free((char *)conn);
- return (FALSE);
- }
-
- if ((next_conn = *connp) != NULL) {
- next_conn->conn_prev->conn_next = conn;
- conn->conn_next = next_conn;
- conn->conn_prev = next_conn->conn_prev;
- next_conn->conn_prev = conn;
- } else {
- conn->conn_next = conn;
- conn->conn_prev = conn;
- *connp = conn;
- }
- return (TRUE);
-}
-
-static int
-discon_get(int fd, struct netconfig *nconf, struct conn_ind **connp)
-{
- struct conn_ind *conn;
- struct t_discon discon;
-
- discon.udata.buf = (char *)0;
- discon.udata.maxlen = 0;
- if (t_rcvdis(fd, &discon) == -1) {
- rdcd_log_tli_error("t_rcvdis", fd, nconf);
- return (-1);
- }
-
- conn = *connp;
- if (conn == NULL)
- return (0);
-
- do {
- if (conn->conn_call->sequence == discon.sequence) {
- if (conn->conn_next == conn)
- *connp = (struct conn_ind *)0;
- else {
- if (conn == *connp) {
- *connp = conn->conn_next;
- }
- conn->conn_next->conn_prev = conn->conn_prev;
- conn->conn_prev->conn_next = conn->conn_next;
- }
- free((char *)conn);
- break;
- }
- conn = conn->conn_next;
- } while (conn != *connp);
-
- return (0);
-}
-
-static void
-cots_listen_event(int fd, int conn_index)
-{
- struct t_call *call;
- struct conn_ind *conn;
- struct conn_ind *conn_head;
- int event;
- struct netconfig *nconf = &conn_polled[conn_index].nc;
- int new_fd;
- struct netbuf addrmask;
- int ret = 0;
-
- conn_head = NULL;
- (void) conn_get(fd, nconf, &conn_head);
-
- while ((conn = conn_head) != NULL) {
- conn_head = conn->conn_next;
- if (conn_head == conn)
- conn_head = NULL;
- else {
- conn_head->conn_prev = conn->conn_prev;
- conn->conn_prev->conn_next = conn_head;
- }
- call = conn->conn_call;
- free(conn);
-
- /*
- * If we have already accepted the maximum number of
- * connections allowed on the command line, then drop
- * the oldest connection (for any protocol) before
- * accepting the new connection. Unless explicitly
- * set on the command line, max_conns_allowed is -1.
- */
- if (max_conns_allowed != -1 && num_conns >= max_conns_allowed)
- conn_close_oldest();
-
- /*
- * Create a new transport endpoint for the same proto as
- * the listener.
- */
- new_fd = rdc_transport_open(nconf);
- if (new_fd == -1) {
- call->udata.len = 0;
- (void) t_snddis(fd, call);
- (void) t_free((char *)call, T_CALL);
- syslog(LOG_ERR, "Cannot establish transport over %s",
- nconf->nc_device);
- continue;
- }
-
- /* Bind to a generic address/port for the accepting stream. */
- if (t_bind(new_fd, NULL, NULL) == -1) {
- rdcd_log_tli_error("t_bind", new_fd, nconf);
- call->udata.len = 0;
- (void) t_snddis(fd, call);
- (void) t_free((char *)call, T_CALL);
- (void) t_close(new_fd);
- continue;
- }
-
- while (t_accept(fd, new_fd, call) == -1) {
- if (t_errno != TLOOK) {
- rdcd_log_tli_error("t_accept", fd, nconf);
- call->udata.len = 0;
- (void) t_snddis(fd, call);
- (void) t_free((char *)call, T_CALL);
- (void) t_close(new_fd);
- goto do_next_conn;
- }
- while (event = t_look(fd)) {
- switch (event) {
- case T_LISTEN:
- (void) conn_get(fd, nconf, &conn_head);
- continue;
-
- case T_DISCONNECT:
- (void) discon_get(fd, nconf,
- &conn_head);
- continue;
-
- default:
- syslog(LOG_ERR,
- "unexpected event 0x%x during "
- "accept processing (%s)",
- event, nconf->nc_proto);
- call->udata.len = 0;
- (void) t_snddis(fd, call);
- (void) t_free((char *)call, T_CALL);
- (void) t_close(new_fd);
- goto do_next_conn;
- }
- }
- }
-
- if (set_addrmask(new_fd, nconf, &addrmask) < 0) {
- (void) syslog(LOG_ERR, "Cannot set address mask for %s",
- nconf->nc_netid);
- (void) t_snddis(new_fd, NULL);
- (void) t_free((char *)call, T_CALL);
- (void) t_close(new_fd);
- continue;
- }
-
- /* Tell kRPC about the new stream. */
- ret = (*Mysvc)(new_fd, addrmask, nconf);
- if (ret < 0) {
- syslog(LOG_ERR,
- "unable to register with kernel rpc: %m");
- free(addrmask.buf);
- (void) t_snddis(new_fd, NULL);
- (void) t_free((char *)call, T_CALL);
- (void) t_close(new_fd);
- goto do_next_conn;
- }
-
- free(addrmask.buf);
- (void) t_free((char *)call, T_CALL);
-
- /*
- * Poll on the new descriptor so that we get disconnect
- * and orderly release indications.
- */
- num_conns++;
- add_to_poll_list(new_fd, nconf);
-
- /* Reset nconf in case it has been moved. */
- nconf = &conn_polled[conn_index].nc;
-do_next_conn:;
- }
-}
-
-static int
-do_poll_cots_action(int fd, int conn_index)
-{
- char buf[256];
- int event;
- int i1;
- int flags;
- struct conn_entry *connent = &conn_polled[conn_index];
- struct netconfig *nconf = &(connent->nc);
- const char *errorstr;
-
- while (event = t_look(fd)) {
- switch (event) {
- case T_LISTEN:
- cots_listen_event(fd, conn_index);
- break;
-
- case T_DATA:
- /*
- * Receive a private notification from CONS rpcmod.
- */
- i1 = t_rcv(fd, buf, sizeof (buf), &flags);
- if (i1 == -1) {
- syslog(LOG_ERR, "t_rcv failed");
- break;
- }
- if (i1 < sizeof (int))
- break;
- i1 = BE32_TO_U32(buf);
- if (i1 == 1 || i1 == 2) {
- /*
- * This connection has been idle for too long,
- * so release it as politely as we can. If we
- * have already initiated an orderly release
- * and we get notified that the stream is
- * still idle, pull the plug. This prevents
- * hung connections from continuing to consume
- * resources.
- */
- if (nconf->nc_semantics == NC_TPI_COTS ||
- connent->closing != 0) {
- (void) t_snddis(fd, (struct t_call *)0);
- goto fdclose;
- }
- /*
- * For NC_TPI_COTS_ORD, the stream is closed
- * and removed from the poll list when the
- * T_ORDREL is received from the provider. We
- * don't wait for it here because it may take
- * a while for the transport to shut down.
- */
- if (t_sndrel(fd) == -1) {
- syslog(LOG_ERR,
- "unable to send orderly release %m");
- }
- connent->closing = 1;
- } else
- syslog(LOG_ERR,
- "unexpected event from CONS rpcmod %d", i1);
- break;
-
- case T_ORDREL:
- /* Perform an orderly release. */
- if (t_rcvrel(fd) == 0) {
- /* T_ORDREL on listen fd's should be ignored */
- if (!is_listen_fd_index(fd)) {
- (void) t_sndrel(fd);
- goto fdclose;
- }
- break;
-
- } else if (t_errno == TLOOK) {
- break;
- } else {
- rdcd_log_tli_error("t_rcvrel", fd, nconf);
- /*
- * check to make sure we do not close
- * listen fd
- */
- if (!is_listen_fd_index(fd))
- break;
- else
- goto fdclose;
- }
-
- case T_DISCONNECT:
- if (t_rcvdis(fd, (struct t_discon *)NULL) == -1)
- rdcd_log_tli_error("t_rcvdis", fd, nconf);
-
- /*
- * T_DISCONNECT on listen fd's should be ignored.
- */
- if (!is_listen_fd_index(fd))
- break;
- else
- goto fdclose;
-
- default:
- if (t_errno == TSYSERR) {
- if ((errorstr = strerror(errno)) == NULL) {
- (void) snprintf(buf, sizeof (buf),
- "Unknown error num %d", errno);
- errorstr = (const char *)buf;
- }
- } else if (event == -1)
- errorstr = t_strerror(t_errno);
- else
- errorstr = "";
-#ifdef DEBUG
- syslog(LOG_ERR,
- "unexpected TLI event (0x%x) on "
- "connection-oriented transport(%s, %d):%s",
- event, nconf->nc_proto, fd, errorstr);
-#endif
-
-fdclose:
- num_conns--;
- remove_from_poll_list(fd);
- (void) t_close(fd);
- return (0);
- }
- }
-
- return (0);
-}
-
-
-/*
- * Called to read and interpret the event on a connectionless descriptor.
- * Returns 0 if successful, or a UNIX error code if failure.
- */
-static int
-do_poll_clts_action(int fd, int conn_index)
-{
- int error;
- int ret;
- int flags;
- struct netconfig *nconf = &conn_polled[conn_index].nc;
- static struct t_unitdata *unitdata = NULL;
- static struct t_uderr *uderr = NULL;
- static int oldfd = -1;
- struct nd_hostservlist *host = NULL;
- struct strbuf ctl[1], data[1];
- /*
- * We just need to have some space to consume the
- * message in the event we can't use the TLI interface to do the
- * job.
- *
- * We flush the message using getmsg(). For the control part
- * we allocate enough for any TPI header plus 32 bytes for address
- * and options. For the data part, there is nothing magic about
- * the size of the array, but 256 bytes is probably better than
- * 1 byte, and we don't expect any data portion anyway.
- *
- * If the array sizes are too small, we handle this because getmsg()
- * (called to consume the message) will return MOREDATA|MORECTL.
- * Thus we just call getmsg() until it's read the message.
- */
- char ctlbuf[sizeof (union T_primitives) + 32];
- char databuf[256];
-
- /*
- * If this is the same descriptor as the last time
- * do_poll_clts_action was called, we can save some
- * de-allocation and allocation.
- */
- if (oldfd != fd) {
- oldfd = fd;
-
- if (unitdata) {
- (void) t_free((char *)unitdata, T_UNITDATA);
- unitdata = NULL;
- }
- if (uderr) {
- (void) t_free((char *)uderr, T_UDERROR);
- uderr = NULL;
- }
- }
-
- /*
- * Allocate a unitdata structure for receiving the event.
- */
- if (unitdata == NULL) {
- /* LINTED pointer alignment */
- unitdata = (struct t_unitdata *)t_alloc(fd, T_UNITDATA, T_ALL);
- if (unitdata == NULL) {
- if (t_errno == TSYSERR) {
- /*
- * Save the error code across
- * syslog(), just in case
- * syslog() gets its own error
- * and therefore overwrites errno.
- */
- error = errno;
- (void) syslog(LOG_ERR,
- "t_alloc(file descriptor %d/transport %s, "
- "T_UNITDATA) failed: %m",
- fd, nconf->nc_proto);
- return (error);
- }
- (void) syslog(LOG_ERR, "t_alloc(file descriptor %d/"
- "transport %s, T_UNITDATA) failed TLI error %d",
- fd, nconf->nc_proto, t_errno);
- goto flush_it;
- }
- }
-
-try_again:
- flags = 0;
-
- /*
- * The idea is we wait for T_UNITDATA_IND's. Of course,
- * we don't get any, because rpcmod filters them out.
- * However, we need to call t_rcvudata() to let TLI
- * tell us we have a T_UDERROR_IND.
- *
- * algorithm is:
- * t_rcvudata(), expecting TLOOK.
- * t_look(), expecting T_UDERR.
- * t_rcvuderr(), expecting success (0).
- * expand destination address into ASCII,
- * and dump it.
- */
-
- ret = t_rcvudata(fd, unitdata, &flags);
- if (ret == 0 || t_errno == TBUFOVFLW) {
- (void) syslog(LOG_WARNING, "t_rcvudata(file descriptor %d/"
- "transport %s) got unexpected data, %d bytes",
- fd, nconf->nc_proto, unitdata->udata.len);
-
- /*
- * Even though we don't expect any data, in case we do,
- * keep reading until there is no more.
- */
- if (flags & T_MORE)
- goto try_again;
-
- return (0);
- }
-
- switch (t_errno) {
- case TNODATA:
- return (0);
- case TSYSERR:
- /*
- * System errors are returned to caller.
- * Save the error code across
- * syslog(), just in case
- * syslog() gets its own error
- * and therefore overwrites errno.
- */
- error = errno;
- (void) syslog(LOG_ERR,
- "t_rcvudata(file descriptor %d/transport %s) %m",
- fd, nconf->nc_proto);
- return (error);
- case TLOOK:
- break;
- default:
- (void) syslog(LOG_ERR,
- "t_rcvudata(file descriptor %d/transport %s) TLI error %d",
- fd, nconf->nc_proto, t_errno);
- goto flush_it;
- }
-
- ret = t_look(fd);
- switch (ret) {
- case 0:
- return (0);
- case -1:
- /*
- * System errors are returned to caller.
- */
- if (t_errno == TSYSERR) {
- /*
- * Save the error code across
- * syslog(), just in case
- * syslog() gets its own error
- * and therefore overwrites errno.
- */
- error = errno;
- (void) syslog(LOG_ERR,
- "t_look(file descriptor %d/transport %s) %m",
- fd, nconf->nc_proto);
- return (error);
- }
- (void) syslog(LOG_ERR,
- "t_look(file descriptor %d/transport %s) TLI error %d",
- fd, nconf->nc_proto, t_errno);
- goto flush_it;
- case T_UDERR:
- break;
- default:
- (void) syslog(LOG_WARNING, "t_look(file descriptor %d/"
- "transport %s) returned %d not T_UDERR (%d)",
- fd, nconf->nc_proto, ret, T_UDERR);
- }
-
- if (uderr == NULL) {
- /* LINTED pointer alignment */
- uderr = (struct t_uderr *)t_alloc(fd, T_UDERROR, T_ALL);
- if (uderr == NULL) {
- if (t_errno == TSYSERR) {
- /*
- * Save the error code across
- * syslog(), just in case
- * syslog() gets its own error
- * and therefore overwrites errno.
- */
- error = errno;
- (void) syslog(LOG_ERR,
- "t_alloc(file descriptor %d/transport %s, "
- "T_UDERROR) failed: %m",
- fd, nconf->nc_proto);
- return (error);
- }
- (void) syslog(LOG_ERR, "t_alloc(file descriptor %d/"
- "transport %s, T_UDERROR) failed TLI error: %d",
- fd, nconf->nc_proto, t_errno);
- goto flush_it;
- }
- }
-
- ret = t_rcvuderr(fd, uderr);
- if (ret == 0) {
-
- /*
- * Save the datagram error in errno, so that the
- * %m argument to syslog picks up the error string.
- */
- errno = uderr->error;
-
- /*
- * Log the datagram error, then log the host that
- * probably triggerred. Cannot log both in the
- * same transaction because of packet size limitations
- * in /dev/log.
- */
- (void) syslog((errno == ECONNREFUSED) ? LOG_DEBUG : LOG_WARNING,
- "%s response over <file descriptor %d/transport %s> "
- "generated error: %m",
- progname, fd, nconf->nc_proto);
-
- /*
- * Try to map the client's address back to a
- * name.
- */
- ret = netdir_getbyaddr(nconf, &host, &uderr->addr);
- if (ret != -1 && host && host->h_cnt > 0 &&
- host->h_hostservs) {
- (void) syslog((errno == ECONNREFUSED) ? LOG_DEBUG : LOG_WARNING,
- "Bad %s response was sent to client with "
- "host name: %s; service port: %s",
- progname, host->h_hostservs->h_host,
- host->h_hostservs->h_serv);
- } else {
- int i, j;
- char *buf;
- char *hex = "0123456789abcdef";
-
- /*
- * Mapping failed, print the whole thing
- * in ASCII hex.
- */
- buf = (char *)malloc(uderr->addr.len * 2 + 1);
- for (i = 0, j = 0; i < uderr->addr.len; i++, j += 2) {
- buf[j] = hex[((uderr->addr.buf[i]) >> 4) & 0xf];
- buf[j+1] = hex[uderr->addr.buf[i] & 0xf];
- }
- buf[j] = '\0';
- (void) syslog((errno == ECONNREFUSED) ?
- LOG_DEBUG : LOG_WARNING,
- "Bad %s response was sent to client with "
- "transport address: 0x%s",
- progname, buf);
- free((void *)buf);
- }
-
- if (ret == 0 && host != NULL)
- netdir_free((void *)host, ND_HOSTSERVLIST);
- return (0);
- }
-
- switch (t_errno) {
- case TNOUDERR:
- goto flush_it;
- case TSYSERR:
- /*
- * System errors are returned to caller.
- * Save the error code across
- * syslog(), just in case
- * syslog() gets its own error
- * and therefore overwrites errno.
- */
- error = errno;
- (void) syslog(LOG_ERR,
- "t_rcvuderr(file descriptor %d/transport %s) %m",
- fd, nconf->nc_proto);
- return (error);
- default:
- (void) syslog(LOG_ERR,
- "t_rcvuderr(file descriptor %d/transport %s) TLI error %d",
- fd, nconf->nc_proto, t_errno);
- goto flush_it;
- }
-
-flush_it:
- /*
- * If we get here, then we could not cope with whatever message
- * we attempted to read, so flush it. If we did read a message,
- * and one isn't present, that is all right, because fd is in
- * nonblocking mode.
- */
- (void) syslog(LOG_ERR,
- "Flushing one input message from <file descriptor %d/transport %s>",
- fd, nconf->nc_proto);
-
- /*
- * Read and discard the message. Do this this until there is
- * no more control/data in the message or until we get an error.
- */
- do {
- ctl->maxlen = sizeof (ctlbuf);
- ctl->buf = ctlbuf;
- data->maxlen = sizeof (databuf);
- data->buf = databuf;
- flags = 0;
- ret = getmsg(fd, ctl, data, &flags);
- if (ret == -1)
- return (errno);
- } while (ret != 0);
-
- return (0);
-}
-
-/*
- * Establish service thread.
- */
-static int
-rdcsvc(int fd, struct netbuf addrmask, struct netconfig *nconf)
-{
-#ifdef __NCALL__
- struct ncall_svc_args nsa;
-#else /* !__NCALL__ */
- struct rdc_svc_args nsa;
- _rdc_ioctl_t rdc_args = { 0, };
-#endif /* __NCALL__ */
-
- nsa.fd = fd;
- nsa.nthr = (max_conns_allowed < 0 ? 16 : max_conns_allowed);
- (void) strncpy(nsa.netid, nconf->nc_netid, sizeof (nsa.netid));
- nsa.addrmask.len = addrmask.len;
- nsa.addrmask.maxlen = addrmask.maxlen;
- nsa.addrmask.buf = addrmask.buf;
-
-#ifdef __NCALL__
- return (sndrsys(NC_IOC_SERVER, &nsa));
-#else /* !__NCALL__ */
- rdc_args.arg0 = (long)&nsa;
- return (sndrsys(RDC_ENABLE_SVR, &rdc_args));
-#endif /* __NCALL__ */
-}
-
-
-
-static int
-nofile_increase(int limit)
-{
- struct rlimit rl;
-
- if (getrlimit(RLIMIT_NOFILE, &rl) == -1) {
- syslog(LOG_ERR,
- "nofile_increase() getrlimit of NOFILE failed: %m");
- return (-1);
- }
-
- if (limit > 0)
- rl.rlim_cur = limit;
- else
- rl.rlim_cur += NOFILE_INC_SIZE;
-
- if (rl.rlim_cur > rl.rlim_max && rl.rlim_max != RLIM_INFINITY)
- rl.rlim_max = rl.rlim_cur;
-
- if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
- syslog(LOG_ERR,
- "nofile_increase() setrlimit of NOFILE to %d failed: %m",
- rl.rlim_cur);
- return (-1);
- }
-
- return (0);
-}
-
-int
-rdcd_bindit(struct netconfig *nconf, struct netbuf **addr,
- struct nd_hostserv *hs, int backlog)
-{
- int fd;
- struct t_bind *ntb;
- struct t_bind tb;
- struct nd_addrlist *addrlist;
- struct t_optmgmt req, resp;
- struct opthdr *opt;
- char reqbuf[128];
-
- if ((fd = rdc_transport_open(nconf)) == -1) {
- syslog(LOG_ERR, "cannot establish transport service over %s",
- nconf->nc_device);
- return (-1);
- }
-
- addrlist = (struct nd_addrlist *)NULL;
- if (netdir_getbyname(nconf, hs, &addrlist) != 0) {
- if (strncmp(nconf->nc_netid, "udp", 3) != 0) {
- syslog(LOG_ERR, "Cannot get address for transport "
- "%s host %s service %s",
- nconf->nc_netid, hs->h_host, hs->h_serv);
- }
- (void) t_close(fd);
- return (-1);
- }
-
- if (strcmp(nconf->nc_proto, "tcp") == 0) {
- /*
- * If we're running over TCP, then set the
- * SO_REUSEADDR option so that we can bind
- * to our preferred address even if previously
- * left connections exist in FIN_WAIT states.
- * This is somewhat bogus, but otherwise you have
- * to wait 2 minutes to restart after killing it.
- */
- if (reuseaddr(fd) == -1) {
- syslog(LOG_WARNING,
- "couldn't set SO_REUSEADDR option on transport");
- }
- }
-
- if (nconf->nc_semantics == NC_TPI_CLTS)
- tb.qlen = 0;
- else
- tb.qlen = backlog;
-
- /* LINTED pointer alignment */
- ntb = (struct t_bind *)t_alloc(fd, T_BIND, T_ALL);
- if (ntb == (struct t_bind *)NULL) {
- syslog(LOG_ERR, "t_alloc failed: t_errno %d, %m", t_errno);
- (void) t_close(fd);
- netdir_free((void *)addrlist, ND_ADDRLIST);
- return (-1);
- }
-
- tb.addr = *(addrlist->n_addrs); /* structure copy */
-
- if (t_bind(fd, &tb, ntb) == -1) {
- syslog(LOG_ERR, "t_bind failed: t_errno %d, %m", t_errno);
- (void) t_free((char *)ntb, T_BIND);
- netdir_free((void *)addrlist, ND_ADDRLIST);
- (void) t_close(fd);
- return (-1);
- }
-
- /* make sure we bound to the right address */
- if (tb.addr.len != ntb->addr.len ||
- memcmp(tb.addr.buf, ntb->addr.buf, tb.addr.len) != 0) {
- syslog(LOG_ERR, "t_bind to wrong address");
- (void) t_free((char *)ntb, T_BIND);
- netdir_free((void *)addrlist, ND_ADDRLIST);
- (void) t_close(fd);
- return (-1);
- }
-
- *addr = &ntb->addr;
- netdir_free((void *)addrlist, ND_ADDRLIST);
-
- if (strcmp(nconf->nc_proto, "tcp") == 0 ||
- strcmp(nconf->nc_proto, "tcp6") == 0) {
- /*
- * Disable the Nagle algorithm on TCP connections.
- * Connections accepted from this listener will
- * inherit the listener options.
- */
-
- /* LINTED pointer alignment */
- opt = (struct opthdr *)reqbuf;
- opt->level = IPPROTO_TCP;
- opt->name = TCP_NODELAY;
- opt->len = sizeof (int);
-
- /* LINTED pointer alignment */
- *(int *)((char *)opt + sizeof (*opt)) = 1;
-
- req.flags = T_NEGOTIATE;
- req.opt.len = sizeof (*opt) + opt->len;
- req.opt.buf = (char *)opt;
- resp.flags = 0;
- resp.opt.buf = reqbuf;
- resp.opt.maxlen = sizeof (reqbuf);
-
- if (t_optmgmt(fd, &req, &resp) < 0 ||
- resp.flags != T_SUCCESS) {
- syslog(LOG_ERR, "couldn't set NODELAY option for "
- "proto %s: t_errno = %d, %m", nconf->nc_proto,
- t_errno);
- }
- }
-
- return (fd);
-}
-
-
-/* ARGSUSED */
-static int
-bind_to_provider(char *provider, char *serv, struct netbuf **addr,
- struct netconfig **retnconf)
-{
- struct netconfig *nconf;
- NCONF_HANDLE *nc;
- struct nd_hostserv hs;
-
- hs.h_host = HOST_SELF;
- hs.h_serv = RDC_SERVICE; /* serv_name_to_port_name(serv); */
-
- if ((nc = setnetconfig()) == (NCONF_HANDLE *)NULL) {
- syslog(LOG_ERR, "setnetconfig failed: %m");
- return (-1);
- }
- while (nconf = getnetconfig(nc)) {
- if (OK_TPI_TYPE(nconf) &&
- strcmp(nconf->nc_device, provider) == 0) {
- *retnconf = nconf;
- return (rdcd_bindit(nconf, addr, &hs, listen_backlog));
- }
- }
- (void) endnetconfig(nc);
- if ((Is_ipv6present() && (strcmp(provider, "/dev/tcp6") == 0)) ||
- (!Is_ipv6present() && (strcmp(provider, "/dev/tcp") == 0)))
- syslog(LOG_ERR, "couldn't find netconfig entry for provider %s",
- provider);
- return (-1);
-}
-
-
-/*
- * For listen fd's index is always less than end_listen_fds.
- * It's value is equal to the number of open file descriptors after the
- * last listen end point was opened but before any connection was accepted.
- */
-static int
-is_listen_fd_index(int index)
-{
- return (index < end_listen_fds);
-}
-
-
-/*
- * Create an address mask appropriate for the transport.
- * The mask is used to obtain the host-specific part of
- * a network address when comparing addresses.
- * For an internet address the host-specific part is just
- * the 32 bit IP address and this part of the mask is set
- * to all-ones. The port number part of the mask is zeroes.
- */
-static int
-set_addrmask(int fd, struct netconfig *nconf, struct netbuf *mask)
-{
- struct t_info info;
-
- /*
- * Find the size of the address we need to mask.
- */
- if (t_getinfo(fd, &info) < 0) {
- t_error("t_getinfo");
- return (-1);
- }
- mask->len = mask->maxlen = info.addr;
- if (info.addr <= 0) {
- syslog(LOG_ERR, "set_addrmask: address size: %ld", info.addr);
- return (-1);
- }
-
- mask->buf = (char *)malloc(mask->len);
- if (mask->buf == NULL) {
- syslog(LOG_ERR, "set_addrmask: no memory");
- return (-1);
- }
- (void) memset(mask->buf, 0, mask->len); /* reset all mask bits */
-
- if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
- /*
- * Set the mask so that the port is ignored.
- */
- /* LINTED pointer alignment */
- ((struct sockaddr_in *)mask->buf)->sin_addr.s_addr =
- (in_addr_t)~0;
- /* LINTED pointer alignment */
- ((struct sockaddr_in *)mask->buf)->sin_family = (sa_family_t)~0;
- }
-#ifdef NC_INET6
- else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0) {
- /* LINTED pointer alignment */
- (void) memset(&((struct sockaddr_in6 *)mask->buf)->sin6_addr,
- (uchar_t)~0, sizeof (struct in6_addr));
- /* LINTED pointer alignment */
- ((struct sockaddr_in6 *)mask->buf)->sin6_family =
- (sa_family_t)~0;
- }
-#endif
- else {
- /*
- * Set all mask bits.
- */
- (void) memset(mask->buf, (uchar_t)~0, mask->len);
- }
- return (0);
-}
-
-#if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8)
-
-static int
-sndrsvcpool(int maxservers)
-{
- struct svcpool_args npa;
-
- npa.id = RDC_SVCPOOL_ID;
- npa.maxthreads = maxservers;
- npa.redline = 0;
- npa.qsize = 0;
- npa.timeout = 0;
- npa.stksize = 0;
- npa.max_same_xprt = 0;
- return (sndrsys(RDC_POOL_CREATE, &npa));
-}
-
-
-/*
- * The following stolen from cmd/fs.d/nfs/lib/thrpool.c
- */
-
-#include <thread.h>
-
-/*
- * Thread to call into the kernel and do work on behalf of SNDR/ncall-ip.
- */
-static void *
-svcstart(void *arg)
-{
- int id = (int)arg;
- int err;
-
- while ((err = sndrsys(RDC_POOL_RUN, &id)) != 0) {
- /*
- * Interrupted by a signal while in the kernel.
- * this process is still alive, try again.
- */
- if (err == EINTR)
- continue;
- else
- break;
- }
-
- /*
- * If we weren't interrupted by a signal, but did
- * return from the kernel, this thread's work is done,
- * and it should exit.
- */
- thr_exit(NULL);
- return (NULL);
-}
-
-/*
- * User-space "creator" thread. This thread blocks in the kernel
- * until new worker threads need to be created for the service
- * pool. On return to userspace, if there is no error, create a
- * new thread for the service pool.
- */
-static void *
-svcblock(void *arg)
-{
- int id = (int)arg;
-
- /* CONSTCOND */
- while (1) {
- thread_t tid;
- int err;
-
- /*
- * Call into the kernel, and hang out there
- * until a thread needs to be created.
- */
- if (err = sndrsys(RDC_POOL_WAIT, &id)) {
- if (err == ECANCELED || err == EBUSY)
- /*
- * If we get back ECANCELED, the service
- * pool is exiting, and we may as well
- * clean up this thread. If EBUSY is
- * returned, there's already a thread
- * looping on this pool, so we should
- * give up.
- */
- break;
- else
- continue;
- }
-
- (void) thr_create(NULL, NULL, svcstart, (void *)id,
- THR_BOUND | THR_DETACHED, &tid);
- }
-
- thr_exit(NULL);
- return (NULL);
-}
-
-static int
-svcwait(int id)
-{
- thread_t tid;
-
- /*
- * Create a bound thread to wait for kernel LWPs that
- * need to be created.
- */
- if (thr_create(NULL, NULL, svcblock, (void *)id,
- THR_BOUND | THR_DETACHED, &tid))
- return (1);
-
- return (0);
-}
-#endif /* Solaris 9+ */
diff --git a/usr/src/cmd/avs/rdc/sndrsubr.c b/usr/src/cmd/avs/rdc/sndrsubr.c
deleted file mode 100644
index 3f3e30b307..0000000000
--- a/usr/src/cmd/avs/rdc/sndrsubr.c
+++ /dev/null
@@ -1,463 +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 <stdio.h>
-#include <sys/mnttab.h>
-#include <errno.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <signal.h>
-
-#include <locale.h>
-#include <langinfo.h>
-#include <libintl.h>
-#include <stdarg.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 "rdcadm.h"
-
-
-int maxqfbas = MAXQFBAS;
-int maxqitems = MAXQITEMS;
-int autosync = AUTOSYNC;
-int asyncthr = ASYNCTHR;
-int qblock = QBLOCK;
-
-int
-mounted(char *device)
-{
- char target[NSC_MAXPATH];
- struct mnttab mntref;
- struct mnttab mntent;
- FILE *mntfp;
- int rdsk;
- char *s;
- int i;
-
- rdsk = i = 0;
- for (s = target; i < NSC_MAXPATH && (*s = *device++); i++) {
- if (*s == 'r' && rdsk == 0 && strncmp(device, "dsk/", 4) == 0)
- rdsk = 1;
- else
- s++;
- }
- *s = '\0';
-
- mntref.mnt_special = target;
- mntref.mnt_mountp = NULL;
- mntref.mnt_fstype = NULL;
- mntref.mnt_mntopts = NULL;
- mntref.mnt_time = NULL;
-
- mntfp = fopen(MNTTAB, "r");
-
- if (mntfp == NULL) {
- rdc_warn(NULL,
- gettext("can not check volume %s against mount table"),
- mntref.mnt_special);
- /* Assume the worst, that it is mounted */
- return (1);
- }
-
- if (getmntany(mntfp, &mntent, &mntref) != -1) {
- /* found something before EOF */
- (void) fclose(mntfp);
- return (1);
- }
-
- (void) fclose(mntfp);
- return (0);
-}
-
-
-/* Needs to match parsing code in rdcboot.c and rdcadm.c */
-char *
-rdc_decode_flag(int flag, int options)
-{
- static char str[32];
-
- switch (flag) {
- case (RDC_CMD_COPY):
- if (options & RDC_OPT_FULL)
- (void) strcpy(str, "-m");
- else
- (void) strcpy(str, "-u");
- if (options & RDC_OPT_REVERSE)
- (void) strcat(str, " -r");
- break;
-
- case (RDC_CMD_DISABLE):
- (void) strcpy(str, "-d");
- break;
-
- case (RDC_CMD_ENABLE):
- if (options & RDC_OPT_SETBMP)
- (void) strcpy(str, "-e");
- else
- (void) strcpy(str, "-E");
- break;
-
- case (RDC_CMD_LOG):
- (void) strcpy(str, "-l");
- break;
-
- case (RDC_CMD_HEALTH):
- (void) strcpy(str, "-H");
- break;
-
- case (RDC_CMD_WAIT):
- (void) strcpy(str, "-w");
- break;
-
- case (RDC_CMD_RECONFIG):
- (void) strcpy(str, "-R ...");
- break;
-
- case (RDC_CMD_TUNABLE):
- (void) strcpy(str, "");
- if (maxqfbas != MAXQFBAS)
- (void) strcat(str, " -F");
- if (maxqitems != MAXQITEMS)
- (void) strcat(str, " -W");
- if (autosync != AUTOSYNC)
- (void) strcat(str, " -a");
- if (asyncthr != ASYNCTHR)
- (void) strcat(str, " -A");
- if (qblock != QBLOCK)
- (void) strcat(str, " -D");
- break;
-
- case (RDC_CMD_SUSPEND):
- (void) strcpy(str, "-s");
- break;
-
- case (RDC_CMD_RESUME):
- (void) strcpy(str, "-r");
- break;
-
- case (RDC_CMD_RESET):
- (void) strcpy(str, "-R");
- break;
-
- case (RDC_CMD_ADDQ):
- (void) strcpy(str, "-q a");
- break;
-
- case (RDC_CMD_REMQ):
- (void) strcpy(str, "-q d");
- break;
-
- case (RDC_CMD_REPQ):
- (void) strcpy(str, "-q r");
- break;
-
- default:
- (void) strcpy(str, gettext("unknown"));
- break;
- }
-
- return (str);
-}
-
-
-static void
-rdc_msg(char *prefix, spcs_s_info_t *status, char *string, va_list ap)
-{
- if (status) {
- (void) fprintf(stderr, "Remote Mirror: %s\n", prefix);
- spcs_s_report(*status, stderr);
- } else {
- (void) fprintf(stderr, "%s: %s: ", program, prefix);
- }
-
- if (string && *string != '\0') {
- (void) vfprintf(stderr, string, ap);
- }
-
- (void) fprintf(stderr, "\n");
-}
-
-void
-rdc_err(spcs_s_info_t *status, char *string, ...)
-{
- va_list ap;
- va_start(ap, string);
-
- rdc_msg(gettext("Error"), status, string, ap);
-
- va_end(ap);
- exit(1);
-}
-
-void
-rdc_warn(spcs_s_info_t *status, char *string, ...)
-{
- va_list ap;
- va_start(ap, string);
-
- rdc_msg(gettext("warning"), status, string, ap);
-
- va_end(ap);
-}
-
-int
-rdc_get_maxsets(void)
-{
- rdc_status_t rdc_status;
- spcs_s_info_t ustatus;
- int rc;
-
- rdc_status.nset = 0;
- 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);
- return (rdc_status.maxsets);
-}
-
-/*
- * Look up a set in libcfg to find the setnumber.
- *
- * ASSUMPTIONS:
- * - a valid cfg handle
- *
- * INPUTS:
- * cfg - cfg handle
- * tohost - secondary hostname
- * tofile - secondary volume
- *
- * OUTPUTS:
- * set number if found, otherwise -1 for an error
- */
-int
-find_setnumber_in_libcfg(CFGFILE *cfg, char *ctag, char *tohost, char *tofile)
-{
- int setnumber;
- int entries, rc;
- char *buf, *secondary, *shost;
- char **entry;
- char *cnode;
- int offset = 0;
-
- if (cfg == NULL) {
-#ifdef DEBUG
- rdc_warn(NULL, "cfg is NULL while looking up set number");
-#endif
- return (-1);
- }
-
- entries = cfg_get_section(cfg, &entry, "sndr");
-
- rc = -1;
- for (setnumber = 1; setnumber <= entries; setnumber++) {
- buf = entry[setnumber - 1];
-
- (void) strtok(buf, " "); /* phost */
- (void) strtok(NULL, " "); /* primary */
- (void) strtok(NULL, " "); /* pbitmap */
- shost = strtok(NULL, " ");
- secondary = strtok(NULL, " ");
-
- if (ctag && *ctag) {
- (void) strtok(NULL, " "); /* sbitmap */
- (void) strtok(NULL, " "); /* type */
- (void) strtok(NULL, " "); /* mode */
- (void) strtok(NULL, " "); /* group */
- cnode = strtok(NULL, " ");
-
- if (ctag && strcmp(cnode, ctag) != 0) {
- /* filter this out */
- ++offset;
- continue;
- }
- }
-
- /* Check secondary volume name first, will get less hits */
- if (strcmp(secondary, tofile) != 0) {
- free(buf);
- continue;
- }
-
- if (strcmp(shost, tohost) == 0) {
- free(buf);
- rc = setnumber - offset;
- break;
- }
-
- free(buf);
- }
-
- while (setnumber < entries)
- free(entry[setnumber++]);
- if (entries)
- free(entry);
-
- return (rc);
-}
-
-void
-get_group_diskq(CFGFILE *cfg, char *group, char *diskq)
-{
- int i;
- char key[CFG_MAX_KEY];
- char buf[CFG_MAX_BUF];
-
- if (*group == '\0')
- return;
- for (i = 1; ; i++) {
- bzero(&key, sizeof (key));
- bzero(&buf, sizeof (buf));
- (void) sprintf(key, "sndr.set%d.group", i);
- if (cfg_get_cstring(cfg, key, &buf, sizeof (buf)) < 0)
- break;
- if (strncmp(group, buf, sizeof (buf)) == 0) {
- (void) sprintf(key, "sndr.set%d.diskq", i);
- if (cfg_get_cstring(cfg, key, diskq, CFG_MAX_BUF) < 0) {
- rdc_warn(NULL, gettext("unable to retrieve "
- "group %s's disk queue"), group);
- }
- }
- }
-}
-
-int
-get_cfg_setid(CFGFILE *cfg, char *ctag, char *tohost, char *tofile)
-{
- int setnum = 0;
- int close_cfg = 0;
- char key[CFG_MAX_KEY];
- char setid[64];
-
- if (cfg == NULL) {
- close_cfg = 1;
- if ((cfg = cfg_open(NULL)) == NULL) {
- return (-1); /* message printed by caller */
- }
- if (!cfg_lock(cfg, CFG_RDLOCK)) {
- cfg_close(cfg);
- return (-1);
- }
- }
- setnum = find_setnumber_in_libcfg(cfg, ctag, tohost, tofile);
- if (setnum < 0)
- return (setnum);
-
- (void) snprintf(key, CFG_MAX_KEY, "sndr.set%d.options", setnum);
- if (cfg_get_single_option(cfg, CFG_SEC_CONF, key, "setid",
- setid, sizeof (setid)) < 0) {
- if (close_cfg)
- cfg_close(cfg);
-
- spcs_log("sndr", NULL,
- gettext("%s unable to get unique setid "
- "for %s:%s"), program, tohost, tofile);
- return (-1);
-
- }
- if (close_cfg)
- cfg_close(cfg);
-
- return (atoi(setid));
-
-}
-
-int
-get_new_cfg_setid(CFGFILE *cfg)
-{
- int setid;
- char buf[CFG_MAX_BUF];
- char *ctag;
-
- /* If in a Sun Cluster, SetIDs need to have a ctag */
- if ((ctag = cfg_get_resource(cfg)) != NULL) {
- ctag = strdup(ctag);
- cfg_resource(cfg, "setid-ctag");
- }
-
- if (cfg_get_cstring(cfg, "setid.set1.value", buf, CFG_MAX_BUF) < 0) {
- setid = 1;
- if (cfg_put_cstring(cfg, "setid", "1", CFG_MAX_BUF) < 0) {
- rdc_err(NULL, "Unable to store new setid");
- }
- } else {
- setid = atoi(buf);
- setid++;
- if (setid <= 0) {
- setid = 1;
- }
- }
-
- bzero(&buf, CFG_MAX_BUF);
- (void) snprintf(buf, sizeof (buf), "%d", setid);
- if (cfg_put_cstring(cfg, "setid.set1.value", buf, CFG_MAX_BUF) < 0) {
- rdc_err(NULL, "Unable to store new setid");
- }
-
- /* Restore old ctag if in a Sun Cluster */
- if (ctag) {
- cfg_resource(cfg, ctag);
- free(ctag);
- }
-
- return (setid);
-}
-
-sigset_t origmask;
-
-void
-block_sigs(void)
-{
- sigset_t allsigs;
-
- (void) sigfillset(&allsigs);
- if (sigprocmask(SIG_BLOCK, &allsigs, &origmask) < 0)
- rdc_warn(NULL, gettext("Unable to block signals"));
-}
-
-void
-unblock_sigs(void)
-{
- if (sigprocmask(SIG_SETMASK, &origmask, NULL) < 0)
- rdc_warn(NULL, gettext("Unable to unblock signals"));
-
-}
diff --git a/usr/src/cmd/avs/rdc/sndrsyncd.c b/usr/src/cmd/avs/rdc/sndrsyncd.c
deleted file mode 100644
index 5f2c56d1b1..0000000000
--- a/usr/src/cmd/avs/rdc/sndrsyncd.c
+++ /dev/null
@@ -1,1695 +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/wait.h>
-#include <stdio.h>
-#include <errno.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <thread.h>
-
-#include <locale.h>
-#include <langinfo.h>
-#include <libintl.h>
-#include <stdarg.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/nsctl/librdc.h>
-
-#include "rdcadm.h"
-
-
-#define RDCADM "/usr/sbin/sndradm"
-#define IIADM "/usr/sbin/iiadm"
-
-#define UPDATE "update"
-#define NOUPDATE "noupdate"
-
-#define RESYNC_SLEEP (3 * 60) /* Three minutes */
-#define MAIN_SLEEP (5 * 60) /* Five minutes */
-#define CFG_WAIT_SLEEP (5) /* 5 sec */
-
-#define MAXHOSTS 1024
-mutex_t cfglock = DEFAULTMUTEX;
-#define LOCKCFG() (void) mutex_lock(&cfglock);
-#define UNLOCKCFG() (void) mutex_unlock(&cfglock);
-
-typedef struct host_list_s {
- char *hosts[MAXHOSTS];
- int numhosts;
- int configured[MAXHOSTS];
- mutex_t hosts_mutex;
-} host_list_t;
-
-host_list_t *host_list;
-
-extern char *basename(char *);
-int rdc_maxsets;
-char *program;
-
-static int clustered = 0;
-
-int isnewhost(char *host);
-void *wait_sync_event();
-void *wait_link_down(void *host);
-void rdc_sync(char *tohost);
-void remove_from_hostlist(char *host);
-void sync_start(char *master);
-void sync_complete(char *master);
-void cleanup_hostlist();
-void group_start(char *group);
-void group_complete(char *group);
-
-
-void
-init_host_list(void)
-{
- host_list = calloc(1, sizeof (host_list_t));
- if (host_list == NULL) {
- spcs_log("sndr", NULL,
- gettext("host list not initialized, cannot run"));
- rdc_err(NULL, gettext("host list not initialized, cannot run"));
- }
- (void) mutex_init(&host_list->hosts_mutex, USYNC_THREAD, NULL);
-}
-
-/* ARGSUSED */
-#ifdef lint
-void
-sndrsyncd_lintmain(argc, argv)
-#else
-int
-main(argc, argv)
-#endif
-int argc;
-char **argv;
-{
- rdc_status_t *rdc_info;
- int size;
- int i;
- pid_t pid;
- spcs_s_info_t ustatus;
- int rc, trc;
- int first = 0;
- char *required;
-
- (void) setlocale(LC_ALL, "");
- (void) textdomain("rdc");
-
- ustatus = spcs_s_ucreate();
-
- program = basename(argv[0]);
-
- init_host_list();
-
- rc = rdc_check_release(&required);
- if (rc < 0) {
- rdc_err(NULL,
- gettext("unable to determine the current "
- "Solaris release: %s\n"), strerror(errno));
- /* NOTREACHED */
- } else if (rc == FALSE) {
- rdc_err(NULL,
- gettext("incorrect Solaris release (requires %s)\n"),
- required);
- /* NOTREACHED */
- }
-
- clustered = cfg_iscluster();
- if (clustered < 0) {
- rdc_err(NULL, gettext("unable to ascertain environment"));
- }
-
- rdc_maxsets = rdc_get_maxsets();
- if (rdc_maxsets == -1) {
- spcs_log("sndr", NULL,
- gettext("%s: unable to get maxsets value from kernel"),
- program);
- rdc_err(NULL,
- gettext("unable to get maxsets value from kernel"));
- }
- size = sizeof (rdc_status_t) + (sizeof (rdc_set_t) * (rdc_maxsets - 1));
- rdc_info = malloc(size);
- if (rdc_info == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s: unable to allocate %ld bytes"),
- program, size);
- rdc_err(NULL,
- gettext("unable to allocate %ld bytes"), size);
- }
- bzero(rdc_info, size);
-
- rdc_info->nset = rdc_maxsets;
-
- /*
- * Fork off a child that becomes the daemon.
- */
- if ((pid = fork()) > 0)
- exit(0);
- else if (pid < 0) {
- spcs_log("sndr", NULL,
- gettext("%s: cannot fork: %s"),
- program, strerror(errno));
- rdc_err(NULL, gettext("cannot fork: %s\n"),
- strerror(errno));
- }
-
- /*
- * In child - become daemon.
- */
-
- for (i = 0; i < 3; i++)
- (void) close(i);
-
- (void) open("/dev/console", O_WRONLY|O_APPEND);
- (void) dup(0);
- (void) dup(0);
- (void) close(0);
-
- (void) setpgrp();
-
- (void) setlocale(LC_ALL, "");
- (void) textdomain("rdc");
-
- /* launch a thread to wait for sync start and sync stop events */
-
- if ((trc = thr_create(NULL, 0, wait_sync_event, NULL,
- THR_BOUND|THR_DETACHED, NULL)) != 0) {
- spcs_log("sndr", NULL,
- gettext("%s: unable to create thread wait_sync_event"),
- program);
- rdc_warn(NULL,
- gettext("%s unable to create thread wait_sync_event"),
- program);
- } else {
-#ifdef DEBUG
- spcs_log("sndr", NULL,
- gettext("%s: thread wait_sync_event started"), program);
-#endif
- ;
- }
-
- for (;;) {
- if (!first) {
- first++;
- (void) sleep(15);
- } else
- (void) sleep(MAIN_SLEEP);
-
- bzero(rdc_info, size);
- rdc_info->nset = rdc_maxsets;
- if (RDC_IOCTL(RDC_STATUS, rdc_info, 0, 0, 0, 0, ustatus)
- != SPCS_S_OK) {
- spcs_log("sndr", &ustatus,
- gettext("%s: status ioctl"),
- program);
- rdc_warn(&ustatus, gettext("status ioctl"));
- continue;
- }
-
- cleanup_hostlist(rdc_info); /* remove non-existent hosts */
-
- /*
- * Check all enabled sets to see if a new remote host has
- * appeared.
- */
- for (i = 0; i < rdc_maxsets; i++) {
- if (!(rdc_info->rdc_set[i].flags & RDC_ENABLED))
- continue;
- /* spawn a new thread for each new host found */
- if (isnewhost(rdc_info->rdc_set[i].secondary.intf)) {
- /*
- * right now, we could be here before
- * the database did the write for this set
- * I could check the lock on the database
- * but I am just going to give up some time here
- * instead. Why do the allocations etc, etc
- * if the set is enabled in the kernel and not
- * in the config, we know that this set has the
- * lock. Why bother adding more contention to
- * the lock.
- * this is a daemon, afterall. its got time
- */
- (void) sleep(CFG_WAIT_SLEEP);
-
- spcs_log("sndr", NULL,
- gettext("%s: new host found (%s) starting "
- "its autosync thread"), program,
- rdc_info->rdc_set[i].secondary.intf);
-
- trc = thr_create(NULL, 0, wait_link_down,
- (void *) rdc_info->rdc_set[i].\
-secondary.intf, THR_BOUND|THR_DETACHED, NULL);
-
- if (trc != 0) {
- spcs_log("sndr", NULL,
- gettext(
- "%s create new autosync "
- "thread failed"), program);
- rdc_warn(NULL, gettext(
- "%s create new autosync "
- "thread failed"), program);
- }
- }
- }
- }
- /* NOTREACHED */
-}
-
-
-/*
- * The kernel wakes up this function every time it detects the link to the
- * specified host has dropped.
- */
-void *
-wait_link_down(void *thehost)
-{
- char *host = (char *)thehost;
- char tmphost[MAX_RDC_HOST_SIZE] = { '\0' };
- spcs_s_info_t ustatus;
-
- if (host)
- (void) strncpy(tmphost, host, MAX_RDC_HOST_SIZE);
-
- ustatus = spcs_s_ucreate();
-
- /* Never give up */
- for (;;) {
-#ifdef DEBUG
- spcs_log("sndr", NULL,
- gettext("%s: awaiting link down ioctl for %s"),
- program, host[0] == '\0' ? tmphost : host);
-#endif
- if (RDC_IOCTL(RDC_LINK_DOWN, host, 0, 0, 0, 0, ustatus)
- != SPCS_S_OK) {
- spcs_log("sndr", &ustatus,
- gettext("%s: link down ioctl"),
- program);
- rdc_warn(&ustatus, gettext("link down ioctl"));
- continue;
- }
-#ifdef DEBUG
-
- spcs_log("sndr", NULL,
- gettext("%s: received link down ioctl for %s"),
- program, host[0] == '\0' ? tmphost : host);
-#endif
- rdc_sync(host[0] == '\0' ? tmphost : host);
- }
- /* LINTED */
-}
-
-
-/*
- * Called when the link to the specified host has dropped.
- * For all Remote Mirror sets using the link that have autosync on,
- * issue rdcadm -u commands until they complete successfully.
- */
-void
-rdc_sync(char *tohost)
-{
- rdc_set_t *rdc_set = NULL;
- int *sync_done = NULL;
- int sets = 0;
- int syncs_done = 0;
- char cmd[256];
- rdc_config_t parms = { 0 };
- spcs_s_info_t ustatus;
- int i;
- int setnumber;
- int numfound = 0;
- char buf[CFG_MAX_BUF];
- char key[CFG_MAX_KEY];
- CFGFILE *cfg = NULL;
- int size;
- int first = 0;
- int death = 0;
- int cfglocked = 0;
-
- ustatus = spcs_s_ucreate();
-
- size = sizeof (rdc_set_t) * rdc_maxsets;
- rdc_set = malloc(size);
- if (rdc_set == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s: unable to allocate %ld bytes"),
- program, size);
- rdc_warn(NULL,
- gettext("unable to allocate %ld bytes"), size);
- goto done;
- }
- bzero(rdc_set, size);
- size = sizeof (int) * rdc_maxsets;
- sync_done = malloc(size);
- if (sync_done == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s: unable to allocate %ld bytes"),
- program, size);
- rdc_warn(NULL,
- gettext("unable to allocate %ld bytes"), size);
- goto done;
- }
- bzero(sync_done, size);
-
- /*
- * Get all sndr entries with shost matching tohost, and save the
- * details in an array.
- */
- for (i = 0; i < rdc_maxsets; i++) {
- setnumber = i + 1;
- bzero(buf, sizeof (buf));
- bzero(key, sizeof (key));
-
- (void) snprintf(key, sizeof (key), "sndr.set%d.shost",
- setnumber);
-
- if (!cfglocked) {
- LOCKCFG();
- if ((cfg = cfg_open(NULL)) == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s: error opening config"),
- program);
-
- rdc_warn(NULL,
- gettext("error opening config"));
- UNLOCKCFG();
- goto done;
- }
-
- if (!cfg_lock(cfg, CFG_RDLOCK)) {
- spcs_log("sndr", NULL,
- gettext("%s: error locking config"),
- program);
- rdc_warn(NULL, gettext("error locking config"));
- goto done;
- }
- }
-
- cfglocked = 1;
-
- if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
- if (numfound == 0) /* no matching hosts */
- death = 1; /* thread will exit */
- break;
- }
- if (strcmp(buf, tohost) != 0)
- continue;
-
- numfound++;
- (void) strncpy(rdc_set[sets].secondary.intf, buf,
- MAX_RDC_HOST_SIZE);
-
- /* Got a matching entry */
-
- (void) snprintf(key, sizeof (key), "sndr.set%d.phost",
- setnumber);
- if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
- break;
- (void) strncpy(rdc_set[sets].primary.intf, buf,
- MAX_RDC_HOST_SIZE);
-
- (void) snprintf(key, sizeof (key), "sndr.set%d.primary",
- setnumber);
- if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
- break;
- (void) strncpy(rdc_set[sets].primary.file, buf, NSC_MAXPATH);
-
- (void) snprintf(key, sizeof (key), "sndr.set%d.secondary",
- setnumber);
- if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
- break;
- (void) strncpy(rdc_set[sets].secondary.file, buf, NSC_MAXPATH);
-
- parms.command = RDC_CMD_STATUS;
- bcopy((void *)(&rdc_set[sets]), (void *)(&parms.rdc_set[0]),
- sizeof (rdc_set_t));
-
- /*
- * release cfg before diving into the kernel
- * this prevents a possible deadlock when doing
- * a reverse sync whick will wake up the sync_event
- * thread which will try and iiadm -c and hang
- * because we still have the cfg_lock. the timed
- * wait cv in the kernel will fail the sync and things
- * will undeadlock.
- */
-
- cfg_close(cfg);
- cfg = NULL;
- cfglocked = 0;
- UNLOCKCFG();
-
- if (RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus) < 0) {
- continue;
- }
- if ((parms.rdc_set[0].autosync == 0) ||
- (!(parms.rdc_set[0].flags & RDC_LOGGING))) {
- continue;
- }
-
- /* Found a suitable set with autosync on, in logging mode */
- sets++;
- }
-
- if (cfg) {
- cfg_close(cfg);
- cfg = NULL;
- UNLOCKCFG();
- }
-
- if (sets == 0) {
-#ifdef DEBUG
- spcs_log("sndr", NULL,
- gettext("%s: no sets requiring autosync found for %s"),
- program, tohost);
-#endif
- if (death) {
- spcs_log("sndr", NULL,
- gettext("%s: autosync thread stopping for %s "
- "(host deconfigured)"), program, tohost);
- }
- goto done;
- }
-
- /* Keep issuing rdcadm -u commands until they have all completed */
- for (;;) {
- if (!first)
- first++;
- else
- (void) sleep(RESYNC_SLEEP);
-
- /* Issue rdcadm -u commands for all remaining sets */
- for (i = 0; i < sets; i++) {
- if (sync_done[i])
- continue;
-
- /*
- * Need to check if autosync was turned off for a set
- * while we were sleeping. We could have the case where
- * an update sync failed and autosync was disabled
- * while we were sleeping and didn't detect the disable.
- * See BugID 4814213.
- */
- parms.command = RDC_CMD_STATUS;
- bcopy((void *)(&rdc_set[i]),
- (void *)(&parms.rdc_set[0]), sizeof (rdc_set_t));
- if (RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0,
- ustatus) < 0) {
- spcs_log("sndr", &ustatus, gettext("%s: "
- "status not available for %s:%s, stopping "
- "this autosync attempt"), program, tohost,
- rdc_set[i].secondary.file);
- sync_done[i] = 1;
- syncs_done++;
- continue;
- }
- if (!(parms.rdc_set[0].autosync)) {
-#ifdef DEBUG
- spcs_log("sndr", NULL, gettext("%s: autosync disabled during sleep, "
- "stopping attempt for set %s:%s"), program, tohost,
- rdc_set[i].secondary.file);
-#endif
- sync_done[i] = 1;
- syncs_done++;
- continue;
- }
-
- (void) sprintf(cmd, "%s -un %s:%s", RDCADM, tohost,
- rdc_set[i].secondary.file);
- spcs_log("sndr", NULL,
- gettext("%s: issuing update sync for %s:%s"),
- program, tohost, rdc_set[i].secondary.file);
- (void) system(cmd);
- }
-
- /* Issue rdcadm -w commands to wait for updates to finish */
- for (i = 0; i < sets; i++) {
- if (sync_done[i])
- continue;
-
- (void) sprintf(cmd, "%s -wn %s:%s", RDCADM, tohost,
- rdc_set[i].secondary.file);
- spcs_log("sndr", NULL,
- gettext("%s: issuing wait for %s:%s"),
- program, tohost, rdc_set[i].secondary.file);
-
- (void) system(cmd);
-
- parms.command = RDC_CMD_STATUS;
- bcopy((void *)(&rdc_set[i]),
- (void *)(&parms.rdc_set[0]), sizeof (rdc_set_t));
-
- if (RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0,
- ustatus) < 0) {
- spcs_log("sndr", &ustatus,
- gettext("%s: status not available for "
- "%s:%s, stopping this autosync attempt"),
- program, tohost, rdc_set[i].secondary.file);
- sync_done[i] = 1;
- syncs_done++;
- continue;
- }
- /* Check if completed OK, failed or autosync off */
- if (!(parms.rdc_set[0].autosync) ||
- !(parms.rdc_set[0].flags & RDC_LOGGING) &&
- !(parms.rdc_set[0].flags & RDC_SYNCING)) {
- sync_done[i] = 1;
- syncs_done++;
- }
- }
-
- if (syncs_done == sets)
- break; /* All completed OK */
- }
-
-done:
- if (cfg) {
- cfg_close(cfg);
- UNLOCKCFG();
- }
- spcs_s_ufree(&ustatus);
- if (sync_done)
- free(sync_done);
- if (rdc_set)
- free(rdc_set);
- if (death) { /* bye bye */
- /*
- * if perhaps we lost some race, lets remove this entry from
- * the list. Then, if something did go wrong, and we did kill
- * a valid thread, it will be detected on the next go around
- * of the thread who is looking for new hosts to spawn threads
- */
-
- remove_from_hostlist(tohost);
- thr_exit(0);
- }
-
- (void) sleep(RESYNC_SLEEP);
-}
-
-/*
- * Wait for notification by the kernel of a sync start or a sync completed OK
- */
-void *
-wait_sync_event()
-{
- spcs_s_info_t ustatus;
- char master[NSC_MAXPATH];
- char group[NSC_MAXPATH];
- int state;
-
- ustatus = spcs_s_ucreate();
-
- master[0] = '\0';
- group[0] = '\0';
-
- /* Never give up */
- for (;;) {
- /* Kernel tells us which volume and group the event is for */
- state = RDC_IOCTL(RDC_SYNC_EVENT, master, group, 0, 0, 0,
- ustatus);
- if (state < SPCS_S_OK) {
- if (errno != EAGAIN) {
- spcs_log("sndr", &ustatus,
- gettext("%s: update ioctl"),
- program);
- rdc_warn(&ustatus, gettext("update ioctl"));
- continue;
- }
- master[0] = '\0';
- continue;
- }
-
- /*
- * If target is mounted at the start of a sync or reverse sync,
- * return a negative ack.
- */
- if ((state == RDC_SYNC_START || state == RDC_RSYNC_START) &&
- mounted(master)) {
- spcs_log("sndr", NULL,
- gettext("%s: %s has a file system mounted"),
- program, master);
- rdc_warn(NULL,
- gettext("%s has a file system mounted"),
- master);
- master[0] = '\0'; /* negative ack */
- continue;
- }
-
- switch (state) {
- case RDC_SYNC_START:
- if (group[0])
- group_start(group);
- else
- sync_start(master);
- break;
-
- case RDC_SYNC_DONE:
- if (group[0])
- group_complete(group);
- else
- sync_complete(master);
- break;
-
- default:
- break;
- }
- }
- /* LINTED */
-}
-
-
-/*
- * A sync has completed OK to a volume not belonging to a group.
- * Set the state of the ndr_ii config entry to "update".
- */
-void
-sync_complete(char *master)
-{
- CFGFILE *cfg = NULL;
- char buf[CFG_MAX_BUF];
- char key[CFG_MAX_KEY];
- int i;
- int setnumber;
- int sev;
-
- LOCKCFG();
- if ((cfg = cfg_open(NULL)) == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s: error opening config"),
- program);
- rdc_warn(NULL, gettext("error opening config"));
- UNLOCKCFG();
- return;
- }
- if (!cfg_lock(cfg, CFG_WRLOCK)) {
- spcs_log("sndr", NULL,
- gettext("%s: error locking config"),
- program);
- rdc_warn(NULL, gettext("error locking config"));
- cfg_close(cfg);
- UNLOCKCFG();
- return;
- }
-
- /* get ndr_ii entries until a match is found */
- 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;
-
- /* Found the matching entry */
-
- /*
- * Set state to "update" so that starting another sync will
- * cause a new Point-in-Time Copy snapshot to be taken.
- */
- (void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
- setnumber);
- if ((cfg_put_cstring(cfg, key, UPDATE, strlen(UPDATE)) < 0) ||
- (cfg_commit(cfg) < 0)) {
- spcs_log("sndr", NULL,
- gettext("%s: unable to update \"%s\" "
- "in configuration storage: %s"),
- program, buf, cfg_error(&sev));
- rdc_warn(NULL,
- gettext("unable to update \"%s\" "
- "in configuration storage: %s"),
- buf, cfg_error(&sev));
- }
- break;
- }
-
- cfg_close(cfg);
- UNLOCKCFG();
-}
-
-
-/*
- * Starting a sync to the specified master volume.
- * Check the ndr_ii config entries to see if a Point-in-Time Copy
- * snapshot should be taken.
- */
-void
-sync_start(char *master)
-{
- char cmd[256];
- char buf[CFG_MAX_BUF];
- char key[CFG_MAX_KEY];
- CFGFILE *cfg = NULL;
- int i;
- int setnumber;
- int found;
- int sev;
- char shadow[NSC_MAXPATH];
- char bitmap[NSC_MAXPATH];
- char *ctag = NULL;
-
- LOCKCFG();
- if ((cfg = cfg_open(NULL)) == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s: error opening config"),
- program);
- rdc_warn(NULL,
- gettext("error opening config"));
- UNLOCKCFG();
- return;
- }
- if (!cfg_lock(cfg, CFG_RDLOCK)) {
- spcs_log("sndr", NULL,
- gettext("%s: error locking config"),
- program);
- rdc_warn(NULL, gettext("error locking config"));
- cfg_close(cfg);
- UNLOCKCFG();
- return;
- }
-
- found = 0;
- /* get ndr_ii entries until a match is found */
- 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;
- (void) strncpy(shadow, buf, NSC_MAXPATH);
-
- (void) snprintf(key, sizeof (key), "ndr_ii.set%d.bitmap",
- setnumber);
- if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
- break;
- (void) strncpy(bitmap, buf, NSC_MAXPATH);
-
- (void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
- setnumber);
- if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
- break;
-
- /*
- * If an PIT snapshot has already been taken, and syncing did
- * not complete, the state will be "noupdate", to indicate we
- * should not take another one at this point.
- */
- if (strcmp(buf, NOUPDATE) != 0)
- found = 1;
-
- break;
- }
-
- if (!found) {
- cfg_close(cfg);
- UNLOCKCFG();
- return;
- }
-
- found = 0;
- /* get ii entries until a match is found */
- for (i = 0; ; i++) {
- setnumber = i + 1;
-
- (void) snprintf(key, sizeof (key), "ii.set%d.shadow",
- setnumber);
- if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
- break;
- if (strcmp(buf, shadow) != 0)
- continue;
-
- /* Matching shadow found, so ii already enabled */
- found = 1;
- break;
- }
-
- if (found) {
- /* Already PIT enabled, so just take a snapshot */
-
- /* Get cluster tag of matching entry */
- (void) snprintf(key, sizeof (key), "ii.set%d.cnode", setnumber);
- if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) >= 0)
- if ((strlen(buf) == 0) || (buf[0] == '-'))
- ctag = "-C local";
- else
- ctag = "";
- (void) sprintf(cmd, "%s %s -u s %s", IIADM, ctag, shadow);
- } else {
- /*
- * If clustered, need to enable PIT Copy sets in the same
- * cluster as the Remote Mirror set
- */
-
- if (clustered) {
- /* Find a RM set with master as the local volume */
-
- for (i = 0; i < rdc_maxsets; i++) {
- setnumber = i + 1;
- (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.primary", setnumber);
- else
- (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, master) != 0)
- continue;
-
- /* Get cluster tag of matching entry */
-
- (void) snprintf(key, sizeof (key),
- "sndr.set%d.cnode", setnumber);
- if (cfg_get_cstring(cfg, key, buf,
- CFG_MAX_BUF) < 0)
- break;
- if ((strlen(buf) == 0) || (buf[0] == '-'))
- ctag = strdup("local");
- else
- ctag = strdup(buf);
- break;
- }
- }
-
- /* Not already enabled, so enable a dependent */
- if (ctag) {
- (void) sprintf(cmd, "%s -C %s -e dep %s %s %s", IIADM,
- ctag, master, shadow, bitmap);
- free(ctag);
- } else
- (void) sprintf(cmd, "%s -e dep %s %s %s", IIADM, master,
- shadow, bitmap);
- }
-
- cfg_close(cfg);
-
- if (system(cmd) != 0) {
- spcs_log("sndr", NULL,
- gettext("Point-in-Time Copy snapshot failed for %s %s %s."
- " Please check validity of ndr_ii entry"),
- master, shadow, bitmap);
- cfg_close(cfg);
- UNLOCKCFG();
- return;
- }
-
- /*
- * PIT Copy enable or update was fine, so update the ndr_ii entry
- * to "noupdate", to prevent invalid point in time copies.
- */
-
- if ((cfg = cfg_open(NULL)) == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s: error opening config"),
- program);
- rdc_warn(NULL,
- gettext("error opening config"));
- UNLOCKCFG();
- return;
- }
- if (!cfg_lock(cfg, CFG_WRLOCK)) {
- spcs_log("sndr", NULL,
- gettext("%s: error locking config"),
- program);
- rdc_warn(NULL, gettext("error locking config"));
- cfg_close(cfg);
- UNLOCKCFG();
- return;
- }
-
- /* get ndr_ii entries until a match is found */
- for (i = 0; ; i++) {
- setnumber = i + 1;
-
- (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;
-
- /* Found the matching entry */
-
- (void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
- setnumber);
- if ((cfg_put_cstring(cfg, key, NOUPDATE,
- strlen(NOUPDATE)) < 0) || (cfg_commit(cfg) < 0)) {
- spcs_log("sndr", NULL,
- gettext("%s: unable to update \"%s\" "
- "in configuration storage: %s"),
- program, buf, cfg_error(&sev));
- rdc_warn(NULL,
- gettext("unable to update \"%s\" "
- "in configuration storage: %s"),
- buf, cfg_error(&sev));
- }
- break;
- }
- cfg_close(cfg);
- UNLOCKCFG();
-}
-
-void
-cleanup_hostlist(rdc_status_t *rdc_info)
-{
- int i, j, k;
- char *host, *exhost;
-
-
- (void) mutex_lock(&host_list->hosts_mutex);
- for (i = 0; i < host_list->numhosts; i++) {
- int found = 0;
- for (j = 0; (j < rdc_maxsets) && !found; j++) {
- if (!rdc_info->rdc_set[j].flags & RDC_ENABLED)
- continue;
- if ((!host_list->configured[i]) ||
- (host_list->hosts[i] == NULL)) {
- (void) mutex_unlock(&host_list->hosts_mutex);
- return;
- }
-
- host = rdc_info->rdc_set[j].secondary.intf;
- if (strcmp(host_list->hosts[i], host) == 0)
- found++;
- }
- if (j == rdc_maxsets) {
- /*
- * this set is not in the kernel, so remove from list
- */
- exhost = host_list->hosts[i];
- if (exhost) {
- free(exhost);
- exhost = NULL;
- }
-
- k = i;
- while (k < host_list->numhosts) {
- host_list->hosts[k] = k < host_list->numhosts - 1 ?
- host_list->hosts[k+1] : NULL;
- k++;
- }
- host_list->numhosts--;
-
- bcopy(&host_list->configured[i+1],
- &host_list->configured[i],
- (MAXHOSTS - i + 1) * sizeof (int));
- host_list->configured[MAXHOSTS - 1] = 0;
- }
- }
- (void) mutex_unlock(&host_list->hosts_mutex);
-}
-
-/*
- * explicity remove a host from the host list
- * also update the configured array
- * called in rdc_sync, just before exiting a thread.
- */
-void
-remove_from_hostlist(char *host)
-{
- int i, k;
- char *exhost;
-
- /* why bother? */
- if ((!host) || (host[0] == '\0'))
- return;
-
- (void) mutex_lock(&host_list->hosts_mutex);
- for (i = 0; i < host_list->numhosts; i++) {
- if (strcmp(host, host_list->hosts[i]) == 0) { /* found it */
- exhost = host_list->hosts[i];
- if (exhost) {
- free(exhost);
- exhost = NULL;
- }
- k = i;
- while (k < host_list->numhosts) {
- host_list->hosts[k] = k < host_list->numhosts - 1 ?
- host_list->hosts[k+1] : NULL;
- k++;
- }
- host_list->numhosts--;
- bcopy(&host_list->configured[i+1],
- &host_list->configured[i],
- (MAXHOSTS - i + 1) * sizeof (int));
- host_list->configured[MAXHOSTS - 1] = 0;
- }
-
- }
- (void) mutex_unlock(&host_list->hosts_mutex);
-}
-/*
- * Check to see if this host isn't in our list, so needs a new rdcsyncd proc
- */
-int
-isnewhost(char *host)
-{
- int i;
- int new;
-
- if (self_check(host)) {
- return (0);
- }
-
- (void) mutex_lock(&host_list->hosts_mutex);
- new = 1;
- for (i = 0; i < MAXHOSTS; i++) {
- if (host_list->configured[i] == 0) {
- host_list->configured[i] = 1;
- host_list->hosts[i] = strdup(host);
- host_list->numhosts++;
- break;
- }
- if (strcmp(host, host_list->hosts[i]) == 0) {
- new = 0;
- break;
- }
- }
- (void) mutex_unlock(&host_list->hosts_mutex);
- if (i == MAXHOSTS)
- new = 0;
- return (new);
-}
-
-
-/*
- * Look for a matching volume name in our remembered list.
- */
-int
-volume_match(char *buf, char **volume_list, int volumes)
-{
- int i;
- char *vol;
-
- for (i = 0; i < volumes; i++) {
- vol = volume_list[i];
- if (strcmp(buf, vol) == 0) {
- return (1);
- }
- }
- return (0);
-}
-
-
-/*
- * A sync has completed to a group. We can only update the ndr_ii entries
- * if all the members of the group have completed their syncs OK.
- * It would be bad to allow some members of the group to have PIT Copy snapshots
- * taken and others not, as they need to be consistent.
- */
-void
-group_complete(char *group)
-{
- char **volumes = NULL;
- spcs_s_info_t ustatus;
- rdc_config_t parms = { 0 };
- char buf[CFG_MAX_BUF];
- char key[CFG_MAX_KEY];
- CFGFILE *cfg = NULL;
- int i;
- int setnumber;
- int found;
- int replicating = 0;
- char primary[NSC_MAXPATH];
- char secondary[NSC_MAXPATH];
- char phost[MAX_RDC_HOST_SIZE];
- char shost[MAX_RDC_HOST_SIZE];
- rdc_set_t *rdc_set;
- int sev;
- char *local_file;
- int size;
-
- ustatus = spcs_s_ucreate();
-
- size = sizeof (char *) * rdc_maxsets;
- volumes = malloc(size);
- if (volumes == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s: unable to allocate %ld bytes"),
- program, size);
- rdc_warn(NULL,
- gettext("unable to allocate %ld bytes"), size);
- goto done;
- }
- bzero(volumes, size);
-
- /*
- * If all members of this group are replicating
- * set ii_ndr state to "update". Otherwise leave them alone.
- */
- LOCKCFG();
- if ((cfg = cfg_open(NULL)) == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s: error opening lconfig"),
- program);
- rdc_warn(NULL, gettext("error opening config"));
- UNLOCKCFG();
- goto done;
- }
-
- if (!cfg_lock(cfg, CFG_RDLOCK)) {
- spcs_log("sndr", NULL,
- gettext("%s: error locking config"),
- program);
- rdc_warn(NULL, gettext("error locking config"));
- goto done;
- }
-
- found = 0;
-
- /* get all RM entries, with a matching group, that are replicating */
- for (i = 0; i < rdc_maxsets; i++) {
- setnumber = i + 1;
-
- (void) snprintf(key, sizeof (key),
- "sndr.set%d.group", setnumber);
- if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
- break;
-
- if (strcmp(buf, group) != 0)
- continue;
-
- /* Found a matching entry */
-
- (void) snprintf(key, sizeof (key),
- "sndr.set%d.primary", setnumber);
- if (cfg_get_cstring(cfg, key, primary, sizeof (primary)) < 0)
- break;
- (void) strcpy(parms.rdc_set->primary.file, primary);
-
- (void) snprintf(key, sizeof (key),
- "sndr.set%d.phost", setnumber);
- if (cfg_get_cstring(cfg, key, phost, sizeof (phost)) < 0)
- break;
- (void) strcpy(parms.rdc_set->primary.intf, phost);
-
- (void) snprintf(key, sizeof (key),
- "sndr.set%d.secondary", setnumber);
- if (cfg_get_cstring(cfg, key, secondary,
- sizeof (secondary)) < 0)
- break;
- (void) strcpy(parms.rdc_set->secondary.file, secondary);
-
- (void) snprintf(key, sizeof (key),
- "sndr.set%d.shost", setnumber);
- if (cfg_get_cstring(cfg, key, shost, sizeof (shost)) < 0)
- break;
- (void) strcpy(parms.rdc_set->secondary.intf, shost);
-
- parms.command = RDC_CMD_STATUS;
- if (RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus) < 0) {
- continue;
- }
-
- /* We found a matching set */
- found++;
-
- if (self_check(phost))
- local_file = primary;
- else
- local_file = secondary;
-
- rdc_set = &parms.rdc_set[0];
- if (!(rdc_set->flags & RDC_LOGGING) &&
- !(rdc_set->flags & RDC_SYNCING)) {
- volumes[replicating] = strdup(local_file);
- if (volumes[replicating] == NULL) {
- size = strlen(local_file);
- spcs_log("sndr", NULL,
- gettext("%s: unable to allocate %ld bytes"),
- program, size);
- rdc_warn(NULL,
- gettext("unable to allocate %ld bytes"),
- size);
- goto done;
- }
- /* We remember all replicating sets */
- replicating++;
- } else
- break; /* Not all replicating, so done */
- }
-
- if (found != replicating)
- goto done;
-
- /* All replicating, so update ndr_ii state fields */
-
- cfg_unlock(cfg);
-
- if (!cfg_lock(cfg, CFG_WRLOCK)) {
- spcs_log("sndr", NULL,
- gettext("%s: error locking lconfig"),
- program);
- rdc_warn(NULL, gettext("error locking config"));
- goto done;
- }
-
- /*
- * Search through the ndr_ii entries for entries
- * that match the saved secondary volume names.
- * Set state to "update".
- */
-
- 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 (!volume_match(buf, volumes, found)) {
- continue;
- }
-
- /* Got a matching entry */
-
- (void) snprintf(key, sizeof (key),
- "ndr_ii.set%d.state", setnumber);
- if ((cfg_put_cstring(cfg, key, UPDATE, strlen(UPDATE)) < 0) ||
- (cfg_commit(cfg) < 0)) {
- spcs_log("sndr", NULL,
- gettext("%s: unable to update \"%s\" "
- "in configuration storage: %s"),
- program, buf, cfg_error(&sev));
- rdc_warn(NULL,
- gettext("unable to update \"%s\" "
- "in configuration storage: %s"),
- buf, cfg_error(&sev));
- }
- }
-
-
-done:
- if (cfg) {
- cfg_close(cfg);
- UNLOCKCFG();
- }
- spcs_s_ufree(&ustatus);
- if (volumes) {
- for (i = 0; i < replicating; i++)
- free(volumes[i]);
- free(volumes);
- }
-}
-
-
-/*
- * Sync started to a member of a group.
- * If all members of the group are in ndr_ii state "update" then take an PIT
- * snapshot on all of them. This will provide a consistent point-in-time
- * copy until whatever syncs take place are all completed.
- */
-void
-group_start(char *group)
-{
- char **masters = NULL;
- char **shadows = NULL;
- char **bitmaps = NULL;
- char cmd[256];
- char buf[CFG_MAX_BUF];
- char key[CFG_MAX_KEY];
- CFGFILE *cfg = NULL;
- int i;
- int j;
- int setnumber;
- int found;
- int sndr_sets = 0;
- int update_needed = 0;
- int sev;
- char *ctag = NULL;
- int commit = 0;
- int size;
-
- size = sizeof (char *) * rdc_maxsets;
- masters = malloc(size);
- if (masters == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s: unable to allocate %ld bytes"),
- program, size);
- rdc_warn(NULL,
- gettext("unable to allocate %ld bytes"), size);
- goto done;
- }
- bzero(masters, size);
- shadows = malloc(size);
- if (shadows == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s: unable to allocate %ld bytes"),
- program, size);
- rdc_warn(NULL,
- gettext("unable to allocate %ld bytes"), size);
- goto done;
- }
- bzero(shadows, size);
- bitmaps = malloc(size);
- if (bitmaps == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s: unable to allocate %ld bytes"),
- program, size);
- rdc_warn(NULL,
- gettext("unable to allocate %ld bytes"), size);
- goto done;
- }
- bzero(bitmaps, size);
-
- LOCKCFG();
- if ((cfg = cfg_open(NULL)) == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s: error opening config"),
- program);
- rdc_warn(NULL,
- gettext("error opening config"));
- UNLOCKCFG();
- goto done;
- }
-
- if (!cfg_lock(cfg, CFG_WRLOCK)) {
- spcs_log("sndr", NULL,
- gettext("%s: error locking config"),
- program);
- rdc_warn(NULL, gettext("error locking config"));
- goto done;
- }
-
- /* Now get all Remote Mirror entries with a matching group */
- for (i = 0; i < rdc_maxsets; i++) {
- setnumber = i + 1;
-
- (void) snprintf(key, sizeof (key),
- "sndr.set%d.group", setnumber);
- if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
- break;
-
- if (strcmp(buf, group) != 0)
- continue;
-
- /* Found a matching entry */
-
- (void) snprintf(key, sizeof (key),
- "sndr.set%d.phost", setnumber);
- if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0)
- break;
-
- if (self_check(buf)) {
- (void) snprintf(key, sizeof (key), "sndr.set%d.primary",
- setnumber);
- } else {
- (void) snprintf(key, sizeof (key),
- "sndr.set%d.secondary", setnumber);
- }
- if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0)
- break;
-
- masters[sndr_sets] = strdup(buf);
- if (masters[sndr_sets] == NULL) {
- size = strlen(buf);
- spcs_log("sndr", NULL,
- gettext("%s: unable to allocate %ld bytes"),
- program, size);
- rdc_warn(NULL,
- gettext("unable to allocate %ld bytes"), size);
- goto done;
- }
- sndr_sets++;
-
- if (ctag == NULL && clustered) {
- /* Get cluster tag of matching entry */
-
- (void) snprintf(key, sizeof (key), "sndr.set%d.cnode",
- setnumber);
- if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) >= 0)
- ctag = strdup(buf);
- }
- }
-
- /*
- * Search through the ndr_ii entries for entries
- * that match the saved local volume names and are in "update" state.
- */
-
- update_needed = 0;
-
- 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 (!volume_match(buf, masters, sndr_sets))
- 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;
- shadows[update_needed] = strdup(buf);
- if (shadows[update_needed] == NULL) {
- size = strlen(buf);
- spcs_log("sndr", NULL,
- gettext("%s: unable to allocate %ld bytes"),
- program, size);
- rdc_warn(NULL,
- gettext("unable to allocate %ld bytes"), size);
- goto done;
- }
-
- (void) snprintf(key, sizeof (key), "ndr_ii.set%d.bitmap",
- setnumber);
- if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
- break;
- }
- bitmaps[update_needed] = strdup(buf);
- if (bitmaps[update_needed] == NULL) {
- size = strlen(buf);
- spcs_log("sndr", NULL,
- gettext("%s: unable to allocate %ld bytes"),
- program, size);
- rdc_warn(NULL,
- gettext("unable to allocate %ld bytes"), size);
- goto done;
- }
-
- (void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
- setnumber);
- if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
- break;
- }
- if (strcmp(buf, UPDATE) != 0) {
- break;
- }
-
- update_needed++;
- }
-
- if (update_needed != sndr_sets) {
-#ifdef DEBUG
- spcs_log("sndr", NULL,
- gettext("%s: group sync: no Point-in-Time Copy snapshot "
- "for %s"), program, group);
-#endif
- goto done;
- }
-
- /* All RM sets in the group have an ndr_ii entry in "update" state */
-
- /* Issue PIT Copy snapshot commands for all sets in the group */
- for (j = 0; j < sndr_sets; j++) {
- found = 0;
-
- /* get ii entries until a match is found */
- for (i = 0; ; i++) {
- setnumber = i + 1;
-
- (void) snprintf(key, sizeof (key), "ii.set%d.shadow",
- setnumber);
- if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
- break;
- if (strcmp(buf, shadows[j]) != 0)
- continue;
-
- /* Matching shadow found, so ii already enabled */
- found = 1;
- break;
- }
-
- if (commit)
- if (cfg_commit(cfg) < 0)
- rdc_warn(NULL, gettext("commit config error"));
- cfg_close(cfg);
-
- if (found) {
- (void) sprintf(cmd, "%s -u s %s", IIADM, shadows[j]);
- } else {
- if (ctag) {
- (void) sprintf(cmd, "%s -C %s -e dep %s %s %s",
- IIADM, ctag, masters[j], shadows[j],
- bitmaps[j]);
- free(ctag);
- ctag = NULL;
- } else
- (void) sprintf(cmd, "%s -e dep %s %s %s", IIADM,
- masters[j], shadows[j], bitmaps[j]);
- }
-
- if (system(cmd) != 0) {
- spcs_log("sndr", NULL,
- gettext("%s: group sync: Point-in-Time Copy"
- " snapshot failed for %s"),
- program, masters[j]);
-
- goto done;
- }
-
- if ((cfg = cfg_open(NULL)) == NULL) {
- spcs_log("sndr", NULL,
- gettext("%s: error opening config"),
- program);
- rdc_warn(NULL,
- gettext("error opening config"));
- goto done;
- }
- if (!cfg_lock(cfg, CFG_WRLOCK)) {
- spcs_log("sndr", NULL,
- gettext("%s: error locking config"),
- program);
- rdc_warn(NULL, gettext("error locking config"));
- goto done;
- }
- commit = 0;
-
- /* PIT enable or update was fine, so update the ndr_ii entry */
-
- /* get ndr_ii entries until a match is found */
- for (i = 0; ; i++) {
- setnumber = i + 1;
-
- (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, shadows[j]) != 0)
- continue;
-
- /* Found the matching entry */
-
- (void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
- setnumber);
- if (cfg_put_cstring(cfg, key, NOUPDATE,
- strlen(NOUPDATE)) < 0) {
- spcs_log("sndr", NULL,
- gettext("%s: unable to update \"%s\" "
- "in configuration storage: %s"),
- program, buf, cfg_error(&sev));
- rdc_warn(NULL,
- gettext("unable to update \"%s\" "
- "in configuration storage: %s"),
- buf, cfg_error(&sev));
- } else
- commit = 1;
- break;
- }
- }
-
- if (commit)
- if (cfg_commit(cfg) < 0)
- rdc_warn(NULL, gettext("commit config error"));
-
- spcs_log("sndr", NULL,
- gettext("%s: group sync: Point-in-Time Copy snapshots completed "
- "for %s"), program, group);
-
-done:
- if (ctag)
- free(ctag);
-
- if (cfg) {
- cfg_close(cfg);
- UNLOCKCFG();
- }
-
- if (masters) {
- for (i = 0; i < sndr_sets; i++) {
- if (masters[i])
- free(masters[i]);
- }
- free(masters);
- }
-
- if (shadows) {
- for (i = 0; i < update_needed; i++) {
- if (shadows[i])
- free(shadows[i]);
- }
- free(shadows);
- }
-
- if (bitmaps) {
- for (i = 0; i < update_needed; i++) {
- if (bitmaps[i])
- free(bitmaps[i]);
- }
- free(bitmaps);
- }
-}