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