xref: /onnv-gate/usr/src/cmd/avs/rdc/sndrsyncd.c (revision 11576:b23c42c0c9d6)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
21*11576SSurya.Prakki@Sun.COM 
227836SJohn.Forte@Sun.COM /*
23*11576SSurya.Prakki@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
247836SJohn.Forte@Sun.COM  * Use is subject to license terms.
257836SJohn.Forte@Sun.COM  */
267836SJohn.Forte@Sun.COM 
277836SJohn.Forte@Sun.COM #include <sys/types.h>
287836SJohn.Forte@Sun.COM #include <sys/wait.h>
297836SJohn.Forte@Sun.COM #include <stdio.h>
307836SJohn.Forte@Sun.COM #include <errno.h>
317836SJohn.Forte@Sun.COM #include <limits.h>
327836SJohn.Forte@Sun.COM #include <fcntl.h>
337836SJohn.Forte@Sun.COM #include <strings.h>
347836SJohn.Forte@Sun.COM #include <stdlib.h>
357836SJohn.Forte@Sun.COM #include <unistd.h>
367836SJohn.Forte@Sun.COM #include <pthread.h>
377836SJohn.Forte@Sun.COM #include <thread.h>
387836SJohn.Forte@Sun.COM 
397836SJohn.Forte@Sun.COM #include <locale.h>
407836SJohn.Forte@Sun.COM #include <langinfo.h>
417836SJohn.Forte@Sun.COM #include <libintl.h>
427836SJohn.Forte@Sun.COM #include <stdarg.h>
437836SJohn.Forte@Sun.COM 
447836SJohn.Forte@Sun.COM #include <sys/nsctl/rdc_io.h>
457836SJohn.Forte@Sun.COM #include <sys/nsctl/rdc_ioctl.h>
467836SJohn.Forte@Sun.COM #include <sys/nsctl/rdc_prot.h>
477836SJohn.Forte@Sun.COM 
487836SJohn.Forte@Sun.COM #include <sys/nsctl/cfg.h>
497836SJohn.Forte@Sun.COM 
507836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s.h>
517836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_u.h>
527836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_errors.h>
537836SJohn.Forte@Sun.COM 
547836SJohn.Forte@Sun.COM #include <sys/nsctl/librdc.h>
557836SJohn.Forte@Sun.COM 
567836SJohn.Forte@Sun.COM #include "rdcadm.h"
577836SJohn.Forte@Sun.COM 
587836SJohn.Forte@Sun.COM 
597836SJohn.Forte@Sun.COM #define	RDCADM "/usr/sbin/sndradm"
607836SJohn.Forte@Sun.COM #define	IIADM "/usr/sbin/iiadm"
617836SJohn.Forte@Sun.COM 
627836SJohn.Forte@Sun.COM #define	UPDATE "update"
637836SJohn.Forte@Sun.COM #define	NOUPDATE "noupdate"
647836SJohn.Forte@Sun.COM 
657836SJohn.Forte@Sun.COM #define	RESYNC_SLEEP	(3 * 60)	/* Three minutes */
667836SJohn.Forte@Sun.COM #define	MAIN_SLEEP	(5 * 60)	/* Five minutes */
677836SJohn.Forte@Sun.COM #define	CFG_WAIT_SLEEP	(5)		/* 5 sec */
687836SJohn.Forte@Sun.COM 
697836SJohn.Forte@Sun.COM #define	MAXHOSTS 1024
707836SJohn.Forte@Sun.COM mutex_t cfglock = DEFAULTMUTEX;
717836SJohn.Forte@Sun.COM #define	LOCKCFG() (void) mutex_lock(&cfglock);
727836SJohn.Forte@Sun.COM #define	UNLOCKCFG() (void) mutex_unlock(&cfglock);
737836SJohn.Forte@Sun.COM 
747836SJohn.Forte@Sun.COM typedef struct host_list_s {
757836SJohn.Forte@Sun.COM 	char *hosts[MAXHOSTS];
767836SJohn.Forte@Sun.COM 	int numhosts;
777836SJohn.Forte@Sun.COM 	int configured[MAXHOSTS];
787836SJohn.Forte@Sun.COM 	mutex_t hosts_mutex;
797836SJohn.Forte@Sun.COM } host_list_t;
807836SJohn.Forte@Sun.COM 
817836SJohn.Forte@Sun.COM host_list_t *host_list;
827836SJohn.Forte@Sun.COM 
837836SJohn.Forte@Sun.COM extern char *basename(char *);
847836SJohn.Forte@Sun.COM int rdc_maxsets;
857836SJohn.Forte@Sun.COM char *program;
867836SJohn.Forte@Sun.COM 
877836SJohn.Forte@Sun.COM static int clustered = 0;
887836SJohn.Forte@Sun.COM 
897836SJohn.Forte@Sun.COM int isnewhost(char *host);
907836SJohn.Forte@Sun.COM void *wait_sync_event();
917836SJohn.Forte@Sun.COM void *wait_link_down(void *host);
927836SJohn.Forte@Sun.COM void rdc_sync(char *tohost);
937836SJohn.Forte@Sun.COM void remove_from_hostlist(char *host);
947836SJohn.Forte@Sun.COM void sync_start(char *master);
957836SJohn.Forte@Sun.COM void sync_complete(char *master);
967836SJohn.Forte@Sun.COM void cleanup_hostlist();
977836SJohn.Forte@Sun.COM void group_start(char *group);
987836SJohn.Forte@Sun.COM void group_complete(char *group);
997836SJohn.Forte@Sun.COM 
1007836SJohn.Forte@Sun.COM 
1017836SJohn.Forte@Sun.COM void
init_host_list(void)1027836SJohn.Forte@Sun.COM init_host_list(void)
1037836SJohn.Forte@Sun.COM {
1047836SJohn.Forte@Sun.COM 	host_list = calloc(1, sizeof (host_list_t));
1057836SJohn.Forte@Sun.COM 	if (host_list == NULL) {
1067836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
1077836SJohn.Forte@Sun.COM 		    gettext("host list not initialized, cannot run"));
1087836SJohn.Forte@Sun.COM 		rdc_err(NULL, gettext("host list not initialized, cannot run"));
1097836SJohn.Forte@Sun.COM 	}
1107836SJohn.Forte@Sun.COM 	(void) mutex_init(&host_list->hosts_mutex, USYNC_THREAD, NULL);
1117836SJohn.Forte@Sun.COM }
1127836SJohn.Forte@Sun.COM 
1137836SJohn.Forte@Sun.COM /* ARGSUSED */
1147836SJohn.Forte@Sun.COM #ifdef lint
1157836SJohn.Forte@Sun.COM void
sndrsyncd_lintmain(argc,argv)1167836SJohn.Forte@Sun.COM sndrsyncd_lintmain(argc, argv)
1177836SJohn.Forte@Sun.COM #else
1187836SJohn.Forte@Sun.COM int
1197836SJohn.Forte@Sun.COM main(argc, argv)
1207836SJohn.Forte@Sun.COM #endif
1217836SJohn.Forte@Sun.COM int argc;
1227836SJohn.Forte@Sun.COM char **argv;
1237836SJohn.Forte@Sun.COM {
1247836SJohn.Forte@Sun.COM 	rdc_status_t *rdc_info;
1257836SJohn.Forte@Sun.COM 	int size;
1267836SJohn.Forte@Sun.COM 	int i;
1277836SJohn.Forte@Sun.COM 	pid_t pid;
1287836SJohn.Forte@Sun.COM 	spcs_s_info_t ustatus;
1297836SJohn.Forte@Sun.COM 	int rc, trc;
1307836SJohn.Forte@Sun.COM 	int first = 0;
1317836SJohn.Forte@Sun.COM 	char *required;
1327836SJohn.Forte@Sun.COM 
1337836SJohn.Forte@Sun.COM 	(void) setlocale(LC_ALL, "");
1347836SJohn.Forte@Sun.COM 	(void) textdomain("rdc");
1357836SJohn.Forte@Sun.COM 
1367836SJohn.Forte@Sun.COM 	ustatus = spcs_s_ucreate();
1377836SJohn.Forte@Sun.COM 
1387836SJohn.Forte@Sun.COM 	program = basename(argv[0]);
1397836SJohn.Forte@Sun.COM 
1407836SJohn.Forte@Sun.COM 	init_host_list();
1417836SJohn.Forte@Sun.COM 
1427836SJohn.Forte@Sun.COM 	rc = rdc_check_release(&required);
1437836SJohn.Forte@Sun.COM 	if (rc < 0) {
1447836SJohn.Forte@Sun.COM 		rdc_err(NULL,
1457836SJohn.Forte@Sun.COM 		    gettext("unable to determine the current "
1467836SJohn.Forte@Sun.COM 		    "Solaris release: %s\n"), strerror(errno));
1477836SJohn.Forte@Sun.COM 		/* NOTREACHED */
1487836SJohn.Forte@Sun.COM 	} else if (rc == FALSE) {
1497836SJohn.Forte@Sun.COM 		rdc_err(NULL,
1507836SJohn.Forte@Sun.COM 		    gettext("incorrect Solaris release (requires %s)\n"),
1517836SJohn.Forte@Sun.COM 		    required);
1527836SJohn.Forte@Sun.COM 		/* NOTREACHED */
1537836SJohn.Forte@Sun.COM 	}
1547836SJohn.Forte@Sun.COM 
1557836SJohn.Forte@Sun.COM 	clustered = cfg_iscluster();
1567836SJohn.Forte@Sun.COM 	if (clustered < 0) {
1577836SJohn.Forte@Sun.COM 		rdc_err(NULL, gettext("unable to ascertain environment"));
1587836SJohn.Forte@Sun.COM 	}
1597836SJohn.Forte@Sun.COM 
1607836SJohn.Forte@Sun.COM 	rdc_maxsets = rdc_get_maxsets();
1617836SJohn.Forte@Sun.COM 	if (rdc_maxsets == -1) {
1627836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
1637836SJohn.Forte@Sun.COM 		    gettext("%s: unable to get maxsets value from kernel"),
1647836SJohn.Forte@Sun.COM 		    program);
1657836SJohn.Forte@Sun.COM 		rdc_err(NULL,
1667836SJohn.Forte@Sun.COM 		    gettext("unable to get maxsets value from kernel"));
1677836SJohn.Forte@Sun.COM 	}
1687836SJohn.Forte@Sun.COM 	size = sizeof (rdc_status_t) + (sizeof (rdc_set_t) * (rdc_maxsets - 1));
1697836SJohn.Forte@Sun.COM 	rdc_info = malloc(size);
1707836SJohn.Forte@Sun.COM 	if (rdc_info == NULL) {
1717836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
1727836SJohn.Forte@Sun.COM 		    gettext("%s: unable to allocate %ld bytes"),
1737836SJohn.Forte@Sun.COM 		    program, size);
1747836SJohn.Forte@Sun.COM 		rdc_err(NULL,
1757836SJohn.Forte@Sun.COM 			gettext("unable to allocate %ld bytes"), size);
1767836SJohn.Forte@Sun.COM 	}
1777836SJohn.Forte@Sun.COM 	bzero(rdc_info, size);
1787836SJohn.Forte@Sun.COM 
1797836SJohn.Forte@Sun.COM 	rdc_info->nset = rdc_maxsets;
1807836SJohn.Forte@Sun.COM 
1817836SJohn.Forte@Sun.COM 	/*
1827836SJohn.Forte@Sun.COM 	 * Fork off a child that becomes the daemon.
1837836SJohn.Forte@Sun.COM 	 */
1847836SJohn.Forte@Sun.COM 	if ((pid = fork()) > 0)
1857836SJohn.Forte@Sun.COM 		exit(0);
1867836SJohn.Forte@Sun.COM 	else if (pid < 0) {
1877836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
1887836SJohn.Forte@Sun.COM 		    gettext("%s: cannot fork: %s"),
1897836SJohn.Forte@Sun.COM 		    program, strerror(errno));
1907836SJohn.Forte@Sun.COM 		rdc_err(NULL, gettext("cannot fork: %s\n"),
1917836SJohn.Forte@Sun.COM 		    strerror(errno));
1927836SJohn.Forte@Sun.COM 	}
1937836SJohn.Forte@Sun.COM 
1947836SJohn.Forte@Sun.COM 	/*
1957836SJohn.Forte@Sun.COM 	 * In child - become daemon.
1967836SJohn.Forte@Sun.COM 	 */
1977836SJohn.Forte@Sun.COM 
1987836SJohn.Forte@Sun.COM 	for (i = 0; i < 3; i++)
1997836SJohn.Forte@Sun.COM 		(void) close(i);
2007836SJohn.Forte@Sun.COM 
2017836SJohn.Forte@Sun.COM 	(void) open("/dev/console", O_WRONLY|O_APPEND);
2027836SJohn.Forte@Sun.COM 	(void) dup(0);
2037836SJohn.Forte@Sun.COM 	(void) dup(0);
2047836SJohn.Forte@Sun.COM 	(void) close(0);
2057836SJohn.Forte@Sun.COM 
2067836SJohn.Forte@Sun.COM 	(void) setpgrp();
2077836SJohn.Forte@Sun.COM 
2087836SJohn.Forte@Sun.COM 	(void) setlocale(LC_ALL, "");
2097836SJohn.Forte@Sun.COM 	(void) textdomain("rdc");
2107836SJohn.Forte@Sun.COM 
2117836SJohn.Forte@Sun.COM 	/* launch a thread to wait for sync start and sync stop events */
2127836SJohn.Forte@Sun.COM 
2137836SJohn.Forte@Sun.COM 	if ((trc = thr_create(NULL, 0, wait_sync_event, NULL,
2147836SJohn.Forte@Sun.COM 	    THR_BOUND|THR_DETACHED, NULL)) != 0) {
2157836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
2167836SJohn.Forte@Sun.COM 		    gettext("%s: unable to create thread wait_sync_event"),
2177836SJohn.Forte@Sun.COM 		    program);
2187836SJohn.Forte@Sun.COM 		rdc_warn(NULL,
2197836SJohn.Forte@Sun.COM 		    gettext("%s unable to create thread wait_sync_event"),
2207836SJohn.Forte@Sun.COM 		    program);
2217836SJohn.Forte@Sun.COM 	} else {
2227836SJohn.Forte@Sun.COM #ifdef DEBUG
2237836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
2247836SJohn.Forte@Sun.COM 		    gettext("%s: thread wait_sync_event started"), program);
2257836SJohn.Forte@Sun.COM #endif
2267836SJohn.Forte@Sun.COM 		;
2277836SJohn.Forte@Sun.COM 	}
2287836SJohn.Forte@Sun.COM 
2297836SJohn.Forte@Sun.COM 	for (;;) {
2307836SJohn.Forte@Sun.COM 		if (!first) {
2317836SJohn.Forte@Sun.COM 			first++;
2327836SJohn.Forte@Sun.COM 			(void) sleep(15);
2337836SJohn.Forte@Sun.COM 		} else
2347836SJohn.Forte@Sun.COM 			(void) sleep(MAIN_SLEEP);
2357836SJohn.Forte@Sun.COM 
2367836SJohn.Forte@Sun.COM 		bzero(rdc_info, size);
2377836SJohn.Forte@Sun.COM 		rdc_info->nset = rdc_maxsets;
2387836SJohn.Forte@Sun.COM 		if (RDC_IOCTL(RDC_STATUS, rdc_info, 0, 0, 0, 0, ustatus)
2397836SJohn.Forte@Sun.COM 		    != SPCS_S_OK) {
2407836SJohn.Forte@Sun.COM 			spcs_log("sndr", &ustatus,
2417836SJohn.Forte@Sun.COM 			    gettext("%s: status ioctl"),
2427836SJohn.Forte@Sun.COM 			    program);
2437836SJohn.Forte@Sun.COM 			rdc_warn(&ustatus, gettext("status ioctl"));
2447836SJohn.Forte@Sun.COM 			continue;
2457836SJohn.Forte@Sun.COM 		}
2467836SJohn.Forte@Sun.COM 
2477836SJohn.Forte@Sun.COM 		cleanup_hostlist(rdc_info); /* remove non-existent hosts */
2487836SJohn.Forte@Sun.COM 
2497836SJohn.Forte@Sun.COM 		/*
2507836SJohn.Forte@Sun.COM 		 * Check all enabled sets to see if a new remote host has
2517836SJohn.Forte@Sun.COM 		 * appeared.
2527836SJohn.Forte@Sun.COM 		 */
2537836SJohn.Forte@Sun.COM 		for (i = 0; i < rdc_maxsets; i++) {
2547836SJohn.Forte@Sun.COM 			if (!(rdc_info->rdc_set[i].flags & RDC_ENABLED))
2557836SJohn.Forte@Sun.COM 				continue;
2567836SJohn.Forte@Sun.COM 			/* spawn a new thread for each new host found */
2577836SJohn.Forte@Sun.COM 			if (isnewhost(rdc_info->rdc_set[i].secondary.intf)) {
2587836SJohn.Forte@Sun.COM 				/*
2597836SJohn.Forte@Sun.COM 				 * right now, we could be here before
2607836SJohn.Forte@Sun.COM 				 * the database did the write for this set
2617836SJohn.Forte@Sun.COM 				 * I could check the lock on the database
2627836SJohn.Forte@Sun.COM 				 * but I am just going to give up some time here
2637836SJohn.Forte@Sun.COM 				 * instead. Why do the allocations etc, etc
2647836SJohn.Forte@Sun.COM 				 * if the set is enabled in the kernel and not
2657836SJohn.Forte@Sun.COM 				 * in the config, we know that this set has the
2667836SJohn.Forte@Sun.COM 				 * lock. Why bother adding more contention to
2677836SJohn.Forte@Sun.COM 				 * the lock.
2687836SJohn.Forte@Sun.COM 				 * this is a daemon, afterall. its got time
2697836SJohn.Forte@Sun.COM 				 */
2707836SJohn.Forte@Sun.COM 				(void) sleep(CFG_WAIT_SLEEP);
2717836SJohn.Forte@Sun.COM 
2727836SJohn.Forte@Sun.COM 				spcs_log("sndr", NULL,
2737836SJohn.Forte@Sun.COM 				    gettext("%s: new host found (%s) starting "
2747836SJohn.Forte@Sun.COM 				    "its autosync thread"), program,
2757836SJohn.Forte@Sun.COM 				    rdc_info->rdc_set[i].secondary.intf);
2767836SJohn.Forte@Sun.COM 
2777836SJohn.Forte@Sun.COM 				trc = thr_create(NULL, 0, wait_link_down,
2787836SJohn.Forte@Sun.COM 				    (void *) rdc_info->rdc_set[i].\
2797836SJohn.Forte@Sun.COM secondary.intf, THR_BOUND|THR_DETACHED, NULL);
2807836SJohn.Forte@Sun.COM 
2817836SJohn.Forte@Sun.COM 				if (trc != 0) {
2827836SJohn.Forte@Sun.COM 					spcs_log("sndr", NULL,
2837836SJohn.Forte@Sun.COM 					    gettext(
2847836SJohn.Forte@Sun.COM 					    "%s create new autosync "
2857836SJohn.Forte@Sun.COM 					    "thread failed"), program);
2867836SJohn.Forte@Sun.COM 					rdc_warn(NULL, gettext(
2877836SJohn.Forte@Sun.COM 					    "%s create new autosync "
2887836SJohn.Forte@Sun.COM 					    "thread failed"), program);
2897836SJohn.Forte@Sun.COM 				}
2907836SJohn.Forte@Sun.COM 			}
2917836SJohn.Forte@Sun.COM 		}
2927836SJohn.Forte@Sun.COM 	}
2937836SJohn.Forte@Sun.COM 	/* NOTREACHED */
2947836SJohn.Forte@Sun.COM }
2957836SJohn.Forte@Sun.COM 
2967836SJohn.Forte@Sun.COM 
2977836SJohn.Forte@Sun.COM /*
2987836SJohn.Forte@Sun.COM  * The kernel wakes up this function every time it detects the link to the
2997836SJohn.Forte@Sun.COM  * specified host has dropped.
3007836SJohn.Forte@Sun.COM  */
3017836SJohn.Forte@Sun.COM void *
wait_link_down(void * thehost)3027836SJohn.Forte@Sun.COM wait_link_down(void *thehost)
3037836SJohn.Forte@Sun.COM {
3047836SJohn.Forte@Sun.COM 	char *host = (char *)thehost;
3057836SJohn.Forte@Sun.COM 	char tmphost[MAX_RDC_HOST_SIZE] = { '\0' };
3067836SJohn.Forte@Sun.COM 	spcs_s_info_t ustatus;
3077836SJohn.Forte@Sun.COM 
3087836SJohn.Forte@Sun.COM 	if (host)
309*11576SSurya.Prakki@Sun.COM 		(void) strncpy(tmphost, host, MAX_RDC_HOST_SIZE);
3107836SJohn.Forte@Sun.COM 
3117836SJohn.Forte@Sun.COM 	ustatus = spcs_s_ucreate();
3127836SJohn.Forte@Sun.COM 
3137836SJohn.Forte@Sun.COM 	/* Never give up */
3147836SJohn.Forte@Sun.COM 	for (;;) {
3157836SJohn.Forte@Sun.COM #ifdef DEBUG
3167836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
3177836SJohn.Forte@Sun.COM 		    gettext("%s: awaiting link down ioctl for %s"),
3187836SJohn.Forte@Sun.COM 		    program, host[0] == '\0' ? tmphost : host);
3197836SJohn.Forte@Sun.COM #endif
3207836SJohn.Forte@Sun.COM 		if (RDC_IOCTL(RDC_LINK_DOWN, host, 0, 0, 0, 0, ustatus)
3217836SJohn.Forte@Sun.COM 		    != SPCS_S_OK) {
3227836SJohn.Forte@Sun.COM 			spcs_log("sndr", &ustatus,
3237836SJohn.Forte@Sun.COM 			    gettext("%s: link down ioctl"),
3247836SJohn.Forte@Sun.COM 			    program);
3257836SJohn.Forte@Sun.COM 			rdc_warn(&ustatus, gettext("link down ioctl"));
3267836SJohn.Forte@Sun.COM 			continue;
3277836SJohn.Forte@Sun.COM 		}
3287836SJohn.Forte@Sun.COM #ifdef DEBUG
3297836SJohn.Forte@Sun.COM 
3307836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
3317836SJohn.Forte@Sun.COM 		    gettext("%s: received link down ioctl for %s"),
3327836SJohn.Forte@Sun.COM 		    program, host[0] == '\0' ? tmphost : host);
3337836SJohn.Forte@Sun.COM #endif
3347836SJohn.Forte@Sun.COM 		rdc_sync(host[0] == '\0' ? tmphost : host);
3357836SJohn.Forte@Sun.COM 	}
3367836SJohn.Forte@Sun.COM 	/* LINTED */
3377836SJohn.Forte@Sun.COM }
3387836SJohn.Forte@Sun.COM 
3397836SJohn.Forte@Sun.COM 
3407836SJohn.Forte@Sun.COM /*
3417836SJohn.Forte@Sun.COM  * Called when the link to the specified host has dropped.
3427836SJohn.Forte@Sun.COM  * For all Remote Mirror sets using the link that have autosync on,
3437836SJohn.Forte@Sun.COM  * issue rdcadm -u commands until they complete successfully.
3447836SJohn.Forte@Sun.COM  */
3457836SJohn.Forte@Sun.COM void
rdc_sync(char * tohost)3467836SJohn.Forte@Sun.COM rdc_sync(char *tohost)
3477836SJohn.Forte@Sun.COM {
3487836SJohn.Forte@Sun.COM 	rdc_set_t *rdc_set = NULL;
3497836SJohn.Forte@Sun.COM 	int *sync_done = NULL;
3507836SJohn.Forte@Sun.COM 	int sets = 0;
3517836SJohn.Forte@Sun.COM 	int syncs_done = 0;
3527836SJohn.Forte@Sun.COM 	char cmd[256];
3537836SJohn.Forte@Sun.COM 	rdc_config_t parms = { 0 };
3547836SJohn.Forte@Sun.COM 	spcs_s_info_t ustatus;
3557836SJohn.Forte@Sun.COM 	int i;
3567836SJohn.Forte@Sun.COM 	int setnumber;
3577836SJohn.Forte@Sun.COM 	int numfound = 0;
3587836SJohn.Forte@Sun.COM 	char buf[CFG_MAX_BUF];
3597836SJohn.Forte@Sun.COM 	char key[CFG_MAX_KEY];
3607836SJohn.Forte@Sun.COM 	CFGFILE *cfg = NULL;
3617836SJohn.Forte@Sun.COM 	int size;
3627836SJohn.Forte@Sun.COM 	int first = 0;
3637836SJohn.Forte@Sun.COM 	int death = 0;
3647836SJohn.Forte@Sun.COM 	int cfglocked = 0;
3657836SJohn.Forte@Sun.COM 
3667836SJohn.Forte@Sun.COM 	ustatus = spcs_s_ucreate();
3677836SJohn.Forte@Sun.COM 
3687836SJohn.Forte@Sun.COM 	size = sizeof (rdc_set_t) * rdc_maxsets;
3697836SJohn.Forte@Sun.COM 	rdc_set = malloc(size);
3707836SJohn.Forte@Sun.COM 	if (rdc_set == NULL) {
3717836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
3727836SJohn.Forte@Sun.COM 		    gettext("%s: unable to allocate %ld bytes"),
3737836SJohn.Forte@Sun.COM 		    program, size);
3747836SJohn.Forte@Sun.COM 		rdc_warn(NULL,
3757836SJohn.Forte@Sun.COM 			gettext("unable to allocate %ld bytes"), size);
3767836SJohn.Forte@Sun.COM 		goto done;
3777836SJohn.Forte@Sun.COM 	}
3787836SJohn.Forte@Sun.COM 	bzero(rdc_set, size);
3797836SJohn.Forte@Sun.COM 	size = sizeof (int) * rdc_maxsets;
3807836SJohn.Forte@Sun.COM 	sync_done = malloc(size);
3817836SJohn.Forte@Sun.COM 	if (sync_done == NULL) {
3827836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
3837836SJohn.Forte@Sun.COM 		    gettext("%s: unable to allocate %ld bytes"),
3847836SJohn.Forte@Sun.COM 		    program, size);
3857836SJohn.Forte@Sun.COM 		rdc_warn(NULL,
3867836SJohn.Forte@Sun.COM 			gettext("unable to allocate %ld bytes"), size);
3877836SJohn.Forte@Sun.COM 		goto done;
3887836SJohn.Forte@Sun.COM 	}
3897836SJohn.Forte@Sun.COM 	bzero(sync_done, size);
3907836SJohn.Forte@Sun.COM 
3917836SJohn.Forte@Sun.COM 	/*
3927836SJohn.Forte@Sun.COM 	 * Get all sndr entries with shost matching tohost, and save the
3937836SJohn.Forte@Sun.COM 	 * details in an array.
3947836SJohn.Forte@Sun.COM 	 */
3957836SJohn.Forte@Sun.COM 	for (i = 0; i < rdc_maxsets; i++) {
3967836SJohn.Forte@Sun.COM 		setnumber = i + 1;
3977836SJohn.Forte@Sun.COM 		bzero(buf, sizeof (buf));
3987836SJohn.Forte@Sun.COM 		bzero(key, sizeof (key));
3997836SJohn.Forte@Sun.COM 
4007836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "sndr.set%d.shost",
4017836SJohn.Forte@Sun.COM 		    setnumber);
4027836SJohn.Forte@Sun.COM 
4037836SJohn.Forte@Sun.COM 		if (!cfglocked) {
4047836SJohn.Forte@Sun.COM 			LOCKCFG();
4057836SJohn.Forte@Sun.COM 			if ((cfg = cfg_open(NULL)) == NULL) {
4067836SJohn.Forte@Sun.COM 				spcs_log("sndr", NULL,
4077836SJohn.Forte@Sun.COM 				    gettext("%s: error opening config"),
4087836SJohn.Forte@Sun.COM 				    program);
4097836SJohn.Forte@Sun.COM 
4107836SJohn.Forte@Sun.COM 				rdc_warn(NULL,
4117836SJohn.Forte@Sun.COM 				    gettext("error opening config"));
4127836SJohn.Forte@Sun.COM 				UNLOCKCFG();
4137836SJohn.Forte@Sun.COM 				goto done;
4147836SJohn.Forte@Sun.COM 			}
4157836SJohn.Forte@Sun.COM 
4167836SJohn.Forte@Sun.COM 			if (!cfg_lock(cfg, CFG_RDLOCK)) {
4177836SJohn.Forte@Sun.COM 				spcs_log("sndr", NULL,
4187836SJohn.Forte@Sun.COM 				    gettext("%s: error locking config"),
4197836SJohn.Forte@Sun.COM 				    program);
4207836SJohn.Forte@Sun.COM 				rdc_warn(NULL, gettext("error locking config"));
4217836SJohn.Forte@Sun.COM 				goto done;
4227836SJohn.Forte@Sun.COM 			}
4237836SJohn.Forte@Sun.COM 		}
4247836SJohn.Forte@Sun.COM 
4257836SJohn.Forte@Sun.COM 		cfglocked = 1;
4267836SJohn.Forte@Sun.COM 
4277836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
4287836SJohn.Forte@Sun.COM 			if (numfound == 0) /* no matching hosts */
4297836SJohn.Forte@Sun.COM 				death = 1; /* thread will exit */
4307836SJohn.Forte@Sun.COM 			break;
4317836SJohn.Forte@Sun.COM 		}
4327836SJohn.Forte@Sun.COM 		if (strcmp(buf, tohost) != 0)
4337836SJohn.Forte@Sun.COM 			continue;
4347836SJohn.Forte@Sun.COM 
4357836SJohn.Forte@Sun.COM 		numfound++;
436*11576SSurya.Prakki@Sun.COM 		(void) strncpy(rdc_set[sets].secondary.intf, buf,
437*11576SSurya.Prakki@Sun.COM 		    MAX_RDC_HOST_SIZE);
4387836SJohn.Forte@Sun.COM 
4397836SJohn.Forte@Sun.COM 		/* Got a matching entry */
4407836SJohn.Forte@Sun.COM 
4417836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "sndr.set%d.phost",
4427836SJohn.Forte@Sun.COM 		    setnumber);
4437836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
4447836SJohn.Forte@Sun.COM 			break;
445*11576SSurya.Prakki@Sun.COM 		(void) strncpy(rdc_set[sets].primary.intf, buf,
446*11576SSurya.Prakki@Sun.COM 		    MAX_RDC_HOST_SIZE);
4477836SJohn.Forte@Sun.COM 
4487836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "sndr.set%d.primary",
4497836SJohn.Forte@Sun.COM 		    setnumber);
4507836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
4517836SJohn.Forte@Sun.COM 			break;
452*11576SSurya.Prakki@Sun.COM 		(void) strncpy(rdc_set[sets].primary.file, buf, NSC_MAXPATH);
4537836SJohn.Forte@Sun.COM 
4547836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "sndr.set%d.secondary",
4557836SJohn.Forte@Sun.COM 		    setnumber);
4567836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
4577836SJohn.Forte@Sun.COM 			break;
458*11576SSurya.Prakki@Sun.COM 		(void) strncpy(rdc_set[sets].secondary.file, buf, NSC_MAXPATH);
4597836SJohn.Forte@Sun.COM 
4607836SJohn.Forte@Sun.COM 		parms.command = RDC_CMD_STATUS;
4617836SJohn.Forte@Sun.COM 		bcopy((void *)(&rdc_set[sets]), (void *)(&parms.rdc_set[0]),
4627836SJohn.Forte@Sun.COM 		    sizeof (rdc_set_t));
4637836SJohn.Forte@Sun.COM 
4647836SJohn.Forte@Sun.COM 		/*
4657836SJohn.Forte@Sun.COM 		 * release cfg before diving into the kernel
4667836SJohn.Forte@Sun.COM 		 * this prevents a possible deadlock when doing
4677836SJohn.Forte@Sun.COM 		 * a reverse sync whick will wake up the sync_event
4687836SJohn.Forte@Sun.COM 		 * thread which will try and iiadm -c and hang
4697836SJohn.Forte@Sun.COM 		 * because we still have the cfg_lock. the timed
4707836SJohn.Forte@Sun.COM 		 * wait cv in the kernel will fail the sync and things
4717836SJohn.Forte@Sun.COM 		 * will undeadlock.
4727836SJohn.Forte@Sun.COM 		 */
4737836SJohn.Forte@Sun.COM 
4747836SJohn.Forte@Sun.COM 		cfg_close(cfg);
4757836SJohn.Forte@Sun.COM 		cfg = NULL;
4767836SJohn.Forte@Sun.COM 		cfglocked = 0;
4777836SJohn.Forte@Sun.COM 		UNLOCKCFG();
4787836SJohn.Forte@Sun.COM 
4797836SJohn.Forte@Sun.COM 		if (RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus) < 0) {
4807836SJohn.Forte@Sun.COM 			continue;
4817836SJohn.Forte@Sun.COM 		}
4827836SJohn.Forte@Sun.COM 		if ((parms.rdc_set[0].autosync == 0) ||
4837836SJohn.Forte@Sun.COM 		    (!(parms.rdc_set[0].flags & RDC_LOGGING))) {
4847836SJohn.Forte@Sun.COM 			continue;
4857836SJohn.Forte@Sun.COM 		}
4867836SJohn.Forte@Sun.COM 
4877836SJohn.Forte@Sun.COM 		/* Found a suitable set with autosync on, in logging mode */
4887836SJohn.Forte@Sun.COM 		sets++;
4897836SJohn.Forte@Sun.COM 	}
4907836SJohn.Forte@Sun.COM 
4917836SJohn.Forte@Sun.COM 	if (cfg) {
4927836SJohn.Forte@Sun.COM 		cfg_close(cfg);
4937836SJohn.Forte@Sun.COM 		cfg = NULL;
4947836SJohn.Forte@Sun.COM 		UNLOCKCFG();
4957836SJohn.Forte@Sun.COM 	}
4967836SJohn.Forte@Sun.COM 
4977836SJohn.Forte@Sun.COM 	if (sets == 0) {
4987836SJohn.Forte@Sun.COM #ifdef DEBUG
4997836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
5007836SJohn.Forte@Sun.COM 		    gettext("%s: no sets requiring autosync found for %s"),
5017836SJohn.Forte@Sun.COM 		    program, tohost);
5027836SJohn.Forte@Sun.COM #endif
5037836SJohn.Forte@Sun.COM 		if (death) {
5047836SJohn.Forte@Sun.COM 			spcs_log("sndr", NULL,
5057836SJohn.Forte@Sun.COM 			    gettext("%s: autosync thread stopping for %s "
5067836SJohn.Forte@Sun.COM 			    "(host deconfigured)"), program, tohost);
5077836SJohn.Forte@Sun.COM 		}
5087836SJohn.Forte@Sun.COM 		goto done;
5097836SJohn.Forte@Sun.COM 	}
5107836SJohn.Forte@Sun.COM 
5117836SJohn.Forte@Sun.COM 	/* Keep issuing rdcadm -u commands until they have all completed */
5127836SJohn.Forte@Sun.COM 	for (;;) {
5137836SJohn.Forte@Sun.COM 		if (!first)
5147836SJohn.Forte@Sun.COM 			first++;
5157836SJohn.Forte@Sun.COM 		else
5167836SJohn.Forte@Sun.COM 			(void) sleep(RESYNC_SLEEP);
5177836SJohn.Forte@Sun.COM 
5187836SJohn.Forte@Sun.COM 		/* Issue rdcadm -u commands for all remaining sets */
5197836SJohn.Forte@Sun.COM 		for (i = 0; i < sets; i++) {
5207836SJohn.Forte@Sun.COM 			if (sync_done[i])
5217836SJohn.Forte@Sun.COM 				continue;
5227836SJohn.Forte@Sun.COM 
5237836SJohn.Forte@Sun.COM 			/*
5247836SJohn.Forte@Sun.COM 			 * Need to check if autosync was turned off for a set
5257836SJohn.Forte@Sun.COM 			 * while we were sleeping. We could have the case where
5267836SJohn.Forte@Sun.COM 			 * an update sync failed and autosync was disabled
5277836SJohn.Forte@Sun.COM 			 * while we were sleeping and didn't detect the disable.
5287836SJohn.Forte@Sun.COM 			 * See BugID 4814213.
5297836SJohn.Forte@Sun.COM 			 */
5307836SJohn.Forte@Sun.COM 			parms.command = RDC_CMD_STATUS;
5317836SJohn.Forte@Sun.COM 			bcopy((void *)(&rdc_set[i]),
5327836SJohn.Forte@Sun.COM 			    (void *)(&parms.rdc_set[0]), sizeof (rdc_set_t));
5337836SJohn.Forte@Sun.COM 			if (RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0,
5347836SJohn.Forte@Sun.COM 			    ustatus) < 0) {
5357836SJohn.Forte@Sun.COM 				spcs_log("sndr", &ustatus, gettext("%s: "
5367836SJohn.Forte@Sun.COM 				    "status not available for %s:%s, stopping "
5377836SJohn.Forte@Sun.COM 				    "this autosync attempt"), program, tohost,
5387836SJohn.Forte@Sun.COM 				    rdc_set[i].secondary.file);
5397836SJohn.Forte@Sun.COM 				sync_done[i] = 1;
5407836SJohn.Forte@Sun.COM 				syncs_done++;
5417836SJohn.Forte@Sun.COM 				continue;
5427836SJohn.Forte@Sun.COM 			}
5437836SJohn.Forte@Sun.COM 			if (!(parms.rdc_set[0].autosync)) {
5447836SJohn.Forte@Sun.COM #ifdef DEBUG
5457836SJohn.Forte@Sun.COM 	spcs_log("sndr", NULL, gettext("%s: autosync disabled during sleep, "
5467836SJohn.Forte@Sun.COM 	    "stopping attempt for set %s:%s"), program, tohost,
5477836SJohn.Forte@Sun.COM 	    rdc_set[i].secondary.file);
5487836SJohn.Forte@Sun.COM #endif
5497836SJohn.Forte@Sun.COM 				sync_done[i] = 1;
5507836SJohn.Forte@Sun.COM 				syncs_done++;
5517836SJohn.Forte@Sun.COM 				continue;
5527836SJohn.Forte@Sun.COM 			}
5537836SJohn.Forte@Sun.COM 
5547836SJohn.Forte@Sun.COM 			(void) sprintf(cmd, "%s -un %s:%s", RDCADM, tohost,
5557836SJohn.Forte@Sun.COM 			    rdc_set[i].secondary.file);
5567836SJohn.Forte@Sun.COM 			spcs_log("sndr", NULL,
5577836SJohn.Forte@Sun.COM 			    gettext("%s: issuing update sync for %s:%s"),
5587836SJohn.Forte@Sun.COM 			    program, tohost, rdc_set[i].secondary.file);
5597836SJohn.Forte@Sun.COM 			(void) system(cmd);
5607836SJohn.Forte@Sun.COM 		}
5617836SJohn.Forte@Sun.COM 
5627836SJohn.Forte@Sun.COM 		/* Issue rdcadm -w commands to wait for updates to finish */
5637836SJohn.Forte@Sun.COM 		for (i = 0; i < sets; i++) {
5647836SJohn.Forte@Sun.COM 			if (sync_done[i])
5657836SJohn.Forte@Sun.COM 				continue;
5667836SJohn.Forte@Sun.COM 
5677836SJohn.Forte@Sun.COM 			(void) sprintf(cmd, "%s -wn %s:%s", RDCADM, tohost,
5687836SJohn.Forte@Sun.COM 			    rdc_set[i].secondary.file);
5697836SJohn.Forte@Sun.COM 			spcs_log("sndr", NULL,
5707836SJohn.Forte@Sun.COM 			    gettext("%s: issuing wait for %s:%s"),
5717836SJohn.Forte@Sun.COM 			    program, tohost, rdc_set[i].secondary.file);
5727836SJohn.Forte@Sun.COM 
5737836SJohn.Forte@Sun.COM 			(void) system(cmd);
5747836SJohn.Forte@Sun.COM 
5757836SJohn.Forte@Sun.COM 			parms.command = RDC_CMD_STATUS;
5767836SJohn.Forte@Sun.COM 			bcopy((void *)(&rdc_set[i]),
5777836SJohn.Forte@Sun.COM 			    (void *)(&parms.rdc_set[0]), sizeof (rdc_set_t));
5787836SJohn.Forte@Sun.COM 
5797836SJohn.Forte@Sun.COM 			if (RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0,
5807836SJohn.Forte@Sun.COM 			    ustatus) < 0) {
5817836SJohn.Forte@Sun.COM 				spcs_log("sndr", &ustatus,
5827836SJohn.Forte@Sun.COM 				    gettext("%s: status not available for "
5837836SJohn.Forte@Sun.COM 				    "%s:%s, stopping this autosync attempt"),
5847836SJohn.Forte@Sun.COM 				    program, tohost, rdc_set[i].secondary.file);
5857836SJohn.Forte@Sun.COM 				sync_done[i] = 1;
5867836SJohn.Forte@Sun.COM 				syncs_done++;
5877836SJohn.Forte@Sun.COM 				continue;
5887836SJohn.Forte@Sun.COM 			}
5897836SJohn.Forte@Sun.COM 			/* Check if completed OK, failed or autosync off */
5907836SJohn.Forte@Sun.COM 			if (!(parms.rdc_set[0].autosync) ||
5917836SJohn.Forte@Sun.COM 			    !(parms.rdc_set[0].flags & RDC_LOGGING) &&
5927836SJohn.Forte@Sun.COM 			    !(parms.rdc_set[0].flags & RDC_SYNCING)) {
5937836SJohn.Forte@Sun.COM 				sync_done[i] = 1;
5947836SJohn.Forte@Sun.COM 				syncs_done++;
5957836SJohn.Forte@Sun.COM 			}
5967836SJohn.Forte@Sun.COM 		}
5977836SJohn.Forte@Sun.COM 
5987836SJohn.Forte@Sun.COM 		if (syncs_done == sets)
5997836SJohn.Forte@Sun.COM 			break;		/* All completed OK */
6007836SJohn.Forte@Sun.COM 	}
6017836SJohn.Forte@Sun.COM 
6027836SJohn.Forte@Sun.COM done:
6037836SJohn.Forte@Sun.COM 	if (cfg) {
6047836SJohn.Forte@Sun.COM 		cfg_close(cfg);
6057836SJohn.Forte@Sun.COM 		UNLOCKCFG();
6067836SJohn.Forte@Sun.COM 	}
6077836SJohn.Forte@Sun.COM 	spcs_s_ufree(&ustatus);
6087836SJohn.Forte@Sun.COM 	if (sync_done)
6097836SJohn.Forte@Sun.COM 		free(sync_done);
6107836SJohn.Forte@Sun.COM 	if (rdc_set)
6117836SJohn.Forte@Sun.COM 		free(rdc_set);
6127836SJohn.Forte@Sun.COM 	if (death) { /* bye bye */
6137836SJohn.Forte@Sun.COM 		/*
6147836SJohn.Forte@Sun.COM 		 * if perhaps we lost some race, lets remove this entry from
6157836SJohn.Forte@Sun.COM 		 * the list. Then, if something did go wrong, and we did kill
6167836SJohn.Forte@Sun.COM 		 * a valid thread, it will be detected on the next go around
6177836SJohn.Forte@Sun.COM 		 * of the thread who is looking for new hosts to spawn threads
6187836SJohn.Forte@Sun.COM 		 */
6197836SJohn.Forte@Sun.COM 
6207836SJohn.Forte@Sun.COM 		remove_from_hostlist(tohost);
6217836SJohn.Forte@Sun.COM 		thr_exit(0);
6227836SJohn.Forte@Sun.COM 	}
6237836SJohn.Forte@Sun.COM 
6247836SJohn.Forte@Sun.COM 	(void) sleep(RESYNC_SLEEP);
6257836SJohn.Forte@Sun.COM }
6267836SJohn.Forte@Sun.COM 
6277836SJohn.Forte@Sun.COM /*
6287836SJohn.Forte@Sun.COM  * Wait for notification by the kernel of a sync start or a sync completed OK
6297836SJohn.Forte@Sun.COM  */
6307836SJohn.Forte@Sun.COM void *
wait_sync_event()6317836SJohn.Forte@Sun.COM wait_sync_event()
6327836SJohn.Forte@Sun.COM {
6337836SJohn.Forte@Sun.COM 	spcs_s_info_t ustatus;
6347836SJohn.Forte@Sun.COM 	char master[NSC_MAXPATH];
6357836SJohn.Forte@Sun.COM 	char group[NSC_MAXPATH];
6367836SJohn.Forte@Sun.COM 	int state;
6377836SJohn.Forte@Sun.COM 
6387836SJohn.Forte@Sun.COM 	ustatus = spcs_s_ucreate();
6397836SJohn.Forte@Sun.COM 
6407836SJohn.Forte@Sun.COM 	master[0] = '\0';
6417836SJohn.Forte@Sun.COM 	group[0] = '\0';
6427836SJohn.Forte@Sun.COM 
6437836SJohn.Forte@Sun.COM 	/* Never give up */
6447836SJohn.Forte@Sun.COM 	for (;;) {
6457836SJohn.Forte@Sun.COM 		/* Kernel tells us which volume and group the event is for */
6467836SJohn.Forte@Sun.COM 		state = RDC_IOCTL(RDC_SYNC_EVENT, master, group, 0, 0, 0,
6477836SJohn.Forte@Sun.COM 		    ustatus);
6487836SJohn.Forte@Sun.COM 		if (state < SPCS_S_OK) {
6497836SJohn.Forte@Sun.COM 			if (errno != EAGAIN) {
6507836SJohn.Forte@Sun.COM 				spcs_log("sndr", &ustatus,
6517836SJohn.Forte@Sun.COM 				    gettext("%s: update ioctl"),
6527836SJohn.Forte@Sun.COM 				    program);
6537836SJohn.Forte@Sun.COM 				rdc_warn(&ustatus, gettext("update ioctl"));
6547836SJohn.Forte@Sun.COM 				continue;
6557836SJohn.Forte@Sun.COM 			}
6567836SJohn.Forte@Sun.COM 			master[0] = '\0';
6577836SJohn.Forte@Sun.COM 			continue;
6587836SJohn.Forte@Sun.COM 		}
6597836SJohn.Forte@Sun.COM 
6607836SJohn.Forte@Sun.COM 		/*
6617836SJohn.Forte@Sun.COM 		 * If target is mounted at the start of a sync or reverse sync,
6627836SJohn.Forte@Sun.COM 		 * return a negative ack.
6637836SJohn.Forte@Sun.COM 		 */
6647836SJohn.Forte@Sun.COM 		if ((state == RDC_SYNC_START || state == RDC_RSYNC_START) &&
6657836SJohn.Forte@Sun.COM 		    mounted(master)) {
6667836SJohn.Forte@Sun.COM 			spcs_log("sndr", NULL,
6677836SJohn.Forte@Sun.COM 			    gettext("%s: %s has a file system mounted"),
6687836SJohn.Forte@Sun.COM 			    program, master);
6697836SJohn.Forte@Sun.COM 			rdc_warn(NULL,
6707836SJohn.Forte@Sun.COM 			    gettext("%s has a file system mounted"),
6717836SJohn.Forte@Sun.COM 			    master);
6727836SJohn.Forte@Sun.COM 			master[0] = '\0';	/* negative ack */
6737836SJohn.Forte@Sun.COM 			continue;
6747836SJohn.Forte@Sun.COM 		}
6757836SJohn.Forte@Sun.COM 
6767836SJohn.Forte@Sun.COM 		switch (state) {
6777836SJohn.Forte@Sun.COM 		case RDC_SYNC_START:
6787836SJohn.Forte@Sun.COM 			if (group[0])
6797836SJohn.Forte@Sun.COM 				group_start(group);
6807836SJohn.Forte@Sun.COM 			else
6817836SJohn.Forte@Sun.COM 				sync_start(master);
6827836SJohn.Forte@Sun.COM 			break;
6837836SJohn.Forte@Sun.COM 
6847836SJohn.Forte@Sun.COM 		case RDC_SYNC_DONE:
6857836SJohn.Forte@Sun.COM 			if (group[0])
6867836SJohn.Forte@Sun.COM 				group_complete(group);
6877836SJohn.Forte@Sun.COM 			else
6887836SJohn.Forte@Sun.COM 				sync_complete(master);
6897836SJohn.Forte@Sun.COM 			break;
6907836SJohn.Forte@Sun.COM 
6917836SJohn.Forte@Sun.COM 		default:
6927836SJohn.Forte@Sun.COM 			break;
6937836SJohn.Forte@Sun.COM 		}
6947836SJohn.Forte@Sun.COM 	}
6957836SJohn.Forte@Sun.COM 	/* LINTED */
6967836SJohn.Forte@Sun.COM }
6977836SJohn.Forte@Sun.COM 
6987836SJohn.Forte@Sun.COM 
6997836SJohn.Forte@Sun.COM /*
7007836SJohn.Forte@Sun.COM  * A sync has completed OK to a volume not belonging to a group.
7017836SJohn.Forte@Sun.COM  * Set the state of the ndr_ii config entry to "update".
7027836SJohn.Forte@Sun.COM  */
7037836SJohn.Forte@Sun.COM void
sync_complete(char * master)7047836SJohn.Forte@Sun.COM sync_complete(char *master)
7057836SJohn.Forte@Sun.COM {
7067836SJohn.Forte@Sun.COM 	CFGFILE *cfg = NULL;
7077836SJohn.Forte@Sun.COM 	char buf[CFG_MAX_BUF];
7087836SJohn.Forte@Sun.COM 	char key[CFG_MAX_KEY];
7097836SJohn.Forte@Sun.COM 	int i;
7107836SJohn.Forte@Sun.COM 	int setnumber;
7117836SJohn.Forte@Sun.COM 	int sev;
7127836SJohn.Forte@Sun.COM 
7137836SJohn.Forte@Sun.COM 	LOCKCFG();
7147836SJohn.Forte@Sun.COM 	if ((cfg = cfg_open(NULL)) == NULL) {
7157836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
7167836SJohn.Forte@Sun.COM 		    gettext("%s: error opening config"),
7177836SJohn.Forte@Sun.COM 		    program);
7187836SJohn.Forte@Sun.COM 		rdc_warn(NULL, gettext("error opening config"));
7197836SJohn.Forte@Sun.COM 		UNLOCKCFG();
7207836SJohn.Forte@Sun.COM 		return;
7217836SJohn.Forte@Sun.COM 	}
7227836SJohn.Forte@Sun.COM 	if (!cfg_lock(cfg, CFG_WRLOCK)) {
7237836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
7247836SJohn.Forte@Sun.COM 		    gettext("%s: error locking config"),
7257836SJohn.Forte@Sun.COM 		    program);
7267836SJohn.Forte@Sun.COM 		rdc_warn(NULL, gettext("error locking config"));
7277836SJohn.Forte@Sun.COM 		cfg_close(cfg);
7287836SJohn.Forte@Sun.COM 		UNLOCKCFG();
7297836SJohn.Forte@Sun.COM 		return;
7307836SJohn.Forte@Sun.COM 	}
7317836SJohn.Forte@Sun.COM 
7327836SJohn.Forte@Sun.COM 	/* get ndr_ii entries until a match is found */
7337836SJohn.Forte@Sun.COM 	for (i = 0; ; i++) {
7347836SJohn.Forte@Sun.COM 		setnumber = i + 1;
7357836SJohn.Forte@Sun.COM 
7367836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.secondary",
7377836SJohn.Forte@Sun.COM 		    setnumber);
7387836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
7397836SJohn.Forte@Sun.COM 			break;
7407836SJohn.Forte@Sun.COM 		if (strcmp(buf, master) != 0)
7417836SJohn.Forte@Sun.COM 			continue;
7427836SJohn.Forte@Sun.COM 
7437836SJohn.Forte@Sun.COM 		/* Found the matching entry */
7447836SJohn.Forte@Sun.COM 
7457836SJohn.Forte@Sun.COM 		/*
7467836SJohn.Forte@Sun.COM 		 * Set state to "update" so that starting another sync will
7477836SJohn.Forte@Sun.COM 		 * cause a new Point-in-Time Copy snapshot to be taken.
7487836SJohn.Forte@Sun.COM 		 */
7497836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
7507836SJohn.Forte@Sun.COM 		    setnumber);
7517836SJohn.Forte@Sun.COM 		if ((cfg_put_cstring(cfg, key, UPDATE, strlen(UPDATE)) < 0) ||
7527836SJohn.Forte@Sun.COM 		    (cfg_commit(cfg) < 0)) {
7537836SJohn.Forte@Sun.COM 			spcs_log("sndr", NULL,
7547836SJohn.Forte@Sun.COM 			    gettext("%s: unable to update \"%s\" "
7557836SJohn.Forte@Sun.COM 			    "in configuration storage: %s"),
7567836SJohn.Forte@Sun.COM 			    program, buf, cfg_error(&sev));
7577836SJohn.Forte@Sun.COM 			rdc_warn(NULL,
7587836SJohn.Forte@Sun.COM 			    gettext("unable to update \"%s\" "
7597836SJohn.Forte@Sun.COM 			    "in configuration storage: %s"),
7607836SJohn.Forte@Sun.COM 			    buf, cfg_error(&sev));
7617836SJohn.Forte@Sun.COM 		}
7627836SJohn.Forte@Sun.COM 		break;
7637836SJohn.Forte@Sun.COM 	}
7647836SJohn.Forte@Sun.COM 
7657836SJohn.Forte@Sun.COM 	cfg_close(cfg);
7667836SJohn.Forte@Sun.COM 	UNLOCKCFG();
7677836SJohn.Forte@Sun.COM }
7687836SJohn.Forte@Sun.COM 
7697836SJohn.Forte@Sun.COM 
7707836SJohn.Forte@Sun.COM /*
7717836SJohn.Forte@Sun.COM  * Starting a sync to the specified master volume.
7727836SJohn.Forte@Sun.COM  * Check the ndr_ii config entries to see if a Point-in-Time Copy
7737836SJohn.Forte@Sun.COM  * snapshot should be taken.
7747836SJohn.Forte@Sun.COM  */
7757836SJohn.Forte@Sun.COM void
sync_start(char * master)7767836SJohn.Forte@Sun.COM sync_start(char *master)
7777836SJohn.Forte@Sun.COM {
7787836SJohn.Forte@Sun.COM 	char cmd[256];
7797836SJohn.Forte@Sun.COM 	char buf[CFG_MAX_BUF];
7807836SJohn.Forte@Sun.COM 	char key[CFG_MAX_KEY];
7817836SJohn.Forte@Sun.COM 	CFGFILE *cfg = NULL;
7827836SJohn.Forte@Sun.COM 	int i;
7837836SJohn.Forte@Sun.COM 	int setnumber;
7847836SJohn.Forte@Sun.COM 	int found;
7857836SJohn.Forte@Sun.COM 	int sev;
7867836SJohn.Forte@Sun.COM 	char shadow[NSC_MAXPATH];
7877836SJohn.Forte@Sun.COM 	char bitmap[NSC_MAXPATH];
7887836SJohn.Forte@Sun.COM 	char *ctag = NULL;
7897836SJohn.Forte@Sun.COM 
7907836SJohn.Forte@Sun.COM 	LOCKCFG();
7917836SJohn.Forte@Sun.COM 	if ((cfg = cfg_open(NULL)) == NULL) {
7927836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
7937836SJohn.Forte@Sun.COM 		    gettext("%s: error opening config"),
7947836SJohn.Forte@Sun.COM 		    program);
7957836SJohn.Forte@Sun.COM 		rdc_warn(NULL,
7967836SJohn.Forte@Sun.COM 		    gettext("error opening config"));
7977836SJohn.Forte@Sun.COM 		UNLOCKCFG();
7987836SJohn.Forte@Sun.COM 		return;
7997836SJohn.Forte@Sun.COM 	}
8007836SJohn.Forte@Sun.COM 	if (!cfg_lock(cfg, CFG_RDLOCK)) {
8017836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
8027836SJohn.Forte@Sun.COM 		    gettext("%s: error locking config"),
8037836SJohn.Forte@Sun.COM 		    program);
8047836SJohn.Forte@Sun.COM 		rdc_warn(NULL, gettext("error locking config"));
8057836SJohn.Forte@Sun.COM 		cfg_close(cfg);
8067836SJohn.Forte@Sun.COM 		UNLOCKCFG();
8077836SJohn.Forte@Sun.COM 		return;
8087836SJohn.Forte@Sun.COM 	}
8097836SJohn.Forte@Sun.COM 
8107836SJohn.Forte@Sun.COM 	found = 0;
8117836SJohn.Forte@Sun.COM 	/* get ndr_ii entries until a match is found */
8127836SJohn.Forte@Sun.COM 	for (i = 0; ; i++) {
8137836SJohn.Forte@Sun.COM 		setnumber = i + 1;
8147836SJohn.Forte@Sun.COM 
8157836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.secondary",
8167836SJohn.Forte@Sun.COM 		    setnumber);
8177836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
8187836SJohn.Forte@Sun.COM 			break;
8197836SJohn.Forte@Sun.COM 		if (strcmp(buf, master) != 0)
8207836SJohn.Forte@Sun.COM 			continue;
8217836SJohn.Forte@Sun.COM 
8227836SJohn.Forte@Sun.COM 		/* Got a matching entry */
8237836SJohn.Forte@Sun.COM 
8247836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.shadow",
8257836SJohn.Forte@Sun.COM 		    setnumber);
8267836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
8277836SJohn.Forte@Sun.COM 			break;
828*11576SSurya.Prakki@Sun.COM 		(void) strncpy(shadow, buf, NSC_MAXPATH);
8297836SJohn.Forte@Sun.COM 
8307836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.bitmap",
8317836SJohn.Forte@Sun.COM 		    setnumber);
8327836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
8337836SJohn.Forte@Sun.COM 			break;
834*11576SSurya.Prakki@Sun.COM 		(void) strncpy(bitmap, buf, NSC_MAXPATH);
8357836SJohn.Forte@Sun.COM 
8367836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
8377836SJohn.Forte@Sun.COM 		    setnumber);
8387836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
8397836SJohn.Forte@Sun.COM 			break;
8407836SJohn.Forte@Sun.COM 
8417836SJohn.Forte@Sun.COM 		/*
8427836SJohn.Forte@Sun.COM 		 * If an PIT snapshot has already been taken, and syncing did
8437836SJohn.Forte@Sun.COM 		 * not complete, the state will be "noupdate", to indicate we
8447836SJohn.Forte@Sun.COM 		 * should not take another one at this point.
8457836SJohn.Forte@Sun.COM 		 */
8467836SJohn.Forte@Sun.COM 		if (strcmp(buf, NOUPDATE) != 0)
8477836SJohn.Forte@Sun.COM 			found = 1;
8487836SJohn.Forte@Sun.COM 
8497836SJohn.Forte@Sun.COM 		break;
8507836SJohn.Forte@Sun.COM 	}
8517836SJohn.Forte@Sun.COM 
8527836SJohn.Forte@Sun.COM 	if (!found) {
8537836SJohn.Forte@Sun.COM 		cfg_close(cfg);
8547836SJohn.Forte@Sun.COM 		UNLOCKCFG();
8557836SJohn.Forte@Sun.COM 		return;
8567836SJohn.Forte@Sun.COM 	}
8577836SJohn.Forte@Sun.COM 
8587836SJohn.Forte@Sun.COM 	found = 0;
8597836SJohn.Forte@Sun.COM 	/* get ii entries until a match is found */
8607836SJohn.Forte@Sun.COM 	for (i = 0; ; i++) {
8617836SJohn.Forte@Sun.COM 		setnumber = i + 1;
8627836SJohn.Forte@Sun.COM 
8637836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ii.set%d.shadow",
8647836SJohn.Forte@Sun.COM 		    setnumber);
8657836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
8667836SJohn.Forte@Sun.COM 			break;
8677836SJohn.Forte@Sun.COM 		if (strcmp(buf, shadow) != 0)
8687836SJohn.Forte@Sun.COM 			continue;
8697836SJohn.Forte@Sun.COM 
8707836SJohn.Forte@Sun.COM 		/* Matching shadow found, so ii already enabled */
8717836SJohn.Forte@Sun.COM 		found = 1;
8727836SJohn.Forte@Sun.COM 		break;
8737836SJohn.Forte@Sun.COM 	}
8747836SJohn.Forte@Sun.COM 
8757836SJohn.Forte@Sun.COM 	if (found) {
8767836SJohn.Forte@Sun.COM 		/* Already PIT enabled, so just take a snapshot */
8777836SJohn.Forte@Sun.COM 
8787836SJohn.Forte@Sun.COM 		/* Get cluster tag of matching entry */
8797836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ii.set%d.cnode", setnumber);
8807836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) >= 0)
8817836SJohn.Forte@Sun.COM 			if ((strlen(buf) == 0) || (buf[0] == '-'))
8827836SJohn.Forte@Sun.COM 					ctag = "-C local";
8837836SJohn.Forte@Sun.COM 				else
8847836SJohn.Forte@Sun.COM 					ctag = "";
8857836SJohn.Forte@Sun.COM 		(void) sprintf(cmd, "%s %s -u s %s", IIADM, ctag, shadow);
8867836SJohn.Forte@Sun.COM 	} else {
8877836SJohn.Forte@Sun.COM 		/*
8887836SJohn.Forte@Sun.COM 		 * If clustered, need to enable PIT Copy sets in the same
8897836SJohn.Forte@Sun.COM 		 * cluster as the Remote Mirror set
8907836SJohn.Forte@Sun.COM 		 */
8917836SJohn.Forte@Sun.COM 
8927836SJohn.Forte@Sun.COM 		if (clustered) {
8937836SJohn.Forte@Sun.COM 			/* Find a RM set with master as the local volume */
8947836SJohn.Forte@Sun.COM 
8957836SJohn.Forte@Sun.COM 			for (i = 0; i < rdc_maxsets; i++) {
8967836SJohn.Forte@Sun.COM 				setnumber = i + 1;
8977836SJohn.Forte@Sun.COM 				(void) snprintf(key, sizeof (key),
8987836SJohn.Forte@Sun.COM 				    "sndr.set%d.phost", setnumber);
8997836SJohn.Forte@Sun.COM 				if (cfg_get_cstring(cfg, key, buf,
9007836SJohn.Forte@Sun.COM 				    CFG_MAX_BUF) < 0)
9017836SJohn.Forte@Sun.COM 					break;
9027836SJohn.Forte@Sun.COM 
9037836SJohn.Forte@Sun.COM 				if (self_check(buf))
9047836SJohn.Forte@Sun.COM 					(void) snprintf(key, sizeof (key),
9057836SJohn.Forte@Sun.COM 					    "sndr.set%d.primary", setnumber);
9067836SJohn.Forte@Sun.COM 				else
9077836SJohn.Forte@Sun.COM 					(void) snprintf(key, sizeof (key),
9087836SJohn.Forte@Sun.COM 					    "sndr.set%d.secondary", setnumber);
9097836SJohn.Forte@Sun.COM 				if (cfg_get_cstring(cfg, key, buf,
9107836SJohn.Forte@Sun.COM 				    CFG_MAX_BUF) < 0)
9117836SJohn.Forte@Sun.COM 					break;
9127836SJohn.Forte@Sun.COM 
9137836SJohn.Forte@Sun.COM 				if (strcmp(buf, master) != 0)
9147836SJohn.Forte@Sun.COM 					continue;
9157836SJohn.Forte@Sun.COM 
9167836SJohn.Forte@Sun.COM 				/* Get cluster tag of matching entry */
9177836SJohn.Forte@Sun.COM 
9187836SJohn.Forte@Sun.COM 				(void) snprintf(key, sizeof (key),
9197836SJohn.Forte@Sun.COM 				    "sndr.set%d.cnode", setnumber);
9207836SJohn.Forte@Sun.COM 				if (cfg_get_cstring(cfg, key, buf,
9217836SJohn.Forte@Sun.COM 				    CFG_MAX_BUF) < 0)
9227836SJohn.Forte@Sun.COM 					break;
9237836SJohn.Forte@Sun.COM 				if ((strlen(buf) == 0) || (buf[0] == '-'))
9247836SJohn.Forte@Sun.COM 					ctag = strdup("local");
9257836SJohn.Forte@Sun.COM 				else
9267836SJohn.Forte@Sun.COM 					ctag = strdup(buf);
9277836SJohn.Forte@Sun.COM 				break;
9287836SJohn.Forte@Sun.COM 			}
9297836SJohn.Forte@Sun.COM 		}
9307836SJohn.Forte@Sun.COM 
9317836SJohn.Forte@Sun.COM 		/* Not already enabled, so enable a dependent */
9327836SJohn.Forte@Sun.COM 		if (ctag) {
9337836SJohn.Forte@Sun.COM 			(void) sprintf(cmd, "%s -C %s -e dep %s %s %s", IIADM,
9347836SJohn.Forte@Sun.COM 			    ctag, master, shadow, bitmap);
9357836SJohn.Forte@Sun.COM 			free(ctag);
9367836SJohn.Forte@Sun.COM 		} else
9377836SJohn.Forte@Sun.COM 			(void) sprintf(cmd, "%s -e dep %s %s %s", IIADM, master,
9387836SJohn.Forte@Sun.COM 			    shadow, bitmap);
9397836SJohn.Forte@Sun.COM 	}
9407836SJohn.Forte@Sun.COM 
9417836SJohn.Forte@Sun.COM 	cfg_close(cfg);
9427836SJohn.Forte@Sun.COM 
9437836SJohn.Forte@Sun.COM 	if (system(cmd) != 0) {
9447836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
9457836SJohn.Forte@Sun.COM 		    gettext("Point-in-Time Copy snapshot failed for %s %s %s."
9467836SJohn.Forte@Sun.COM 		    " Please check validity of ndr_ii entry"),
9477836SJohn.Forte@Sun.COM 		    master, shadow, bitmap);
9487836SJohn.Forte@Sun.COM 		cfg_close(cfg);
9497836SJohn.Forte@Sun.COM 		UNLOCKCFG();
9507836SJohn.Forte@Sun.COM 		return;
9517836SJohn.Forte@Sun.COM 	}
9527836SJohn.Forte@Sun.COM 
9537836SJohn.Forte@Sun.COM 	/*
9547836SJohn.Forte@Sun.COM 	 * PIT Copy enable or update was fine, so update the ndr_ii entry
9557836SJohn.Forte@Sun.COM 	 * to "noupdate", to prevent invalid point in time copies.
9567836SJohn.Forte@Sun.COM 	 */
9577836SJohn.Forte@Sun.COM 
9587836SJohn.Forte@Sun.COM 	if ((cfg = cfg_open(NULL)) == NULL) {
9597836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
9607836SJohn.Forte@Sun.COM 		    gettext("%s: error opening config"),
9617836SJohn.Forte@Sun.COM 		    program);
9627836SJohn.Forte@Sun.COM 		rdc_warn(NULL,
9637836SJohn.Forte@Sun.COM 		    gettext("error opening config"));
9647836SJohn.Forte@Sun.COM 		UNLOCKCFG();
9657836SJohn.Forte@Sun.COM 		return;
9667836SJohn.Forte@Sun.COM 	}
9677836SJohn.Forte@Sun.COM 	if (!cfg_lock(cfg, CFG_WRLOCK)) {
9687836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
9697836SJohn.Forte@Sun.COM 		    gettext("%s: error locking config"),
9707836SJohn.Forte@Sun.COM 		    program);
9717836SJohn.Forte@Sun.COM 		rdc_warn(NULL, gettext("error locking config"));
9727836SJohn.Forte@Sun.COM 		cfg_close(cfg);
9737836SJohn.Forte@Sun.COM 		UNLOCKCFG();
9747836SJohn.Forte@Sun.COM 		return;
9757836SJohn.Forte@Sun.COM 	}
9767836SJohn.Forte@Sun.COM 
9777836SJohn.Forte@Sun.COM 	/* get ndr_ii entries until a match is found */
9787836SJohn.Forte@Sun.COM 	for (i = 0; ; i++) {
9797836SJohn.Forte@Sun.COM 		setnumber = i + 1;
9807836SJohn.Forte@Sun.COM 
9817836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.shadow",
9827836SJohn.Forte@Sun.COM 		    setnumber);
9837836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
9847836SJohn.Forte@Sun.COM 			break;
9857836SJohn.Forte@Sun.COM 		if (strcmp(buf, shadow) != 0)
9867836SJohn.Forte@Sun.COM 			continue;
9877836SJohn.Forte@Sun.COM 
9887836SJohn.Forte@Sun.COM 		/* Found the matching entry */
9897836SJohn.Forte@Sun.COM 
9907836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
9917836SJohn.Forte@Sun.COM 		    setnumber);
9927836SJohn.Forte@Sun.COM 		if ((cfg_put_cstring(cfg, key, NOUPDATE,
9937836SJohn.Forte@Sun.COM 			strlen(NOUPDATE)) < 0) || (cfg_commit(cfg) < 0)) {
9947836SJohn.Forte@Sun.COM 			spcs_log("sndr", NULL,
9957836SJohn.Forte@Sun.COM 			    gettext("%s: unable to update \"%s\" "
9967836SJohn.Forte@Sun.COM 			    "in configuration storage: %s"),
9977836SJohn.Forte@Sun.COM 			    program, buf, cfg_error(&sev));
9987836SJohn.Forte@Sun.COM 			rdc_warn(NULL,
9997836SJohn.Forte@Sun.COM 			    gettext("unable to update \"%s\" "
10007836SJohn.Forte@Sun.COM 			    "in configuration storage: %s"),
10017836SJohn.Forte@Sun.COM 			    buf, cfg_error(&sev));
10027836SJohn.Forte@Sun.COM 		}
10037836SJohn.Forte@Sun.COM 		break;
10047836SJohn.Forte@Sun.COM 	}
10057836SJohn.Forte@Sun.COM 	cfg_close(cfg);
10067836SJohn.Forte@Sun.COM 	UNLOCKCFG();
10077836SJohn.Forte@Sun.COM }
10087836SJohn.Forte@Sun.COM 
10097836SJohn.Forte@Sun.COM void
cleanup_hostlist(rdc_status_t * rdc_info)10107836SJohn.Forte@Sun.COM cleanup_hostlist(rdc_status_t *rdc_info)
10117836SJohn.Forte@Sun.COM {
10127836SJohn.Forte@Sun.COM 	int i, j, k;
10137836SJohn.Forte@Sun.COM 	char *host, *exhost;
10147836SJohn.Forte@Sun.COM 
10157836SJohn.Forte@Sun.COM 
10167836SJohn.Forte@Sun.COM 	(void) mutex_lock(&host_list->hosts_mutex);
10177836SJohn.Forte@Sun.COM 	for (i = 0; i < host_list->numhosts; i++) {
10187836SJohn.Forte@Sun.COM 		int found = 0;
10197836SJohn.Forte@Sun.COM 		for (j = 0; (j < rdc_maxsets) && !found; j++) {
10207836SJohn.Forte@Sun.COM 			if (!rdc_info->rdc_set[j].flags & RDC_ENABLED)
10217836SJohn.Forte@Sun.COM 				continue;
10227836SJohn.Forte@Sun.COM 			if ((!host_list->configured[i]) ||
10237836SJohn.Forte@Sun.COM 			    (host_list->hosts[i] == '\0')) {
10247836SJohn.Forte@Sun.COM 				(void) mutex_unlock(&host_list->hosts_mutex);
10257836SJohn.Forte@Sun.COM 				return;
10267836SJohn.Forte@Sun.COM 			}
10277836SJohn.Forte@Sun.COM 
10287836SJohn.Forte@Sun.COM 			host = rdc_info->rdc_set[j].secondary.intf;
10297836SJohn.Forte@Sun.COM 			if (strcmp(host_list->hosts[i], host) == 0)
10307836SJohn.Forte@Sun.COM 				found++;
10317836SJohn.Forte@Sun.COM 		}
10327836SJohn.Forte@Sun.COM 		if (j == rdc_maxsets) {
10337836SJohn.Forte@Sun.COM 			/*
10347836SJohn.Forte@Sun.COM 			 * this set is not in the kernel, so remove from list
10357836SJohn.Forte@Sun.COM 			 */
10367836SJohn.Forte@Sun.COM 			exhost = host_list->hosts[i];
10377836SJohn.Forte@Sun.COM 			if (exhost) {
10387836SJohn.Forte@Sun.COM 				free(exhost);
10397836SJohn.Forte@Sun.COM 				exhost = NULL;
10407836SJohn.Forte@Sun.COM 			}
10417836SJohn.Forte@Sun.COM 
10427836SJohn.Forte@Sun.COM 			k = i;
10437836SJohn.Forte@Sun.COM 			while (k < host_list->numhosts) {
10447836SJohn.Forte@Sun.COM 			    host_list->hosts[k] = k < host_list->numhosts - 1 ?
10457836SJohn.Forte@Sun.COM 				host_list->hosts[k+1] : NULL;
10467836SJohn.Forte@Sun.COM 			    k++;
10477836SJohn.Forte@Sun.COM 			}
10487836SJohn.Forte@Sun.COM 			host_list->numhosts--;
10497836SJohn.Forte@Sun.COM 
10507836SJohn.Forte@Sun.COM 			bcopy(&host_list->configured[i+1],
10517836SJohn.Forte@Sun.COM 			    &host_list->configured[i],
10527836SJohn.Forte@Sun.COM 			    (MAXHOSTS - i + 1) * sizeof (int));
10537836SJohn.Forte@Sun.COM 			host_list->configured[MAXHOSTS - 1] = 0;
10547836SJohn.Forte@Sun.COM 		}
10557836SJohn.Forte@Sun.COM 	}
10567836SJohn.Forte@Sun.COM 	(void) mutex_unlock(&host_list->hosts_mutex);
10577836SJohn.Forte@Sun.COM }
10587836SJohn.Forte@Sun.COM 
10597836SJohn.Forte@Sun.COM /*
10607836SJohn.Forte@Sun.COM  * explicity remove a host from the host list
10617836SJohn.Forte@Sun.COM  * also update the configured array
10627836SJohn.Forte@Sun.COM  * called in rdc_sync, just before exiting a thread.
10637836SJohn.Forte@Sun.COM  */
10647836SJohn.Forte@Sun.COM void
remove_from_hostlist(char * host)10657836SJohn.Forte@Sun.COM remove_from_hostlist(char *host)
10667836SJohn.Forte@Sun.COM {
10677836SJohn.Forte@Sun.COM 	int i, k;
10687836SJohn.Forte@Sun.COM 	char *exhost;
10697836SJohn.Forte@Sun.COM 
10707836SJohn.Forte@Sun.COM 	/* why bother? */
10717836SJohn.Forte@Sun.COM 	if ((!host) || (host[0] == '\0'))
10727836SJohn.Forte@Sun.COM 		return;
10737836SJohn.Forte@Sun.COM 
10747836SJohn.Forte@Sun.COM 	(void) mutex_lock(&host_list->hosts_mutex);
10757836SJohn.Forte@Sun.COM 	for (i = 0; i < host_list->numhosts; i++) {
10767836SJohn.Forte@Sun.COM 		if (strcmp(host, host_list->hosts[i]) == 0) { /* found it */
10777836SJohn.Forte@Sun.COM 			exhost = host_list->hosts[i];
10787836SJohn.Forte@Sun.COM 			if (exhost) {
10797836SJohn.Forte@Sun.COM 				free(exhost);
10807836SJohn.Forte@Sun.COM 				exhost = NULL;
10817836SJohn.Forte@Sun.COM 			}
10827836SJohn.Forte@Sun.COM 			k = i;
10837836SJohn.Forte@Sun.COM 			while (k < host_list->numhosts) {
10847836SJohn.Forte@Sun.COM 			    host_list->hosts[k] = k < host_list->numhosts - 1 ?
10857836SJohn.Forte@Sun.COM 				host_list->hosts[k+1] : NULL;
10867836SJohn.Forte@Sun.COM 			    k++;
10877836SJohn.Forte@Sun.COM 			}
10887836SJohn.Forte@Sun.COM 			host_list->numhosts--;
10897836SJohn.Forte@Sun.COM 			bcopy(&host_list->configured[i+1],
10907836SJohn.Forte@Sun.COM 			    &host_list->configured[i],
10917836SJohn.Forte@Sun.COM 			    (MAXHOSTS - i + 1) * sizeof (int));
10927836SJohn.Forte@Sun.COM 			host_list->configured[MAXHOSTS - 1] = 0;
10937836SJohn.Forte@Sun.COM 		}
10947836SJohn.Forte@Sun.COM 
10957836SJohn.Forte@Sun.COM 	}
10967836SJohn.Forte@Sun.COM 	(void) mutex_unlock(&host_list->hosts_mutex);
10977836SJohn.Forte@Sun.COM }
10987836SJohn.Forte@Sun.COM /*
10997836SJohn.Forte@Sun.COM  * Check to see if this host isn't in our list, so needs a new rdcsyncd proc
11007836SJohn.Forte@Sun.COM  */
11017836SJohn.Forte@Sun.COM int
isnewhost(char * host)11027836SJohn.Forte@Sun.COM isnewhost(char *host)
11037836SJohn.Forte@Sun.COM {
11047836SJohn.Forte@Sun.COM 	int i;
11057836SJohn.Forte@Sun.COM 	int new;
11067836SJohn.Forte@Sun.COM 
11077836SJohn.Forte@Sun.COM 	if (self_check(host)) {
11087836SJohn.Forte@Sun.COM 		return (0);
11097836SJohn.Forte@Sun.COM 	}
11107836SJohn.Forte@Sun.COM 
11117836SJohn.Forte@Sun.COM 	(void) mutex_lock(&host_list->hosts_mutex);
11127836SJohn.Forte@Sun.COM 	new = 1;
11137836SJohn.Forte@Sun.COM 	for (i = 0; i < MAXHOSTS; i++) {
11147836SJohn.Forte@Sun.COM 		if (host_list->configured[i] == 0) {
11157836SJohn.Forte@Sun.COM 			host_list->configured[i] = 1;
11167836SJohn.Forte@Sun.COM 			host_list->hosts[i] = strdup(host);
11177836SJohn.Forte@Sun.COM 			host_list->numhosts++;
11187836SJohn.Forte@Sun.COM 			break;
11197836SJohn.Forte@Sun.COM 		}
11207836SJohn.Forte@Sun.COM 		if (strcmp(host, host_list->hosts[i]) == 0) {
11217836SJohn.Forte@Sun.COM 			new = 0;
11227836SJohn.Forte@Sun.COM 			break;
11237836SJohn.Forte@Sun.COM 		}
11247836SJohn.Forte@Sun.COM 	}
11257836SJohn.Forte@Sun.COM 	(void) mutex_unlock(&host_list->hosts_mutex);
11267836SJohn.Forte@Sun.COM 	if (i == MAXHOSTS)
11277836SJohn.Forte@Sun.COM 		new = 0;
11287836SJohn.Forte@Sun.COM 	return (new);
11297836SJohn.Forte@Sun.COM }
11307836SJohn.Forte@Sun.COM 
11317836SJohn.Forte@Sun.COM 
11327836SJohn.Forte@Sun.COM /*
11337836SJohn.Forte@Sun.COM  * Look for a matching volume name in our remembered list.
11347836SJohn.Forte@Sun.COM  */
11357836SJohn.Forte@Sun.COM int
volume_match(char * buf,char ** volume_list,int volumes)11367836SJohn.Forte@Sun.COM volume_match(char *buf, char **volume_list, int volumes)
11377836SJohn.Forte@Sun.COM {
11387836SJohn.Forte@Sun.COM 	int i;
11397836SJohn.Forte@Sun.COM 	char *vol;
11407836SJohn.Forte@Sun.COM 
11417836SJohn.Forte@Sun.COM 	for (i = 0; i < volumes; i++) {
11427836SJohn.Forte@Sun.COM 		vol = volume_list[i];
11437836SJohn.Forte@Sun.COM 		if (strcmp(buf, vol) == 0) {
11447836SJohn.Forte@Sun.COM 			return (1);
11457836SJohn.Forte@Sun.COM 		}
11467836SJohn.Forte@Sun.COM 	}
11477836SJohn.Forte@Sun.COM 	return (0);
11487836SJohn.Forte@Sun.COM }
11497836SJohn.Forte@Sun.COM 
11507836SJohn.Forte@Sun.COM 
11517836SJohn.Forte@Sun.COM /*
11527836SJohn.Forte@Sun.COM  * A sync has completed to a group. We can only update the ndr_ii entries
11537836SJohn.Forte@Sun.COM  * if all the members of the group have completed their syncs OK.
11547836SJohn.Forte@Sun.COM  * It would be bad to allow some members of the group to have PIT Copy snapshots
11557836SJohn.Forte@Sun.COM  * taken and others not, as they need to be consistent.
11567836SJohn.Forte@Sun.COM  */
11577836SJohn.Forte@Sun.COM void
group_complete(char * group)11587836SJohn.Forte@Sun.COM group_complete(char *group)
11597836SJohn.Forte@Sun.COM {
11607836SJohn.Forte@Sun.COM 	char **volumes = NULL;
11617836SJohn.Forte@Sun.COM 	spcs_s_info_t ustatus;
11627836SJohn.Forte@Sun.COM 	rdc_config_t parms = { 0 };
11637836SJohn.Forte@Sun.COM 	char buf[CFG_MAX_BUF];
11647836SJohn.Forte@Sun.COM 	char key[CFG_MAX_KEY];
11657836SJohn.Forte@Sun.COM 	CFGFILE *cfg = NULL;
11667836SJohn.Forte@Sun.COM 	int i;
11677836SJohn.Forte@Sun.COM 	int setnumber;
11687836SJohn.Forte@Sun.COM 	int found;
11697836SJohn.Forte@Sun.COM 	int replicating = 0;
11707836SJohn.Forte@Sun.COM 	char primary[NSC_MAXPATH];
11717836SJohn.Forte@Sun.COM 	char secondary[NSC_MAXPATH];
11727836SJohn.Forte@Sun.COM 	char phost[MAX_RDC_HOST_SIZE];
11737836SJohn.Forte@Sun.COM 	char shost[MAX_RDC_HOST_SIZE];
11747836SJohn.Forte@Sun.COM 	rdc_set_t *rdc_set;
11757836SJohn.Forte@Sun.COM 	int sev;
11767836SJohn.Forte@Sun.COM 	char *local_file;
11777836SJohn.Forte@Sun.COM 	int size;
11787836SJohn.Forte@Sun.COM 
11797836SJohn.Forte@Sun.COM 	ustatus = spcs_s_ucreate();
11807836SJohn.Forte@Sun.COM 
11817836SJohn.Forte@Sun.COM 	size = sizeof (char *) * rdc_maxsets;
11827836SJohn.Forte@Sun.COM 	volumes = malloc(size);
11837836SJohn.Forte@Sun.COM 	if (volumes == NULL) {
11847836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
11857836SJohn.Forte@Sun.COM 		    gettext("%s: unable to allocate %ld bytes"),
11867836SJohn.Forte@Sun.COM 		    program, size);
11877836SJohn.Forte@Sun.COM 		rdc_warn(NULL,
11887836SJohn.Forte@Sun.COM 			gettext("unable to allocate %ld bytes"), size);
11897836SJohn.Forte@Sun.COM 		goto done;
11907836SJohn.Forte@Sun.COM 	}
11917836SJohn.Forte@Sun.COM 	bzero(volumes, size);
11927836SJohn.Forte@Sun.COM 
11937836SJohn.Forte@Sun.COM 	/*
11947836SJohn.Forte@Sun.COM 	 * If all members of this group are replicating
11957836SJohn.Forte@Sun.COM 	 * set ii_ndr state to "update". Otherwise leave them alone.
11967836SJohn.Forte@Sun.COM 	 */
11977836SJohn.Forte@Sun.COM 	LOCKCFG();
11987836SJohn.Forte@Sun.COM 	if ((cfg = cfg_open(NULL)) == NULL) {
11997836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
12007836SJohn.Forte@Sun.COM 		    gettext("%s: error opening lconfig"),
12017836SJohn.Forte@Sun.COM 		    program);
12027836SJohn.Forte@Sun.COM 		rdc_warn(NULL, gettext("error opening config"));
12037836SJohn.Forte@Sun.COM 		UNLOCKCFG();
12047836SJohn.Forte@Sun.COM 		goto done;
12057836SJohn.Forte@Sun.COM 	}
12067836SJohn.Forte@Sun.COM 
12077836SJohn.Forte@Sun.COM 	if (!cfg_lock(cfg, CFG_RDLOCK)) {
12087836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
12097836SJohn.Forte@Sun.COM 		    gettext("%s: error locking config"),
12107836SJohn.Forte@Sun.COM 		    program);
12117836SJohn.Forte@Sun.COM 		rdc_warn(NULL, gettext("error locking config"));
12127836SJohn.Forte@Sun.COM 		goto done;
12137836SJohn.Forte@Sun.COM 	}
12147836SJohn.Forte@Sun.COM 
12157836SJohn.Forte@Sun.COM 	found = 0;
12167836SJohn.Forte@Sun.COM 
12177836SJohn.Forte@Sun.COM 	/* get all RM entries, with a matching group, that are replicating */
12187836SJohn.Forte@Sun.COM 	for (i = 0; i < rdc_maxsets; i++) {
12197836SJohn.Forte@Sun.COM 		setnumber = i + 1;
12207836SJohn.Forte@Sun.COM 
12217836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key),
12227836SJohn.Forte@Sun.COM 		    "sndr.set%d.group", setnumber);
12237836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
12247836SJohn.Forte@Sun.COM 			break;
12257836SJohn.Forte@Sun.COM 
12267836SJohn.Forte@Sun.COM 		if (strcmp(buf, group) != 0)
12277836SJohn.Forte@Sun.COM 			continue;
12287836SJohn.Forte@Sun.COM 
12297836SJohn.Forte@Sun.COM 		/* Found a matching entry */
12307836SJohn.Forte@Sun.COM 
12317836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key),
12327836SJohn.Forte@Sun.COM 		    "sndr.set%d.primary", setnumber);
12337836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, primary, sizeof (primary)) < 0)
12347836SJohn.Forte@Sun.COM 			break;
1235*11576SSurya.Prakki@Sun.COM 		(void) strcpy(parms.rdc_set->primary.file, primary);
12367836SJohn.Forte@Sun.COM 
12377836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key),
12387836SJohn.Forte@Sun.COM 		    "sndr.set%d.phost", setnumber);
12397836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, phost, sizeof (phost)) < 0)
12407836SJohn.Forte@Sun.COM 			break;
1241*11576SSurya.Prakki@Sun.COM 		(void) strcpy(parms.rdc_set->primary.intf, phost);
12427836SJohn.Forte@Sun.COM 
12437836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key),
12447836SJohn.Forte@Sun.COM 		    "sndr.set%d.secondary", setnumber);
12457836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, secondary,
12467836SJohn.Forte@Sun.COM 				sizeof (secondary)) < 0)
12477836SJohn.Forte@Sun.COM 			break;
1248*11576SSurya.Prakki@Sun.COM 		(void) strcpy(parms.rdc_set->secondary.file, secondary);
12497836SJohn.Forte@Sun.COM 
12507836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key),
12517836SJohn.Forte@Sun.COM 		    "sndr.set%d.shost", setnumber);
12527836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, shost, sizeof (shost)) < 0)
12537836SJohn.Forte@Sun.COM 			break;
1254*11576SSurya.Prakki@Sun.COM 		(void) strcpy(parms.rdc_set->secondary.intf, shost);
12557836SJohn.Forte@Sun.COM 
12567836SJohn.Forte@Sun.COM 		parms.command = RDC_CMD_STATUS;
12577836SJohn.Forte@Sun.COM 		if (RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus) < 0) {
12587836SJohn.Forte@Sun.COM 			continue;
12597836SJohn.Forte@Sun.COM 		}
12607836SJohn.Forte@Sun.COM 
12617836SJohn.Forte@Sun.COM 		/* We found a matching set */
12627836SJohn.Forte@Sun.COM 		found++;
12637836SJohn.Forte@Sun.COM 
12647836SJohn.Forte@Sun.COM 		if (self_check(phost))
12657836SJohn.Forte@Sun.COM 			local_file = primary;
12667836SJohn.Forte@Sun.COM 		else
12677836SJohn.Forte@Sun.COM 			local_file = secondary;
12687836SJohn.Forte@Sun.COM 
12697836SJohn.Forte@Sun.COM 		rdc_set = &parms.rdc_set[0];
12707836SJohn.Forte@Sun.COM 		if (!(rdc_set->flags & RDC_LOGGING) &&
12717836SJohn.Forte@Sun.COM 		    !(rdc_set->flags & RDC_SYNCING)) {
12727836SJohn.Forte@Sun.COM 			volumes[replicating] = strdup(local_file);
12737836SJohn.Forte@Sun.COM 			if (volumes[replicating] == NULL) {
12747836SJohn.Forte@Sun.COM 				size = strlen(local_file);
12757836SJohn.Forte@Sun.COM 				spcs_log("sndr", NULL,
12767836SJohn.Forte@Sun.COM 				    gettext("%s: unable to allocate %ld bytes"),
12777836SJohn.Forte@Sun.COM 				    program, size);
12787836SJohn.Forte@Sun.COM 				rdc_warn(NULL,
12797836SJohn.Forte@Sun.COM 				    gettext("unable to allocate %ld bytes"),
12807836SJohn.Forte@Sun.COM 				    size);
12817836SJohn.Forte@Sun.COM 				goto done;
12827836SJohn.Forte@Sun.COM 			}
12837836SJohn.Forte@Sun.COM 			/* We remember all replicating sets */
12847836SJohn.Forte@Sun.COM 			replicating++;
12857836SJohn.Forte@Sun.COM 		} else
12867836SJohn.Forte@Sun.COM 			break;		/* Not all replicating, so done */
12877836SJohn.Forte@Sun.COM 	}
12887836SJohn.Forte@Sun.COM 
12897836SJohn.Forte@Sun.COM 	if (found != replicating)
12907836SJohn.Forte@Sun.COM 		goto done;
12917836SJohn.Forte@Sun.COM 
12927836SJohn.Forte@Sun.COM 	/* All replicating, so update ndr_ii state fields */
12937836SJohn.Forte@Sun.COM 
12947836SJohn.Forte@Sun.COM 	cfg_unlock(cfg);
12957836SJohn.Forte@Sun.COM 
12967836SJohn.Forte@Sun.COM 	if (!cfg_lock(cfg, CFG_WRLOCK)) {
12977836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
12987836SJohn.Forte@Sun.COM 		    gettext("%s: error locking lconfig"),
12997836SJohn.Forte@Sun.COM 		    program);
13007836SJohn.Forte@Sun.COM 		rdc_warn(NULL, gettext("error locking config"));
13017836SJohn.Forte@Sun.COM 		goto done;
13027836SJohn.Forte@Sun.COM 	}
13037836SJohn.Forte@Sun.COM 
13047836SJohn.Forte@Sun.COM 	/*
13057836SJohn.Forte@Sun.COM 	 * Search through the ndr_ii entries for entries
13067836SJohn.Forte@Sun.COM 	 * that match the saved secondary volume names.
13077836SJohn.Forte@Sun.COM 	 * Set state to "update".
13087836SJohn.Forte@Sun.COM 	 */
13097836SJohn.Forte@Sun.COM 
13107836SJohn.Forte@Sun.COM 	for (i = 0; ; i++) {
13117836SJohn.Forte@Sun.COM 		setnumber = i + 1;
13127836SJohn.Forte@Sun.COM 
13137836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.secondary",
13147836SJohn.Forte@Sun.COM 		    setnumber);
13157836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
13167836SJohn.Forte@Sun.COM 			break;
13177836SJohn.Forte@Sun.COM 
13187836SJohn.Forte@Sun.COM 		if (!volume_match(buf, volumes, found)) {
13197836SJohn.Forte@Sun.COM 			continue;
13207836SJohn.Forte@Sun.COM 		}
13217836SJohn.Forte@Sun.COM 
13227836SJohn.Forte@Sun.COM 		/* Got a matching entry */
13237836SJohn.Forte@Sun.COM 
13247836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key),
13257836SJohn.Forte@Sun.COM 		    "ndr_ii.set%d.state", setnumber);
13267836SJohn.Forte@Sun.COM 		if ((cfg_put_cstring(cfg, key, UPDATE, strlen(UPDATE)) < 0) ||
13277836SJohn.Forte@Sun.COM 		    (cfg_commit(cfg) < 0)) {
13287836SJohn.Forte@Sun.COM 			spcs_log("sndr", NULL,
13297836SJohn.Forte@Sun.COM 			    gettext("%s: unable to update \"%s\" "
13307836SJohn.Forte@Sun.COM 			    "in configuration storage: %s"),
13317836SJohn.Forte@Sun.COM 			    program, buf, cfg_error(&sev));
13327836SJohn.Forte@Sun.COM 			rdc_warn(NULL,
13337836SJohn.Forte@Sun.COM 			    gettext("unable to update \"%s\" "
13347836SJohn.Forte@Sun.COM 			    "in configuration storage: %s"),
13357836SJohn.Forte@Sun.COM 			    buf, cfg_error(&sev));
13367836SJohn.Forte@Sun.COM 		}
13377836SJohn.Forte@Sun.COM 	}
13387836SJohn.Forte@Sun.COM 
13397836SJohn.Forte@Sun.COM 
13407836SJohn.Forte@Sun.COM done:
13417836SJohn.Forte@Sun.COM 	if (cfg) {
13427836SJohn.Forte@Sun.COM 		cfg_close(cfg);
13437836SJohn.Forte@Sun.COM 		UNLOCKCFG();
13447836SJohn.Forte@Sun.COM 	}
13457836SJohn.Forte@Sun.COM 	spcs_s_ufree(&ustatus);
13467836SJohn.Forte@Sun.COM 	if (volumes) {
13477836SJohn.Forte@Sun.COM 		for (i = 0; i < replicating; i++)
13487836SJohn.Forte@Sun.COM 			free(volumes[i]);
13497836SJohn.Forte@Sun.COM 		free(volumes);
13507836SJohn.Forte@Sun.COM 	}
13517836SJohn.Forte@Sun.COM }
13527836SJohn.Forte@Sun.COM 
13537836SJohn.Forte@Sun.COM 
13547836SJohn.Forte@Sun.COM /*
13557836SJohn.Forte@Sun.COM  * Sync started to a member of a group.
13567836SJohn.Forte@Sun.COM  * If all members of the group are in ndr_ii state "update" then take an PIT
13577836SJohn.Forte@Sun.COM  * snapshot on all of them. This will provide a consistent point-in-time
13587836SJohn.Forte@Sun.COM  * copy until whatever syncs take place are all completed.
13597836SJohn.Forte@Sun.COM  */
13607836SJohn.Forte@Sun.COM void
group_start(char * group)13617836SJohn.Forte@Sun.COM group_start(char *group)
13627836SJohn.Forte@Sun.COM {
13637836SJohn.Forte@Sun.COM 	char **masters = NULL;
13647836SJohn.Forte@Sun.COM 	char **shadows = NULL;
13657836SJohn.Forte@Sun.COM 	char **bitmaps = NULL;
13667836SJohn.Forte@Sun.COM 	char cmd[256];
13677836SJohn.Forte@Sun.COM 	char buf[CFG_MAX_BUF];
13687836SJohn.Forte@Sun.COM 	char key[CFG_MAX_KEY];
13697836SJohn.Forte@Sun.COM 	CFGFILE *cfg = NULL;
13707836SJohn.Forte@Sun.COM 	int i;
13717836SJohn.Forte@Sun.COM 	int j;
13727836SJohn.Forte@Sun.COM 	int setnumber;
13737836SJohn.Forte@Sun.COM 	int found;
13747836SJohn.Forte@Sun.COM 	int sndr_sets = 0;
13757836SJohn.Forte@Sun.COM 	int update_needed = 0;
13767836SJohn.Forte@Sun.COM 	int sev;
13777836SJohn.Forte@Sun.COM 	char *ctag = NULL;
13787836SJohn.Forte@Sun.COM 	int commit = 0;
13797836SJohn.Forte@Sun.COM 	int size;
13807836SJohn.Forte@Sun.COM 
13817836SJohn.Forte@Sun.COM 	size = sizeof (char *) * rdc_maxsets;
13827836SJohn.Forte@Sun.COM 	masters = malloc(size);
13837836SJohn.Forte@Sun.COM 	if (masters == NULL) {
13847836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
13857836SJohn.Forte@Sun.COM 		    gettext("%s: unable to allocate %ld bytes"),
13867836SJohn.Forte@Sun.COM 		    program, size);
13877836SJohn.Forte@Sun.COM 		rdc_warn(NULL,
13887836SJohn.Forte@Sun.COM 			gettext("unable to allocate %ld bytes"), size);
13897836SJohn.Forte@Sun.COM 		goto done;
13907836SJohn.Forte@Sun.COM 	}
13917836SJohn.Forte@Sun.COM 	bzero(masters, size);
13927836SJohn.Forte@Sun.COM 	shadows = malloc(size);
13937836SJohn.Forte@Sun.COM 	if (shadows == NULL) {
13947836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
13957836SJohn.Forte@Sun.COM 		    gettext("%s: unable to allocate %ld bytes"),
13967836SJohn.Forte@Sun.COM 		    program, size);
13977836SJohn.Forte@Sun.COM 		rdc_warn(NULL,
13987836SJohn.Forte@Sun.COM 			gettext("unable to allocate %ld bytes"), size);
13997836SJohn.Forte@Sun.COM 		goto done;
14007836SJohn.Forte@Sun.COM 	}
14017836SJohn.Forte@Sun.COM 	bzero(shadows, size);
14027836SJohn.Forte@Sun.COM 	bitmaps = malloc(size);
14037836SJohn.Forte@Sun.COM 	if (bitmaps == NULL) {
14047836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
14057836SJohn.Forte@Sun.COM 		    gettext("%s: unable to allocate %ld bytes"),
14067836SJohn.Forte@Sun.COM 		    program, size);
14077836SJohn.Forte@Sun.COM 		rdc_warn(NULL,
14087836SJohn.Forte@Sun.COM 			gettext("unable to allocate %ld bytes"), size);
14097836SJohn.Forte@Sun.COM 		goto done;
14107836SJohn.Forte@Sun.COM 	}
14117836SJohn.Forte@Sun.COM 	bzero(bitmaps, size);
14127836SJohn.Forte@Sun.COM 
14137836SJohn.Forte@Sun.COM 	LOCKCFG();
14147836SJohn.Forte@Sun.COM 	if ((cfg = cfg_open(NULL)) == NULL) {
14157836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
14167836SJohn.Forte@Sun.COM 		    gettext("%s: error opening config"),
14177836SJohn.Forte@Sun.COM 		    program);
14187836SJohn.Forte@Sun.COM 		rdc_warn(NULL,
14197836SJohn.Forte@Sun.COM 		    gettext("error opening config"));
14207836SJohn.Forte@Sun.COM 		UNLOCKCFG();
14217836SJohn.Forte@Sun.COM 		goto done;
14227836SJohn.Forte@Sun.COM 	}
14237836SJohn.Forte@Sun.COM 
14247836SJohn.Forte@Sun.COM 	if (!cfg_lock(cfg, CFG_WRLOCK)) {
14257836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
14267836SJohn.Forte@Sun.COM 		    gettext("%s: error locking config"),
14277836SJohn.Forte@Sun.COM 		    program);
14287836SJohn.Forte@Sun.COM 		rdc_warn(NULL, gettext("error locking config"));
14297836SJohn.Forte@Sun.COM 		goto done;
14307836SJohn.Forte@Sun.COM 	}
14317836SJohn.Forte@Sun.COM 
14327836SJohn.Forte@Sun.COM 	/* Now get all Remote Mirror entries with a matching group */
14337836SJohn.Forte@Sun.COM 	for (i = 0; i < rdc_maxsets; i++) {
14347836SJohn.Forte@Sun.COM 		setnumber = i + 1;
14357836SJohn.Forte@Sun.COM 
14367836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key),
14377836SJohn.Forte@Sun.COM 		    "sndr.set%d.group", setnumber);
14387836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
14397836SJohn.Forte@Sun.COM 			break;
14407836SJohn.Forte@Sun.COM 
14417836SJohn.Forte@Sun.COM 		if (strcmp(buf, group) != 0)
14427836SJohn.Forte@Sun.COM 			continue;
14437836SJohn.Forte@Sun.COM 
14447836SJohn.Forte@Sun.COM 		/* Found a matching entry */
14457836SJohn.Forte@Sun.COM 
14467836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key),
14477836SJohn.Forte@Sun.COM 		    "sndr.set%d.phost", setnumber);
14487836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0)
14497836SJohn.Forte@Sun.COM 			break;
14507836SJohn.Forte@Sun.COM 
14517836SJohn.Forte@Sun.COM 		if (self_check(buf)) {
14527836SJohn.Forte@Sun.COM 			(void) snprintf(key, sizeof (key), "sndr.set%d.primary",
14537836SJohn.Forte@Sun.COM 			    setnumber);
14547836SJohn.Forte@Sun.COM 		} else {
14557836SJohn.Forte@Sun.COM 			(void) snprintf(key, sizeof (key),
14567836SJohn.Forte@Sun.COM 			    "sndr.set%d.secondary", setnumber);
14577836SJohn.Forte@Sun.COM 		}
14587836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0)
14597836SJohn.Forte@Sun.COM 			break;
14607836SJohn.Forte@Sun.COM 
14617836SJohn.Forte@Sun.COM 		masters[sndr_sets] = strdup(buf);
14627836SJohn.Forte@Sun.COM 		if (masters[sndr_sets] == NULL) {
14637836SJohn.Forte@Sun.COM 			size = strlen(buf);
14647836SJohn.Forte@Sun.COM 			spcs_log("sndr", NULL,
14657836SJohn.Forte@Sun.COM 			    gettext("%s: unable to allocate %ld bytes"),
14667836SJohn.Forte@Sun.COM 			    program, size);
14677836SJohn.Forte@Sun.COM 			rdc_warn(NULL,
14687836SJohn.Forte@Sun.COM 				gettext("unable to allocate %ld bytes"), size);
14697836SJohn.Forte@Sun.COM 			goto done;
14707836SJohn.Forte@Sun.COM 		}
14717836SJohn.Forte@Sun.COM 		sndr_sets++;
14727836SJohn.Forte@Sun.COM 
14737836SJohn.Forte@Sun.COM 		if (ctag == NULL && clustered) {
14747836SJohn.Forte@Sun.COM 			/* Get cluster tag of matching entry */
14757836SJohn.Forte@Sun.COM 
14767836SJohn.Forte@Sun.COM 			(void) snprintf(key, sizeof (key), "sndr.set%d.cnode",
14777836SJohn.Forte@Sun.COM 			    setnumber);
14787836SJohn.Forte@Sun.COM 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) >= 0)
14797836SJohn.Forte@Sun.COM 				ctag = strdup(buf);
14807836SJohn.Forte@Sun.COM 		}
14817836SJohn.Forte@Sun.COM 	}
14827836SJohn.Forte@Sun.COM 
14837836SJohn.Forte@Sun.COM 	/*
14847836SJohn.Forte@Sun.COM 	 * Search through the ndr_ii entries for entries
14857836SJohn.Forte@Sun.COM 	 * that match the saved local volume names and are in "update" state.
14867836SJohn.Forte@Sun.COM 	 */
14877836SJohn.Forte@Sun.COM 
14887836SJohn.Forte@Sun.COM 	update_needed = 0;
14897836SJohn.Forte@Sun.COM 
14907836SJohn.Forte@Sun.COM 	for (i = 0; ; i++) {
14917836SJohn.Forte@Sun.COM 		setnumber = i + 1;
14927836SJohn.Forte@Sun.COM 
14937836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.secondary",
14947836SJohn.Forte@Sun.COM 		    setnumber);
14957836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
14967836SJohn.Forte@Sun.COM 			break;
14977836SJohn.Forte@Sun.COM 
14987836SJohn.Forte@Sun.COM 		if (!volume_match(buf, masters, sndr_sets))
14997836SJohn.Forte@Sun.COM 			continue;
15007836SJohn.Forte@Sun.COM 
15017836SJohn.Forte@Sun.COM 		/* Got a matching entry */
15027836SJohn.Forte@Sun.COM 
15037836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.shadow",
15047836SJohn.Forte@Sun.COM 		    setnumber);
15057836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
15067836SJohn.Forte@Sun.COM 			break;
15077836SJohn.Forte@Sun.COM 		shadows[update_needed] = strdup(buf);
15087836SJohn.Forte@Sun.COM 		if (shadows[update_needed] == NULL) {
15097836SJohn.Forte@Sun.COM 			size = strlen(buf);
15107836SJohn.Forte@Sun.COM 			spcs_log("sndr", NULL,
15117836SJohn.Forte@Sun.COM 			    gettext("%s: unable to allocate %ld bytes"),
15127836SJohn.Forte@Sun.COM 			    program, size);
15137836SJohn.Forte@Sun.COM 			rdc_warn(NULL,
15147836SJohn.Forte@Sun.COM 				gettext("unable to allocate %ld bytes"), size);
15157836SJohn.Forte@Sun.COM 			goto done;
15167836SJohn.Forte@Sun.COM 		}
15177836SJohn.Forte@Sun.COM 
15187836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.bitmap",
15197836SJohn.Forte@Sun.COM 		    setnumber);
15207836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
15217836SJohn.Forte@Sun.COM 			break;
15227836SJohn.Forte@Sun.COM 		}
15237836SJohn.Forte@Sun.COM 		bitmaps[update_needed] = strdup(buf);
15247836SJohn.Forte@Sun.COM 		if (bitmaps[update_needed] == NULL) {
15257836SJohn.Forte@Sun.COM 			size = strlen(buf);
15267836SJohn.Forte@Sun.COM 			spcs_log("sndr", NULL,
15277836SJohn.Forte@Sun.COM 			    gettext("%s: unable to allocate %ld bytes"),
15287836SJohn.Forte@Sun.COM 			    program, size);
15297836SJohn.Forte@Sun.COM 			rdc_warn(NULL,
15307836SJohn.Forte@Sun.COM 				gettext("unable to allocate %ld bytes"), size);
15317836SJohn.Forte@Sun.COM 			goto done;
15327836SJohn.Forte@Sun.COM 		}
15337836SJohn.Forte@Sun.COM 
15347836SJohn.Forte@Sun.COM 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
15357836SJohn.Forte@Sun.COM 		    setnumber);
15367836SJohn.Forte@Sun.COM 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
15377836SJohn.Forte@Sun.COM 			break;
15387836SJohn.Forte@Sun.COM 		}
15397836SJohn.Forte@Sun.COM 		if (strcmp(buf, UPDATE) != 0) {
15407836SJohn.Forte@Sun.COM 			break;
15417836SJohn.Forte@Sun.COM 		}
15427836SJohn.Forte@Sun.COM 
15437836SJohn.Forte@Sun.COM 		update_needed++;
15447836SJohn.Forte@Sun.COM 	}
15457836SJohn.Forte@Sun.COM 
15467836SJohn.Forte@Sun.COM 	if (update_needed != sndr_sets) {
15477836SJohn.Forte@Sun.COM #ifdef DEBUG
15487836SJohn.Forte@Sun.COM 		spcs_log("sndr", NULL,
15497836SJohn.Forte@Sun.COM 		    gettext("%s: group sync: no Point-in-Time Copy snapshot "
15507836SJohn.Forte@Sun.COM 			    "for %s"), program, group);
15517836SJohn.Forte@Sun.COM #endif
15527836SJohn.Forte@Sun.COM 		goto done;
15537836SJohn.Forte@Sun.COM 	}
15547836SJohn.Forte@Sun.COM 
15557836SJohn.Forte@Sun.COM 	/* All RM sets in the group have an ndr_ii entry in "update" state */
15567836SJohn.Forte@Sun.COM 
15577836SJohn.Forte@Sun.COM 	/* Issue PIT Copy snapshot commands for all sets in the group */
15587836SJohn.Forte@Sun.COM 	for (j = 0; j < sndr_sets; j++) {
15597836SJohn.Forte@Sun.COM 		found = 0;
15607836SJohn.Forte@Sun.COM 
15617836SJohn.Forte@Sun.COM 		/* get ii entries until a match is found */
15627836SJohn.Forte@Sun.COM 		for (i = 0; ; i++) {
15637836SJohn.Forte@Sun.COM 			setnumber = i + 1;
15647836SJohn.Forte@Sun.COM 
15657836SJohn.Forte@Sun.COM 			(void) snprintf(key, sizeof (key), "ii.set%d.shadow",
15667836SJohn.Forte@Sun.COM 			    setnumber);
15677836SJohn.Forte@Sun.COM 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
15687836SJohn.Forte@Sun.COM 				break;
15697836SJohn.Forte@Sun.COM 			if (strcmp(buf, shadows[j]) != 0)
15707836SJohn.Forte@Sun.COM 				continue;
15717836SJohn.Forte@Sun.COM 
15727836SJohn.Forte@Sun.COM 			/* Matching shadow found, so ii already enabled */
15737836SJohn.Forte@Sun.COM 			found = 1;
15747836SJohn.Forte@Sun.COM 			break;
15757836SJohn.Forte@Sun.COM 		}
15767836SJohn.Forte@Sun.COM 
15777836SJohn.Forte@Sun.COM 		if (commit)
15787836SJohn.Forte@Sun.COM 			if (cfg_commit(cfg) < 0)
15797836SJohn.Forte@Sun.COM 				rdc_warn(NULL, gettext("commit config error"));
15807836SJohn.Forte@Sun.COM 		cfg_close(cfg);
15817836SJohn.Forte@Sun.COM 
15827836SJohn.Forte@Sun.COM 		if (found) {
15837836SJohn.Forte@Sun.COM 			(void) sprintf(cmd, "%s -u s %s", IIADM, shadows[j]);
15847836SJohn.Forte@Sun.COM 		} else {
15857836SJohn.Forte@Sun.COM 			if (ctag) {
15867836SJohn.Forte@Sun.COM 				(void) sprintf(cmd, "%s -C %s -e dep %s %s %s",
15877836SJohn.Forte@Sun.COM 				    IIADM, ctag, masters[j], shadows[j],
15887836SJohn.Forte@Sun.COM 				    bitmaps[j]);
15897836SJohn.Forte@Sun.COM 				free(ctag);
15907836SJohn.Forte@Sun.COM 				ctag = NULL;
15917836SJohn.Forte@Sun.COM 			} else
15927836SJohn.Forte@Sun.COM 				(void) sprintf(cmd, "%s -e dep %s %s %s", IIADM,
15937836SJohn.Forte@Sun.COM 				    masters[j], shadows[j], bitmaps[j]);
15947836SJohn.Forte@Sun.COM 		}
15957836SJohn.Forte@Sun.COM 
15967836SJohn.Forte@Sun.COM 		if (system(cmd) != 0) {
15977836SJohn.Forte@Sun.COM 			spcs_log("sndr", NULL,
15987836SJohn.Forte@Sun.COM 			    gettext("%s: group sync: Point-in-Time Copy"
15997836SJohn.Forte@Sun.COM 			    " snapshot failed for %s"),
16007836SJohn.Forte@Sun.COM 			    program, masters[j]);
16017836SJohn.Forte@Sun.COM 
16027836SJohn.Forte@Sun.COM 			goto done;
16037836SJohn.Forte@Sun.COM 		}
16047836SJohn.Forte@Sun.COM 
16057836SJohn.Forte@Sun.COM 		if ((cfg = cfg_open(NULL)) == NULL) {
16067836SJohn.Forte@Sun.COM 			spcs_log("sndr", NULL,
16077836SJohn.Forte@Sun.COM 			    gettext("%s: error opening config"),
16087836SJohn.Forte@Sun.COM 			    program);
16097836SJohn.Forte@Sun.COM 			rdc_warn(NULL,
16107836SJohn.Forte@Sun.COM 			    gettext("error opening config"));
16117836SJohn.Forte@Sun.COM 			goto done;
16127836SJohn.Forte@Sun.COM 		}
16137836SJohn.Forte@Sun.COM 		if (!cfg_lock(cfg, CFG_WRLOCK)) {
16147836SJohn.Forte@Sun.COM 			spcs_log("sndr", NULL,
16157836SJohn.Forte@Sun.COM 			    gettext("%s: error locking config"),
16167836SJohn.Forte@Sun.COM 			    program);
16177836SJohn.Forte@Sun.COM 			rdc_warn(NULL, gettext("error locking config"));
16187836SJohn.Forte@Sun.COM 			goto done;
16197836SJohn.Forte@Sun.COM 		}
16207836SJohn.Forte@Sun.COM 		commit = 0;
16217836SJohn.Forte@Sun.COM 
16227836SJohn.Forte@Sun.COM 		/* PIT enable or update was fine, so update the ndr_ii entry */
16237836SJohn.Forte@Sun.COM 
16247836SJohn.Forte@Sun.COM 		/* get ndr_ii entries until a match is found */
16257836SJohn.Forte@Sun.COM 		for (i = 0; ; i++) {
16267836SJohn.Forte@Sun.COM 			setnumber = i + 1;
16277836SJohn.Forte@Sun.COM 
16287836SJohn.Forte@Sun.COM 			(void) snprintf(key, sizeof (key),
16297836SJohn.Forte@Sun.COM 			    "ndr_ii.set%d.shadow", setnumber);
16307836SJohn.Forte@Sun.COM 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
16317836SJohn.Forte@Sun.COM 				break;
16327836SJohn.Forte@Sun.COM 			if (strcmp(buf, shadows[j]) != 0)
16337836SJohn.Forte@Sun.COM 				continue;
16347836SJohn.Forte@Sun.COM 
16357836SJohn.Forte@Sun.COM 			/* Found the matching entry */
16367836SJohn.Forte@Sun.COM 
16377836SJohn.Forte@Sun.COM 			(void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
16387836SJohn.Forte@Sun.COM 			    setnumber);
16397836SJohn.Forte@Sun.COM 			if (cfg_put_cstring(cfg, key, NOUPDATE,
16407836SJohn.Forte@Sun.COM 			    strlen(NOUPDATE)) < 0) {
16417836SJohn.Forte@Sun.COM 				spcs_log("sndr", NULL,
16427836SJohn.Forte@Sun.COM 				    gettext("%s: unable to update \"%s\" "
16437836SJohn.Forte@Sun.COM 				    "in configuration storage: %s"),
16447836SJohn.Forte@Sun.COM 				    program, buf, cfg_error(&sev));
16457836SJohn.Forte@Sun.COM 				rdc_warn(NULL,
16467836SJohn.Forte@Sun.COM 				    gettext("unable to update \"%s\" "
16477836SJohn.Forte@Sun.COM 				    "in configuration storage: %s"),
16487836SJohn.Forte@Sun.COM 				    buf, cfg_error(&sev));
16497836SJohn.Forte@Sun.COM 			} else
16507836SJohn.Forte@Sun.COM 				commit = 1;
16517836SJohn.Forte@Sun.COM 			break;
16527836SJohn.Forte@Sun.COM 		}
16537836SJohn.Forte@Sun.COM 	}
16547836SJohn.Forte@Sun.COM 
16557836SJohn.Forte@Sun.COM 	if (commit)
16567836SJohn.Forte@Sun.COM 		if (cfg_commit(cfg) < 0)
16577836SJohn.Forte@Sun.COM 			rdc_warn(NULL, gettext("commit config error"));
16587836SJohn.Forte@Sun.COM 
16597836SJohn.Forte@Sun.COM 	spcs_log("sndr", NULL,
16607836SJohn.Forte@Sun.COM 	    gettext("%s: group sync: Point-in-Time Copy snapshots completed "
16617836SJohn.Forte@Sun.COM 		    "for %s"), program, group);
16627836SJohn.Forte@Sun.COM 
16637836SJohn.Forte@Sun.COM done:
16647836SJohn.Forte@Sun.COM 	if (ctag)
16657836SJohn.Forte@Sun.COM 		free(ctag);
16667836SJohn.Forte@Sun.COM 
16677836SJohn.Forte@Sun.COM 	if (cfg) {
16687836SJohn.Forte@Sun.COM 		cfg_close(cfg);
16697836SJohn.Forte@Sun.COM 		UNLOCKCFG();
16707836SJohn.Forte@Sun.COM 	}
16717836SJohn.Forte@Sun.COM 
16727836SJohn.Forte@Sun.COM 	if (masters) {
16737836SJohn.Forte@Sun.COM 		for (i = 0; i < sndr_sets; i++) {
16747836SJohn.Forte@Sun.COM 			if (masters[i])
16757836SJohn.Forte@Sun.COM 				free(masters[i]);
16767836SJohn.Forte@Sun.COM 		}
16777836SJohn.Forte@Sun.COM 		free(masters);
16787836SJohn.Forte@Sun.COM 	}
16797836SJohn.Forte@Sun.COM 
16807836SJohn.Forte@Sun.COM 	if (shadows) {
16817836SJohn.Forte@Sun.COM 		for (i = 0; i < update_needed; i++) {
16827836SJohn.Forte@Sun.COM 			if (shadows[i])
16837836SJohn.Forte@Sun.COM 				free(shadows[i]);
16847836SJohn.Forte@Sun.COM 		}
16857836SJohn.Forte@Sun.COM 		free(shadows);
16867836SJohn.Forte@Sun.COM 	}
16877836SJohn.Forte@Sun.COM 
16887836SJohn.Forte@Sun.COM 	if (bitmaps) {
16897836SJohn.Forte@Sun.COM 		for (i = 0; i < update_needed; i++) {
16907836SJohn.Forte@Sun.COM 			if (bitmaps[i])
16917836SJohn.Forte@Sun.COM 				free(bitmaps[i]);
16927836SJohn.Forte@Sun.COM 		}
16937836SJohn.Forte@Sun.COM 		free(bitmaps);
16947836SJohn.Forte@Sun.COM 	}
16957836SJohn.Forte@Sun.COM }
1696