xref: /titanic_44/usr/src/cmd/avs/dsw/iicpshd.c (revision 9b79392525856301c6f8962f189c2a32242af618)
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 2010 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 		(void) 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 	(void) fprintf(stderr, gettext("Usage:\n"));
116 	(void) fprintf(stderr,
117 	    gettext("\tiicpshd [-s] old_shadow new_shadow\n"));
118 	exit(1);
119 }
120 
121 void
122 copyshd(char *old_vol, char *new_vol)
123 {
124 	int dsw_fd;
125 	FILE *ifp;
126 	char header[FBA_SIZE(1) * DSW_CBLK_FBA];
127 	ii_header_t *hp;
128 	dsw_stat_t args;
129 
130 	/*LINTED pointer alignment*/
131 	hp = (ii_header_t *)&header;
132 
133 	dsw_fd = open(DSWDEV, O_RDONLY);
134 	if (dsw_fd < 0) {
135 		perror(DSWDEV);
136 		exit(1);
137 	}
138 	if (*old_vol != '/' || *new_vol != '/') {
139 		(void) fprintf(stderr, gettext("Both old and new shadow "
140 		    "file names must begin with a /.\n"));
141 		exit(1);
142 	}
143 
144 	if (strlen(new_vol) > DSW_NAMELEN) {
145 		(void) fprintf(stderr,
146 		    gettext("New shadow name is to long.\n"));
147 		exit(1);
148 	}
149 
150 	/* check old shadow is in dscfg */
151 	if (find_cfg_info(old_vol, SHADOW_TOKEN) == 0) {
152 		(void) fprintf(stderr,
153 		    gettext("Old shadow not in existing cfg\n"));
154 		exit(1);
155 	}
156 
157 	/* check ii set status, suspend if need */
158 	(void) strncpy(args.shadow_vol, old_vol, DSW_NAMELEN);
159 	args.shadow_vol[DSW_NAMELEN-1] = '\0';
160 	args.status = spcs_s_ucreate();
161 	if (ioctl(dsw_fd, DSWIOC_STAT, &args) != -1) {
162 		(void) fprintf(stderr, gettext("Suspend the Point-in-Time Copy "
163 		    "set first\n"));
164 		(void) close(dsw_fd);
165 		exit(1);
166 	}
167 
168 	if (copy_shadow) {
169 		if (copy_shadow_vol(old_vol, new_vol) == 0) {
170 			perror(gettext("Write new shadow failed"));
171 			(void) close(dsw_fd);
172 			exit(1);
173 		}
174 	}
175 	if (find_cfg_info(old_vol, SV_TOKEN) == 0) {
176 		(void) fprintf(stderr,
177 		    gettext("Old shadow not in existing cfg\n"));
178 		exit(1);
179 	}
180 	if (find_cfg_info(old_vol, DSVOL_TOKEN) == 0) {
181 		(void) fprintf(stderr,
182 		    gettext("Old shadow not in existing cfg\n"));
183 		exit(1);
184 	}
185 	if (strstr(real_bitmap, "/rdsk/") == NULL) {
186 		(void) fprintf(stderr,
187 		    gettext("%s is not a character device\n"), real_bitmap);
188 		exit(1);
189 	}
190 
191 	/* use block device /dsk/ to update bitmap header */
192 	convert_to_blockdevice();
193 
194 	/* open bitmap by using update mode */
195 	if ((ifp = fopen(real_bitmap, "r+")) == NULL) {
196 		(void) fprintf(stderr, gettext("Can't open bitmap file\n"));
197 		exit(1);
198 	}
199 
200 	/* Check old header looks like an II bitmap header */
201 	if (fread(&header, DSW_CBLK_FBA, FBA_SIZE(1), ifp) != FBA_SIZE(1)) {
202 		(void) fprintf(stderr, gettext("Can't read bitmap file\n"));
203 		exit(1);
204 	}
205 
206 	if (hp->ii_magic != DSW_CLEAN && hp->ii_magic != DSW_DIRTY) {
207 		(void) fprintf(stderr,
208 		    gettext("%s is not a Point-in-Time Copy "
209 		    "shadow.\n"), old_vol);
210 		exit(1);
211 	}
212 
213 	if (strncmp(hp->shadow_vol, old_vol, DSW_NAMELEN) != 0) {
214 		(void) fprintf(stderr, gettext("%s has Point-in-Time Copy "
215 		    "shadow magic number,\n"
216 		    "but does not contain correct data.\n"), old_vol);
217 		exit(1);
218 	}
219 
220 	(void) memset(hp->shadow_vol, 0, DSW_NAMELEN);
221 	(void) strncpy(hp->shadow_vol, new_vol, DSW_NAMELEN);
222 
223 	/* reset the pointer position */
224 	rewind(ifp);
225 	if (fwrite(&header, DSW_CBLK_FBA, FBA_SIZE(1), ifp) != FBA_SIZE(1)) {
226 		perror(new_vol);
227 		(void) fprintf(stderr,
228 		    gettext("Can't write new bitmap header\n"));
229 		exit(1);
230 	}
231 	(void) fclose(ifp);
232 	(void) close(dsw_fd);
233 	if (update_dscfg(new_vol) == 0) {
234 		(void) fprintf(stderr, gettext("Failed to update dscfg.\n"));
235 		exit(1);
236 	} else {
237 		spcs_log("ii", NULL,
238 		    "iicpshd copy shadow from %s to %s",
239 		    old_vol, new_vol);
240 	}
241 }
242 
243 /*
244  * find_cfg_info()
245  *
246  */
247 
248 int
249 find_cfg_info(char *volume, char *token)
250 {
251 	int i;
252 	/* get read lock */
253 	if (!cfg_lock(cfg, CFG_RDLOCK)) {
254 		spcs_log("ii", NULL,
255 		    "iicpbmp CFG_RDLOCK failed, errno %d", errno);
256 		(void) fprintf(stderr, gettext("Error locking config\n"));
257 		exit(1);
258 	}
259 	for (i = 1; ; i++) {
260 		bzero(buf, CFG_MAX_BUF);
261 		(void) snprintf(key, sizeof (key), token, i);
262 		if (cfg_get_cstring(cfg, key, buf, DSW_NAMELEN) < 0) {
263 			cfg_unlock(cfg);
264 			return (0);
265 		}
266 		if (strcmp(buf, volume) == 0) {
267 			if (strcmp(token, SHADOW_TOKEN) == 0) {
268 				(void) snprintf(key, sizeof (key),
269 				    BITMAP_TOKEN, i);
270 				(void) cfg_get_cstring(cfg, key,
271 				    real_bitmap, DSW_NAMELEN);
272 				set_number = i;
273 			} else if (strcmp(token, SV_TOKEN) == 0) {
274 				sv_number = i;
275 			} else if (strcmp(token, DSVOL_TOKEN) == 0) {
276 				dsvol_number = i;
277 			}
278 			/* release read lock */
279 			cfg_unlock(cfg);
280 			return (1);
281 		}
282 	}
283 }
284 
285 int
286 copy_shadow_vol(char *old_shadow, char *new_shadow) {
287 	int i;
288 	char cp_buffer[256];
289 	FILE *ishdfp, *oshdfp;
290 	if ((ishdfp = fopen(old_shadow, "r")) == NULL) {
291 		(void) fprintf(stderr, gettext("Can't open old shadow file\n"));
292 		return (0);
293 	}
294 	if ((oshdfp = fopen(new_shadow, "w")) == NULL) {
295 		(void) fprintf(stderr, gettext("Can't open new shadow file\n"));
296 		return (0);
297 	}
298 
299 	/* Copy the shadow vol */
300 	while ((i = fread(cp_buffer, sizeof (char), sizeof (cp_buffer), ishdfp))
301 		> 0) {
302 		if (fwrite(cp_buffer, sizeof (char), i, oshdfp) != i) {
303 			(void) fclose(ishdfp);
304 			(void) fclose(oshdfp);
305 			return (0);
306 		}
307 	}
308 	(void) fclose(ishdfp);
309 	(void) fclose(oshdfp);
310 	return (1);
311 }
312 
313 int
314 update_dscfg(char *new_shadow) {
315 
316 	int len = strlen(new_shadow);
317 	/* get write lock */
318 	if (!cfg_lock(cfg, CFG_WRLOCK)) {
319 		spcs_log("ii", NULL,
320 		    "iicpbmp CFG_WRLOCK failed, errno %d", errno);
321 		(void) fprintf(stderr, gettext("Error locking config\n"));
322 		return (0);
323 	}
324 	(void) sprintf(key, SHADOW_TOKEN, set_number);
325 	if (cfg_put_cstring(cfg, key, new_shadow, len) < 0) {
326 		perror("cfg_put_cstring");
327 		return (0);
328 	}
329 	(void) sprintf(key, SV_TOKEN, sv_number);
330 	if (cfg_put_cstring(cfg, key, new_shadow, len) < 0) {
331 		perror("cfg_put_cstring");
332 		return (0);
333 	}
334 	(void) sprintf(key, DSVOL_TOKEN, dsvol_number);
335 	if (cfg_put_cstring(cfg, key, new_shadow, len) < 0) {
336 		perror("cfg_put_cstring");
337 		return (0);
338 	}
339 	(void) cfg_commit(cfg);
340 	cfg_unlock(cfg);
341 	return (1);
342 }
343 
344 void
345 convert_to_blockdevice() {
346 	int len = strlen(real_bitmap);
347 	int i = 0, j = 0;
348 	char *temp_string = malloc(len-1);
349 	while (i < len + 1) {
350 		if (real_bitmap[i] != 'r') {
351 			temp_string[j] = real_bitmap[i];
352 			j++;
353 		}
354 		i++;
355 	}
356 	(void) strcpy(real_bitmap, temp_string);
357 	free(temp_string);
358 }
359