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