1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/time.h> 29 #include <errno.h> 30 #include <signal.h> 31 #include <stdio.h> 32 #include <string.h> 33 #include <fcntl.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <values.h> 37 #include <locale.h> 38 #include <sys/stat.h> 39 #include <strings.h> 40 #include <stdarg.h> 41 #include <sys/param.h> 42 #include <nsctl.h> 43 44 #include <sys/nsctl/cfg.h> 45 #include <sys/unistat/spcs_s.h> 46 #include <sys/unistat/spcs_s_u.h> 47 #include <sys/unistat/spcs_errors.h> 48 #include <sys/nsctl/dsw.h> 49 #include <sys/nsctl/dsw_dev.h> /* for bitmap format */ 50 51 #define DSW_TEXT_DOMAIN "II" 52 #define BITMAP_TOKEN "ii.set%d.bitmap" 53 #define SHADOW_TOKEN "ii.set%d.shadow" 54 #define SV_TOKEN "sv.set%d.vol" 55 #define DSVOL_TOKEN "dsvol.set%d.path" 56 57 void iicpshd_usage(); 58 void copyshd(char *, char *); 59 int find_cfg_info(char *, char *); 60 int copy_shadow_vol(char *, char *); 61 void convert_to_blockdevice(); 62 int update_dscfg(char *); 63 64 extern int optind; 65 66 extern char *optarg; 67 extern int optind, opterr, optopt; 68 int copy_shadow = 1; 69 CFGFILE *cfg; 70 char real_bitmap[DSW_NAMELEN]; 71 char buf[CFG_MAX_BUF]; 72 char key[CFG_MAX_KEY]; 73 int set_number; 74 int sv_number; 75 int dsvol_number; 76 77 #ifdef lint 78 int 79 iicpshd_lintmain(int argc, char *argv[]) 80 #else 81 int 82 main(int argc, char *argv[]) 83 #endif 84 { 85 if (argc > 1) { 86 if (strcmp(argv[1], "-s") == 0) { 87 /* don't copy shadow, only update dscfg and ii header */ 88 copy_shadow = 0; 89 argc--; 90 argv++; 91 } 92 } 93 94 if (argc == 1 || (argc%2) == 0) /* must have pairs of filenames */ 95 iicpshd_usage(); 96 97 /* open dscfg anyway */ 98 if ((cfg = cfg_open(NULL)) == NULL) { 99 fprintf(stderr, gettext("Error opening config\n")); 100 exit(1); 101 } 102 103 for (argv++; *argv != NULL; argv += 2) 104 copyshd(argv[0], argv[1]); 105 106 /* close dscfg */ 107 cfg_close(cfg); 108 exit(0); 109 return (0); 110 } 111 112 void 113 iicpshd_usage() 114 { 115 fprintf(stderr, gettext("Usage:\n")); 116 fprintf(stderr, gettext("\tiicpshd [-s] old_shadow new_shadow\n")); 117 exit(1); 118 } 119 120 void 121 copyshd(char *old_vol, char *new_vol) 122 { 123 int dsw_fd; 124 FILE *ifp; 125 char header[FBA_SIZE(1) * DSW_CBLK_FBA]; 126 ii_header_t *hp; 127 dsw_stat_t args; 128 129 /*LINTED pointer alignment*/ 130 hp = (ii_header_t *)&header; 131 132 dsw_fd = open(DSWDEV, O_RDONLY); 133 if (dsw_fd < 0) { 134 perror(DSWDEV); 135 exit(1); 136 } 137 if (*old_vol != '/' || *new_vol != '/') { 138 fprintf(stderr, gettext( 139 "Both old and new shadow file names must begin with a /.\n")); 140 exit(1); 141 } 142 143 if (strlen(new_vol) > DSW_NAMELEN) { 144 fprintf(stderr, gettext("New shadow name is to long.\n")); 145 exit(1); 146 } 147 148 /* check old shadow is in dscfg */ 149 if (find_cfg_info(old_vol, SHADOW_TOKEN) == 0) { 150 fprintf(stderr, gettext("Old shadow not in existing cfg\n")); 151 exit(1); 152 } 153 154 /* check ii set status, suspend if need */ 155 strncpy(args.shadow_vol, old_vol, DSW_NAMELEN); 156 args.shadow_vol[DSW_NAMELEN-1] = '\0'; 157 args.status = spcs_s_ucreate(); 158 if (ioctl(dsw_fd, DSWIOC_STAT, &args) != -1) { 159 fprintf(stderr, gettext("Suspend the Point-in-Time Copy " 160 "set first\n")); 161 close(dsw_fd); 162 exit(1); 163 } 164 165 if (copy_shadow) { 166 if (copy_shadow_vol(old_vol, new_vol) == 0) { 167 perror(gettext("Write new shadow failed")); 168 close(dsw_fd); 169 exit(1); 170 } 171 } 172 if (find_cfg_info(old_vol, SV_TOKEN) == 0) { 173 fprintf(stderr, gettext("Old shadow not in existing cfg\n")); 174 exit(1); 175 } 176 if (find_cfg_info(old_vol, DSVOL_TOKEN) == 0) { 177 fprintf(stderr, gettext("Old shadow not in existing cfg\n")); 178 exit(1); 179 } 180 if (strstr(real_bitmap, "/rdsk/") == NULL) { 181 fprintf(stderr, 182 gettext("%s is not a character device\n"), real_bitmap); 183 exit(1); 184 } 185 186 /* use block device /dsk/ to update bitmap header */ 187 convert_to_blockdevice(); 188 189 /* open bitmap by using update mode */ 190 if ((ifp = fopen(real_bitmap, "r+")) == NULL) { 191 fprintf(stderr, gettext("Can't open bitmap file\n")); 192 exit(1); 193 } 194 195 /* Check old header looks like an II bitmap header */ 196 if (fread(&header, DSW_CBLK_FBA, FBA_SIZE(1), ifp) != FBA_SIZE(1)) { 197 fprintf(stderr, gettext("Can't read bitmap file\n")); 198 exit(1); 199 } 200 201 if (hp->ii_magic != DSW_CLEAN && hp->ii_magic != DSW_DIRTY) { 202 fprintf(stderr, gettext("%s is not an Point-in-Time Copy " 203 "shadow.\n"), old_vol); 204 exit(1); 205 } 206 207 if (strncmp(hp->shadow_vol, old_vol, DSW_NAMELEN) != 0) { 208 fprintf(stderr, gettext( 209 "%s has Point-in-Time Copy shadow magic number,\n" 210 "but does not contain correct data.\n"), old_vol); 211 exit(1); 212 } 213 214 memset(hp->shadow_vol, 0, DSW_NAMELEN); 215 strncpy(hp->shadow_vol, new_vol, DSW_NAMELEN); 216 217 /* reset the pointer position */ 218 rewind(ifp); 219 if (fwrite(&header, DSW_CBLK_FBA, FBA_SIZE(1), ifp) != FBA_SIZE(1)) { 220 perror(new_vol); 221 fprintf(stderr, gettext("Can't write new bitmap header\n")); 222 exit(1); 223 } 224 fclose(ifp); 225 close(dsw_fd); 226 if (update_dscfg(new_vol) == 0) { 227 fprintf(stderr, gettext("Failed to update dscfg.\n")); 228 exit(1); 229 } else { 230 spcs_log("ii", NULL, 231 "iicpshd copy shadow from %s to %s", 232 old_vol, new_vol); 233 } 234 } 235 236 /* 237 * find_cfg_info() 238 * 239 */ 240 241 int 242 find_cfg_info(char *volume, char *token) 243 { 244 int i; 245 /* get read lock */ 246 if (!cfg_lock(cfg, CFG_RDLOCK)) { 247 spcs_log("ii", NULL, 248 "iicpbmp CFG_RDLOCK failed, errno %d", errno); 249 fprintf(stderr, gettext("Error locking config\n")); 250 exit(1); 251 } 252 for (i = 1; ; i++) { 253 bzero(buf, CFG_MAX_BUF); 254 snprintf(key, sizeof (key), token, i); 255 if (cfg_get_cstring(cfg, key, buf, DSW_NAMELEN) < 0) { 256 cfg_unlock(cfg); 257 return (0); 258 } 259 if (strcmp(buf, volume) == 0) { 260 if (strcmp(token, SHADOW_TOKEN) == 0) { 261 snprintf(key, sizeof (key), BITMAP_TOKEN, i); 262 cfg_get_cstring 263 (cfg, key, real_bitmap, DSW_NAMELEN); 264 set_number = i; 265 } else if (strcmp(token, SV_TOKEN) == 0) { 266 sv_number = i; 267 } else if (strcmp(token, DSVOL_TOKEN) == 0) { 268 dsvol_number = i; 269 } 270 /* release read lock */ 271 cfg_unlock(cfg); 272 return (1); 273 } 274 } 275 } 276 277 int 278 copy_shadow_vol(char *old_shadow, char *new_shadow) { 279 int i; 280 char cp_buffer[256]; 281 FILE *ishdfp, *oshdfp; 282 if ((ishdfp = fopen(old_shadow, "r")) == NULL) { 283 fprintf(stderr, gettext("Can't open old shadow file\n")); 284 return (0); 285 } 286 if ((oshdfp = fopen(new_shadow, "w")) == NULL) { 287 fprintf(stderr, gettext("Can't open new shadow file\n")); 288 return (0); 289 } 290 291 /* Copy the shadow vol */ 292 while ((i = fread(cp_buffer, sizeof (char), sizeof (cp_buffer), ishdfp)) 293 > 0) { 294 if (fwrite(cp_buffer, sizeof (char), i, oshdfp) != i) { 295 fclose(ishdfp); 296 fclose(oshdfp); 297 return (0); 298 } 299 } 300 fclose(ishdfp); 301 fclose(oshdfp); 302 return (1); 303 } 304 305 int 306 update_dscfg(char *new_shadow) { 307 308 int len = strlen(new_shadow); 309 /* get write lock */ 310 if (!cfg_lock(cfg, CFG_WRLOCK)) { 311 spcs_log("ii", NULL, 312 "iicpbmp CFG_WRLOCK failed, errno %d", errno); 313 fprintf(stderr, gettext("Error locking config\n")); 314 return (0); 315 } 316 sprintf(key, SHADOW_TOKEN, set_number); 317 if (cfg_put_cstring(cfg, key, new_shadow, len) < 0) { 318 perror("cfg_put_cstring"); 319 return (0); 320 } 321 sprintf(key, SV_TOKEN, sv_number); 322 if (cfg_put_cstring(cfg, key, new_shadow, len) < 0) { 323 perror("cfg_put_cstring"); 324 return (0); 325 } 326 sprintf(key, DSVOL_TOKEN, dsvol_number); 327 if (cfg_put_cstring(cfg, key, new_shadow, len) < 0) { 328 perror("cfg_put_cstring"); 329 return (0); 330 } 331 cfg_commit(cfg); 332 cfg_unlock(cfg); 333 return (1); 334 } 335 336 void 337 convert_to_blockdevice() { 338 int len = strlen(real_bitmap); 339 int i = 0, j = 0; 340 char *temp_string = malloc(len-1); 341 while (i < len + 1) { 342 if (real_bitmap[i] != 'r') { 343 temp_string[j] = real_bitmap[i]; 344 j++; 345 } 346 i++; 347 } 348 strcpy(real_bitmap, temp_string); 349 free(temp_string); 350 } 351