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
iiboot_msg(char * prefix,spcs_s_info_t * status,char * string,va_list ap)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
iiboot_err(spcs_s_info_t * status,char * string,...)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
iiboot_warn(spcs_s_info_t * status,char * string,...)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
sigchld(int sig)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
iiboot_lintmain(int argc,char * argv[])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
set_is_offline(char * cflags)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
read_resume_cfg()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
read_suspend_cfg()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
parseopts(argc,argv,flag)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
iiboot_usage()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