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