xref: /titanic_52/usr/src/cmd/avs/rdc/sndrsyncd.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte #include <sys/types.h>
27*fcf3ce44SJohn Forte #include <sys/wait.h>
28*fcf3ce44SJohn Forte #include <stdio.h>
29*fcf3ce44SJohn Forte #include <errno.h>
30*fcf3ce44SJohn Forte #include <limits.h>
31*fcf3ce44SJohn Forte #include <fcntl.h>
32*fcf3ce44SJohn Forte #include <strings.h>
33*fcf3ce44SJohn Forte #include <stdlib.h>
34*fcf3ce44SJohn Forte #include <unistd.h>
35*fcf3ce44SJohn Forte #include <pthread.h>
36*fcf3ce44SJohn Forte #include <thread.h>
37*fcf3ce44SJohn Forte 
38*fcf3ce44SJohn Forte #include <locale.h>
39*fcf3ce44SJohn Forte #include <langinfo.h>
40*fcf3ce44SJohn Forte #include <libintl.h>
41*fcf3ce44SJohn Forte #include <stdarg.h>
42*fcf3ce44SJohn Forte 
43*fcf3ce44SJohn Forte #include <sys/nsctl/rdc_io.h>
44*fcf3ce44SJohn Forte #include <sys/nsctl/rdc_ioctl.h>
45*fcf3ce44SJohn Forte #include <sys/nsctl/rdc_prot.h>
46*fcf3ce44SJohn Forte 
47*fcf3ce44SJohn Forte #include <sys/nsctl/cfg.h>
48*fcf3ce44SJohn Forte 
49*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s.h>
50*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s_u.h>
51*fcf3ce44SJohn Forte #include <sys/unistat/spcs_errors.h>
52*fcf3ce44SJohn Forte 
53*fcf3ce44SJohn Forte #include <sys/nsctl/librdc.h>
54*fcf3ce44SJohn Forte 
55*fcf3ce44SJohn Forte #include "rdcadm.h"
56*fcf3ce44SJohn Forte 
57*fcf3ce44SJohn Forte 
58*fcf3ce44SJohn Forte #define	RDCADM "/usr/sbin/sndradm"
59*fcf3ce44SJohn Forte #define	IIADM "/usr/sbin/iiadm"
60*fcf3ce44SJohn Forte 
61*fcf3ce44SJohn Forte #define	UPDATE "update"
62*fcf3ce44SJohn Forte #define	NOUPDATE "noupdate"
63*fcf3ce44SJohn Forte 
64*fcf3ce44SJohn Forte #define	RESYNC_SLEEP	(3 * 60)	/* Three minutes */
65*fcf3ce44SJohn Forte #define	MAIN_SLEEP	(5 * 60)	/* Five minutes */
66*fcf3ce44SJohn Forte #define	CFG_WAIT_SLEEP	(5)		/* 5 sec */
67*fcf3ce44SJohn Forte 
68*fcf3ce44SJohn Forte #define	MAXHOSTS 1024
69*fcf3ce44SJohn Forte mutex_t cfglock = DEFAULTMUTEX;
70*fcf3ce44SJohn Forte #define	LOCKCFG() (void) mutex_lock(&cfglock);
71*fcf3ce44SJohn Forte #define	UNLOCKCFG() (void) mutex_unlock(&cfglock);
72*fcf3ce44SJohn Forte 
73*fcf3ce44SJohn Forte typedef struct host_list_s {
74*fcf3ce44SJohn Forte 	char *hosts[MAXHOSTS];
75*fcf3ce44SJohn Forte 	int numhosts;
76*fcf3ce44SJohn Forte 	int configured[MAXHOSTS];
77*fcf3ce44SJohn Forte 	mutex_t hosts_mutex;
78*fcf3ce44SJohn Forte } host_list_t;
79*fcf3ce44SJohn Forte 
80*fcf3ce44SJohn Forte host_list_t *host_list;
81*fcf3ce44SJohn Forte 
82*fcf3ce44SJohn Forte extern char *basename(char *);
83*fcf3ce44SJohn Forte int rdc_maxsets;
84*fcf3ce44SJohn Forte char *program;
85*fcf3ce44SJohn Forte 
86*fcf3ce44SJohn Forte static int clustered = 0;
87*fcf3ce44SJohn Forte 
88*fcf3ce44SJohn Forte int isnewhost(char *host);
89*fcf3ce44SJohn Forte void *wait_sync_event();
90*fcf3ce44SJohn Forte void *wait_link_down(void *host);
91*fcf3ce44SJohn Forte void rdc_sync(char *tohost);
92*fcf3ce44SJohn Forte void remove_from_hostlist(char *host);
93*fcf3ce44SJohn Forte void sync_start(char *master);
94*fcf3ce44SJohn Forte void sync_complete(char *master);
95*fcf3ce44SJohn Forte void cleanup_hostlist();
96*fcf3ce44SJohn Forte void group_start(char *group);
97*fcf3ce44SJohn Forte void group_complete(char *group);
98*fcf3ce44SJohn Forte 
99*fcf3ce44SJohn Forte 
100*fcf3ce44SJohn Forte void
101*fcf3ce44SJohn Forte init_host_list(void)
102*fcf3ce44SJohn Forte {
103*fcf3ce44SJohn Forte 	host_list = calloc(1, sizeof (host_list_t));
104*fcf3ce44SJohn Forte 	if (host_list == NULL) {
105*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
106*fcf3ce44SJohn Forte 		    gettext("host list not initialized, cannot run"));
107*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("host list not initialized, cannot run"));
108*fcf3ce44SJohn Forte 	}
109*fcf3ce44SJohn Forte 	(void) mutex_init(&host_list->hosts_mutex, USYNC_THREAD, NULL);
110*fcf3ce44SJohn Forte }
111*fcf3ce44SJohn Forte 
112*fcf3ce44SJohn Forte /* ARGSUSED */
113*fcf3ce44SJohn Forte #ifdef lint
114*fcf3ce44SJohn Forte void
115*fcf3ce44SJohn Forte sndrsyncd_lintmain(argc, argv)
116*fcf3ce44SJohn Forte #else
117*fcf3ce44SJohn Forte int
118*fcf3ce44SJohn Forte main(argc, argv)
119*fcf3ce44SJohn Forte #endif
120*fcf3ce44SJohn Forte int argc;
121*fcf3ce44SJohn Forte char **argv;
122*fcf3ce44SJohn Forte {
123*fcf3ce44SJohn Forte 	rdc_status_t *rdc_info;
124*fcf3ce44SJohn Forte 	int size;
125*fcf3ce44SJohn Forte 	int i;
126*fcf3ce44SJohn Forte 	pid_t pid;
127*fcf3ce44SJohn Forte 	spcs_s_info_t ustatus;
128*fcf3ce44SJohn Forte 	int rc, trc;
129*fcf3ce44SJohn Forte 	int first = 0;
130*fcf3ce44SJohn Forte 	char *required;
131*fcf3ce44SJohn Forte 
132*fcf3ce44SJohn Forte 	(void) setlocale(LC_ALL, "");
133*fcf3ce44SJohn Forte 	(void) textdomain("rdc");
134*fcf3ce44SJohn Forte 
135*fcf3ce44SJohn Forte 	ustatus = spcs_s_ucreate();
136*fcf3ce44SJohn Forte 
137*fcf3ce44SJohn Forte 	program = basename(argv[0]);
138*fcf3ce44SJohn Forte 
139*fcf3ce44SJohn Forte 	init_host_list();
140*fcf3ce44SJohn Forte 
141*fcf3ce44SJohn Forte 	rc = rdc_check_release(&required);
142*fcf3ce44SJohn Forte 	if (rc < 0) {
143*fcf3ce44SJohn Forte 		rdc_err(NULL,
144*fcf3ce44SJohn Forte 		    gettext("unable to determine the current "
145*fcf3ce44SJohn Forte 		    "Solaris release: %s\n"), strerror(errno));
146*fcf3ce44SJohn Forte 		/* NOTREACHED */
147*fcf3ce44SJohn Forte 	} else if (rc == FALSE) {
148*fcf3ce44SJohn Forte 		rdc_err(NULL,
149*fcf3ce44SJohn Forte 		    gettext("incorrect Solaris release (requires %s)\n"),
150*fcf3ce44SJohn Forte 		    required);
151*fcf3ce44SJohn Forte 		/* NOTREACHED */
152*fcf3ce44SJohn Forte 	}
153*fcf3ce44SJohn Forte 
154*fcf3ce44SJohn Forte 	clustered = cfg_iscluster();
155*fcf3ce44SJohn Forte 	if (clustered < 0) {
156*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("unable to ascertain environment"));
157*fcf3ce44SJohn Forte 	}
158*fcf3ce44SJohn Forte 
159*fcf3ce44SJohn Forte 	rdc_maxsets = rdc_get_maxsets();
160*fcf3ce44SJohn Forte 	if (rdc_maxsets == -1) {
161*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
162*fcf3ce44SJohn Forte 		    gettext("%s: unable to get maxsets value from kernel"),
163*fcf3ce44SJohn Forte 		    program);
164*fcf3ce44SJohn Forte 		rdc_err(NULL,
165*fcf3ce44SJohn Forte 		    gettext("unable to get maxsets value from kernel"));
166*fcf3ce44SJohn Forte 	}
167*fcf3ce44SJohn Forte 	size = sizeof (rdc_status_t) + (sizeof (rdc_set_t) * (rdc_maxsets - 1));
168*fcf3ce44SJohn Forte 	rdc_info = malloc(size);
169*fcf3ce44SJohn Forte 	if (rdc_info == NULL) {
170*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
171*fcf3ce44SJohn Forte 		    gettext("%s: unable to allocate %ld bytes"),
172*fcf3ce44SJohn Forte 		    program, size);
173*fcf3ce44SJohn Forte 		rdc_err(NULL,
174*fcf3ce44SJohn Forte 			gettext("unable to allocate %ld bytes"), size);
175*fcf3ce44SJohn Forte 	}
176*fcf3ce44SJohn Forte 	bzero(rdc_info, size);
177*fcf3ce44SJohn Forte 
178*fcf3ce44SJohn Forte 	rdc_info->nset = rdc_maxsets;
179*fcf3ce44SJohn Forte 
180*fcf3ce44SJohn Forte 	/*
181*fcf3ce44SJohn Forte 	 * Fork off a child that becomes the daemon.
182*fcf3ce44SJohn Forte 	 */
183*fcf3ce44SJohn Forte 	if ((pid = fork()) > 0)
184*fcf3ce44SJohn Forte 		exit(0);
185*fcf3ce44SJohn Forte 	else if (pid < 0) {
186*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
187*fcf3ce44SJohn Forte 		    gettext("%s: cannot fork: %s"),
188*fcf3ce44SJohn Forte 		    program, strerror(errno));
189*fcf3ce44SJohn Forte 		rdc_err(NULL, gettext("cannot fork: %s\n"),
190*fcf3ce44SJohn Forte 		    strerror(errno));
191*fcf3ce44SJohn Forte 	}
192*fcf3ce44SJohn Forte 
193*fcf3ce44SJohn Forte 	/*
194*fcf3ce44SJohn Forte 	 * In child - become daemon.
195*fcf3ce44SJohn Forte 	 */
196*fcf3ce44SJohn Forte 
197*fcf3ce44SJohn Forte 	for (i = 0; i < 3; i++)
198*fcf3ce44SJohn Forte 		(void) close(i);
199*fcf3ce44SJohn Forte 
200*fcf3ce44SJohn Forte 	(void) open("/dev/console", O_WRONLY|O_APPEND);
201*fcf3ce44SJohn Forte 	(void) dup(0);
202*fcf3ce44SJohn Forte 	(void) dup(0);
203*fcf3ce44SJohn Forte 	(void) close(0);
204*fcf3ce44SJohn Forte 
205*fcf3ce44SJohn Forte 	(void) setpgrp();
206*fcf3ce44SJohn Forte 
207*fcf3ce44SJohn Forte 	(void) setlocale(LC_ALL, "");
208*fcf3ce44SJohn Forte 	(void) textdomain("rdc");
209*fcf3ce44SJohn Forte 
210*fcf3ce44SJohn Forte 	/* launch a thread to wait for sync start and sync stop events */
211*fcf3ce44SJohn Forte 
212*fcf3ce44SJohn Forte 	if ((trc = thr_create(NULL, 0, wait_sync_event, NULL,
213*fcf3ce44SJohn Forte 	    THR_BOUND|THR_DETACHED, NULL)) != 0) {
214*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
215*fcf3ce44SJohn Forte 		    gettext("%s: unable to create thread wait_sync_event"),
216*fcf3ce44SJohn Forte 		    program);
217*fcf3ce44SJohn Forte 		rdc_warn(NULL,
218*fcf3ce44SJohn Forte 		    gettext("%s unable to create thread wait_sync_event"),
219*fcf3ce44SJohn Forte 		    program);
220*fcf3ce44SJohn Forte 	} else {
221*fcf3ce44SJohn Forte #ifdef DEBUG
222*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
223*fcf3ce44SJohn Forte 		    gettext("%s: thread wait_sync_event started"), program);
224*fcf3ce44SJohn Forte #endif
225*fcf3ce44SJohn Forte 		;
226*fcf3ce44SJohn Forte 	}
227*fcf3ce44SJohn Forte 
228*fcf3ce44SJohn Forte 	for (;;) {
229*fcf3ce44SJohn Forte 		if (!first) {
230*fcf3ce44SJohn Forte 			first++;
231*fcf3ce44SJohn Forte 			(void) sleep(15);
232*fcf3ce44SJohn Forte 		} else
233*fcf3ce44SJohn Forte 			(void) sleep(MAIN_SLEEP);
234*fcf3ce44SJohn Forte 
235*fcf3ce44SJohn Forte 		bzero(rdc_info, size);
236*fcf3ce44SJohn Forte 		rdc_info->nset = rdc_maxsets;
237*fcf3ce44SJohn Forte 		if (RDC_IOCTL(RDC_STATUS, rdc_info, 0, 0, 0, 0, ustatus)
238*fcf3ce44SJohn Forte 		    != SPCS_S_OK) {
239*fcf3ce44SJohn Forte 			spcs_log("sndr", &ustatus,
240*fcf3ce44SJohn Forte 			    gettext("%s: status ioctl"),
241*fcf3ce44SJohn Forte 			    program);
242*fcf3ce44SJohn Forte 			rdc_warn(&ustatus, gettext("status ioctl"));
243*fcf3ce44SJohn Forte 			continue;
244*fcf3ce44SJohn Forte 		}
245*fcf3ce44SJohn Forte 
246*fcf3ce44SJohn Forte 		cleanup_hostlist(rdc_info); /* remove non-existent hosts */
247*fcf3ce44SJohn Forte 
248*fcf3ce44SJohn Forte 		/*
249*fcf3ce44SJohn Forte 		 * Check all enabled sets to see if a new remote host has
250*fcf3ce44SJohn Forte 		 * appeared.
251*fcf3ce44SJohn Forte 		 */
252*fcf3ce44SJohn Forte 		for (i = 0; i < rdc_maxsets; i++) {
253*fcf3ce44SJohn Forte 			if (!(rdc_info->rdc_set[i].flags & RDC_ENABLED))
254*fcf3ce44SJohn Forte 				continue;
255*fcf3ce44SJohn Forte 			/* spawn a new thread for each new host found */
256*fcf3ce44SJohn Forte 			if (isnewhost(rdc_info->rdc_set[i].secondary.intf)) {
257*fcf3ce44SJohn Forte 				/*
258*fcf3ce44SJohn Forte 				 * right now, we could be here before
259*fcf3ce44SJohn Forte 				 * the database did the write for this set
260*fcf3ce44SJohn Forte 				 * I could check the lock on the database
261*fcf3ce44SJohn Forte 				 * but I am just going to give up some time here
262*fcf3ce44SJohn Forte 				 * instead. Why do the allocations etc, etc
263*fcf3ce44SJohn Forte 				 * if the set is enabled in the kernel and not
264*fcf3ce44SJohn Forte 				 * in the config, we know that this set has the
265*fcf3ce44SJohn Forte 				 * lock. Why bother adding more contention to
266*fcf3ce44SJohn Forte 				 * the lock.
267*fcf3ce44SJohn Forte 				 * this is a daemon, afterall. its got time
268*fcf3ce44SJohn Forte 				 */
269*fcf3ce44SJohn Forte 				(void) sleep(CFG_WAIT_SLEEP);
270*fcf3ce44SJohn Forte 
271*fcf3ce44SJohn Forte 				spcs_log("sndr", NULL,
272*fcf3ce44SJohn Forte 				    gettext("%s: new host found (%s) starting "
273*fcf3ce44SJohn Forte 				    "its autosync thread"), program,
274*fcf3ce44SJohn Forte 				    rdc_info->rdc_set[i].secondary.intf);
275*fcf3ce44SJohn Forte 
276*fcf3ce44SJohn Forte 				trc = thr_create(NULL, 0, wait_link_down,
277*fcf3ce44SJohn Forte 				    (void *) rdc_info->rdc_set[i].\
278*fcf3ce44SJohn Forte secondary.intf, THR_BOUND|THR_DETACHED, NULL);
279*fcf3ce44SJohn Forte 
280*fcf3ce44SJohn Forte 				if (trc != 0) {
281*fcf3ce44SJohn Forte 					spcs_log("sndr", NULL,
282*fcf3ce44SJohn Forte 					    gettext(
283*fcf3ce44SJohn Forte 					    "%s create new autosync "
284*fcf3ce44SJohn Forte 					    "thread failed"), program);
285*fcf3ce44SJohn Forte 					rdc_warn(NULL, gettext(
286*fcf3ce44SJohn Forte 					    "%s create new autosync "
287*fcf3ce44SJohn Forte 					    "thread failed"), program);
288*fcf3ce44SJohn Forte 				}
289*fcf3ce44SJohn Forte 			}
290*fcf3ce44SJohn Forte 		}
291*fcf3ce44SJohn Forte 	}
292*fcf3ce44SJohn Forte 	/* NOTREACHED */
293*fcf3ce44SJohn Forte }
294*fcf3ce44SJohn Forte 
295*fcf3ce44SJohn Forte 
296*fcf3ce44SJohn Forte /*
297*fcf3ce44SJohn Forte  * The kernel wakes up this function every time it detects the link to the
298*fcf3ce44SJohn Forte  * specified host has dropped.
299*fcf3ce44SJohn Forte  */
300*fcf3ce44SJohn Forte void *
301*fcf3ce44SJohn Forte wait_link_down(void *thehost)
302*fcf3ce44SJohn Forte {
303*fcf3ce44SJohn Forte 	char *host = (char *)thehost;
304*fcf3ce44SJohn Forte 	char tmphost[MAX_RDC_HOST_SIZE] = { '\0' };
305*fcf3ce44SJohn Forte 	spcs_s_info_t ustatus;
306*fcf3ce44SJohn Forte 
307*fcf3ce44SJohn Forte 	if (host)
308*fcf3ce44SJohn Forte 		strncpy(tmphost, host, MAX_RDC_HOST_SIZE);
309*fcf3ce44SJohn Forte 
310*fcf3ce44SJohn Forte 	ustatus = spcs_s_ucreate();
311*fcf3ce44SJohn Forte 
312*fcf3ce44SJohn Forte 	/* Never give up */
313*fcf3ce44SJohn Forte 	for (;;) {
314*fcf3ce44SJohn Forte #ifdef DEBUG
315*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
316*fcf3ce44SJohn Forte 		    gettext("%s: awaiting link down ioctl for %s"),
317*fcf3ce44SJohn Forte 		    program, host[0] == '\0' ? tmphost : host);
318*fcf3ce44SJohn Forte #endif
319*fcf3ce44SJohn Forte 		if (RDC_IOCTL(RDC_LINK_DOWN, host, 0, 0, 0, 0, ustatus)
320*fcf3ce44SJohn Forte 		    != SPCS_S_OK) {
321*fcf3ce44SJohn Forte 			spcs_log("sndr", &ustatus,
322*fcf3ce44SJohn Forte 			    gettext("%s: link down ioctl"),
323*fcf3ce44SJohn Forte 			    program);
324*fcf3ce44SJohn Forte 			rdc_warn(&ustatus, gettext("link down ioctl"));
325*fcf3ce44SJohn Forte 			continue;
326*fcf3ce44SJohn Forte 		}
327*fcf3ce44SJohn Forte #ifdef DEBUG
328*fcf3ce44SJohn Forte 
329*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
330*fcf3ce44SJohn Forte 		    gettext("%s: received link down ioctl for %s"),
331*fcf3ce44SJohn Forte 		    program, host[0] == '\0' ? tmphost : host);
332*fcf3ce44SJohn Forte #endif
333*fcf3ce44SJohn Forte 		rdc_sync(host[0] == '\0' ? tmphost : host);
334*fcf3ce44SJohn Forte 	}
335*fcf3ce44SJohn Forte 	/* LINTED */
336*fcf3ce44SJohn Forte }
337*fcf3ce44SJohn Forte 
338*fcf3ce44SJohn Forte 
339*fcf3ce44SJohn Forte /*
340*fcf3ce44SJohn Forte  * Called when the link to the specified host has dropped.
341*fcf3ce44SJohn Forte  * For all Remote Mirror sets using the link that have autosync on,
342*fcf3ce44SJohn Forte  * issue rdcadm -u commands until they complete successfully.
343*fcf3ce44SJohn Forte  */
344*fcf3ce44SJohn Forte void
345*fcf3ce44SJohn Forte rdc_sync(char *tohost)
346*fcf3ce44SJohn Forte {
347*fcf3ce44SJohn Forte 	rdc_set_t *rdc_set = NULL;
348*fcf3ce44SJohn Forte 	int *sync_done = NULL;
349*fcf3ce44SJohn Forte 	int sets = 0;
350*fcf3ce44SJohn Forte 	int syncs_done = 0;
351*fcf3ce44SJohn Forte 	char cmd[256];
352*fcf3ce44SJohn Forte 	rdc_config_t parms = { 0 };
353*fcf3ce44SJohn Forte 	spcs_s_info_t ustatus;
354*fcf3ce44SJohn Forte 	int i;
355*fcf3ce44SJohn Forte 	int setnumber;
356*fcf3ce44SJohn Forte 	int numfound = 0;
357*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
358*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
359*fcf3ce44SJohn Forte 	CFGFILE *cfg = NULL;
360*fcf3ce44SJohn Forte 	int size;
361*fcf3ce44SJohn Forte 	int first = 0;
362*fcf3ce44SJohn Forte 	int death = 0;
363*fcf3ce44SJohn Forte 	int cfglocked = 0;
364*fcf3ce44SJohn Forte 
365*fcf3ce44SJohn Forte 	ustatus = spcs_s_ucreate();
366*fcf3ce44SJohn Forte 
367*fcf3ce44SJohn Forte 	size = sizeof (rdc_set_t) * rdc_maxsets;
368*fcf3ce44SJohn Forte 	rdc_set = malloc(size);
369*fcf3ce44SJohn Forte 	if (rdc_set == NULL) {
370*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
371*fcf3ce44SJohn Forte 		    gettext("%s: unable to allocate %ld bytes"),
372*fcf3ce44SJohn Forte 		    program, size);
373*fcf3ce44SJohn Forte 		rdc_warn(NULL,
374*fcf3ce44SJohn Forte 			gettext("unable to allocate %ld bytes"), size);
375*fcf3ce44SJohn Forte 		goto done;
376*fcf3ce44SJohn Forte 	}
377*fcf3ce44SJohn Forte 	bzero(rdc_set, size);
378*fcf3ce44SJohn Forte 	size = sizeof (int) * rdc_maxsets;
379*fcf3ce44SJohn Forte 	sync_done = malloc(size);
380*fcf3ce44SJohn Forte 	if (sync_done == NULL) {
381*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
382*fcf3ce44SJohn Forte 		    gettext("%s: unable to allocate %ld bytes"),
383*fcf3ce44SJohn Forte 		    program, size);
384*fcf3ce44SJohn Forte 		rdc_warn(NULL,
385*fcf3ce44SJohn Forte 			gettext("unable to allocate %ld bytes"), size);
386*fcf3ce44SJohn Forte 		goto done;
387*fcf3ce44SJohn Forte 	}
388*fcf3ce44SJohn Forte 	bzero(sync_done, size);
389*fcf3ce44SJohn Forte 
390*fcf3ce44SJohn Forte 	/*
391*fcf3ce44SJohn Forte 	 * Get all sndr entries with shost matching tohost, and save the
392*fcf3ce44SJohn Forte 	 * details in an array.
393*fcf3ce44SJohn Forte 	 */
394*fcf3ce44SJohn Forte 	for (i = 0; i < rdc_maxsets; i++) {
395*fcf3ce44SJohn Forte 		setnumber = i + 1;
396*fcf3ce44SJohn Forte 		bzero(buf, sizeof (buf));
397*fcf3ce44SJohn Forte 		bzero(key, sizeof (key));
398*fcf3ce44SJohn Forte 
399*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "sndr.set%d.shost",
400*fcf3ce44SJohn Forte 		    setnumber);
401*fcf3ce44SJohn Forte 
402*fcf3ce44SJohn Forte 		if (!cfglocked) {
403*fcf3ce44SJohn Forte 			LOCKCFG();
404*fcf3ce44SJohn Forte 			if ((cfg = cfg_open(NULL)) == NULL) {
405*fcf3ce44SJohn Forte 				spcs_log("sndr", NULL,
406*fcf3ce44SJohn Forte 				    gettext("%s: error opening config"),
407*fcf3ce44SJohn Forte 				    program);
408*fcf3ce44SJohn Forte 
409*fcf3ce44SJohn Forte 				rdc_warn(NULL,
410*fcf3ce44SJohn Forte 				    gettext("error opening config"));
411*fcf3ce44SJohn Forte 				UNLOCKCFG();
412*fcf3ce44SJohn Forte 				goto done;
413*fcf3ce44SJohn Forte 			}
414*fcf3ce44SJohn Forte 
415*fcf3ce44SJohn Forte 			if (!cfg_lock(cfg, CFG_RDLOCK)) {
416*fcf3ce44SJohn Forte 				spcs_log("sndr", NULL,
417*fcf3ce44SJohn Forte 				    gettext("%s: error locking config"),
418*fcf3ce44SJohn Forte 				    program);
419*fcf3ce44SJohn Forte 				rdc_warn(NULL, gettext("error locking config"));
420*fcf3ce44SJohn Forte 				goto done;
421*fcf3ce44SJohn Forte 			}
422*fcf3ce44SJohn Forte 		}
423*fcf3ce44SJohn Forte 
424*fcf3ce44SJohn Forte 		cfglocked = 1;
425*fcf3ce44SJohn Forte 
426*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
427*fcf3ce44SJohn Forte 			if (numfound == 0) /* no matching hosts */
428*fcf3ce44SJohn Forte 				death = 1; /* thread will exit */
429*fcf3ce44SJohn Forte 			break;
430*fcf3ce44SJohn Forte 		}
431*fcf3ce44SJohn Forte 		if (strcmp(buf, tohost) != 0)
432*fcf3ce44SJohn Forte 			continue;
433*fcf3ce44SJohn Forte 
434*fcf3ce44SJohn Forte 		numfound++;
435*fcf3ce44SJohn Forte 		strncpy(rdc_set[sets].secondary.intf, buf, MAX_RDC_HOST_SIZE);
436*fcf3ce44SJohn Forte 
437*fcf3ce44SJohn Forte 		/* Got a matching entry */
438*fcf3ce44SJohn Forte 
439*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "sndr.set%d.phost",
440*fcf3ce44SJohn Forte 		    setnumber);
441*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
442*fcf3ce44SJohn Forte 			break;
443*fcf3ce44SJohn Forte 		strncpy(rdc_set[sets].primary.intf, buf, MAX_RDC_HOST_SIZE);
444*fcf3ce44SJohn Forte 
445*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "sndr.set%d.primary",
446*fcf3ce44SJohn Forte 		    setnumber);
447*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
448*fcf3ce44SJohn Forte 			break;
449*fcf3ce44SJohn Forte 		strncpy(rdc_set[sets].primary.file, buf, NSC_MAXPATH);
450*fcf3ce44SJohn Forte 
451*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "sndr.set%d.secondary",
452*fcf3ce44SJohn Forte 		    setnumber);
453*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
454*fcf3ce44SJohn Forte 			break;
455*fcf3ce44SJohn Forte 		strncpy(rdc_set[sets].secondary.file, buf, NSC_MAXPATH);
456*fcf3ce44SJohn Forte 
457*fcf3ce44SJohn Forte 		parms.command = RDC_CMD_STATUS;
458*fcf3ce44SJohn Forte 		bcopy((void *)(&rdc_set[sets]), (void *)(&parms.rdc_set[0]),
459*fcf3ce44SJohn Forte 		    sizeof (rdc_set_t));
460*fcf3ce44SJohn Forte 
461*fcf3ce44SJohn Forte 		/*
462*fcf3ce44SJohn Forte 		 * release cfg before diving into the kernel
463*fcf3ce44SJohn Forte 		 * this prevents a possible deadlock when doing
464*fcf3ce44SJohn Forte 		 * a reverse sync whick will wake up the sync_event
465*fcf3ce44SJohn Forte 		 * thread which will try and iiadm -c and hang
466*fcf3ce44SJohn Forte 		 * because we still have the cfg_lock. the timed
467*fcf3ce44SJohn Forte 		 * wait cv in the kernel will fail the sync and things
468*fcf3ce44SJohn Forte 		 * will undeadlock.
469*fcf3ce44SJohn Forte 		 */
470*fcf3ce44SJohn Forte 
471*fcf3ce44SJohn Forte 		cfg_close(cfg);
472*fcf3ce44SJohn Forte 		cfg = NULL;
473*fcf3ce44SJohn Forte 		cfglocked = 0;
474*fcf3ce44SJohn Forte 		UNLOCKCFG();
475*fcf3ce44SJohn Forte 
476*fcf3ce44SJohn Forte 		if (RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus) < 0) {
477*fcf3ce44SJohn Forte 			continue;
478*fcf3ce44SJohn Forte 		}
479*fcf3ce44SJohn Forte 		if ((parms.rdc_set[0].autosync == 0) ||
480*fcf3ce44SJohn Forte 		    (!(parms.rdc_set[0].flags & RDC_LOGGING))) {
481*fcf3ce44SJohn Forte 			continue;
482*fcf3ce44SJohn Forte 		}
483*fcf3ce44SJohn Forte 
484*fcf3ce44SJohn Forte 		/* Found a suitable set with autosync on, in logging mode */
485*fcf3ce44SJohn Forte 		sets++;
486*fcf3ce44SJohn Forte 	}
487*fcf3ce44SJohn Forte 
488*fcf3ce44SJohn Forte 	if (cfg) {
489*fcf3ce44SJohn Forte 		cfg_close(cfg);
490*fcf3ce44SJohn Forte 		cfg = NULL;
491*fcf3ce44SJohn Forte 		UNLOCKCFG();
492*fcf3ce44SJohn Forte 	}
493*fcf3ce44SJohn Forte 
494*fcf3ce44SJohn Forte 	if (sets == 0) {
495*fcf3ce44SJohn Forte #ifdef DEBUG
496*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
497*fcf3ce44SJohn Forte 		    gettext("%s: no sets requiring autosync found for %s"),
498*fcf3ce44SJohn Forte 		    program, tohost);
499*fcf3ce44SJohn Forte #endif
500*fcf3ce44SJohn Forte 		if (death) {
501*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
502*fcf3ce44SJohn Forte 			    gettext("%s: autosync thread stopping for %s "
503*fcf3ce44SJohn Forte 			    "(host deconfigured)"), program, tohost);
504*fcf3ce44SJohn Forte 		}
505*fcf3ce44SJohn Forte 		goto done;
506*fcf3ce44SJohn Forte 	}
507*fcf3ce44SJohn Forte 
508*fcf3ce44SJohn Forte 	/* Keep issuing rdcadm -u commands until they have all completed */
509*fcf3ce44SJohn Forte 	for (;;) {
510*fcf3ce44SJohn Forte 		if (!first)
511*fcf3ce44SJohn Forte 			first++;
512*fcf3ce44SJohn Forte 		else
513*fcf3ce44SJohn Forte 			(void) sleep(RESYNC_SLEEP);
514*fcf3ce44SJohn Forte 
515*fcf3ce44SJohn Forte 		/* Issue rdcadm -u commands for all remaining sets */
516*fcf3ce44SJohn Forte 		for (i = 0; i < sets; i++) {
517*fcf3ce44SJohn Forte 			if (sync_done[i])
518*fcf3ce44SJohn Forte 				continue;
519*fcf3ce44SJohn Forte 
520*fcf3ce44SJohn Forte 			/*
521*fcf3ce44SJohn Forte 			 * Need to check if autosync was turned off for a set
522*fcf3ce44SJohn Forte 			 * while we were sleeping. We could have the case where
523*fcf3ce44SJohn Forte 			 * an update sync failed and autosync was disabled
524*fcf3ce44SJohn Forte 			 * while we were sleeping and didn't detect the disable.
525*fcf3ce44SJohn Forte 			 * See BugID 4814213.
526*fcf3ce44SJohn Forte 			 */
527*fcf3ce44SJohn Forte 			parms.command = RDC_CMD_STATUS;
528*fcf3ce44SJohn Forte 			bcopy((void *)(&rdc_set[i]),
529*fcf3ce44SJohn Forte 			    (void *)(&parms.rdc_set[0]), sizeof (rdc_set_t));
530*fcf3ce44SJohn Forte 			if (RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0,
531*fcf3ce44SJohn Forte 			    ustatus) < 0) {
532*fcf3ce44SJohn Forte 				spcs_log("sndr", &ustatus, gettext("%s: "
533*fcf3ce44SJohn Forte 				    "status not available for %s:%s, stopping "
534*fcf3ce44SJohn Forte 				    "this autosync attempt"), program, tohost,
535*fcf3ce44SJohn Forte 				    rdc_set[i].secondary.file);
536*fcf3ce44SJohn Forte 				sync_done[i] = 1;
537*fcf3ce44SJohn Forte 				syncs_done++;
538*fcf3ce44SJohn Forte 				continue;
539*fcf3ce44SJohn Forte 			}
540*fcf3ce44SJohn Forte 			if (!(parms.rdc_set[0].autosync)) {
541*fcf3ce44SJohn Forte #ifdef DEBUG
542*fcf3ce44SJohn Forte 	spcs_log("sndr", NULL, gettext("%s: autosync disabled during sleep, "
543*fcf3ce44SJohn Forte 	    "stopping attempt for set %s:%s"), program, tohost,
544*fcf3ce44SJohn Forte 	    rdc_set[i].secondary.file);
545*fcf3ce44SJohn Forte #endif
546*fcf3ce44SJohn Forte 				sync_done[i] = 1;
547*fcf3ce44SJohn Forte 				syncs_done++;
548*fcf3ce44SJohn Forte 				continue;
549*fcf3ce44SJohn Forte 			}
550*fcf3ce44SJohn Forte 
551*fcf3ce44SJohn Forte 			(void) sprintf(cmd, "%s -un %s:%s", RDCADM, tohost,
552*fcf3ce44SJohn Forte 			    rdc_set[i].secondary.file);
553*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
554*fcf3ce44SJohn Forte 			    gettext("%s: issuing update sync for %s:%s"),
555*fcf3ce44SJohn Forte 			    program, tohost, rdc_set[i].secondary.file);
556*fcf3ce44SJohn Forte 			(void) system(cmd);
557*fcf3ce44SJohn Forte 		}
558*fcf3ce44SJohn Forte 
559*fcf3ce44SJohn Forte 		/* Issue rdcadm -w commands to wait for updates to finish */
560*fcf3ce44SJohn Forte 		for (i = 0; i < sets; i++) {
561*fcf3ce44SJohn Forte 			if (sync_done[i])
562*fcf3ce44SJohn Forte 				continue;
563*fcf3ce44SJohn Forte 
564*fcf3ce44SJohn Forte 			(void) sprintf(cmd, "%s -wn %s:%s", RDCADM, tohost,
565*fcf3ce44SJohn Forte 			    rdc_set[i].secondary.file);
566*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
567*fcf3ce44SJohn Forte 			    gettext("%s: issuing wait for %s:%s"),
568*fcf3ce44SJohn Forte 			    program, tohost, rdc_set[i].secondary.file);
569*fcf3ce44SJohn Forte 
570*fcf3ce44SJohn Forte 			(void) system(cmd);
571*fcf3ce44SJohn Forte 
572*fcf3ce44SJohn Forte 			parms.command = RDC_CMD_STATUS;
573*fcf3ce44SJohn Forte 			bcopy((void *)(&rdc_set[i]),
574*fcf3ce44SJohn Forte 			    (void *)(&parms.rdc_set[0]), sizeof (rdc_set_t));
575*fcf3ce44SJohn Forte 
576*fcf3ce44SJohn Forte 			if (RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0,
577*fcf3ce44SJohn Forte 			    ustatus) < 0) {
578*fcf3ce44SJohn Forte 				spcs_log("sndr", &ustatus,
579*fcf3ce44SJohn Forte 				    gettext("%s: status not available for "
580*fcf3ce44SJohn Forte 				    "%s:%s, stopping this autosync attempt"),
581*fcf3ce44SJohn Forte 				    program, tohost, rdc_set[i].secondary.file);
582*fcf3ce44SJohn Forte 				sync_done[i] = 1;
583*fcf3ce44SJohn Forte 				syncs_done++;
584*fcf3ce44SJohn Forte 				continue;
585*fcf3ce44SJohn Forte 			}
586*fcf3ce44SJohn Forte 			/* Check if completed OK, failed or autosync off */
587*fcf3ce44SJohn Forte 			if (!(parms.rdc_set[0].autosync) ||
588*fcf3ce44SJohn Forte 			    !(parms.rdc_set[0].flags & RDC_LOGGING) &&
589*fcf3ce44SJohn Forte 			    !(parms.rdc_set[0].flags & RDC_SYNCING)) {
590*fcf3ce44SJohn Forte 				sync_done[i] = 1;
591*fcf3ce44SJohn Forte 				syncs_done++;
592*fcf3ce44SJohn Forte 			}
593*fcf3ce44SJohn Forte 		}
594*fcf3ce44SJohn Forte 
595*fcf3ce44SJohn Forte 		if (syncs_done == sets)
596*fcf3ce44SJohn Forte 			break;		/* All completed OK */
597*fcf3ce44SJohn Forte 	}
598*fcf3ce44SJohn Forte 
599*fcf3ce44SJohn Forte done:
600*fcf3ce44SJohn Forte 	if (cfg) {
601*fcf3ce44SJohn Forte 		cfg_close(cfg);
602*fcf3ce44SJohn Forte 		UNLOCKCFG();
603*fcf3ce44SJohn Forte 	}
604*fcf3ce44SJohn Forte 	spcs_s_ufree(&ustatus);
605*fcf3ce44SJohn Forte 	if (sync_done)
606*fcf3ce44SJohn Forte 		free(sync_done);
607*fcf3ce44SJohn Forte 	if (rdc_set)
608*fcf3ce44SJohn Forte 		free(rdc_set);
609*fcf3ce44SJohn Forte 	if (death) { /* bye bye */
610*fcf3ce44SJohn Forte 		/*
611*fcf3ce44SJohn Forte 		 * if perhaps we lost some race, lets remove this entry from
612*fcf3ce44SJohn Forte 		 * the list. Then, if something did go wrong, and we did kill
613*fcf3ce44SJohn Forte 		 * a valid thread, it will be detected on the next go around
614*fcf3ce44SJohn Forte 		 * of the thread who is looking for new hosts to spawn threads
615*fcf3ce44SJohn Forte 		 */
616*fcf3ce44SJohn Forte 
617*fcf3ce44SJohn Forte 		remove_from_hostlist(tohost);
618*fcf3ce44SJohn Forte 		thr_exit(0);
619*fcf3ce44SJohn Forte 	}
620*fcf3ce44SJohn Forte 
621*fcf3ce44SJohn Forte 	(void) sleep(RESYNC_SLEEP);
622*fcf3ce44SJohn Forte }
623*fcf3ce44SJohn Forte 
624*fcf3ce44SJohn Forte /*
625*fcf3ce44SJohn Forte  * Wait for notification by the kernel of a sync start or a sync completed OK
626*fcf3ce44SJohn Forte  */
627*fcf3ce44SJohn Forte void *
628*fcf3ce44SJohn Forte wait_sync_event()
629*fcf3ce44SJohn Forte {
630*fcf3ce44SJohn Forte 	spcs_s_info_t ustatus;
631*fcf3ce44SJohn Forte 	char master[NSC_MAXPATH];
632*fcf3ce44SJohn Forte 	char group[NSC_MAXPATH];
633*fcf3ce44SJohn Forte 	int state;
634*fcf3ce44SJohn Forte 
635*fcf3ce44SJohn Forte 	ustatus = spcs_s_ucreate();
636*fcf3ce44SJohn Forte 
637*fcf3ce44SJohn Forte 	master[0] = '\0';
638*fcf3ce44SJohn Forte 	group[0] = '\0';
639*fcf3ce44SJohn Forte 
640*fcf3ce44SJohn Forte 	/* Never give up */
641*fcf3ce44SJohn Forte 	for (;;) {
642*fcf3ce44SJohn Forte 		/* Kernel tells us which volume and group the event is for */
643*fcf3ce44SJohn Forte 		state = RDC_IOCTL(RDC_SYNC_EVENT, master, group, 0, 0, 0,
644*fcf3ce44SJohn Forte 		    ustatus);
645*fcf3ce44SJohn Forte 		if (state < SPCS_S_OK) {
646*fcf3ce44SJohn Forte 			if (errno != EAGAIN) {
647*fcf3ce44SJohn Forte 				spcs_log("sndr", &ustatus,
648*fcf3ce44SJohn Forte 				    gettext("%s: update ioctl"),
649*fcf3ce44SJohn Forte 				    program);
650*fcf3ce44SJohn Forte 				rdc_warn(&ustatus, gettext("update ioctl"));
651*fcf3ce44SJohn Forte 				continue;
652*fcf3ce44SJohn Forte 			}
653*fcf3ce44SJohn Forte 			master[0] = '\0';
654*fcf3ce44SJohn Forte 			continue;
655*fcf3ce44SJohn Forte 		}
656*fcf3ce44SJohn Forte 
657*fcf3ce44SJohn Forte 		/*
658*fcf3ce44SJohn Forte 		 * If target is mounted at the start of a sync or reverse sync,
659*fcf3ce44SJohn Forte 		 * return a negative ack.
660*fcf3ce44SJohn Forte 		 */
661*fcf3ce44SJohn Forte 		if ((state == RDC_SYNC_START || state == RDC_RSYNC_START) &&
662*fcf3ce44SJohn Forte 		    mounted(master)) {
663*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
664*fcf3ce44SJohn Forte 			    gettext("%s: %s has a file system mounted"),
665*fcf3ce44SJohn Forte 			    program, master);
666*fcf3ce44SJohn Forte 			rdc_warn(NULL,
667*fcf3ce44SJohn Forte 			    gettext("%s has a file system mounted"),
668*fcf3ce44SJohn Forte 			    master);
669*fcf3ce44SJohn Forte 			master[0] = '\0';	/* negative ack */
670*fcf3ce44SJohn Forte 			continue;
671*fcf3ce44SJohn Forte 		}
672*fcf3ce44SJohn Forte 
673*fcf3ce44SJohn Forte 		switch (state) {
674*fcf3ce44SJohn Forte 		case RDC_SYNC_START:
675*fcf3ce44SJohn Forte 			if (group[0])
676*fcf3ce44SJohn Forte 				group_start(group);
677*fcf3ce44SJohn Forte 			else
678*fcf3ce44SJohn Forte 				sync_start(master);
679*fcf3ce44SJohn Forte 			break;
680*fcf3ce44SJohn Forte 
681*fcf3ce44SJohn Forte 		case RDC_SYNC_DONE:
682*fcf3ce44SJohn Forte 			if (group[0])
683*fcf3ce44SJohn Forte 				group_complete(group);
684*fcf3ce44SJohn Forte 			else
685*fcf3ce44SJohn Forte 				sync_complete(master);
686*fcf3ce44SJohn Forte 			break;
687*fcf3ce44SJohn Forte 
688*fcf3ce44SJohn Forte 		default:
689*fcf3ce44SJohn Forte 			break;
690*fcf3ce44SJohn Forte 		}
691*fcf3ce44SJohn Forte 	}
692*fcf3ce44SJohn Forte 	/* LINTED */
693*fcf3ce44SJohn Forte }
694*fcf3ce44SJohn Forte 
695*fcf3ce44SJohn Forte 
696*fcf3ce44SJohn Forte /*
697*fcf3ce44SJohn Forte  * A sync has completed OK to a volume not belonging to a group.
698*fcf3ce44SJohn Forte  * Set the state of the ndr_ii config entry to "update".
699*fcf3ce44SJohn Forte  */
700*fcf3ce44SJohn Forte void
701*fcf3ce44SJohn Forte sync_complete(char *master)
702*fcf3ce44SJohn Forte {
703*fcf3ce44SJohn Forte 	CFGFILE *cfg = NULL;
704*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
705*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
706*fcf3ce44SJohn Forte 	int i;
707*fcf3ce44SJohn Forte 	int setnumber;
708*fcf3ce44SJohn Forte 	int sev;
709*fcf3ce44SJohn Forte 
710*fcf3ce44SJohn Forte 	LOCKCFG();
711*fcf3ce44SJohn Forte 	if ((cfg = cfg_open(NULL)) == NULL) {
712*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
713*fcf3ce44SJohn Forte 		    gettext("%s: error opening config"),
714*fcf3ce44SJohn Forte 		    program);
715*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("error opening config"));
716*fcf3ce44SJohn Forte 		UNLOCKCFG();
717*fcf3ce44SJohn Forte 		return;
718*fcf3ce44SJohn Forte 	}
719*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, CFG_WRLOCK)) {
720*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
721*fcf3ce44SJohn Forte 		    gettext("%s: error locking config"),
722*fcf3ce44SJohn Forte 		    program);
723*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("error locking config"));
724*fcf3ce44SJohn Forte 		cfg_close(cfg);
725*fcf3ce44SJohn Forte 		UNLOCKCFG();
726*fcf3ce44SJohn Forte 		return;
727*fcf3ce44SJohn Forte 	}
728*fcf3ce44SJohn Forte 
729*fcf3ce44SJohn Forte 	/* get ndr_ii entries until a match is found */
730*fcf3ce44SJohn Forte 	for (i = 0; ; i++) {
731*fcf3ce44SJohn Forte 		setnumber = i + 1;
732*fcf3ce44SJohn Forte 
733*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.secondary",
734*fcf3ce44SJohn Forte 		    setnumber);
735*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
736*fcf3ce44SJohn Forte 			break;
737*fcf3ce44SJohn Forte 		if (strcmp(buf, master) != 0)
738*fcf3ce44SJohn Forte 			continue;
739*fcf3ce44SJohn Forte 
740*fcf3ce44SJohn Forte 		/* Found the matching entry */
741*fcf3ce44SJohn Forte 
742*fcf3ce44SJohn Forte 		/*
743*fcf3ce44SJohn Forte 		 * Set state to "update" so that starting another sync will
744*fcf3ce44SJohn Forte 		 * cause a new Point-in-Time Copy snapshot to be taken.
745*fcf3ce44SJohn Forte 		 */
746*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
747*fcf3ce44SJohn Forte 		    setnumber);
748*fcf3ce44SJohn Forte 		if ((cfg_put_cstring(cfg, key, UPDATE, strlen(UPDATE)) < 0) ||
749*fcf3ce44SJohn Forte 		    (cfg_commit(cfg) < 0)) {
750*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
751*fcf3ce44SJohn Forte 			    gettext("%s: unable to update \"%s\" "
752*fcf3ce44SJohn Forte 			    "in configuration storage: %s"),
753*fcf3ce44SJohn Forte 			    program, buf, cfg_error(&sev));
754*fcf3ce44SJohn Forte 			rdc_warn(NULL,
755*fcf3ce44SJohn Forte 			    gettext("unable to update \"%s\" "
756*fcf3ce44SJohn Forte 			    "in configuration storage: %s"),
757*fcf3ce44SJohn Forte 			    buf, cfg_error(&sev));
758*fcf3ce44SJohn Forte 		}
759*fcf3ce44SJohn Forte 		break;
760*fcf3ce44SJohn Forte 	}
761*fcf3ce44SJohn Forte 
762*fcf3ce44SJohn Forte 	cfg_close(cfg);
763*fcf3ce44SJohn Forte 	UNLOCKCFG();
764*fcf3ce44SJohn Forte }
765*fcf3ce44SJohn Forte 
766*fcf3ce44SJohn Forte 
767*fcf3ce44SJohn Forte /*
768*fcf3ce44SJohn Forte  * Starting a sync to the specified master volume.
769*fcf3ce44SJohn Forte  * Check the ndr_ii config entries to see if a Point-in-Time Copy
770*fcf3ce44SJohn Forte  * snapshot should be taken.
771*fcf3ce44SJohn Forte  */
772*fcf3ce44SJohn Forte void
773*fcf3ce44SJohn Forte sync_start(char *master)
774*fcf3ce44SJohn Forte {
775*fcf3ce44SJohn Forte 	char cmd[256];
776*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
777*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
778*fcf3ce44SJohn Forte 	CFGFILE *cfg = NULL;
779*fcf3ce44SJohn Forte 	int i;
780*fcf3ce44SJohn Forte 	int setnumber;
781*fcf3ce44SJohn Forte 	int found;
782*fcf3ce44SJohn Forte 	int sev;
783*fcf3ce44SJohn Forte 	char shadow[NSC_MAXPATH];
784*fcf3ce44SJohn Forte 	char bitmap[NSC_MAXPATH];
785*fcf3ce44SJohn Forte 	char *ctag = NULL;
786*fcf3ce44SJohn Forte 
787*fcf3ce44SJohn Forte 	LOCKCFG();
788*fcf3ce44SJohn Forte 	if ((cfg = cfg_open(NULL)) == NULL) {
789*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
790*fcf3ce44SJohn Forte 		    gettext("%s: error opening config"),
791*fcf3ce44SJohn Forte 		    program);
792*fcf3ce44SJohn Forte 		rdc_warn(NULL,
793*fcf3ce44SJohn Forte 		    gettext("error opening config"));
794*fcf3ce44SJohn Forte 		UNLOCKCFG();
795*fcf3ce44SJohn Forte 		return;
796*fcf3ce44SJohn Forte 	}
797*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, CFG_RDLOCK)) {
798*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
799*fcf3ce44SJohn Forte 		    gettext("%s: error locking config"),
800*fcf3ce44SJohn Forte 		    program);
801*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("error locking config"));
802*fcf3ce44SJohn Forte 		cfg_close(cfg);
803*fcf3ce44SJohn Forte 		UNLOCKCFG();
804*fcf3ce44SJohn Forte 		return;
805*fcf3ce44SJohn Forte 	}
806*fcf3ce44SJohn Forte 
807*fcf3ce44SJohn Forte 	found = 0;
808*fcf3ce44SJohn Forte 	/* get ndr_ii entries until a match is found */
809*fcf3ce44SJohn Forte 	for (i = 0; ; i++) {
810*fcf3ce44SJohn Forte 		setnumber = i + 1;
811*fcf3ce44SJohn Forte 
812*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.secondary",
813*fcf3ce44SJohn Forte 		    setnumber);
814*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
815*fcf3ce44SJohn Forte 			break;
816*fcf3ce44SJohn Forte 		if (strcmp(buf, master) != 0)
817*fcf3ce44SJohn Forte 			continue;
818*fcf3ce44SJohn Forte 
819*fcf3ce44SJohn Forte 		/* Got a matching entry */
820*fcf3ce44SJohn Forte 
821*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.shadow",
822*fcf3ce44SJohn Forte 		    setnumber);
823*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
824*fcf3ce44SJohn Forte 			break;
825*fcf3ce44SJohn Forte 		strncpy(shadow, buf, NSC_MAXPATH);
826*fcf3ce44SJohn Forte 
827*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.bitmap",
828*fcf3ce44SJohn Forte 		    setnumber);
829*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
830*fcf3ce44SJohn Forte 			break;
831*fcf3ce44SJohn Forte 		strncpy(bitmap, buf, NSC_MAXPATH);
832*fcf3ce44SJohn Forte 
833*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
834*fcf3ce44SJohn Forte 		    setnumber);
835*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
836*fcf3ce44SJohn Forte 			break;
837*fcf3ce44SJohn Forte 
838*fcf3ce44SJohn Forte 		/*
839*fcf3ce44SJohn Forte 		 * If an PIT snapshot has already been taken, and syncing did
840*fcf3ce44SJohn Forte 		 * not complete, the state will be "noupdate", to indicate we
841*fcf3ce44SJohn Forte 		 * should not take another one at this point.
842*fcf3ce44SJohn Forte 		 */
843*fcf3ce44SJohn Forte 		if (strcmp(buf, NOUPDATE) != 0)
844*fcf3ce44SJohn Forte 			found = 1;
845*fcf3ce44SJohn Forte 
846*fcf3ce44SJohn Forte 		break;
847*fcf3ce44SJohn Forte 	}
848*fcf3ce44SJohn Forte 
849*fcf3ce44SJohn Forte 	if (!found) {
850*fcf3ce44SJohn Forte 		cfg_close(cfg);
851*fcf3ce44SJohn Forte 		UNLOCKCFG();
852*fcf3ce44SJohn Forte 		return;
853*fcf3ce44SJohn Forte 	}
854*fcf3ce44SJohn Forte 
855*fcf3ce44SJohn Forte 	found = 0;
856*fcf3ce44SJohn Forte 	/* get ii entries until a match is found */
857*fcf3ce44SJohn Forte 	for (i = 0; ; i++) {
858*fcf3ce44SJohn Forte 		setnumber = i + 1;
859*fcf3ce44SJohn Forte 
860*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ii.set%d.shadow",
861*fcf3ce44SJohn Forte 		    setnumber);
862*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
863*fcf3ce44SJohn Forte 			break;
864*fcf3ce44SJohn Forte 		if (strcmp(buf, shadow) != 0)
865*fcf3ce44SJohn Forte 			continue;
866*fcf3ce44SJohn Forte 
867*fcf3ce44SJohn Forte 		/* Matching shadow found, so ii already enabled */
868*fcf3ce44SJohn Forte 		found = 1;
869*fcf3ce44SJohn Forte 		break;
870*fcf3ce44SJohn Forte 	}
871*fcf3ce44SJohn Forte 
872*fcf3ce44SJohn Forte 	if (found) {
873*fcf3ce44SJohn Forte 		/* Already PIT enabled, so just take a snapshot */
874*fcf3ce44SJohn Forte 
875*fcf3ce44SJohn Forte 		/* Get cluster tag of matching entry */
876*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ii.set%d.cnode", setnumber);
877*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) >= 0)
878*fcf3ce44SJohn Forte 			if ((strlen(buf) == 0) || (buf[0] == '-'))
879*fcf3ce44SJohn Forte 					ctag = "-C local";
880*fcf3ce44SJohn Forte 				else
881*fcf3ce44SJohn Forte 					ctag = "";
882*fcf3ce44SJohn Forte 		(void) sprintf(cmd, "%s %s -u s %s", IIADM, ctag, shadow);
883*fcf3ce44SJohn Forte 	} else {
884*fcf3ce44SJohn Forte 		/*
885*fcf3ce44SJohn Forte 		 * If clustered, need to enable PIT Copy sets in the same
886*fcf3ce44SJohn Forte 		 * cluster as the Remote Mirror set
887*fcf3ce44SJohn Forte 		 */
888*fcf3ce44SJohn Forte 
889*fcf3ce44SJohn Forte 		if (clustered) {
890*fcf3ce44SJohn Forte 			/* Find a RM set with master as the local volume */
891*fcf3ce44SJohn Forte 
892*fcf3ce44SJohn Forte 			for (i = 0; i < rdc_maxsets; i++) {
893*fcf3ce44SJohn Forte 				setnumber = i + 1;
894*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
895*fcf3ce44SJohn Forte 				    "sndr.set%d.phost", setnumber);
896*fcf3ce44SJohn Forte 				if (cfg_get_cstring(cfg, key, buf,
897*fcf3ce44SJohn Forte 				    CFG_MAX_BUF) < 0)
898*fcf3ce44SJohn Forte 					break;
899*fcf3ce44SJohn Forte 
900*fcf3ce44SJohn Forte 				if (self_check(buf))
901*fcf3ce44SJohn Forte 					(void) snprintf(key, sizeof (key),
902*fcf3ce44SJohn Forte 					    "sndr.set%d.primary", setnumber);
903*fcf3ce44SJohn Forte 				else
904*fcf3ce44SJohn Forte 					(void) snprintf(key, sizeof (key),
905*fcf3ce44SJohn Forte 					    "sndr.set%d.secondary", setnumber);
906*fcf3ce44SJohn Forte 				if (cfg_get_cstring(cfg, key, buf,
907*fcf3ce44SJohn Forte 				    CFG_MAX_BUF) < 0)
908*fcf3ce44SJohn Forte 					break;
909*fcf3ce44SJohn Forte 
910*fcf3ce44SJohn Forte 				if (strcmp(buf, master) != 0)
911*fcf3ce44SJohn Forte 					continue;
912*fcf3ce44SJohn Forte 
913*fcf3ce44SJohn Forte 				/* Get cluster tag of matching entry */
914*fcf3ce44SJohn Forte 
915*fcf3ce44SJohn Forte 				(void) snprintf(key, sizeof (key),
916*fcf3ce44SJohn Forte 				    "sndr.set%d.cnode", setnumber);
917*fcf3ce44SJohn Forte 				if (cfg_get_cstring(cfg, key, buf,
918*fcf3ce44SJohn Forte 				    CFG_MAX_BUF) < 0)
919*fcf3ce44SJohn Forte 					break;
920*fcf3ce44SJohn Forte 				if ((strlen(buf) == 0) || (buf[0] == '-'))
921*fcf3ce44SJohn Forte 					ctag = strdup("local");
922*fcf3ce44SJohn Forte 				else
923*fcf3ce44SJohn Forte 					ctag = strdup(buf);
924*fcf3ce44SJohn Forte 				break;
925*fcf3ce44SJohn Forte 			}
926*fcf3ce44SJohn Forte 		}
927*fcf3ce44SJohn Forte 
928*fcf3ce44SJohn Forte 		/* Not already enabled, so enable a dependent */
929*fcf3ce44SJohn Forte 		if (ctag) {
930*fcf3ce44SJohn Forte 			(void) sprintf(cmd, "%s -C %s -e dep %s %s %s", IIADM,
931*fcf3ce44SJohn Forte 			    ctag, master, shadow, bitmap);
932*fcf3ce44SJohn Forte 			free(ctag);
933*fcf3ce44SJohn Forte 		} else
934*fcf3ce44SJohn Forte 			(void) sprintf(cmd, "%s -e dep %s %s %s", IIADM, master,
935*fcf3ce44SJohn Forte 			    shadow, bitmap);
936*fcf3ce44SJohn Forte 	}
937*fcf3ce44SJohn Forte 
938*fcf3ce44SJohn Forte 	cfg_close(cfg);
939*fcf3ce44SJohn Forte 
940*fcf3ce44SJohn Forte 	if (system(cmd) != 0) {
941*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
942*fcf3ce44SJohn Forte 		    gettext("Point-in-Time Copy snapshot failed for %s %s %s."
943*fcf3ce44SJohn Forte 		    " Please check validity of ndr_ii entry"),
944*fcf3ce44SJohn Forte 		    master, shadow, bitmap);
945*fcf3ce44SJohn Forte 		cfg_close(cfg);
946*fcf3ce44SJohn Forte 		UNLOCKCFG();
947*fcf3ce44SJohn Forte 		return;
948*fcf3ce44SJohn Forte 	}
949*fcf3ce44SJohn Forte 
950*fcf3ce44SJohn Forte 	/*
951*fcf3ce44SJohn Forte 	 * PIT Copy enable or update was fine, so update the ndr_ii entry
952*fcf3ce44SJohn Forte 	 * to "noupdate", to prevent invalid point in time copies.
953*fcf3ce44SJohn Forte 	 */
954*fcf3ce44SJohn Forte 
955*fcf3ce44SJohn Forte 	if ((cfg = cfg_open(NULL)) == NULL) {
956*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
957*fcf3ce44SJohn Forte 		    gettext("%s: error opening config"),
958*fcf3ce44SJohn Forte 		    program);
959*fcf3ce44SJohn Forte 		rdc_warn(NULL,
960*fcf3ce44SJohn Forte 		    gettext("error opening config"));
961*fcf3ce44SJohn Forte 		UNLOCKCFG();
962*fcf3ce44SJohn Forte 		return;
963*fcf3ce44SJohn Forte 	}
964*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, CFG_WRLOCK)) {
965*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
966*fcf3ce44SJohn Forte 		    gettext("%s: error locking config"),
967*fcf3ce44SJohn Forte 		    program);
968*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("error locking config"));
969*fcf3ce44SJohn Forte 		cfg_close(cfg);
970*fcf3ce44SJohn Forte 		UNLOCKCFG();
971*fcf3ce44SJohn Forte 		return;
972*fcf3ce44SJohn Forte 	}
973*fcf3ce44SJohn Forte 
974*fcf3ce44SJohn Forte 	/* get ndr_ii entries until a match is found */
975*fcf3ce44SJohn Forte 	for (i = 0; ; i++) {
976*fcf3ce44SJohn Forte 		setnumber = i + 1;
977*fcf3ce44SJohn Forte 
978*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.shadow",
979*fcf3ce44SJohn Forte 		    setnumber);
980*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
981*fcf3ce44SJohn Forte 			break;
982*fcf3ce44SJohn Forte 		if (strcmp(buf, shadow) != 0)
983*fcf3ce44SJohn Forte 			continue;
984*fcf3ce44SJohn Forte 
985*fcf3ce44SJohn Forte 		/* Found the matching entry */
986*fcf3ce44SJohn Forte 
987*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
988*fcf3ce44SJohn Forte 		    setnumber);
989*fcf3ce44SJohn Forte 		if ((cfg_put_cstring(cfg, key, NOUPDATE,
990*fcf3ce44SJohn Forte 			strlen(NOUPDATE)) < 0) || (cfg_commit(cfg) < 0)) {
991*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
992*fcf3ce44SJohn Forte 			    gettext("%s: unable to update \"%s\" "
993*fcf3ce44SJohn Forte 			    "in configuration storage: %s"),
994*fcf3ce44SJohn Forte 			    program, buf, cfg_error(&sev));
995*fcf3ce44SJohn Forte 			rdc_warn(NULL,
996*fcf3ce44SJohn Forte 			    gettext("unable to update \"%s\" "
997*fcf3ce44SJohn Forte 			    "in configuration storage: %s"),
998*fcf3ce44SJohn Forte 			    buf, cfg_error(&sev));
999*fcf3ce44SJohn Forte 		}
1000*fcf3ce44SJohn Forte 		break;
1001*fcf3ce44SJohn Forte 	}
1002*fcf3ce44SJohn Forte 	cfg_close(cfg);
1003*fcf3ce44SJohn Forte 	UNLOCKCFG();
1004*fcf3ce44SJohn Forte }
1005*fcf3ce44SJohn Forte 
1006*fcf3ce44SJohn Forte void
1007*fcf3ce44SJohn Forte cleanup_hostlist(rdc_status_t *rdc_info)
1008*fcf3ce44SJohn Forte {
1009*fcf3ce44SJohn Forte 	int i, j, k;
1010*fcf3ce44SJohn Forte 	char *host, *exhost;
1011*fcf3ce44SJohn Forte 
1012*fcf3ce44SJohn Forte 
1013*fcf3ce44SJohn Forte 	(void) mutex_lock(&host_list->hosts_mutex);
1014*fcf3ce44SJohn Forte 	for (i = 0; i < host_list->numhosts; i++) {
1015*fcf3ce44SJohn Forte 		int found = 0;
1016*fcf3ce44SJohn Forte 		for (j = 0; (j < rdc_maxsets) && !found; j++) {
1017*fcf3ce44SJohn Forte 			if (!rdc_info->rdc_set[j].flags & RDC_ENABLED)
1018*fcf3ce44SJohn Forte 				continue;
1019*fcf3ce44SJohn Forte 			if ((!host_list->configured[i]) ||
1020*fcf3ce44SJohn Forte 			    (host_list->hosts[i] == '\0')) {
1021*fcf3ce44SJohn Forte 				(void) mutex_unlock(&host_list->hosts_mutex);
1022*fcf3ce44SJohn Forte 				return;
1023*fcf3ce44SJohn Forte 			}
1024*fcf3ce44SJohn Forte 
1025*fcf3ce44SJohn Forte 			host = rdc_info->rdc_set[j].secondary.intf;
1026*fcf3ce44SJohn Forte 			if (strcmp(host_list->hosts[i], host) == 0)
1027*fcf3ce44SJohn Forte 				found++;
1028*fcf3ce44SJohn Forte 		}
1029*fcf3ce44SJohn Forte 		if (j == rdc_maxsets) {
1030*fcf3ce44SJohn Forte 			/*
1031*fcf3ce44SJohn Forte 			 * this set is not in the kernel, so remove from list
1032*fcf3ce44SJohn Forte 			 */
1033*fcf3ce44SJohn Forte 			exhost = host_list->hosts[i];
1034*fcf3ce44SJohn Forte 			if (exhost) {
1035*fcf3ce44SJohn Forte 				free(exhost);
1036*fcf3ce44SJohn Forte 				exhost = NULL;
1037*fcf3ce44SJohn Forte 			}
1038*fcf3ce44SJohn Forte 
1039*fcf3ce44SJohn Forte 			k = i;
1040*fcf3ce44SJohn Forte 			while (k < host_list->numhosts) {
1041*fcf3ce44SJohn Forte 			    host_list->hosts[k] = k < host_list->numhosts - 1 ?
1042*fcf3ce44SJohn Forte 				host_list->hosts[k+1] : NULL;
1043*fcf3ce44SJohn Forte 			    k++;
1044*fcf3ce44SJohn Forte 			}
1045*fcf3ce44SJohn Forte 			host_list->numhosts--;
1046*fcf3ce44SJohn Forte 
1047*fcf3ce44SJohn Forte 			bcopy(&host_list->configured[i+1],
1048*fcf3ce44SJohn Forte 			    &host_list->configured[i],
1049*fcf3ce44SJohn Forte 			    (MAXHOSTS - i + 1) * sizeof (int));
1050*fcf3ce44SJohn Forte 			host_list->configured[MAXHOSTS - 1] = 0;
1051*fcf3ce44SJohn Forte 		}
1052*fcf3ce44SJohn Forte 	}
1053*fcf3ce44SJohn Forte 	(void) mutex_unlock(&host_list->hosts_mutex);
1054*fcf3ce44SJohn Forte }
1055*fcf3ce44SJohn Forte 
1056*fcf3ce44SJohn Forte /*
1057*fcf3ce44SJohn Forte  * explicity remove a host from the host list
1058*fcf3ce44SJohn Forte  * also update the configured array
1059*fcf3ce44SJohn Forte  * called in rdc_sync, just before exiting a thread.
1060*fcf3ce44SJohn Forte  */
1061*fcf3ce44SJohn Forte void
1062*fcf3ce44SJohn Forte remove_from_hostlist(char *host)
1063*fcf3ce44SJohn Forte {
1064*fcf3ce44SJohn Forte 	int i, k;
1065*fcf3ce44SJohn Forte 	char *exhost;
1066*fcf3ce44SJohn Forte 
1067*fcf3ce44SJohn Forte 	/* why bother? */
1068*fcf3ce44SJohn Forte 	if ((!host) || (host[0] == '\0'))
1069*fcf3ce44SJohn Forte 		return;
1070*fcf3ce44SJohn Forte 
1071*fcf3ce44SJohn Forte 	(void) mutex_lock(&host_list->hosts_mutex);
1072*fcf3ce44SJohn Forte 	for (i = 0; i < host_list->numhosts; i++) {
1073*fcf3ce44SJohn Forte 		if (strcmp(host, host_list->hosts[i]) == 0) { /* found it */
1074*fcf3ce44SJohn Forte 			exhost = host_list->hosts[i];
1075*fcf3ce44SJohn Forte 			if (exhost) {
1076*fcf3ce44SJohn Forte 				free(exhost);
1077*fcf3ce44SJohn Forte 				exhost = NULL;
1078*fcf3ce44SJohn Forte 			}
1079*fcf3ce44SJohn Forte 			k = i;
1080*fcf3ce44SJohn Forte 			while (k < host_list->numhosts) {
1081*fcf3ce44SJohn Forte 			    host_list->hosts[k] = k < host_list->numhosts - 1 ?
1082*fcf3ce44SJohn Forte 				host_list->hosts[k+1] : NULL;
1083*fcf3ce44SJohn Forte 			    k++;
1084*fcf3ce44SJohn Forte 			}
1085*fcf3ce44SJohn Forte 			host_list->numhosts--;
1086*fcf3ce44SJohn Forte 			bcopy(&host_list->configured[i+1],
1087*fcf3ce44SJohn Forte 			    &host_list->configured[i],
1088*fcf3ce44SJohn Forte 			    (MAXHOSTS - i + 1) * sizeof (int));
1089*fcf3ce44SJohn Forte 			host_list->configured[MAXHOSTS - 1] = 0;
1090*fcf3ce44SJohn Forte 		}
1091*fcf3ce44SJohn Forte 
1092*fcf3ce44SJohn Forte 	}
1093*fcf3ce44SJohn Forte 	(void) mutex_unlock(&host_list->hosts_mutex);
1094*fcf3ce44SJohn Forte }
1095*fcf3ce44SJohn Forte /*
1096*fcf3ce44SJohn Forte  * Check to see if this host isn't in our list, so needs a new rdcsyncd proc
1097*fcf3ce44SJohn Forte  */
1098*fcf3ce44SJohn Forte int
1099*fcf3ce44SJohn Forte isnewhost(char *host)
1100*fcf3ce44SJohn Forte {
1101*fcf3ce44SJohn Forte 	int i;
1102*fcf3ce44SJohn Forte 	int new;
1103*fcf3ce44SJohn Forte 
1104*fcf3ce44SJohn Forte 	if (self_check(host)) {
1105*fcf3ce44SJohn Forte 		return (0);
1106*fcf3ce44SJohn Forte 	}
1107*fcf3ce44SJohn Forte 
1108*fcf3ce44SJohn Forte 	(void) mutex_lock(&host_list->hosts_mutex);
1109*fcf3ce44SJohn Forte 	new = 1;
1110*fcf3ce44SJohn Forte 	for (i = 0; i < MAXHOSTS; i++) {
1111*fcf3ce44SJohn Forte 		if (host_list->configured[i] == 0) {
1112*fcf3ce44SJohn Forte 			host_list->configured[i] = 1;
1113*fcf3ce44SJohn Forte 			host_list->hosts[i] = strdup(host);
1114*fcf3ce44SJohn Forte 			host_list->numhosts++;
1115*fcf3ce44SJohn Forte 			break;
1116*fcf3ce44SJohn Forte 		}
1117*fcf3ce44SJohn Forte 		if (strcmp(host, host_list->hosts[i]) == 0) {
1118*fcf3ce44SJohn Forte 			new = 0;
1119*fcf3ce44SJohn Forte 			break;
1120*fcf3ce44SJohn Forte 		}
1121*fcf3ce44SJohn Forte 	}
1122*fcf3ce44SJohn Forte 	(void) mutex_unlock(&host_list->hosts_mutex);
1123*fcf3ce44SJohn Forte 	if (i == MAXHOSTS)
1124*fcf3ce44SJohn Forte 		new = 0;
1125*fcf3ce44SJohn Forte 	return (new);
1126*fcf3ce44SJohn Forte }
1127*fcf3ce44SJohn Forte 
1128*fcf3ce44SJohn Forte 
1129*fcf3ce44SJohn Forte /*
1130*fcf3ce44SJohn Forte  * Look for a matching volume name in our remembered list.
1131*fcf3ce44SJohn Forte  */
1132*fcf3ce44SJohn Forte int
1133*fcf3ce44SJohn Forte volume_match(char *buf, char **volume_list, int volumes)
1134*fcf3ce44SJohn Forte {
1135*fcf3ce44SJohn Forte 	int i;
1136*fcf3ce44SJohn Forte 	char *vol;
1137*fcf3ce44SJohn Forte 
1138*fcf3ce44SJohn Forte 	for (i = 0; i < volumes; i++) {
1139*fcf3ce44SJohn Forte 		vol = volume_list[i];
1140*fcf3ce44SJohn Forte 		if (strcmp(buf, vol) == 0) {
1141*fcf3ce44SJohn Forte 			return (1);
1142*fcf3ce44SJohn Forte 		}
1143*fcf3ce44SJohn Forte 	}
1144*fcf3ce44SJohn Forte 	return (0);
1145*fcf3ce44SJohn Forte }
1146*fcf3ce44SJohn Forte 
1147*fcf3ce44SJohn Forte 
1148*fcf3ce44SJohn Forte /*
1149*fcf3ce44SJohn Forte  * A sync has completed to a group. We can only update the ndr_ii entries
1150*fcf3ce44SJohn Forte  * if all the members of the group have completed their syncs OK.
1151*fcf3ce44SJohn Forte  * It would be bad to allow some members of the group to have PIT Copy snapshots
1152*fcf3ce44SJohn Forte  * taken and others not, as they need to be consistent.
1153*fcf3ce44SJohn Forte  */
1154*fcf3ce44SJohn Forte void
1155*fcf3ce44SJohn Forte group_complete(char *group)
1156*fcf3ce44SJohn Forte {
1157*fcf3ce44SJohn Forte 	char **volumes = NULL;
1158*fcf3ce44SJohn Forte 	spcs_s_info_t ustatus;
1159*fcf3ce44SJohn Forte 	rdc_config_t parms = { 0 };
1160*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
1161*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
1162*fcf3ce44SJohn Forte 	CFGFILE *cfg = NULL;
1163*fcf3ce44SJohn Forte 	int i;
1164*fcf3ce44SJohn Forte 	int setnumber;
1165*fcf3ce44SJohn Forte 	int found;
1166*fcf3ce44SJohn Forte 	int replicating = 0;
1167*fcf3ce44SJohn Forte 	char primary[NSC_MAXPATH];
1168*fcf3ce44SJohn Forte 	char secondary[NSC_MAXPATH];
1169*fcf3ce44SJohn Forte 	char phost[MAX_RDC_HOST_SIZE];
1170*fcf3ce44SJohn Forte 	char shost[MAX_RDC_HOST_SIZE];
1171*fcf3ce44SJohn Forte 	rdc_set_t *rdc_set;
1172*fcf3ce44SJohn Forte 	int sev;
1173*fcf3ce44SJohn Forte 	char *local_file;
1174*fcf3ce44SJohn Forte 	int size;
1175*fcf3ce44SJohn Forte 
1176*fcf3ce44SJohn Forte 	ustatus = spcs_s_ucreate();
1177*fcf3ce44SJohn Forte 
1178*fcf3ce44SJohn Forte 	size = sizeof (char *) * rdc_maxsets;
1179*fcf3ce44SJohn Forte 	volumes = malloc(size);
1180*fcf3ce44SJohn Forte 	if (volumes == NULL) {
1181*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
1182*fcf3ce44SJohn Forte 		    gettext("%s: unable to allocate %ld bytes"),
1183*fcf3ce44SJohn Forte 		    program, size);
1184*fcf3ce44SJohn Forte 		rdc_warn(NULL,
1185*fcf3ce44SJohn Forte 			gettext("unable to allocate %ld bytes"), size);
1186*fcf3ce44SJohn Forte 		goto done;
1187*fcf3ce44SJohn Forte 	}
1188*fcf3ce44SJohn Forte 	bzero(volumes, size);
1189*fcf3ce44SJohn Forte 
1190*fcf3ce44SJohn Forte 	/*
1191*fcf3ce44SJohn Forte 	 * If all members of this group are replicating
1192*fcf3ce44SJohn Forte 	 * set ii_ndr state to "update". Otherwise leave them alone.
1193*fcf3ce44SJohn Forte 	 */
1194*fcf3ce44SJohn Forte 	LOCKCFG();
1195*fcf3ce44SJohn Forte 	if ((cfg = cfg_open(NULL)) == NULL) {
1196*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
1197*fcf3ce44SJohn Forte 		    gettext("%s: error opening lconfig"),
1198*fcf3ce44SJohn Forte 		    program);
1199*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("error opening config"));
1200*fcf3ce44SJohn Forte 		UNLOCKCFG();
1201*fcf3ce44SJohn Forte 		goto done;
1202*fcf3ce44SJohn Forte 	}
1203*fcf3ce44SJohn Forte 
1204*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, CFG_RDLOCK)) {
1205*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
1206*fcf3ce44SJohn Forte 		    gettext("%s: error locking config"),
1207*fcf3ce44SJohn Forte 		    program);
1208*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("error locking config"));
1209*fcf3ce44SJohn Forte 		goto done;
1210*fcf3ce44SJohn Forte 	}
1211*fcf3ce44SJohn Forte 
1212*fcf3ce44SJohn Forte 	found = 0;
1213*fcf3ce44SJohn Forte 
1214*fcf3ce44SJohn Forte 	/* get all RM entries, with a matching group, that are replicating */
1215*fcf3ce44SJohn Forte 	for (i = 0; i < rdc_maxsets; i++) {
1216*fcf3ce44SJohn Forte 		setnumber = i + 1;
1217*fcf3ce44SJohn Forte 
1218*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key),
1219*fcf3ce44SJohn Forte 		    "sndr.set%d.group", setnumber);
1220*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
1221*fcf3ce44SJohn Forte 			break;
1222*fcf3ce44SJohn Forte 
1223*fcf3ce44SJohn Forte 		if (strcmp(buf, group) != 0)
1224*fcf3ce44SJohn Forte 			continue;
1225*fcf3ce44SJohn Forte 
1226*fcf3ce44SJohn Forte 		/* Found a matching entry */
1227*fcf3ce44SJohn Forte 
1228*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key),
1229*fcf3ce44SJohn Forte 		    "sndr.set%d.primary", setnumber);
1230*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, primary, sizeof (primary)) < 0)
1231*fcf3ce44SJohn Forte 			break;
1232*fcf3ce44SJohn Forte 		strcpy(parms.rdc_set->primary.file, primary);
1233*fcf3ce44SJohn Forte 
1234*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key),
1235*fcf3ce44SJohn Forte 		    "sndr.set%d.phost", setnumber);
1236*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, phost, sizeof (phost)) < 0)
1237*fcf3ce44SJohn Forte 			break;
1238*fcf3ce44SJohn Forte 		strcpy(parms.rdc_set->primary.intf, phost);
1239*fcf3ce44SJohn Forte 
1240*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key),
1241*fcf3ce44SJohn Forte 		    "sndr.set%d.secondary", setnumber);
1242*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, secondary,
1243*fcf3ce44SJohn Forte 				sizeof (secondary)) < 0)
1244*fcf3ce44SJohn Forte 			break;
1245*fcf3ce44SJohn Forte 		strcpy(parms.rdc_set->secondary.file, secondary);
1246*fcf3ce44SJohn Forte 
1247*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key),
1248*fcf3ce44SJohn Forte 		    "sndr.set%d.shost", setnumber);
1249*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, shost, sizeof (shost)) < 0)
1250*fcf3ce44SJohn Forte 			break;
1251*fcf3ce44SJohn Forte 		strcpy(parms.rdc_set->secondary.intf, shost);
1252*fcf3ce44SJohn Forte 
1253*fcf3ce44SJohn Forte 		parms.command = RDC_CMD_STATUS;
1254*fcf3ce44SJohn Forte 		if (RDC_IOCTL(RDC_CONFIG, &parms, NULL, 0, 0, 0, ustatus) < 0) {
1255*fcf3ce44SJohn Forte 			continue;
1256*fcf3ce44SJohn Forte 		}
1257*fcf3ce44SJohn Forte 
1258*fcf3ce44SJohn Forte 		/* We found a matching set */
1259*fcf3ce44SJohn Forte 		found++;
1260*fcf3ce44SJohn Forte 
1261*fcf3ce44SJohn Forte 		if (self_check(phost))
1262*fcf3ce44SJohn Forte 			local_file = primary;
1263*fcf3ce44SJohn Forte 		else
1264*fcf3ce44SJohn Forte 			local_file = secondary;
1265*fcf3ce44SJohn Forte 
1266*fcf3ce44SJohn Forte 		rdc_set = &parms.rdc_set[0];
1267*fcf3ce44SJohn Forte 		if (!(rdc_set->flags & RDC_LOGGING) &&
1268*fcf3ce44SJohn Forte 		    !(rdc_set->flags & RDC_SYNCING)) {
1269*fcf3ce44SJohn Forte 			volumes[replicating] = strdup(local_file);
1270*fcf3ce44SJohn Forte 			if (volumes[replicating] == NULL) {
1271*fcf3ce44SJohn Forte 				size = strlen(local_file);
1272*fcf3ce44SJohn Forte 				spcs_log("sndr", NULL,
1273*fcf3ce44SJohn Forte 				    gettext("%s: unable to allocate %ld bytes"),
1274*fcf3ce44SJohn Forte 				    program, size);
1275*fcf3ce44SJohn Forte 				rdc_warn(NULL,
1276*fcf3ce44SJohn Forte 				    gettext("unable to allocate %ld bytes"),
1277*fcf3ce44SJohn Forte 				    size);
1278*fcf3ce44SJohn Forte 				goto done;
1279*fcf3ce44SJohn Forte 			}
1280*fcf3ce44SJohn Forte 			/* We remember all replicating sets */
1281*fcf3ce44SJohn Forte 			replicating++;
1282*fcf3ce44SJohn Forte 		} else
1283*fcf3ce44SJohn Forte 			break;		/* Not all replicating, so done */
1284*fcf3ce44SJohn Forte 	}
1285*fcf3ce44SJohn Forte 
1286*fcf3ce44SJohn Forte 	if (found != replicating)
1287*fcf3ce44SJohn Forte 		goto done;
1288*fcf3ce44SJohn Forte 
1289*fcf3ce44SJohn Forte 	/* All replicating, so update ndr_ii state fields */
1290*fcf3ce44SJohn Forte 
1291*fcf3ce44SJohn Forte 	cfg_unlock(cfg);
1292*fcf3ce44SJohn Forte 
1293*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, CFG_WRLOCK)) {
1294*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
1295*fcf3ce44SJohn Forte 		    gettext("%s: error locking lconfig"),
1296*fcf3ce44SJohn Forte 		    program);
1297*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("error locking config"));
1298*fcf3ce44SJohn Forte 		goto done;
1299*fcf3ce44SJohn Forte 	}
1300*fcf3ce44SJohn Forte 
1301*fcf3ce44SJohn Forte 	/*
1302*fcf3ce44SJohn Forte 	 * Search through the ndr_ii entries for entries
1303*fcf3ce44SJohn Forte 	 * that match the saved secondary volume names.
1304*fcf3ce44SJohn Forte 	 * Set state to "update".
1305*fcf3ce44SJohn Forte 	 */
1306*fcf3ce44SJohn Forte 
1307*fcf3ce44SJohn Forte 	for (i = 0; ; i++) {
1308*fcf3ce44SJohn Forte 		setnumber = i + 1;
1309*fcf3ce44SJohn Forte 
1310*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.secondary",
1311*fcf3ce44SJohn Forte 		    setnumber);
1312*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
1313*fcf3ce44SJohn Forte 			break;
1314*fcf3ce44SJohn Forte 
1315*fcf3ce44SJohn Forte 		if (!volume_match(buf, volumes, found)) {
1316*fcf3ce44SJohn Forte 			continue;
1317*fcf3ce44SJohn Forte 		}
1318*fcf3ce44SJohn Forte 
1319*fcf3ce44SJohn Forte 		/* Got a matching entry */
1320*fcf3ce44SJohn Forte 
1321*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key),
1322*fcf3ce44SJohn Forte 		    "ndr_ii.set%d.state", setnumber);
1323*fcf3ce44SJohn Forte 		if ((cfg_put_cstring(cfg, key, UPDATE, strlen(UPDATE)) < 0) ||
1324*fcf3ce44SJohn Forte 		    (cfg_commit(cfg) < 0)) {
1325*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
1326*fcf3ce44SJohn Forte 			    gettext("%s: unable to update \"%s\" "
1327*fcf3ce44SJohn Forte 			    "in configuration storage: %s"),
1328*fcf3ce44SJohn Forte 			    program, buf, cfg_error(&sev));
1329*fcf3ce44SJohn Forte 			rdc_warn(NULL,
1330*fcf3ce44SJohn Forte 			    gettext("unable to update \"%s\" "
1331*fcf3ce44SJohn Forte 			    "in configuration storage: %s"),
1332*fcf3ce44SJohn Forte 			    buf, cfg_error(&sev));
1333*fcf3ce44SJohn Forte 		}
1334*fcf3ce44SJohn Forte 	}
1335*fcf3ce44SJohn Forte 
1336*fcf3ce44SJohn Forte 
1337*fcf3ce44SJohn Forte done:
1338*fcf3ce44SJohn Forte 	if (cfg) {
1339*fcf3ce44SJohn Forte 		cfg_close(cfg);
1340*fcf3ce44SJohn Forte 		UNLOCKCFG();
1341*fcf3ce44SJohn Forte 	}
1342*fcf3ce44SJohn Forte 	spcs_s_ufree(&ustatus);
1343*fcf3ce44SJohn Forte 	if (volumes) {
1344*fcf3ce44SJohn Forte 		for (i = 0; i < replicating; i++)
1345*fcf3ce44SJohn Forte 			free(volumes[i]);
1346*fcf3ce44SJohn Forte 		free(volumes);
1347*fcf3ce44SJohn Forte 	}
1348*fcf3ce44SJohn Forte }
1349*fcf3ce44SJohn Forte 
1350*fcf3ce44SJohn Forte 
1351*fcf3ce44SJohn Forte /*
1352*fcf3ce44SJohn Forte  * Sync started to a member of a group.
1353*fcf3ce44SJohn Forte  * If all members of the group are in ndr_ii state "update" then take an PIT
1354*fcf3ce44SJohn Forte  * snapshot on all of them. This will provide a consistent point-in-time
1355*fcf3ce44SJohn Forte  * copy until whatever syncs take place are all completed.
1356*fcf3ce44SJohn Forte  */
1357*fcf3ce44SJohn Forte void
1358*fcf3ce44SJohn Forte group_start(char *group)
1359*fcf3ce44SJohn Forte {
1360*fcf3ce44SJohn Forte 	char **masters = NULL;
1361*fcf3ce44SJohn Forte 	char **shadows = NULL;
1362*fcf3ce44SJohn Forte 	char **bitmaps = NULL;
1363*fcf3ce44SJohn Forte 	char cmd[256];
1364*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
1365*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
1366*fcf3ce44SJohn Forte 	CFGFILE *cfg = NULL;
1367*fcf3ce44SJohn Forte 	int i;
1368*fcf3ce44SJohn Forte 	int j;
1369*fcf3ce44SJohn Forte 	int setnumber;
1370*fcf3ce44SJohn Forte 	int found;
1371*fcf3ce44SJohn Forte 	int sndr_sets = 0;
1372*fcf3ce44SJohn Forte 	int update_needed = 0;
1373*fcf3ce44SJohn Forte 	int sev;
1374*fcf3ce44SJohn Forte 	char *ctag = NULL;
1375*fcf3ce44SJohn Forte 	int commit = 0;
1376*fcf3ce44SJohn Forte 	int size;
1377*fcf3ce44SJohn Forte 
1378*fcf3ce44SJohn Forte 	size = sizeof (char *) * rdc_maxsets;
1379*fcf3ce44SJohn Forte 	masters = malloc(size);
1380*fcf3ce44SJohn Forte 	if (masters == NULL) {
1381*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
1382*fcf3ce44SJohn Forte 		    gettext("%s: unable to allocate %ld bytes"),
1383*fcf3ce44SJohn Forte 		    program, size);
1384*fcf3ce44SJohn Forte 		rdc_warn(NULL,
1385*fcf3ce44SJohn Forte 			gettext("unable to allocate %ld bytes"), size);
1386*fcf3ce44SJohn Forte 		goto done;
1387*fcf3ce44SJohn Forte 	}
1388*fcf3ce44SJohn Forte 	bzero(masters, size);
1389*fcf3ce44SJohn Forte 	shadows = malloc(size);
1390*fcf3ce44SJohn Forte 	if (shadows == NULL) {
1391*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
1392*fcf3ce44SJohn Forte 		    gettext("%s: unable to allocate %ld bytes"),
1393*fcf3ce44SJohn Forte 		    program, size);
1394*fcf3ce44SJohn Forte 		rdc_warn(NULL,
1395*fcf3ce44SJohn Forte 			gettext("unable to allocate %ld bytes"), size);
1396*fcf3ce44SJohn Forte 		goto done;
1397*fcf3ce44SJohn Forte 	}
1398*fcf3ce44SJohn Forte 	bzero(shadows, size);
1399*fcf3ce44SJohn Forte 	bitmaps = malloc(size);
1400*fcf3ce44SJohn Forte 	if (bitmaps == NULL) {
1401*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
1402*fcf3ce44SJohn Forte 		    gettext("%s: unable to allocate %ld bytes"),
1403*fcf3ce44SJohn Forte 		    program, size);
1404*fcf3ce44SJohn Forte 		rdc_warn(NULL,
1405*fcf3ce44SJohn Forte 			gettext("unable to allocate %ld bytes"), size);
1406*fcf3ce44SJohn Forte 		goto done;
1407*fcf3ce44SJohn Forte 	}
1408*fcf3ce44SJohn Forte 	bzero(bitmaps, size);
1409*fcf3ce44SJohn Forte 
1410*fcf3ce44SJohn Forte 	LOCKCFG();
1411*fcf3ce44SJohn Forte 	if ((cfg = cfg_open(NULL)) == NULL) {
1412*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
1413*fcf3ce44SJohn Forte 		    gettext("%s: error opening config"),
1414*fcf3ce44SJohn Forte 		    program);
1415*fcf3ce44SJohn Forte 		rdc_warn(NULL,
1416*fcf3ce44SJohn Forte 		    gettext("error opening config"));
1417*fcf3ce44SJohn Forte 		UNLOCKCFG();
1418*fcf3ce44SJohn Forte 		goto done;
1419*fcf3ce44SJohn Forte 	}
1420*fcf3ce44SJohn Forte 
1421*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, CFG_WRLOCK)) {
1422*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
1423*fcf3ce44SJohn Forte 		    gettext("%s: error locking config"),
1424*fcf3ce44SJohn Forte 		    program);
1425*fcf3ce44SJohn Forte 		rdc_warn(NULL, gettext("error locking config"));
1426*fcf3ce44SJohn Forte 		goto done;
1427*fcf3ce44SJohn Forte 	}
1428*fcf3ce44SJohn Forte 
1429*fcf3ce44SJohn Forte 	/* Now get all Remote Mirror entries with a matching group */
1430*fcf3ce44SJohn Forte 	for (i = 0; i < rdc_maxsets; i++) {
1431*fcf3ce44SJohn Forte 		setnumber = i + 1;
1432*fcf3ce44SJohn Forte 
1433*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key),
1434*fcf3ce44SJohn Forte 		    "sndr.set%d.group", setnumber);
1435*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
1436*fcf3ce44SJohn Forte 			break;
1437*fcf3ce44SJohn Forte 
1438*fcf3ce44SJohn Forte 		if (strcmp(buf, group) != 0)
1439*fcf3ce44SJohn Forte 			continue;
1440*fcf3ce44SJohn Forte 
1441*fcf3ce44SJohn Forte 		/* Found a matching entry */
1442*fcf3ce44SJohn Forte 
1443*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key),
1444*fcf3ce44SJohn Forte 		    "sndr.set%d.phost", setnumber);
1445*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0)
1446*fcf3ce44SJohn Forte 			break;
1447*fcf3ce44SJohn Forte 
1448*fcf3ce44SJohn Forte 		if (self_check(buf)) {
1449*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key), "sndr.set%d.primary",
1450*fcf3ce44SJohn Forte 			    setnumber);
1451*fcf3ce44SJohn Forte 		} else {
1452*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key),
1453*fcf3ce44SJohn Forte 			    "sndr.set%d.secondary", setnumber);
1454*fcf3ce44SJohn Forte 		}
1455*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0)
1456*fcf3ce44SJohn Forte 			break;
1457*fcf3ce44SJohn Forte 
1458*fcf3ce44SJohn Forte 		masters[sndr_sets] = strdup(buf);
1459*fcf3ce44SJohn Forte 		if (masters[sndr_sets] == NULL) {
1460*fcf3ce44SJohn Forte 			size = strlen(buf);
1461*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
1462*fcf3ce44SJohn Forte 			    gettext("%s: unable to allocate %ld bytes"),
1463*fcf3ce44SJohn Forte 			    program, size);
1464*fcf3ce44SJohn Forte 			rdc_warn(NULL,
1465*fcf3ce44SJohn Forte 				gettext("unable to allocate %ld bytes"), size);
1466*fcf3ce44SJohn Forte 			goto done;
1467*fcf3ce44SJohn Forte 		}
1468*fcf3ce44SJohn Forte 		sndr_sets++;
1469*fcf3ce44SJohn Forte 
1470*fcf3ce44SJohn Forte 		if (ctag == NULL && clustered) {
1471*fcf3ce44SJohn Forte 			/* Get cluster tag of matching entry */
1472*fcf3ce44SJohn Forte 
1473*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key), "sndr.set%d.cnode",
1474*fcf3ce44SJohn Forte 			    setnumber);
1475*fcf3ce44SJohn Forte 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) >= 0)
1476*fcf3ce44SJohn Forte 				ctag = strdup(buf);
1477*fcf3ce44SJohn Forte 		}
1478*fcf3ce44SJohn Forte 	}
1479*fcf3ce44SJohn Forte 
1480*fcf3ce44SJohn Forte 	/*
1481*fcf3ce44SJohn Forte 	 * Search through the ndr_ii entries for entries
1482*fcf3ce44SJohn Forte 	 * that match the saved local volume names and are in "update" state.
1483*fcf3ce44SJohn Forte 	 */
1484*fcf3ce44SJohn Forte 
1485*fcf3ce44SJohn Forte 	update_needed = 0;
1486*fcf3ce44SJohn Forte 
1487*fcf3ce44SJohn Forte 	for (i = 0; ; i++) {
1488*fcf3ce44SJohn Forte 		setnumber = i + 1;
1489*fcf3ce44SJohn Forte 
1490*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.secondary",
1491*fcf3ce44SJohn Forte 		    setnumber);
1492*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
1493*fcf3ce44SJohn Forte 			break;
1494*fcf3ce44SJohn Forte 
1495*fcf3ce44SJohn Forte 		if (!volume_match(buf, masters, sndr_sets))
1496*fcf3ce44SJohn Forte 			continue;
1497*fcf3ce44SJohn Forte 
1498*fcf3ce44SJohn Forte 		/* Got a matching entry */
1499*fcf3ce44SJohn Forte 
1500*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.shadow",
1501*fcf3ce44SJohn Forte 		    setnumber);
1502*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
1503*fcf3ce44SJohn Forte 			break;
1504*fcf3ce44SJohn Forte 		shadows[update_needed] = strdup(buf);
1505*fcf3ce44SJohn Forte 		if (shadows[update_needed] == NULL) {
1506*fcf3ce44SJohn Forte 			size = strlen(buf);
1507*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
1508*fcf3ce44SJohn Forte 			    gettext("%s: unable to allocate %ld bytes"),
1509*fcf3ce44SJohn Forte 			    program, size);
1510*fcf3ce44SJohn Forte 			rdc_warn(NULL,
1511*fcf3ce44SJohn Forte 				gettext("unable to allocate %ld bytes"), size);
1512*fcf3ce44SJohn Forte 			goto done;
1513*fcf3ce44SJohn Forte 		}
1514*fcf3ce44SJohn Forte 
1515*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.bitmap",
1516*fcf3ce44SJohn Forte 		    setnumber);
1517*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
1518*fcf3ce44SJohn Forte 			break;
1519*fcf3ce44SJohn Forte 		}
1520*fcf3ce44SJohn Forte 		bitmaps[update_needed] = strdup(buf);
1521*fcf3ce44SJohn Forte 		if (bitmaps[update_needed] == NULL) {
1522*fcf3ce44SJohn Forte 			size = strlen(buf);
1523*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
1524*fcf3ce44SJohn Forte 			    gettext("%s: unable to allocate %ld bytes"),
1525*fcf3ce44SJohn Forte 			    program, size);
1526*fcf3ce44SJohn Forte 			rdc_warn(NULL,
1527*fcf3ce44SJohn Forte 				gettext("unable to allocate %ld bytes"), size);
1528*fcf3ce44SJohn Forte 			goto done;
1529*fcf3ce44SJohn Forte 		}
1530*fcf3ce44SJohn Forte 
1531*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
1532*fcf3ce44SJohn Forte 		    setnumber);
1533*fcf3ce44SJohn Forte 		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
1534*fcf3ce44SJohn Forte 			break;
1535*fcf3ce44SJohn Forte 		}
1536*fcf3ce44SJohn Forte 		if (strcmp(buf, UPDATE) != 0) {
1537*fcf3ce44SJohn Forte 			break;
1538*fcf3ce44SJohn Forte 		}
1539*fcf3ce44SJohn Forte 
1540*fcf3ce44SJohn Forte 		update_needed++;
1541*fcf3ce44SJohn Forte 	}
1542*fcf3ce44SJohn Forte 
1543*fcf3ce44SJohn Forte 	if (update_needed != sndr_sets) {
1544*fcf3ce44SJohn Forte #ifdef DEBUG
1545*fcf3ce44SJohn Forte 		spcs_log("sndr", NULL,
1546*fcf3ce44SJohn Forte 		    gettext("%s: group sync: no Point-in-Time Copy snapshot "
1547*fcf3ce44SJohn Forte 			    "for %s"), program, group);
1548*fcf3ce44SJohn Forte #endif
1549*fcf3ce44SJohn Forte 		goto done;
1550*fcf3ce44SJohn Forte 	}
1551*fcf3ce44SJohn Forte 
1552*fcf3ce44SJohn Forte 	/* All RM sets in the group have an ndr_ii entry in "update" state */
1553*fcf3ce44SJohn Forte 
1554*fcf3ce44SJohn Forte 	/* Issue PIT Copy snapshot commands for all sets in the group */
1555*fcf3ce44SJohn Forte 	for (j = 0; j < sndr_sets; j++) {
1556*fcf3ce44SJohn Forte 		found = 0;
1557*fcf3ce44SJohn Forte 
1558*fcf3ce44SJohn Forte 		/* get ii entries until a match is found */
1559*fcf3ce44SJohn Forte 		for (i = 0; ; i++) {
1560*fcf3ce44SJohn Forte 			setnumber = i + 1;
1561*fcf3ce44SJohn Forte 
1562*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key), "ii.set%d.shadow",
1563*fcf3ce44SJohn Forte 			    setnumber);
1564*fcf3ce44SJohn Forte 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
1565*fcf3ce44SJohn Forte 				break;
1566*fcf3ce44SJohn Forte 			if (strcmp(buf, shadows[j]) != 0)
1567*fcf3ce44SJohn Forte 				continue;
1568*fcf3ce44SJohn Forte 
1569*fcf3ce44SJohn Forte 			/* Matching shadow found, so ii already enabled */
1570*fcf3ce44SJohn Forte 			found = 1;
1571*fcf3ce44SJohn Forte 			break;
1572*fcf3ce44SJohn Forte 		}
1573*fcf3ce44SJohn Forte 
1574*fcf3ce44SJohn Forte 		if (commit)
1575*fcf3ce44SJohn Forte 			if (cfg_commit(cfg) < 0)
1576*fcf3ce44SJohn Forte 				rdc_warn(NULL, gettext("commit config error"));
1577*fcf3ce44SJohn Forte 		cfg_close(cfg);
1578*fcf3ce44SJohn Forte 
1579*fcf3ce44SJohn Forte 		if (found) {
1580*fcf3ce44SJohn Forte 			(void) sprintf(cmd, "%s -u s %s", IIADM, shadows[j]);
1581*fcf3ce44SJohn Forte 		} else {
1582*fcf3ce44SJohn Forte 			if (ctag) {
1583*fcf3ce44SJohn Forte 				(void) sprintf(cmd, "%s -C %s -e dep %s %s %s",
1584*fcf3ce44SJohn Forte 				    IIADM, ctag, masters[j], shadows[j],
1585*fcf3ce44SJohn Forte 				    bitmaps[j]);
1586*fcf3ce44SJohn Forte 				free(ctag);
1587*fcf3ce44SJohn Forte 				ctag = NULL;
1588*fcf3ce44SJohn Forte 			} else
1589*fcf3ce44SJohn Forte 				(void) sprintf(cmd, "%s -e dep %s %s %s", IIADM,
1590*fcf3ce44SJohn Forte 				    masters[j], shadows[j], bitmaps[j]);
1591*fcf3ce44SJohn Forte 		}
1592*fcf3ce44SJohn Forte 
1593*fcf3ce44SJohn Forte 		if (system(cmd) != 0) {
1594*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
1595*fcf3ce44SJohn Forte 			    gettext("%s: group sync: Point-in-Time Copy"
1596*fcf3ce44SJohn Forte 			    " snapshot failed for %s"),
1597*fcf3ce44SJohn Forte 			    program, masters[j]);
1598*fcf3ce44SJohn Forte 
1599*fcf3ce44SJohn Forte 			goto done;
1600*fcf3ce44SJohn Forte 		}
1601*fcf3ce44SJohn Forte 
1602*fcf3ce44SJohn Forte 		if ((cfg = cfg_open(NULL)) == NULL) {
1603*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
1604*fcf3ce44SJohn Forte 			    gettext("%s: error opening config"),
1605*fcf3ce44SJohn Forte 			    program);
1606*fcf3ce44SJohn Forte 			rdc_warn(NULL,
1607*fcf3ce44SJohn Forte 			    gettext("error opening config"));
1608*fcf3ce44SJohn Forte 			goto done;
1609*fcf3ce44SJohn Forte 		}
1610*fcf3ce44SJohn Forte 		if (!cfg_lock(cfg, CFG_WRLOCK)) {
1611*fcf3ce44SJohn Forte 			spcs_log("sndr", NULL,
1612*fcf3ce44SJohn Forte 			    gettext("%s: error locking config"),
1613*fcf3ce44SJohn Forte 			    program);
1614*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("error locking config"));
1615*fcf3ce44SJohn Forte 			goto done;
1616*fcf3ce44SJohn Forte 		}
1617*fcf3ce44SJohn Forte 		commit = 0;
1618*fcf3ce44SJohn Forte 
1619*fcf3ce44SJohn Forte 		/* PIT enable or update was fine, so update the ndr_ii entry */
1620*fcf3ce44SJohn Forte 
1621*fcf3ce44SJohn Forte 		/* get ndr_ii entries until a match is found */
1622*fcf3ce44SJohn Forte 		for (i = 0; ; i++) {
1623*fcf3ce44SJohn Forte 			setnumber = i + 1;
1624*fcf3ce44SJohn Forte 
1625*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key),
1626*fcf3ce44SJohn Forte 			    "ndr_ii.set%d.shadow", setnumber);
1627*fcf3ce44SJohn Forte 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0)
1628*fcf3ce44SJohn Forte 				break;
1629*fcf3ce44SJohn Forte 			if (strcmp(buf, shadows[j]) != 0)
1630*fcf3ce44SJohn Forte 				continue;
1631*fcf3ce44SJohn Forte 
1632*fcf3ce44SJohn Forte 			/* Found the matching entry */
1633*fcf3ce44SJohn Forte 
1634*fcf3ce44SJohn Forte 			(void) snprintf(key, sizeof (key), "ndr_ii.set%d.state",
1635*fcf3ce44SJohn Forte 			    setnumber);
1636*fcf3ce44SJohn Forte 			if (cfg_put_cstring(cfg, key, NOUPDATE,
1637*fcf3ce44SJohn Forte 			    strlen(NOUPDATE)) < 0) {
1638*fcf3ce44SJohn Forte 				spcs_log("sndr", NULL,
1639*fcf3ce44SJohn Forte 				    gettext("%s: unable to update \"%s\" "
1640*fcf3ce44SJohn Forte 				    "in configuration storage: %s"),
1641*fcf3ce44SJohn Forte 				    program, buf, cfg_error(&sev));
1642*fcf3ce44SJohn Forte 				rdc_warn(NULL,
1643*fcf3ce44SJohn Forte 				    gettext("unable to update \"%s\" "
1644*fcf3ce44SJohn Forte 				    "in configuration storage: %s"),
1645*fcf3ce44SJohn Forte 				    buf, cfg_error(&sev));
1646*fcf3ce44SJohn Forte 			} else
1647*fcf3ce44SJohn Forte 				commit = 1;
1648*fcf3ce44SJohn Forte 			break;
1649*fcf3ce44SJohn Forte 		}
1650*fcf3ce44SJohn Forte 	}
1651*fcf3ce44SJohn Forte 
1652*fcf3ce44SJohn Forte 	if (commit)
1653*fcf3ce44SJohn Forte 		if (cfg_commit(cfg) < 0)
1654*fcf3ce44SJohn Forte 			rdc_warn(NULL, gettext("commit config error"));
1655*fcf3ce44SJohn Forte 
1656*fcf3ce44SJohn Forte 	spcs_log("sndr", NULL,
1657*fcf3ce44SJohn Forte 	    gettext("%s: group sync: Point-in-Time Copy snapshots completed "
1658*fcf3ce44SJohn Forte 		    "for %s"), program, group);
1659*fcf3ce44SJohn Forte 
1660*fcf3ce44SJohn Forte done:
1661*fcf3ce44SJohn Forte 	if (ctag)
1662*fcf3ce44SJohn Forte 		free(ctag);
1663*fcf3ce44SJohn Forte 
1664*fcf3ce44SJohn Forte 	if (cfg) {
1665*fcf3ce44SJohn Forte 		cfg_close(cfg);
1666*fcf3ce44SJohn Forte 		UNLOCKCFG();
1667*fcf3ce44SJohn Forte 	}
1668*fcf3ce44SJohn Forte 
1669*fcf3ce44SJohn Forte 	if (masters) {
1670*fcf3ce44SJohn Forte 		for (i = 0; i < sndr_sets; i++) {
1671*fcf3ce44SJohn Forte 			if (masters[i])
1672*fcf3ce44SJohn Forte 				free(masters[i]);
1673*fcf3ce44SJohn Forte 		}
1674*fcf3ce44SJohn Forte 		free(masters);
1675*fcf3ce44SJohn Forte 	}
1676*fcf3ce44SJohn Forte 
1677*fcf3ce44SJohn Forte 	if (shadows) {
1678*fcf3ce44SJohn Forte 		for (i = 0; i < update_needed; i++) {
1679*fcf3ce44SJohn Forte 			if (shadows[i])
1680*fcf3ce44SJohn Forte 				free(shadows[i]);
1681*fcf3ce44SJohn Forte 		}
1682*fcf3ce44SJohn Forte 		free(shadows);
1683*fcf3ce44SJohn Forte 	}
1684*fcf3ce44SJohn Forte 
1685*fcf3ce44SJohn Forte 	if (bitmaps) {
1686*fcf3ce44SJohn Forte 		for (i = 0; i < update_needed; i++) {
1687*fcf3ce44SJohn Forte 			if (bitmaps[i])
1688*fcf3ce44SJohn Forte 				free(bitmaps[i]);
1689*fcf3ce44SJohn Forte 		}
1690*fcf3ce44SJohn Forte 		free(bitmaps);
1691*fcf3ce44SJohn Forte 	}
1692*fcf3ce44SJohn Forte }
1693