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