xref: /titanic_41/usr/src/cmd/avs/rdc/sndrsubr.c (revision a2f144d1eca25f33af1e19affd8eda208f547108)
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  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/types.h>
27 #include <stdio.h>
28 #include <sys/mnttab.h>
29 #include <errno.h>
30 #include <limits.h>
31 #include <fcntl.h>
32 #include <strings.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <sys/stat.h>
36 #include <signal.h>
37 
38 #include <locale.h>
39 #include <langinfo.h>
40 #include <libintl.h>
41 #include <stdarg.h>
42 #include <sys/nsctl/rdc_io.h>
43 #include <sys/nsctl/rdc_ioctl.h>
44 #include <sys/nsctl/rdc_prot.h>
45 
46 #include <sys/nsctl/cfg.h>
47 
48 #include <sys/unistat/spcs_s.h>
49 #include <sys/unistat/spcs_s_u.h>
50 #include <sys/unistat/spcs_errors.h>
51 
52 #include "rdcadm.h"
53 
54 
55 int maxqfbas = MAXQFBAS;
56 int maxqitems = MAXQITEMS;
57 int autosync = AUTOSYNC;
58 int asyncthr = ASYNCTHR;
59 int qblock = QBLOCK;
60 
61 int
62 mounted(char *device)
63 {
64 	char target[NSC_MAXPATH];
65 	struct mnttab mntref;
66 	struct mnttab mntent;
67 	FILE *mntfp;
68 	int rdsk;
69 	char *s;
70 	int i;
71 
72 	rdsk = i = 0;
73 	for (s = target; i < NSC_MAXPATH && (*s = *device++); i++) {
74 		if (*s == 'r' && rdsk == 0 && strncmp(device, "dsk/", 4) == 0)
75 			rdsk = 1;
76 		else
77 			s++;
78 	}
79 	*s = '\0';
80 
81 	mntref.mnt_special = target;
82 	mntref.mnt_mountp = NULL;
83 	mntref.mnt_fstype = NULL;
84 	mntref.mnt_mntopts = NULL;
85 	mntref.mnt_time = NULL;
86 
87 	mntfp = fopen(MNTTAB, "r");
88 
89 	if (mntfp == NULL) {
90 		rdc_warn(NULL,
91 			gettext("can not check volume %s against mount table"),
92 			mntref.mnt_special);
93 		/* Assume the worst, that it is mounted */
94 		return (1);
95 	}
96 
97 	if (getmntany(mntfp, &mntent, &mntref) != -1) {
98 		/* found something before EOF */
99 		(void) fclose(mntfp);
100 		return (1);
101 	}
102 
103 	(void) fclose(mntfp);
104 	return (0);
105 }
106 
107 
108 /* Needs to match parsing code in rdcboot.c and rdcadm.c */
109 char *
110 rdc_decode_flag(int flag, int options)
111 {
112 	static char str[32];
113 
114 	switch (flag) {
115 	case (RDC_CMD_COPY):
116 		if (options & RDC_OPT_FULL)
117 			strcpy(str, "-m");
118 		else
119 			strcpy(str, "-u");
120 		if (options & RDC_OPT_REVERSE)
121 			strcat(str, " -r");
122 		break;
123 
124 	case (RDC_CMD_DISABLE):
125 		strcpy(str, "-d");
126 		break;
127 
128 	case (RDC_CMD_ENABLE):
129 		if (options & RDC_OPT_SETBMP)
130 			strcpy(str, "-e");
131 		else
132 			strcpy(str, "-E");
133 		break;
134 
135 	case (RDC_CMD_LOG):
136 		strcpy(str, "-l");
137 		break;
138 
139 	case (RDC_CMD_HEALTH):
140 		strcpy(str, "-H");
141 		break;
142 
143 	case (RDC_CMD_WAIT):
144 		strcpy(str, "-w");
145 		break;
146 
147 	case (RDC_CMD_RECONFIG):
148 		strcpy(str, "-R ...");
149 		break;
150 
151 	case (RDC_CMD_TUNABLE):
152 		strcpy(str, "");
153 		if (maxqfbas != MAXQFBAS)
154 			strcat(str, " -F");
155 		if (maxqitems != MAXQITEMS)
156 			strcat(str, " -W");
157 		if (autosync != AUTOSYNC)
158 			strcat(str, " -a");
159 		if (asyncthr != ASYNCTHR)
160 			strcat(str, " -A");
161 		if (qblock != QBLOCK)
162 			strcat(str, " -D");
163 		break;
164 
165 	case (RDC_CMD_SUSPEND):
166 		strcpy(str, "-s");
167 		break;
168 
169 	case (RDC_CMD_RESUME):
170 		strcpy(str, "-r");
171 		break;
172 
173 	case (RDC_CMD_RESET):
174 		strcpy(str, "-R");
175 		break;
176 
177 	case (RDC_CMD_ADDQ):
178 		strcpy(str, "-q a");
179 		break;
180 
181 	case (RDC_CMD_REMQ):
182 		strcpy(str, "-q d");
183 		break;
184 
185 	case (RDC_CMD_REPQ):
186 		strcpy(str, "-q r");
187 		break;
188 
189 	default:
190 		strcpy(str, gettext("unknown"));
191 		break;
192 	}
193 
194 	return (str);
195 }
196 
197 
198 static void
199 rdc_msg(char *prefix, spcs_s_info_t *status, char *string, va_list ap)
200 {
201 	if (status) {
202 		(void) fprintf(stderr, "Remote Mirror: %s\n", prefix);
203 		spcs_s_report(*status, stderr);
204 	} else {
205 		(void) fprintf(stderr, "%s: %s: ", program, prefix);
206 	}
207 
208 	if (string && *string != '\0') {
209 		(void) vfprintf(stderr, string, ap);
210 	}
211 
212 	(void) fprintf(stderr, "\n");
213 }
214 
215 void
216 rdc_err(spcs_s_info_t *status, char *string, ...)
217 {
218 	va_list ap;
219 	va_start(ap, string);
220 
221 	rdc_msg(gettext("Error"), status, string, ap);
222 
223 	va_end(ap);
224 	exit(1);
225 }
226 
227 void
228 rdc_warn(spcs_s_info_t *status, char *string, ...)
229 {
230 	va_list ap;
231 	va_start(ap, string);
232 
233 	rdc_msg(gettext("warning"), status, string, ap);
234 
235 	va_end(ap);
236 }
237 
238 int
239 rdc_get_maxsets(void)
240 {
241 	rdc_status_t rdc_status;
242 	spcs_s_info_t ustatus;
243 	int rc;
244 
245 	rdc_status.nset = 0;
246 	ustatus = spcs_s_ucreate();
247 
248 	rc = RDC_IOCTL(RDC_STATUS, &rdc_status, 0, 0, 0, 0, ustatus);
249 	if (rc == SPCS_S_ERROR) {
250 		rdc_err(&ustatus, gettext("statistics error"));
251 	}
252 
253 	spcs_s_ufree(&ustatus);
254 	return (rdc_status.maxsets);
255 }
256 
257 /*
258  * Look up a set in libcfg to find the setnumber.
259  *
260  * ASSUMPTIONS:
261  *      - a valid cfg handle
262  *
263  * INPUTS:
264  *      cfg - cfg handle
265  *      tohost - secondary hostname
266  *      tofile - secondary volume
267  *
268  * OUTPUTS:
269  *      set number if found, otherwise -1 for an error
270  */
271 int
272 find_setnumber_in_libcfg(CFGFILE *cfg, char *ctag, char *tohost, char *tofile)
273 {
274 	int setnumber;
275 	int entries, rc;
276 	char *buf, *secondary, *shost;
277 	char **entry;
278 	char *cnode;
279 	int offset = 0;
280 
281 	if (cfg == NULL) {
282 #ifdef DEBUG
283 		rdc_warn(NULL, "cfg is NULL while looking up set number");
284 #endif
285 		return (-1);
286 	}
287 
288 	entries = cfg_get_section(cfg, &entry, "sndr");
289 
290 	rc = -1;
291 	for (setnumber = 1; setnumber <= entries; setnumber++) {
292 		buf = entry[setnumber - 1];
293 
294 		(void) strtok(buf, " ");	/* phost */
295 		(void) strtok(NULL, " ");	/* primary */
296 		(void) strtok(NULL, " ");	/* pbitmap */
297 		shost = strtok(NULL, " ");
298 		secondary = strtok(NULL, " ");
299 
300 		if (ctag && *ctag) {
301 			(void) strtok(NULL, " ");	/* sbitmap */
302 			(void) strtok(NULL, " ");	/* type */
303 			(void) strtok(NULL, " ");	/* mode */
304 			(void) strtok(NULL, " ");	/* group */
305 			cnode = strtok(NULL, " ");
306 
307 			if (ctag && strcmp(cnode, ctag) != 0) {
308 				/* filter this out */
309 				++offset;
310 				continue;
311 			}
312 		}
313 
314 		/* Check secondary volume name first, will get less hits */
315 		if (strcmp(secondary, tofile) != 0) {
316 			free(buf);
317 			continue;
318 		}
319 
320 		if (strcmp(shost, tohost) == 0) {
321 			free(buf);
322 			rc = setnumber - offset;
323 			break;
324 		}
325 
326 		free(buf);
327 	}
328 
329 	while (setnumber < entries)
330 		free(entry[setnumber++]);
331 	if (entries)
332 		free(entry);
333 
334 	return (rc);
335 }
336 
337 void
338 get_group_diskq(CFGFILE *cfg, char *group, char *diskq)
339 {
340 	int i;
341 	char key[CFG_MAX_KEY];
342 	char buf[CFG_MAX_BUF];
343 
344 	if (*group == '\0')
345 		return;
346 	for (i = 1; ; i++) {
347 		bzero(&key, sizeof (key));
348 		bzero(&buf, sizeof (buf));
349 		(void) sprintf(key, "sndr.set%d.group", i);
350 		if (cfg_get_cstring(cfg, key, &buf, sizeof (buf)) < 0)
351 			break;
352 		if (strncmp(group, buf, sizeof (buf)) == 0) {
353 			(void) sprintf(key, "sndr.set%d.diskq", i);
354 			if (cfg_get_cstring(cfg, key, diskq, CFG_MAX_BUF) < 0) {
355 				rdc_warn(NULL, gettext("unable to retrieve "
356 				    "group %s's disk queue"), group);
357 			}
358 		}
359 	}
360 }
361 
362 int
363 get_cfg_setid(CFGFILE *cfg, char *ctag, char *tohost, char *tofile)
364 {
365 	int setnum = 0;
366 	int close_cfg = 0;
367 	char key[CFG_MAX_KEY];
368 	char setid[64];
369 
370 	if (cfg == NULL) {
371 		close_cfg = 1;
372 		if ((cfg = cfg_open(NULL)) == NULL) {
373 			return (-1); /* message printed by caller */
374 		}
375 		if (!cfg_lock(cfg, CFG_RDLOCK)) {
376 			cfg_close(cfg);
377 			return (-1);
378 		}
379 	}
380 	setnum = find_setnumber_in_libcfg(cfg, ctag, tohost, tofile);
381 	if (setnum < 0)
382 		return (setnum);
383 
384 	(void) snprintf(key, CFG_MAX_KEY, "sndr.set%d.options", setnum);
385 	if (cfg_get_single_option(cfg, CFG_SEC_CONF, key, "setid",
386 		    setid, sizeof (setid)) < 0) {
387 		if (close_cfg)
388 			cfg_close(cfg);
389 
390 		spcs_log("sndr", NULL,
391 		    gettext("%s unable to get unique setid "
392 		    "for %s:%s"), program, tohost, tofile);
393 		return (-1);
394 
395 	}
396 	if (close_cfg)
397 		cfg_close(cfg);
398 
399 	return (atoi(setid));
400 
401 }
402 
403 int
404 get_new_cfg_setid(CFGFILE *cfg)
405 {
406 	int setid;
407 	char buf[CFG_MAX_BUF];
408 	char *ctag;
409 
410 	/* If in a Sun Cluster, SetIDs need to have a ctag */
411 	if ((ctag = cfg_get_resource(cfg)) != NULL) {
412 		ctag = strdup(ctag);
413 		cfg_resource(cfg, "setid-ctag");
414 	}
415 
416 	if (cfg_get_cstring(cfg, "setid.set1.value", buf, CFG_MAX_BUF) < 0) {
417 		setid = 1;
418 		if (cfg_put_cstring(cfg, "setid", "1", CFG_MAX_BUF) < 0) {
419 			rdc_err(NULL, "Unable to store new setid");
420 		}
421 	} else {
422 		setid = atoi(buf);
423 		setid++;
424 		if (setid <= 0) {
425 			setid = 1;
426 		}
427 	}
428 
429 	bzero(&buf, CFG_MAX_BUF);
430 	(void) snprintf(buf, sizeof (buf), "%d", setid);
431 	if (cfg_put_cstring(cfg, "setid.set1.value", buf, CFG_MAX_BUF) < 0) {
432 		rdc_err(NULL, "Unable to store new setid");
433 	}
434 
435 	/* Restore old ctag if in a Sun Cluster */
436 	if (ctag) {
437 		cfg_resource(cfg, ctag);
438 		free(ctag);
439 	}
440 
441 	return (setid);
442 }
443 
444 sigset_t origmask;
445 
446 void
447 block_sigs(void)
448 {
449 	sigset_t allsigs;
450 
451 	sigfillset(&allsigs);
452 	if (sigprocmask(SIG_BLOCK, &allsigs, &origmask) < 0)
453 		rdc_warn(NULL, gettext("Unable to block signals"));
454 }
455 
456 void
457 unblock_sigs(void)
458 {
459 	if (sigprocmask(SIG_SETMASK, &origmask, NULL) < 0)
460 		rdc_warn(NULL, gettext("Unable to unblock signals"));
461 
462 }
463