xref: /titanic_44/usr/src/cmd/avs/dsw/iicpshd.c (revision 7c2fbfb345896881c631598ee3852ce9ce33fb07)
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