8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / librdc / common / rdcpersist.c
blob703c8eef1151e123d51e26f7d07c76b206ff3907
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/mkdev.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <stropts.h>
32 #include <stdio.h>
33 #include <errno.h>
34 #include <libintl.h>
35 #include <locale.h>
36 #include <stdlib.h>
38 #include <sys/nsctl/rdcerr.h>
39 #include <sys/nsctl/rdc_ioctl.h>
40 #include <sys/nsctl/librdc.h>
41 #include <sys/nsctl/cfg.h>
42 #include <sys/nsctl/nsc_hash.h>
43 #include <sys/nsctl/sv.h>
45 #include <sys/unistat/spcs_dtrinkets.h>
46 #include <sys/unistat/spcs_etrinkets.h>
47 #include <sys/unistat/spcs_s.h>
48 #include <sys/unistat/spcs_s_u.h>
49 #include <sys/unistat/spcs_s_impl.h>
50 #include <sys/unistat/spcs_errors.h>
52 typedef struct volcount_s {
53 int count;
54 } volcount_t;
56 hash_node_t **volhash = NULL;
58 char *
59 config2buf(char *buf, rdcconfig_t *rdc)
61 snprintf(buf, CFG_MAX_BUF, "%s %s %s %s %s %s %s %s %s %s %s",
62 rdc->phost, rdc->pfile, rdc->pbmp, rdc->shost, rdc->sfile,
63 rdc->sbmp, rdc->direct, rdc->mode, rdc->group ? rdc->group : "",
64 rdc->ctag ? rdc->ctag : "", rdc->options ? rdc->options : "");
65 return (buf);
70 * SV type functions.
73 static void
74 load_rdc_vols(CFGFILE *cfg)
76 int set;
77 char key[ CFG_MAX_KEY ];
78 char buf[ CFG_MAX_BUF ];
79 char *vol, *bmp, *host1, *host2;
80 volcount_t *volcount;
82 if (volhash) {
83 return;
86 cfg_rewind(cfg, CFG_SEC_CONF);
87 volhash = nsc_create_hash();
88 for (set = 1; /*CSTYLED*/; set++) {
89 snprintf(key, CFG_MAX_KEY, "sndr.set%d", set);
90 if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF)) {
91 break;
94 host1 = strtok(buf, " ");
95 vol = strtok(NULL, " ");
96 bmp = strtok(NULL, " ");
98 if (!self_check(host1)) {
99 /* next one had better be ours */
100 host2 = strtok(NULL, " ");
101 vol = strtok(NULL, " ");
102 bmp = strtok(NULL, " ");
104 if (!self_check(host2)) {
105 continue;
109 /* primary vol may be used more than once */
110 volcount = (volcount_t *)nsc_lookup(volhash, vol);
111 if (volcount) {
112 volcount->count++;
113 } else {
114 volcount = (volcount_t *)malloc(sizeof (volcount_t));
115 volcount->count = 1;
116 nsc_insert_node(volhash, volcount, vol);
119 /* bitmap ought to be only used once */
120 volcount = (volcount_t *)nsc_lookup(volhash, bmp);
121 if (volcount) {
122 /* argh */
123 volcount->count++;
124 } else {
125 volcount = (volcount_t *)malloc(sizeof (volcount_t));
126 volcount->count = 1;
127 nsc_insert_node(volhash, volcount, bmp);
133 sv_enable_one_nocfg(char *vol)
135 struct stat sb;
136 sv_conf_t svc;
137 int fd;
139 bzero(&svc, sizeof (svc));
140 if (stat(vol, &sb) != 0) {
141 rdc_set_error(NULL, RDC_OS, 0, "unable to stat %s", vol);
142 return (-1);
144 if (!S_ISCHR(sb.st_mode)) {
145 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL, "%s is not"
146 " a character device", vol);
147 return (-1);
150 svc.svc_major = major(sb.st_rdev);
151 svc.svc_minor = minor(sb.st_rdev);
152 strncpy(svc.svc_path, vol, sizeof (svc.svc_path));
154 fd = open(SV_DEVICE, O_RDONLY);
155 if (fd < 0) {
156 rdc_set_error(NULL, RDC_OS, 0, 0);
157 return (-1);
160 svc.svc_flag = (NSC_DEVICE | NSC_CACHE);
161 svc.svc_error = spcs_s_ucreate();
163 if (ioctl(fd, SVIOC_ENABLE, &svc) < 0) {
164 if (errno != SV_EENABLED) {
165 rdc_set_error(&svc.svc_error, RDC_INTERNAL,
166 RDC_NONFATAL, 0);
167 return (-1);
171 spcs_log("sv", NULL, gettext("enabled %s"), svc.svc_path);
173 close(fd);
174 return (1);
178 sv_enable_nocfg(rdcconfig_t *rdc)
180 struct stat stbv;
181 struct stat stbb;
182 sv_conf_t svcv;
183 sv_conf_t svcb;
184 char vol[NSC_MAXPATH];
185 char bmp[NSC_MAXPATH];
186 int fd = -1;
189 if (self_check(rdc->phost)) {
190 strncpy(vol, rdc->pfile, NSC_MAXPATH);
191 strncpy(bmp, rdc->pbmp, NSC_MAXPATH);
192 } else {
193 strncpy(vol, rdc->sfile, NSC_MAXPATH);
194 strncpy(bmp, rdc->sbmp, NSC_MAXPATH);
197 bzero(&svcv, sizeof (svcv));
198 bzero(&svcb, sizeof (svcb));
200 if ((stat(vol, &stbv) != 0) || (stat(bmp, &stbb) != 0))
201 return (-1);
203 if ((!S_ISCHR(stbv.st_mode)) || (!S_ISCHR(stbb.st_mode)))
204 return (-1);
206 svcv.svc_major = major(stbv.st_rdev);
207 svcb.svc_minor = minor(stbb.st_rdev);
209 strncpy(svcv.svc_path, vol, sizeof (svcv.svc_path));
210 strncpy(svcb.svc_path, bmp, sizeof (svcb.svc_path));
212 fd = open(SV_DEVICE, O_RDONLY);
213 if (fd < 0)
214 return (-1);
216 /* SV enable the volume */
217 svcv.svc_flag = (NSC_DEVICE | NSC_CACHE);
218 svcv.svc_error = spcs_s_ucreate();
220 if (ioctl(fd, SVIOC_ENABLE, &svcv) < 0) {
221 if (errno != SV_EENABLED) {
222 spcs_log("sv", &svcv.svc_error,
223 gettext("unable to enable %s"),
224 svcv.svc_path);
225 spcs_s_ufree(&svcv.svc_error);
226 return (-1);
230 /* SV enable the bitmap disable the vol on error */
231 svcb.svc_flag = (NSC_DEVICE | NSC_CACHE);
232 svcb.svc_error = spcs_s_ucreate();
234 if (ioctl(fd, SVIOC_ENABLE, &svcb) < 0) {
235 if (errno != SV_EENABLED) {
236 spcs_log("sv", &svcb.svc_error,
237 gettext("unable to enable %s"),
238 svcb.svc_path);
239 if (ioctl(fd, SVIOC_DISABLE, &svcv) < 0)
240 spcs_log("sv", &svcv.svc_error,
241 gettext("unable to disable %s"),
242 svcv.svc_path);
244 spcs_s_ufree(&svcv.svc_error);
245 spcs_s_ufree(&svcb.svc_error);
246 return (-1);
251 spcs_log("sv", NULL, gettext("enabled %s"), svcv.svc_path);
252 spcs_log("sv", NULL, gettext("enabled %s"), svcb.svc_path);
253 spcs_s_ufree(&svcv.svc_error);
254 spcs_s_ufree(&svcb.svc_error);
257 if (fd >= 0)
258 (void) close(fd);
260 return (1);
264 do_autosv_enable(CFGFILE *cfg, rdcconfig_t *rdc)
266 char vol[NSC_MAXPATH];
267 char bmp[NSC_MAXPATH];
269 cfg_load_svols(cfg);
270 cfg_load_dsvols(cfg);
271 cfg_load_shadows(cfg);
272 load_rdc_vols(cfg);
274 if (self_check(rdc->phost)) {
275 strncpy(vol, rdc->pfile, NSC_MAXPATH);
276 strncpy(bmp, rdc->pbmp, NSC_MAXPATH);
277 } else {
278 strncpy(vol, rdc->sfile, NSC_MAXPATH);
279 strncpy(bmp, rdc->sbmp, NSC_MAXPATH);
281 if (nsc_lookup(volhash, vol) == NULL) {
282 if (cfg_vol_enable(cfg, vol, rdc->ctag, "sndr") < 0) {
283 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
284 "auto sv enable failed for %s", vol);
285 return (-1);
288 if (nsc_lookup(volhash, bmp) == NULL) {
289 if (cfg_vol_enable(cfg, bmp, rdc->ctag, "sndr") < 0) {
290 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
291 "auto sv enable failed for %s", vol);
292 return (-1);
296 nsc_remove_all(volhash, free);
297 volhash = NULL;
299 cfg_unload_shadows();
300 cfg_unload_dsvols();
301 cfg_unload_svols();
303 return (1);
307 do_autosv_disable(CFGFILE *cfg, rdcconfig_t *rdc)
309 char vol[NSC_MAXPATH];
310 char bmp[NSC_MAXPATH];
311 volcount_t *vc;
313 cfg_load_svols(cfg);
314 cfg_load_dsvols(cfg);
315 cfg_load_shadows(cfg);
316 load_rdc_vols(cfg);
318 if (self_check(rdc->phost)) {
319 strncpy(vol, rdc->pfile, NSC_MAXPATH);
320 strncpy(bmp, rdc->pbmp, NSC_MAXPATH);
321 } else {
322 strncpy(vol, rdc->sfile, NSC_MAXPATH);
323 strncpy(bmp, rdc->sbmp, NSC_MAXPATH);
326 vc = nsc_lookup(volhash, vol);
327 if (vc && (vc->count == 1)) {
328 if (cfg_vol_disable(cfg, vol, rdc->ctag, "sndr") < 0)
329 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
330 "auto sv disable failed for %s", vol);
331 } else if (!vc) {
332 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
333 "Unable to find %s in config", vol);
335 vc = nsc_lookup(volhash, bmp);
336 if (vc && (vc->count == 1)) {
337 if (cfg_vol_disable(cfg, bmp, rdc->ctag, "sndr") < 0)
338 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
339 "auto sv disable failed for %s", bmp);
341 } else if (!vc) {
342 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
343 "Unable to find %s in config", bmp);
346 return (1);
351 * do sv enables for the appropriate vol
352 * and bitmap. If called without persistance
353 * it will follow a chain and sv enable all
354 * otherwise, it will enable only the one
355 * set.
358 sv_enable(CFGFILE *cfg, rdcconfig_t *rdcs)
360 rdcconfig_t *rdcp = NULL;
362 rdcp = rdcs;
363 if (!rdcp->persist) {
365 return (sv_enable_nocfg(rdcp));
367 } else if (cfg == NULL) {
369 return (-1);
373 do_autosv_enable(cfg, rdcp);
375 return (1);
379 sv_disable(CFGFILE *cfg, rdcconfig_t *rdcs)
381 rdcconfig_t *rdcp;
383 rdcp = rdcs;
384 if (!rdcp->persist) { /* don't disable */
386 return (1);
388 } else if (cfg == NULL) {
390 return (-1);
394 do_autosv_disable(cfg, rdcp);
396 return (1);
401 * disable the appropriate bitmap in rdc
402 * and replace it with bitmap
405 sv_reconfig(CFGFILE *cfg, rdcconfig_t *rdc, char *oldbmp, char *newbmp)
407 rdcconfig_t *rdcp;
408 int fail = 0;
410 rdcp = rdc;
411 if (!rdcp->persist) { /* just enable, don't disable */
413 sv_enable_one_nocfg(newbmp);
415 } else if (rdcp->persist) { /* do sv disable and enable */
416 volcount_t *vc;
418 cfg_load_svols(cfg);
419 cfg_load_dsvols(cfg);
420 cfg_load_shadows(cfg);
421 load_rdc_vols(cfg);
423 vc = (volcount_t *)nsc_lookup(volhash, oldbmp);
424 if (vc && (vc->count == 1)) {
425 if (cfg_vol_disable(cfg, oldbmp, rdc->ctag, "sndr") < 0)
426 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
427 "auto sv disable failed for %s", oldbmp);
430 if (nsc_lookup(volhash, newbmp) == NULL) {
431 if (cfg_vol_enable(cfg,
432 newbmp, rdc->ctag, "sndr") < 0) {
434 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
435 "auto sv enable failed for %s", newbmp);
436 fail++;
439 nsc_remove_all(volhash, free);
440 volhash = NULL;
442 cfg_unload_shadows();
443 cfg_unload_dsvols();
444 cfg_unload_svols();
445 if (fail)
446 return (-1);
449 return (1);
454 * SNDR functions
458 * add_to_rdc_cfg
459 * this adds the successfully created rdc sets to libdscfg,
460 * also, as auto_sv stuff is part of libdscfg, it does the
461 * auto_sv stuff and enables the correct volumes
464 add_to_rdc_cfg(rdcconfig_t *rdcs)
466 CFGFILE *cfg;
467 rdcconfig_t *rdcp;
468 char *buf;
471 buf = calloc(CFG_MAX_BUF, sizeof (char));
472 if (!buf) {
473 rdc_set_error(NULL, RDC_OS, RDC_FATAL, NULL);
474 return (NULL);
477 if ((cfg = cfg_open(NULL)) == NULL) {
478 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
479 return (-1);
481 if ((cfg_lock(cfg, CFG_WRLOCK)) < 0) {
482 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
483 return (-1);
486 rdcp = rdcs;
487 while (rdcp) {
488 buf = config2buf(buf, rdcp);
489 if ((sv_enable(cfg, rdcp) < 0) ||
490 (cfg_put_cstring(cfg, "sndr", buf, CFG_MAX_BUF) < 0)) {
491 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
492 free(buf);
493 return (-1);
495 rdcp = rdcp->next;
497 if (!cfg_commit(cfg)) {
498 rdc_set_error(NULL, RDC_DSCFG, 0, NULL);
499 return (-1);
502 cfg_close(cfg);
504 return (0);
508 cfg_lookup(CFGFILE *cfg, char *shost, char *sfile)
510 char buf[CFG_MAX_BUF];
511 char key[CFG_MAX_KEY];
512 int setnum;
513 int numsets = 0;
515 numsets = cfg_get_num_entries(cfg, "sndr");
516 for (setnum = 1; setnum <= numsets; setnum++) {
517 bzero(key, CFG_MAX_KEY);
518 snprintf(key, CFG_MAX_KEY, "sndr.set%d.shost", setnum);
519 if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
520 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
521 return (-1);
523 if (strncmp(buf, shost, strlen(shost)))
524 continue;
526 bzero(key, CFG_MAX_KEY);
527 snprintf(key, CFG_MAX_KEY, "sndr.set%d.secondary", setnum);
528 if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
529 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
530 return (-1);
532 if (strncmp(buf, sfile, strlen(sfile)))
533 continue;
534 break;
536 return (setnum);
539 void
540 remove_from_rdc_cfg(rdcconfig_t *rdcs)
542 CFGFILE *cfg;
543 rdcconfig_t *rdcp;
544 char key[CFG_MAX_KEY];
546 rdcp = rdcs;
547 cfg = cfg_open(NULL);
548 cfg_lock(cfg, CFG_WRLOCK);
550 while (rdcp) {
551 snprintf(key, CFG_MAX_KEY, "sndr.set%d",
552 cfg_lookup(cfg, rdcp->shost, rdcp->sfile));
553 if ((sv_disable(cfg, rdcp) < 0) ||
554 (cfg_put_cstring(cfg, key, NULL, 0)) < 0) {
555 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
558 rdcp = rdcp->next;
560 cfg_commit(cfg);
561 cfg_close(cfg);
563 /*ARGSUSED*/
565 replace_entry(int offset, char *entry)
567 return (1);
571 * this will set the value at "field" in dscfg to the
572 * value contained in entry.
573 * for things like bitmap reconfigs, only pass one rdc
574 * not a chain
577 replace_cfgfield(rdcconfig_t *rdc, char *field, char *entry)
579 CFGFILE *cfg;
580 rdcconfig_t *rdcp;
581 char key[CFG_MAX_KEY];
582 char newentry[CFG_MAX_BUF];
583 char oldbmp[CFG_MAX_BUF];
584 int setnum;
585 int ispbmp = 0;
586 int issbmp = 0;
588 if (strncmp(field, "pbitmap", NSC_MAXPATH) == 0)
589 ispbmp++;
590 if (strncmp(field, "sbitmap", NSC_MAXPATH) == 0)
591 issbmp++;
593 bzero(newentry, sizeof (newentry));
594 if (!entry || strlen(entry) == 0)
595 *newentry = '-';
596 else
597 strncpy(newentry, entry, CFG_MAX_BUF);
600 if ((cfg = cfg_open(NULL)) == NULL) {
601 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
602 return (-1);
604 if ((cfg_lock(cfg, CFG_WRLOCK)) < 0) {
605 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
606 return (-1);
609 rdcp = rdc;
610 while (rdcp) {
611 if ((setnum = cfg_lookup(cfg, rdcp->shost, rdcp->sfile)) < 0) {
612 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
613 return (-1);
615 snprintf(key, CFG_MAX_KEY, "sndr.set%d.%s", setnum, field);
616 if (!((ispbmp || issbmp) &&
617 (cfg_get_cstring(cfg, key, oldbmp, CFG_MAX_BUF)) == 0)) {
618 rdc_set_error(NULL, RDC_DSCFG, 0, "unable to get %s",
619 key);
621 if (((ispbmp && self_check(rdcp->phost)) ||
622 (issbmp && self_check(rdcp->shost))) &&
623 (sv_reconfig(cfg, rdcp, oldbmp, newentry) < 0)) {
624 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
625 "unable to sv reconfig %s to %s", oldbmp, newentry);
626 return (-1);
629 if ((cfg_put_cstring(cfg, key, newentry, CFG_MAX_BUF)) < 0) {
630 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
631 return (-1);
633 rdcp = rdcp->next;
635 cfg_commit(cfg);
636 cfg_close(cfg);
637 return (1);
641 * reverse_in_cfg
642 * used by RDC_OPT_REVERSE_ROLE
643 * swaps primary info and secondary info
646 reverse_in_cfg(rdcconfig_t *rdc)
648 CFGFILE *cfg;
649 rdcconfig_t *rdcp = NULL;
650 char key[CFG_MAX_KEY];
651 int setnum;
653 if ((cfg = cfg_open(NULL)) == NULL) {
654 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
655 return (-1);
657 if ((cfg_lock(cfg, CFG_WRLOCK)) < 0) {
658 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
659 return (-1);
662 rdcp = rdc;
663 while (rdcp) {
664 if ((setnum = cfg_lookup(cfg, rdcp->shost, rdcp->sfile)) < 0) {
665 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
666 goto badconfig;
668 bzero(key, CFG_MAX_KEY);
669 snprintf(key, CFG_MAX_KEY, "sndr.set%d.phost", setnum);
670 if ((cfg_put_cstring(cfg, key, rdcp->shost, CFG_MAX_BUF)) < 0) {
671 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
672 goto badconfig;
674 bzero(key, CFG_MAX_KEY);
675 snprintf(key, CFG_MAX_KEY, "sndr.set%d.primary", setnum);
676 if ((cfg_put_cstring(cfg, key, rdcp->sfile, CFG_MAX_BUF)) < 0) {
677 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
678 goto badconfig;
680 bzero(key, CFG_MAX_KEY);
681 snprintf(key, CFG_MAX_KEY, "sndr.set%d.pbitmap", setnum);
682 if ((cfg_put_cstring(cfg, key, rdcp->sbmp, CFG_MAX_BUF)) < 0) {
683 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
684 goto badconfig;
686 bzero(key, CFG_MAX_KEY);
687 snprintf(key, CFG_MAX_KEY, "sndr.set%d.shost", setnum);
688 if ((cfg_put_cstring(cfg, key, rdcp->phost, CFG_MAX_BUF)) < 0) {
689 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
690 goto badconfig;
692 bzero(key, CFG_MAX_KEY);
693 snprintf(key, CFG_MAX_KEY, "sndr.set%d.secondary", setnum);
694 if ((cfg_put_cstring(cfg, key, rdcp->pfile, CFG_MAX_BUF)) < 0) {
695 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
696 goto badconfig;
698 bzero(key, CFG_MAX_KEY);
699 snprintf(key, CFG_MAX_KEY, "sndr.set%d.sbitmap", setnum);
700 if ((cfg_put_cstring(cfg, key, rdcp->pbmp, CFG_MAX_BUF)) < 0) {
701 rdc_set_error(NULL, RDC_DSCFG, 0, 0);
702 goto badconfig;
704 rdcp = rdcp->next;
706 if (!cfg_commit(cfg)) {
707 cfg_close(cfg);
708 return (-1);
710 cfg_close(cfg);
711 return (0);
713 badconfig:
714 cfg_close(cfg);
715 return (-1);