diff options
Diffstat (limited to 'usr/src/cmd/avs/rdc')
-rw-r--r-- | usr/src/cmd/avs/rdc/Makefile | 118 | ||||
-rw-r--r-- | usr/src/cmd/avs/rdc/etc/Makefile | 71 | ||||
-rw-r--r-- | usr/src/cmd/avs/rdc/etc/rdc.cluster.sh | 74 | ||||
-rw-r--r-- | usr/src/cmd/avs/rdc/etc/rdc.sh | 186 | ||||
-rw-r--r-- | usr/src/cmd/avs/rdc/etc/rdcfinish.sh | 90 | ||||
-rw-r--r-- | usr/src/cmd/avs/rdc/rdc_ioctl.c | 87 | ||||
-rw-r--r-- | usr/src/cmd/avs/rdc/rdcadm.h | 67 | ||||
-rw-r--r-- | usr/src/cmd/avs/rdc/sndradm.c | 5715 | ||||
-rw-r--r-- | usr/src/cmd/avs/rdc/sndrboot.c | 881 | ||||
-rw-r--r-- | usr/src/cmd/avs/rdc/sndrd.c | 2013 | ||||
-rw-r--r-- | usr/src/cmd/avs/rdc/sndrsubr.c | 463 | ||||
-rw-r--r-- | usr/src/cmd/avs/rdc/sndrsyncd.c | 1695 |
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); - } -} |