xref: /titanic_53/usr/src/cmd/avs/dsw/iiboot.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 <sys/param.h>
30*fcf3ce44SJohn Forte #include <errno.h>
31*fcf3ce44SJohn Forte #include <limits.h>
32*fcf3ce44SJohn Forte #include <fcntl.h>
33*fcf3ce44SJohn Forte #include <strings.h>
34*fcf3ce44SJohn Forte #include <stdlib.h>
35*fcf3ce44SJohn Forte #include <unistd.h>
36*fcf3ce44SJohn Forte #include <signal.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 #include <ctype.h>
43*fcf3ce44SJohn Forte 
44*fcf3ce44SJohn Forte #include <sys/nsctl/cfg.h>
45*fcf3ce44SJohn Forte 
46*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s.h>
47*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s_u.h>
48*fcf3ce44SJohn Forte #include <sys/unistat/spcs_errors.h>
49*fcf3ce44SJohn Forte 
50*fcf3ce44SJohn Forte #include <sys/nsctl/dsw.h>
51*fcf3ce44SJohn Forte #include <sys/nskernd.h>
52*fcf3ce44SJohn Forte 
53*fcf3ce44SJohn Forte #define	MAX_PROCESSES 64
54*fcf3ce44SJohn Forte 
55*fcf3ce44SJohn Forte int parseopts(int, char **, int *);
56*fcf3ce44SJohn Forte int read_resume_cfg();
57*fcf3ce44SJohn Forte int read_suspend_cfg();
58*fcf3ce44SJohn Forte void iiboot_usage(void);
59*fcf3ce44SJohn Forte extern char *basename(char *);
60*fcf3ce44SJohn Forte 
61*fcf3ce44SJohn Forte dsw_config_t *resume_list = 0;
62*fcf3ce44SJohn Forte dsw_ioctl_t *suspend_list = 0;
63*fcf3ce44SJohn Forte int	n_structs;
64*fcf3ce44SJohn Forte char *program;
65*fcf3ce44SJohn Forte char *cfg_cluster_tag = NULL;
66*fcf3ce44SJohn Forte 
67*fcf3ce44SJohn Forte volatile int fork_cnt;
68*fcf3ce44SJohn Forte volatile int fork_rc;
69*fcf3ce44SJohn Forte 
70*fcf3ce44SJohn Forte static void
71*fcf3ce44SJohn Forte iiboot_msg(char *prefix, spcs_s_info_t *status, char *string, va_list ap)
72*fcf3ce44SJohn Forte {
73*fcf3ce44SJohn Forte 	if (status) {
74*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "II: %s\n", prefix);
75*fcf3ce44SJohn Forte 		spcs_s_report(*status, stderr);
76*fcf3ce44SJohn Forte 		spcs_s_ufree(status);
77*fcf3ce44SJohn Forte 	} else {
78*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s: %s: ", program, prefix);
79*fcf3ce44SJohn Forte 	}
80*fcf3ce44SJohn Forte 
81*fcf3ce44SJohn Forte 	if (string && *string != '\0') {
82*fcf3ce44SJohn Forte 		(void) vfprintf(stderr, string, ap);
83*fcf3ce44SJohn Forte 	}
84*fcf3ce44SJohn Forte 
85*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "\n");
86*fcf3ce44SJohn Forte }
87*fcf3ce44SJohn Forte 
88*fcf3ce44SJohn Forte static void
89*fcf3ce44SJohn Forte iiboot_err(spcs_s_info_t *status, char *string, ...)
90*fcf3ce44SJohn Forte {
91*fcf3ce44SJohn Forte 	va_list ap;
92*fcf3ce44SJohn Forte 	va_start(ap, string);
93*fcf3ce44SJohn Forte 
94*fcf3ce44SJohn Forte 	iiboot_msg(gettext("Error"), status, string, ap);
95*fcf3ce44SJohn Forte 
96*fcf3ce44SJohn Forte 	va_end(ap);
97*fcf3ce44SJohn Forte 	exit(1);
98*fcf3ce44SJohn Forte }
99*fcf3ce44SJohn Forte 
100*fcf3ce44SJohn Forte static void
101*fcf3ce44SJohn Forte iiboot_warn(spcs_s_info_t *status, char *string, ...)
102*fcf3ce44SJohn Forte {
103*fcf3ce44SJohn Forte 	va_list ap;
104*fcf3ce44SJohn Forte 	va_start(ap, string);
105*fcf3ce44SJohn Forte 
106*fcf3ce44SJohn Forte 	iiboot_msg(gettext("warning"), status, string, ap);
107*fcf3ce44SJohn Forte 
108*fcf3ce44SJohn Forte 	va_end(ap);
109*fcf3ce44SJohn Forte }
110*fcf3ce44SJohn Forte 
111*fcf3ce44SJohn Forte /* ARGSUSED */
112*fcf3ce44SJohn Forte static void
113*fcf3ce44SJohn Forte sigchld(int sig)
114*fcf3ce44SJohn Forte {
115*fcf3ce44SJohn Forte 	int wait_loc = 0;
116*fcf3ce44SJohn Forte 
117*fcf3ce44SJohn Forte 	wait(&wait_loc);
118*fcf3ce44SJohn Forte 	if (WIFEXITED(wait_loc) && (WEXITSTATUS(wait_loc) == 0)) {
119*fcf3ce44SJohn Forte 		;
120*fcf3ce44SJohn Forte 		/*EMPTY*/
121*fcf3ce44SJohn Forte 	} else {
122*fcf3ce44SJohn Forte 		fork_rc = WEXITSTATUS(wait_loc);
123*fcf3ce44SJohn Forte 	}
124*fcf3ce44SJohn Forte 
125*fcf3ce44SJohn Forte 	if (fork_cnt > 0)
126*fcf3ce44SJohn Forte 		--fork_cnt;
127*fcf3ce44SJohn Forte }
128*fcf3ce44SJohn Forte 
129*fcf3ce44SJohn Forte 
130*fcf3ce44SJohn Forte int
131*fcf3ce44SJohn Forte #ifdef lint
132*fcf3ce44SJohn Forte iiboot_lintmain(int argc, char *argv[])
133*fcf3ce44SJohn Forte #else
134*fcf3ce44SJohn Forte main(int argc, char *argv[])
135*fcf3ce44SJohn Forte #endif
136*fcf3ce44SJohn Forte {
137*fcf3ce44SJohn Forte 	int pairs;
138*fcf3ce44SJohn Forte 	pid_t pid = 0;
139*fcf3ce44SJohn Forte 	int flag = 0;
140*fcf3ce44SJohn Forte 	int i, j;
141*fcf3ce44SJohn Forte 	int rc;
142*fcf3ce44SJohn Forte 	int	ioctl_fd;
143*fcf3ce44SJohn Forte 	void *ioarg;
144*fcf3ce44SJohn Forte 	dsw_ioctl_t *ii_iop, ii_suspend;
145*fcf3ce44SJohn Forte 	dsw_list_t args = {0};
146*fcf3ce44SJohn Forte 	dsw_config_t *ii_cfgp, *lp = NULL;
147*fcf3ce44SJohn Forte 	spcs_s_info_t ustatus;
148*fcf3ce44SJohn Forte 	int max_processes = MAX_PROCESSES;
149*fcf3ce44SJohn Forte 
150*fcf3ce44SJohn Forte 	(void) setlocale(LC_ALL, "");
151*fcf3ce44SJohn Forte 	(void) textdomain("ii");
152*fcf3ce44SJohn Forte 
153*fcf3ce44SJohn Forte 	program = strdup(basename(argv[0]));
154*fcf3ce44SJohn Forte 
155*fcf3ce44SJohn Forte 	if ((ioctl_fd = open(DSWDEV, O_RDWR, 0)) == -1) {
156*fcf3ce44SJohn Forte 		spcs_log("ii", NULL, "iiboot open %s failed, errno %d",
157*fcf3ce44SJohn Forte 			DSWDEV, errno);
158*fcf3ce44SJohn Forte 		iiboot_err(NULL,
159*fcf3ce44SJohn Forte 		    gettext("Failed to open Point-in-Time Copy control "
160*fcf3ce44SJohn Forte 			    "device"));
161*fcf3ce44SJohn Forte 	}
162*fcf3ce44SJohn Forte 
163*fcf3ce44SJohn Forte 	if (parseopts(argc, argv, &flag))
164*fcf3ce44SJohn Forte 		return (1);
165*fcf3ce44SJohn Forte 
166*fcf3ce44SJohn Forte 	if (flag == DSWIOC_RESUME)
167*fcf3ce44SJohn Forte 		pairs = read_resume_cfg();
168*fcf3ce44SJohn Forte 	else
169*fcf3ce44SJohn Forte 		pairs = -1;
170*fcf3ce44SJohn Forte 
171*fcf3ce44SJohn Forte 	if (pairs == 0) {
172*fcf3ce44SJohn Forte #ifdef DEBUG
173*fcf3ce44SJohn Forte 		iiboot_err(NULL,
174*fcf3ce44SJohn Forte 		    gettext("Config contains no Point-in-Time Copy sets"));
175*fcf3ce44SJohn Forte #endif
176*fcf3ce44SJohn Forte 		return (0);
177*fcf3ce44SJohn Forte 	}
178*fcf3ce44SJohn Forte 
179*fcf3ce44SJohn Forte 	if (cfg_cluster_tag == NULL && flag != DSWIOC_RESUME) {
180*fcf3ce44SJohn Forte 		if (ioctl(ioctl_fd, DSWIOC_SHUTDOWN, 0) < 0) {
181*fcf3ce44SJohn Forte 			spcs_log("ii", &ustatus, "iiboot shutdown failed");
182*fcf3ce44SJohn Forte 			iiboot_err(NULL, gettext("SHUTDOWN ioctl error"));
183*fcf3ce44SJohn Forte 		}
184*fcf3ce44SJohn Forte 		return (0);
185*fcf3ce44SJohn Forte 	} else if (cfg_cluster_tag != NULL && flag == DSWIOC_SUSPEND) {
186*fcf3ce44SJohn Forte 		bzero(&ii_suspend, sizeof (dsw_ioctl_t));
187*fcf3ce44SJohn Forte 		ii_suspend.status = spcs_s_ucreate();
188*fcf3ce44SJohn Forte 		ii_suspend.flags = CV_IS_CLUSTER;
189*fcf3ce44SJohn Forte 		strncpy(ii_suspend.shadow_vol, cfg_cluster_tag, DSW_NAMELEN);
190*fcf3ce44SJohn Forte 		rc = ioctl(ioctl_fd, flag, &ii_suspend);
191*fcf3ce44SJohn Forte 		if ((rc) && (errno != DSW_ECNOTFOUND)) {
192*fcf3ce44SJohn Forte 			spcs_log("ii", &ii_suspend.status,
193*fcf3ce44SJohn Forte 			    "iiboot resume cluster %s failed", cfg_cluster_tag);
194*fcf3ce44SJohn Forte 			iiboot_err(&ii_suspend.status, gettext("ioctl error"));
195*fcf3ce44SJohn Forte 			spcs_s_ufree(&ii_suspend.status);
196*fcf3ce44SJohn Forte 			return (-1);
197*fcf3ce44SJohn Forte 		}
198*fcf3ce44SJohn Forte 		spcs_s_ufree(&ii_suspend.status);
199*fcf3ce44SJohn Forte 		return (0);
200*fcf3ce44SJohn Forte 
201*fcf3ce44SJohn Forte 	} else if ((cfg_cluster_tag != NULL) && (flag == DSWIOC_RESUME)) {
202*fcf3ce44SJohn Forte 		/*
203*fcf3ce44SJohn Forte 		 * If we are running in a Sun Cluster, this is a resume
204*fcf3ce44SJohn Forte 		 * operation, get a list of all shadow volumes, where the
205*fcf3ce44SJohn Forte 		 * shadow volumes match the shadows of the sets being resumed
206*fcf3ce44SJohn Forte 		 */
207*fcf3ce44SJohn Forte 		rc = ioctl(ioctl_fd, DSWIOC_LISTLEN, &args);
208*fcf3ce44SJohn Forte 		if (rc == -1) {
209*fcf3ce44SJohn Forte 			spcs_log("ii", NULL,
210*fcf3ce44SJohn Forte 				"iiboot get LIST failed, errno %d", errno);
211*fcf3ce44SJohn Forte 			iiboot_err(NULL,
212*fcf3ce44SJohn Forte 				gettext("Failed to get LIST of Point-in-Time "
213*fcf3ce44SJohn Forte 				    "sets"));
214*fcf3ce44SJohn Forte 			return (-1);
215*fcf3ce44SJohn Forte 		}
216*fcf3ce44SJohn Forte 
217*fcf3ce44SJohn Forte 		args.status = spcs_s_ucreate();
218*fcf3ce44SJohn Forte 		args.list_used = 0;
219*fcf3ce44SJohn Forte 		args.list_size = rc + 4;
220*fcf3ce44SJohn Forte 		lp = args.list = (dsw_config_t *)
221*fcf3ce44SJohn Forte 		    malloc(args.list_size * sizeof (dsw_config_t));
222*fcf3ce44SJohn Forte 		if (args.list == NULL) {
223*fcf3ce44SJohn Forte 			iiboot_err(NULL,
224*fcf3ce44SJohn Forte 				gettext("Failed to allocate memory"));
225*fcf3ce44SJohn Forte 		}
226*fcf3ce44SJohn Forte 		if (ioctl(ioctl_fd, DSWIOC_LIST, &args)  == -1) {
227*fcf3ce44SJohn Forte 			spcs_log("ii", &args.status, "Failed to get LIST");
228*fcf3ce44SJohn Forte 			iiboot_err(&args.status, gettext("ioctl error"));
229*fcf3ce44SJohn Forte 		}
230*fcf3ce44SJohn Forte 		spcs_s_ufree(&args.status);
231*fcf3ce44SJohn Forte 
232*fcf3ce44SJohn Forte 		/* Remove all elements that are not in the resume list */
233*fcf3ce44SJohn Forte 		for (j = args.list_used; j; j--) {
234*fcf3ce44SJohn Forte 			for (i = 0; i < pairs; i++) {
235*fcf3ce44SJohn Forte 				if (strcmp(lp->shadow_vol,
236*fcf3ce44SJohn Forte 				    resume_list[i].shadow_vol) == 0) {
237*fcf3ce44SJohn Forte 					if (strlen(lp->cluster_tag) == 0) {
238*fcf3ce44SJohn Forte 						lp++;
239*fcf3ce44SJohn Forte 						break;
240*fcf3ce44SJohn Forte 					}
241*fcf3ce44SJohn Forte 				}
242*fcf3ce44SJohn Forte 			}
243*fcf3ce44SJohn Forte 			if (i != pairs)
244*fcf3ce44SJohn Forte 				continue;
245*fcf3ce44SJohn Forte 			memmove(lp, lp + 1, j * sizeof (dsw_config_t));
246*fcf3ce44SJohn Forte 			args.list_used--;
247*fcf3ce44SJohn Forte 		}
248*fcf3ce44SJohn Forte 	}
249*fcf3ce44SJohn Forte 
250*fcf3ce44SJohn Forte 	sigset(SIGCHLD, sigchld);
251*fcf3ce44SJohn Forte 	fork_cnt = fork_rc = 0;
252*fcf3ce44SJohn Forte 	for (i = 0; i < pairs; i++) {
253*fcf3ce44SJohn Forte 		ustatus = spcs_s_ucreate();
254*fcf3ce44SJohn Forte 		if (flag == DSWIOC_RESUME) {
255*fcf3ce44SJohn Forte 			ioarg = (void *) (ii_cfgp = (resume_list + i));
256*fcf3ce44SJohn Forte 			ii_cfgp->status = ustatus;
257*fcf3ce44SJohn Forte 			pid = fork();
258*fcf3ce44SJohn Forte 		} else {
259*fcf3ce44SJohn Forte 			ioarg = (void *) (ii_iop = (suspend_list + i));
260*fcf3ce44SJohn Forte 			ii_iop->status = ustatus;
261*fcf3ce44SJohn Forte 		}
262*fcf3ce44SJohn Forte 		while (pid == -1) {		/* error forking */
263*fcf3ce44SJohn Forte 			perror("fork");
264*fcf3ce44SJohn Forte 
265*fcf3ce44SJohn Forte 			/* back off on the max processes and try again */
266*fcf3ce44SJohn Forte 			--max_processes;
267*fcf3ce44SJohn Forte 			if (fork_cnt > 0) {
268*fcf3ce44SJohn Forte 				pause();
269*fcf3ce44SJohn Forte 			}
270*fcf3ce44SJohn Forte 			pid = fork();
271*fcf3ce44SJohn Forte 		}
272*fcf3ce44SJohn Forte 
273*fcf3ce44SJohn Forte 		if (pid > 0) {		/* this is parent process */
274*fcf3ce44SJohn Forte 			++fork_cnt;
275*fcf3ce44SJohn Forte 			while (fork_cnt > MAX_PROCESSES) {
276*fcf3ce44SJohn Forte 				pause();
277*fcf3ce44SJohn Forte 			}
278*fcf3ce44SJohn Forte 			continue;
279*fcf3ce44SJohn Forte 		}
280*fcf3ce44SJohn Forte 
281*fcf3ce44SJohn Forte 		rc = ioctl(ioctl_fd, flag, ioarg);
282*fcf3ce44SJohn Forte 		if (rc == SPCS_S_ERROR) {
283*fcf3ce44SJohn Forte 			if (flag == DSWIOC_RESUME)
284*fcf3ce44SJohn Forte 				spcs_log("ii", &ustatus,
285*fcf3ce44SJohn Forte 					"iiboot resume %s failed",
286*fcf3ce44SJohn Forte 					ii_cfgp->shadow_vol);
287*fcf3ce44SJohn Forte 			else
288*fcf3ce44SJohn Forte 				spcs_log("ii", &ustatus,
289*fcf3ce44SJohn Forte 					"iiboot suspend %s failed",
290*fcf3ce44SJohn Forte 					ii_iop->shadow_vol);
291*fcf3ce44SJohn Forte 			iiboot_err(&ustatus, gettext("ioctl error"));
292*fcf3ce44SJohn Forte 		}
293*fcf3ce44SJohn Forte 		/* Resuming child */
294*fcf3ce44SJohn Forte 		spcs_s_ufree(&ustatus);
295*fcf3ce44SJohn Forte 		if (flag == DSWIOC_RESUME)
296*fcf3ce44SJohn Forte 			exit(0);
297*fcf3ce44SJohn Forte 	}
298*fcf3ce44SJohn Forte 
299*fcf3ce44SJohn Forte 	/*
300*fcf3ce44SJohn Forte 	 * Allow all processes to finish up before exiting
301*fcf3ce44SJohn Forte 	 * Set rc for success
302*fcf3ce44SJohn Forte 	 */
303*fcf3ce44SJohn Forte 	while (fork_cnt > 0) {
304*fcf3ce44SJohn Forte 		alarm(60);		/* wake up in 60 secs just in case */
305*fcf3ce44SJohn Forte 		pause();
306*fcf3ce44SJohn Forte 	}
307*fcf3ce44SJohn Forte 	alarm(0);
308*fcf3ce44SJohn Forte 
309*fcf3ce44SJohn Forte 	/* Disable duplicate shadows that were part of the implicit join */
310*fcf3ce44SJohn Forte 	if ((j = args.list_used) != 0) {
311*fcf3ce44SJohn Forte 		int setno;
312*fcf3ce44SJohn Forte 		char key[CFG_MAX_KEY], buf[CFG_MAX_BUF], sn[CFG_MAX_BUF];
313*fcf3ce44SJohn Forte 		CFGFILE *cfg;
314*fcf3ce44SJohn Forte 		char *mst, *shd, *ctag;
315*fcf3ce44SJohn Forte 		pid_t pid = fork();
316*fcf3ce44SJohn Forte 
317*fcf3ce44SJohn Forte 		if (pid == -1) {
318*fcf3ce44SJohn Forte 			iiboot_err(NULL, gettext("Failed to fork"));
319*fcf3ce44SJohn Forte 			return (errno);
320*fcf3ce44SJohn Forte 		} else if (pid > 0) {
321*fcf3ce44SJohn Forte 			return (0);	/* Parent, OK exit */
322*fcf3ce44SJohn Forte 		}
323*fcf3ce44SJohn Forte 
324*fcf3ce44SJohn Forte 		for (j = args.list_used, lp = args.list; j; j--, lp++) {
325*fcf3ce44SJohn Forte 		    setno = 0;
326*fcf3ce44SJohn Forte 		    while (++setno) {
327*fcf3ce44SJohn Forte 
328*fcf3ce44SJohn Forte 			/*
329*fcf3ce44SJohn Forte 			 * Open the configuration database
330*fcf3ce44SJohn Forte 			 */
331*fcf3ce44SJohn Forte 			if (!(cfg = cfg_open(""))) {
332*fcf3ce44SJohn Forte 			    iiboot_err(NULL, gettext("Failed to open dscfg"));
333*fcf3ce44SJohn Forte 			    return (-1);
334*fcf3ce44SJohn Forte 			}
335*fcf3ce44SJohn Forte 
336*fcf3ce44SJohn Forte 			/* Sooner or later, this lock will be free */
337*fcf3ce44SJohn Forte 			while (!cfg_lock(cfg, CFG_WRLOCK))
338*fcf3ce44SJohn Forte 				sleep(2);
339*fcf3ce44SJohn Forte 
340*fcf3ce44SJohn Forte 			snprintf(key, CFG_MAX_KEY, "ii.set%d", setno);
341*fcf3ce44SJohn Forte 			if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
342*fcf3ce44SJohn Forte 				cfg_close(cfg);
343*fcf3ce44SJohn Forte 				break;
344*fcf3ce44SJohn Forte 			}
345*fcf3ce44SJohn Forte 
346*fcf3ce44SJohn Forte 			/* For imported shadows, master must be special tag */
347*fcf3ce44SJohn Forte 			mst = strtok(buf, " ");		/* master */
348*fcf3ce44SJohn Forte 			shd = strtok(NULL, " ");	/* shadow */
349*fcf3ce44SJohn Forte 			(void) strtok(NULL, " ");	/* bitmap */
350*fcf3ce44SJohn Forte 			(void) strtok(NULL, " ");	/* mode */
351*fcf3ce44SJohn Forte 			(void) strtok(NULL, " ");	/* overflow */
352*fcf3ce44SJohn Forte 			ctag = strtok(NULL, " ");	/* cnode */
353*fcf3ce44SJohn Forte 
354*fcf3ce44SJohn Forte 			/*
355*fcf3ce44SJohn Forte 			 * For this record to be processed, the shadow volume
356*fcf3ce44SJohn Forte 			 * name must match and the cluster tag must be blank
357*fcf3ce44SJohn Forte 			 */
358*fcf3ce44SJohn Forte 			if (strcmp(lp->shadow_vol, shd) || strcmp(ctag, "-")) {
359*fcf3ce44SJohn Forte 				cfg_close(cfg);
360*fcf3ce44SJohn Forte 				continue;
361*fcf3ce44SJohn Forte 			}
362*fcf3ce44SJohn Forte 
363*fcf3ce44SJohn Forte 			/* Derrive local cluster tag */
364*fcf3ce44SJohn Forte 			if (cfg_l_dgname(lp->shadow_vol, sn, sizeof (sn)))
365*fcf3ce44SJohn Forte 				ctag = sn;
366*fcf3ce44SJohn Forte 			else
367*fcf3ce44SJohn Forte 				iiboot_err(NULL, gettext(
368*fcf3ce44SJohn Forte 					"Failed to device group for shadow %s"),
369*fcf3ce44SJohn Forte 					lp->shadow_vol);
370*fcf3ce44SJohn Forte 
371*fcf3ce44SJohn Forte 			/* disable master volume if not imported */
372*fcf3ce44SJohn Forte 			if (strcmp(mst, II_IMPORTED_SHADOW))
373*fcf3ce44SJohn Forte 			    if (cfg_vol_disable(cfg, mst, cfg_cluster_tag,
374*fcf3ce44SJohn Forte 				"ii") < 0)
375*fcf3ce44SJohn Forte 				iiboot_err(NULL, gettext(
376*fcf3ce44SJohn Forte 				    "SV disable of master failed"));
377*fcf3ce44SJohn Forte 
378*fcf3ce44SJohn Forte 			/*
379*fcf3ce44SJohn Forte 			 * Delete the Imported Shadow set
380*fcf3ce44SJohn Forte 			 */
381*fcf3ce44SJohn Forte 			if (cfg_put_cstring(cfg, key, NULL, 0) < 0) {
382*fcf3ce44SJohn Forte 				iiboot_err(NULL, gettext(
383*fcf3ce44SJohn Forte 					"Failed to delete Imported shadow %s"),
384*fcf3ce44SJohn Forte 					lp->shadow_vol);
385*fcf3ce44SJohn Forte 			}
386*fcf3ce44SJohn Forte 
387*fcf3ce44SJohn Forte 			/*
388*fcf3ce44SJohn Forte 			 * SV disable shadow volume
389*fcf3ce44SJohn Forte 			 */
390*fcf3ce44SJohn Forte 			if (cfg_vol_disable(cfg, shd, NULL, "ii") < 0)
391*fcf3ce44SJohn Forte 				iiboot_err(NULL, gettext(
392*fcf3ce44SJohn Forte 					"SV disable of shadow failed"));
393*fcf3ce44SJohn Forte 
394*fcf3ce44SJohn Forte 			/*
395*fcf3ce44SJohn Forte 			 * Commit the delete
396*fcf3ce44SJohn Forte 			 */
397*fcf3ce44SJohn Forte 			cfg_commit(cfg);
398*fcf3ce44SJohn Forte 			cfg_close(cfg);
399*fcf3ce44SJohn Forte 
400*fcf3ce44SJohn Forte 			/*
401*fcf3ce44SJohn Forte 			 * Open the configuration database
402*fcf3ce44SJohn Forte 			 */
403*fcf3ce44SJohn Forte 			if (!(cfg = cfg_open(""))) {
404*fcf3ce44SJohn Forte 			    iiboot_err(NULL, gettext("Failed to open dscfg"));
405*fcf3ce44SJohn Forte 			    return (-1);
406*fcf3ce44SJohn Forte 			}
407*fcf3ce44SJohn Forte 
408*fcf3ce44SJohn Forte 			/* Sooner or later, this lock will be free */
409*fcf3ce44SJohn Forte 			while (!cfg_lock(cfg, CFG_WRLOCK))
410*fcf3ce44SJohn Forte 				sleep(2);
411*fcf3ce44SJohn Forte 
412*fcf3ce44SJohn Forte 			/* Set cluster tag for Shadow volume */
413*fcf3ce44SJohn Forte 			cfg_vol_enable(cfg, shd, ctag, "ii");
414*fcf3ce44SJohn Forte 
415*fcf3ce44SJohn Forte 
416*fcf3ce44SJohn Forte 			/*
417*fcf3ce44SJohn Forte 			 * Commit the delete
418*fcf3ce44SJohn Forte 			 */
419*fcf3ce44SJohn Forte 			cfg_commit(cfg);
420*fcf3ce44SJohn Forte 			cfg_close(cfg);
421*fcf3ce44SJohn Forte 		    }
422*fcf3ce44SJohn Forte 		}
423*fcf3ce44SJohn Forte 	}
424*fcf3ce44SJohn Forte 	return (fork_rc);
425*fcf3ce44SJohn Forte }
426*fcf3ce44SJohn Forte 
427*fcf3ce44SJohn Forte static int
428*fcf3ce44SJohn Forte set_is_offline(char *cflags)
429*fcf3ce44SJohn Forte {
430*fcf3ce44SJohn Forte 	unsigned int flags;
431*fcf3ce44SJohn Forte 	int conv;
432*fcf3ce44SJohn Forte 
433*fcf3ce44SJohn Forte 	if (!cflags || !*cflags)
434*fcf3ce44SJohn Forte 		return (0);
435*fcf3ce44SJohn Forte 
436*fcf3ce44SJohn Forte 	/* convert flags to an int */
437*fcf3ce44SJohn Forte 	conv = sscanf(cflags, "%x", &flags);
438*fcf3ce44SJohn Forte 	return ((conv == 1) && ((flags & DSW_OFFLINE) != 0));
439*fcf3ce44SJohn Forte }
440*fcf3ce44SJohn Forte 
441*fcf3ce44SJohn Forte /*
442*fcf3ce44SJohn Forte  * read_resume_cfg()
443*fcf3ce44SJohn Forte  *
444*fcf3ce44SJohn Forte  * DESCRIPTION: Read the relevant config info via libcfg
445*fcf3ce44SJohn Forte  *
446*fcf3ce44SJohn Forte  * Outputs:
447*fcf3ce44SJohn Forte  *	int i			Number of Point-in-Time Copy sets
448*fcf3ce44SJohn Forte  *
449*fcf3ce44SJohn Forte  * Side Effects: The 0 to i-1 entries in the resume_list are filled.
450*fcf3ce44SJohn Forte  *
451*fcf3ce44SJohn Forte  */
452*fcf3ce44SJohn Forte 
453*fcf3ce44SJohn Forte int
454*fcf3ce44SJohn Forte read_resume_cfg()
455*fcf3ce44SJohn Forte {
456*fcf3ce44SJohn Forte 	CFGFILE *cfg;
457*fcf3ce44SJohn Forte 	int i;
458*fcf3ce44SJohn Forte 	char *buf, **entry, *mst, *shd, *bmp, *ctag, *opt, *ptr;
459*fcf3ce44SJohn Forte 	int valid_sets;
460*fcf3ce44SJohn Forte 	dsw_config_t *p;
461*fcf3ce44SJohn Forte 	static int offset = sizeof (NSKERN_II_BMP_OPTION);
462*fcf3ce44SJohn Forte 
463*fcf3ce44SJohn Forte 	spcs_log("ii", NULL, "iiboot resume cluster tag %s",
464*fcf3ce44SJohn Forte 			cfg_cluster_tag ? cfg_cluster_tag : "<none>");
465*fcf3ce44SJohn Forte 	if ((cfg = cfg_open("")) == NULL) {
466*fcf3ce44SJohn Forte 		spcs_log("ii", NULL, "iiboot cfg_open failed, errno %d",
467*fcf3ce44SJohn Forte 			errno);
468*fcf3ce44SJohn Forte 		iiboot_err(NULL, gettext("Error opening config"));
469*fcf3ce44SJohn Forte 	}
470*fcf3ce44SJohn Forte 
471*fcf3ce44SJohn Forte 	cfg_resource(cfg, cfg_cluster_tag);
472*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, CFG_RDLOCK)) {
473*fcf3ce44SJohn Forte 		spcs_log("ii", NULL, "iiboot CFG_RDLOCK failed, errno %d",
474*fcf3ce44SJohn Forte 			errno);
475*fcf3ce44SJohn Forte 		iiboot_err(NULL, gettext("Error locking config"));
476*fcf3ce44SJohn Forte 	}
477*fcf3ce44SJohn Forte 
478*fcf3ce44SJohn Forte 	/* Determine number of set, if zero return 0 */
479*fcf3ce44SJohn Forte 	if ((n_structs = cfg_get_section(cfg, &entry, "ii")) == 0)
480*fcf3ce44SJohn Forte 		return (0);
481*fcf3ce44SJohn Forte 
482*fcf3ce44SJohn Forte 	resume_list = calloc(n_structs, sizeof (*resume_list));
483*fcf3ce44SJohn Forte 	if (resume_list == NULL) {
484*fcf3ce44SJohn Forte 		spcs_log("ii", NULL, "iiboot resume realloc failed, errno %d",
485*fcf3ce44SJohn Forte 		    errno);
486*fcf3ce44SJohn Forte 		iiboot_err(NULL, gettext("Resume realloc failed"));
487*fcf3ce44SJohn Forte 	}
488*fcf3ce44SJohn Forte 
489*fcf3ce44SJohn Forte 	valid_sets = 0;
490*fcf3ce44SJohn Forte 	p = resume_list;
491*fcf3ce44SJohn Forte 	for (i = 0; i < n_structs; i++) {
492*fcf3ce44SJohn Forte 		buf = entry[i];
493*fcf3ce44SJohn Forte 		mst = strtok(buf, " ");
494*fcf3ce44SJohn Forte 		shd = strtok(NULL, " ");
495*fcf3ce44SJohn Forte 		bmp = strtok(NULL, " ");
496*fcf3ce44SJohn Forte 		(void) strtok(NULL, " ");	/* mode */
497*fcf3ce44SJohn Forte 		(void) strtok(NULL, " ");	/* overflow */
498*fcf3ce44SJohn Forte 		ctag = strtok(NULL, " ");	/* ctag */
499*fcf3ce44SJohn Forte 		if (ctag)
500*fcf3ce44SJohn Forte 			ctag += strspn(ctag, "-");
501*fcf3ce44SJohn Forte 		opt = strtok(NULL, " ");
502*fcf3ce44SJohn Forte 
503*fcf3ce44SJohn Forte 		if (!mst || !shd || !bmp)
504*fcf3ce44SJohn Forte 			break;
505*fcf3ce44SJohn Forte 
506*fcf3ce44SJohn Forte 		/* If cluster tags don't match, skip record */
507*fcf3ce44SJohn Forte 		if ((cfg_cluster_tag && strcmp(ctag, cfg_cluster_tag)) ||
508*fcf3ce44SJohn Forte 		    (!cfg_cluster_tag && strlen(ctag))) {
509*fcf3ce44SJohn Forte 			free(buf);
510*fcf3ce44SJohn Forte 			continue;
511*fcf3ce44SJohn Forte 		}
512*fcf3ce44SJohn Forte 
513*fcf3ce44SJohn Forte 		ptr = strstr(opt, NSKERN_II_BMP_OPTION "=");
514*fcf3ce44SJohn Forte 		if (ptr && set_is_offline(ptr + offset)) {
515*fcf3ce44SJohn Forte 			free(buf);
516*fcf3ce44SJohn Forte 			continue;
517*fcf3ce44SJohn Forte 		}
518*fcf3ce44SJohn Forte 
519*fcf3ce44SJohn Forte 		strncpy(p->master_vol, mst, DSW_NAMELEN);
520*fcf3ce44SJohn Forte 		strncpy(p->shadow_vol, shd, DSW_NAMELEN);
521*fcf3ce44SJohn Forte 		strncpy(p->bitmap_vol, bmp, DSW_NAMELEN);
522*fcf3ce44SJohn Forte 		if (ctag)
523*fcf3ce44SJohn Forte 			strncpy(p->cluster_tag, ctag, DSW_NAMELEN);
524*fcf3ce44SJohn Forte 		free(buf);
525*fcf3ce44SJohn Forte 		++p;
526*fcf3ce44SJohn Forte 		++valid_sets;
527*fcf3ce44SJohn Forte 	}
528*fcf3ce44SJohn Forte 
529*fcf3ce44SJohn Forte 	while (i < n_structs)
530*fcf3ce44SJohn Forte 		free(entry[i++]);
531*fcf3ce44SJohn Forte 	if (entry)
532*fcf3ce44SJohn Forte 		free(entry);
533*fcf3ce44SJohn Forte 
534*fcf3ce44SJohn Forte 	cfg_close(cfg);
535*fcf3ce44SJohn Forte 	return (valid_sets);
536*fcf3ce44SJohn Forte }
537*fcf3ce44SJohn Forte 
538*fcf3ce44SJohn Forte /*
539*fcf3ce44SJohn Forte  * read_suspend_cfg()
540*fcf3ce44SJohn Forte  *
541*fcf3ce44SJohn Forte  * DESCRIPTION: Read the relevant config info via libcfg
542*fcf3ce44SJohn Forte  *
543*fcf3ce44SJohn Forte  * Outputs:
544*fcf3ce44SJohn Forte  *	int i			Number of Point-in-Time Copy sets
545*fcf3ce44SJohn Forte  *
546*fcf3ce44SJohn Forte  * Side Effects: The 0 to i-1 entries in the suspend_list are filled.
547*fcf3ce44SJohn Forte  *
548*fcf3ce44SJohn Forte  */
549*fcf3ce44SJohn Forte 
550*fcf3ce44SJohn Forte int
551*fcf3ce44SJohn Forte read_suspend_cfg()
552*fcf3ce44SJohn Forte {
553*fcf3ce44SJohn Forte 	int rc;
554*fcf3ce44SJohn Forte 	CFGFILE *cfg;
555*fcf3ce44SJohn Forte 	int i;
556*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
557*fcf3ce44SJohn Forte 	char key[CFG_MAX_KEY];
558*fcf3ce44SJohn Forte 	int setnumber;
559*fcf3ce44SJohn Forte 	dsw_ioctl_t *p;
560*fcf3ce44SJohn Forte 
561*fcf3ce44SJohn Forte 	spcs_log("ii", NULL, "iiboot suspend cluster tag %s",
562*fcf3ce44SJohn Forte 			cfg_cluster_tag ? cfg_cluster_tag : "<none>");
563*fcf3ce44SJohn Forte 
564*fcf3ce44SJohn Forte 	if (cfg_cluster_tag == NULL) {
565*fcf3ce44SJohn Forte 		return (1);
566*fcf3ce44SJohn Forte 	}
567*fcf3ce44SJohn Forte 
568*fcf3ce44SJohn Forte 	if ((cfg = cfg_open("")) == NULL) {
569*fcf3ce44SJohn Forte 		spcs_log("ii", NULL, "iiboot cfg_open failed, errno %d",
570*fcf3ce44SJohn Forte 			errno);
571*fcf3ce44SJohn Forte 		iiboot_err(NULL, gettext("Error opening config"));
572*fcf3ce44SJohn Forte 	}
573*fcf3ce44SJohn Forte 
574*fcf3ce44SJohn Forte 	cfg_resource(cfg, cfg_cluster_tag);
575*fcf3ce44SJohn Forte 	if (!cfg_lock(cfg, CFG_RDLOCK)) {
576*fcf3ce44SJohn Forte 		spcs_log("ii", NULL, "iiboot CFG_RDLOCK failed, errno %d",
577*fcf3ce44SJohn Forte 			errno);
578*fcf3ce44SJohn Forte 		iiboot_err(NULL, gettext("Error locking config"));
579*fcf3ce44SJohn Forte 	}
580*fcf3ce44SJohn Forte 
581*fcf3ce44SJohn Forte 
582*fcf3ce44SJohn Forte 	/*CSTYLED*/
583*fcf3ce44SJohn Forte 	for (i = 0; ; i++) {
584*fcf3ce44SJohn Forte 		setnumber = i + 1;
585*fcf3ce44SJohn Forte 
586*fcf3ce44SJohn Forte 		bzero(buf, CFG_MAX_BUF);
587*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ii.set%d", setnumber);
588*fcf3ce44SJohn Forte 		rc = cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF);
589*fcf3ce44SJohn Forte 		if (rc < 0)
590*fcf3ce44SJohn Forte 			break;
591*fcf3ce44SJohn Forte 		if (n_structs < setnumber) {
592*fcf3ce44SJohn Forte 			n_structs += 2;
593*fcf3ce44SJohn Forte 			suspend_list = realloc(suspend_list,
594*fcf3ce44SJohn Forte 					sizeof (*suspend_list) * n_structs);
595*fcf3ce44SJohn Forte 			if (suspend_list == NULL) {
596*fcf3ce44SJohn Forte 			    spcs_log("ii", NULL,
597*fcf3ce44SJohn Forte 			    "iiboot suspend realloc failed, errno %d",
598*fcf3ce44SJohn Forte 			    errno);
599*fcf3ce44SJohn Forte 			    iiboot_err(NULL, gettext("Suspend realloc failed"));
600*fcf3ce44SJohn Forte 			}
601*fcf3ce44SJohn Forte 		}
602*fcf3ce44SJohn Forte 		p = suspend_list + i;
603*fcf3ce44SJohn Forte 
604*fcf3ce44SJohn Forte 		(void) snprintf(key, sizeof (key), "ii.set%d.shadow",
605*fcf3ce44SJohn Forte 		    setnumber);
606*fcf3ce44SJohn Forte 		(void) cfg_get_cstring(cfg, key, p->shadow_vol, DSW_NAMELEN);
607*fcf3ce44SJohn Forte 
608*fcf3ce44SJohn Forte 	}
609*fcf3ce44SJohn Forte 
610*fcf3ce44SJohn Forte 	cfg_close(cfg);
611*fcf3ce44SJohn Forte 	return (i);
612*fcf3ce44SJohn Forte }
613*fcf3ce44SJohn Forte 
614*fcf3ce44SJohn Forte 
615*fcf3ce44SJohn Forte int
616*fcf3ce44SJohn Forte parseopts(argc, argv, flag)
617*fcf3ce44SJohn Forte int argc;
618*fcf3ce44SJohn Forte char **argv;
619*fcf3ce44SJohn Forte int *flag;
620*fcf3ce44SJohn Forte {
621*fcf3ce44SJohn Forte 	int  errflag = 0;
622*fcf3ce44SJohn Forte 	int  Cflag = 0;
623*fcf3ce44SJohn Forte 	char c;
624*fcf3ce44SJohn Forte 	char inval = 0;
625*fcf3ce44SJohn Forte 
626*fcf3ce44SJohn Forte 	while ((c = getopt(argc, argv, "hrsC:")) != -1) {
627*fcf3ce44SJohn Forte 		switch (c) {
628*fcf3ce44SJohn Forte 		case 'C':
629*fcf3ce44SJohn Forte 			if (Cflag) {
630*fcf3ce44SJohn Forte 				iiboot_warn(NULL,
631*fcf3ce44SJohn Forte 				    gettext("-C specified multiple times"));
632*fcf3ce44SJohn Forte 				iiboot_usage();
633*fcf3ce44SJohn Forte 				return (-1);
634*fcf3ce44SJohn Forte 			}
635*fcf3ce44SJohn Forte 
636*fcf3ce44SJohn Forte 			Cflag++;
637*fcf3ce44SJohn Forte 			cfg_cluster_tag = (optarg[0] == '-') ? NULL : optarg;
638*fcf3ce44SJohn Forte 			break;
639*fcf3ce44SJohn Forte 
640*fcf3ce44SJohn Forte 		case 'h':
641*fcf3ce44SJohn Forte 			iiboot_usage();
642*fcf3ce44SJohn Forte 			exit(0);
643*fcf3ce44SJohn Forte 			/* NOTREACHED */
644*fcf3ce44SJohn Forte 
645*fcf3ce44SJohn Forte 		case 'r':
646*fcf3ce44SJohn Forte 			if (*flag)
647*fcf3ce44SJohn Forte 				inval = 1;
648*fcf3ce44SJohn Forte 			*flag = DSWIOC_RESUME;
649*fcf3ce44SJohn Forte 			break;
650*fcf3ce44SJohn Forte 		case 's':
651*fcf3ce44SJohn Forte 			if (*flag)
652*fcf3ce44SJohn Forte 				inval = 1;
653*fcf3ce44SJohn Forte 			*flag = DSWIOC_SUSPEND;
654*fcf3ce44SJohn Forte 			break;
655*fcf3ce44SJohn Forte 		case '?':
656*fcf3ce44SJohn Forte 			errflag++;
657*fcf3ce44SJohn Forte 		}
658*fcf3ce44SJohn Forte 	}
659*fcf3ce44SJohn Forte 
660*fcf3ce44SJohn Forte 	if (inval) {
661*fcf3ce44SJohn Forte 		iiboot_warn(NULL, gettext("Invalid argument combination"));
662*fcf3ce44SJohn Forte 		errflag = 1;
663*fcf3ce44SJohn Forte 	}
664*fcf3ce44SJohn Forte 
665*fcf3ce44SJohn Forte 	if (!*flag || errflag) {
666*fcf3ce44SJohn Forte 		iiboot_usage();
667*fcf3ce44SJohn Forte 		return (-1);
668*fcf3ce44SJohn Forte 	}
669*fcf3ce44SJohn Forte 
670*fcf3ce44SJohn Forte 	return (0);
671*fcf3ce44SJohn Forte }
672*fcf3ce44SJohn Forte 
673*fcf3ce44SJohn Forte void
674*fcf3ce44SJohn Forte iiboot_usage()
675*fcf3ce44SJohn Forte {
676*fcf3ce44SJohn Forte 	(void) fprintf(stderr, gettext("usage:\n"));
677*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
678*fcf3ce44SJohn Forte 		gettext("\t%s -r [-C tag]\t\tresume\n"), program);
679*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
680*fcf3ce44SJohn Forte 		gettext("\t%s -s [-C tag]\t\tsuspend\n"), program);
681*fcf3ce44SJohn Forte 	(void) fprintf(stderr, gettext("\t%s -h\t\t\tthis help message\n"),
682*fcf3ce44SJohn Forte 	    program);
683*fcf3ce44SJohn Forte }
684