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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 #include <sys/types.h>
34 #include <sys/stream.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
42 #include <sys/unistat/spcs_s.h>
43 #include <sys/unistat/spcs_s_u.h>
44 #include <sys/unistat/spcs_s_impl.h>
45 #include <sys/unistat/spcs_errors.h>
47 #include <sys/nsctl/rdc_io.h>
48 #include <sys/nsctl/rdc_ioctl.h>
49 #include <sys/nsctl/rdc_prot.h>
50 #include <sys/nsctl/librdc.h>
51 #include <sys/nsctl/rdcrules.h>
52 #include <sys/nsctl/rdcerr.h>
53 #include <sys/nsctl/cfg.h>
55 #include <sys/unistat/spcs_dtrinkets.h>
56 #include <sys/unistat/spcs_etrinkets.h>
58 #include <sys/socket.h>
59 #include <netinet/in.h>
60 #include <arpa/inet.h>
61 #include <netinet/tcp.h>
62 #include <rpc/rpc_com.h>
65 struct netbuf svaddr
, *svp
;
66 struct netconfig nconf
, *conf
;
67 struct knetconfig knconf
;
70 * libdscfg type stuff here
72 extern int sv_enable(CFGFILE
*cfg
, rdcconfig_t
*rdc
);
73 extern int add_to_rdc_cfg(rdcconfig_t
*rdcs
);
74 extern int remove_from_rdc_cfg(rdcconfig_t
*rdcs
);
75 extern int replace_cfgfield(rdcconfig_t
*rdcs
, char *field
, char *value
);
76 extern int reverse_in_cfg(rdcconfig_t
*rdcs
);
79 rdc_dup_config(rdcconfig_t
*orig
)
83 rc
= (rdcconfig_t
*)calloc(1, sizeof (*rc
));
85 rdc_set_error(NULL
, RDC_OS
, RDC_FATAL
, NULL
);
90 rc
->next
= NULL
; /* don't want to hook into wrong chaing */
95 * takes in a chain of rdcconfig_t's and a chain
96 * of rdc_rc_t's, checks for success in the rdc_rc_t,
97 * then adds the corresponding rdcconfig_t to the return
101 chain_successful(rdcconfig_t
*rdcs
, rdc_rc_t
*rcs
)
105 rdcconfig_t
*ret
= NULL
;
106 rdcconfig_t
*retp
= NULL
;
113 if ((ret
== NULL
) && (rdcp
->persist
)) {
114 retp
= ret
= rdc_dup_config(rdcp
);
116 } else if ((ret
) && (rdcp
->persist
)) {
117 retp
->next
= rdc_dup_config(rdcp
);
129 config2set(rdcconfig_t
*rdc
)
133 bzero(&urdc
, sizeof (rdc_set_t
));
134 strncpy(urdc
.primary
.intf
, rdc
->phost
, MAX_RDC_HOST_SIZE
);
135 strncpy(urdc
.primary
.file
, rdc
->pfile
, NSC_MAXPATH
);
136 strncpy(urdc
.primary
.bitmap
, rdc
->pbmp
, NSC_MAXPATH
);
137 strncpy(urdc
.secondary
.intf
, rdc
->shost
, MAX_RDC_HOST_SIZE
);
138 strncpy(urdc
.secondary
.file
, rdc
->sfile
, NSC_MAXPATH
);
139 strncpy(urdc
.secondary
.bitmap
, rdc
->sbmp
, NSC_MAXPATH
);
140 strncpy(urdc
.group_name
, rdc
->group
, NSC_MAXPATH
);
150 rc
= (rdc_rc_t
*)calloc(1, sizeof (*rc
));
152 rdc_set_error(NULL
, RDC_OS
, RDC_FATAL
, NULL
);
159 rdc_config(rdc_config_t
*rdccfg
)
163 spcs_s_info_t ustatus
;
165 bzero(&rc
, sizeof (rc
));
166 ustatus
= spcs_s_ucreate();
168 if (self_check(rdccfg
->rdc_set
->primary
.intf
)) {
169 rdccfg
->options
|= RDC_OPT_PRIMARY
;
170 /* this needs changin if we do campus */
171 rdccfg
->rdc_set
->direct_file
[0] = 0;
173 rdccfg
->options
|= RDC_OPT_SECONDARY
;
176 /* set up return stuff.. */
177 set
= &rdccfg
->rdc_set
[0];
178 strncpy(rc
.set
.phost
, set
->primary
.intf
, MAX_RDC_HOST_SIZE
);
179 strncpy(rc
.set
.pfile
, set
->primary
.file
, NSC_MAXPATH
);
180 strncpy(rc
.set
.shost
, set
->secondary
.intf
, MAX_RDC_HOST_SIZE
);
181 strncpy(rc
.set
.sfile
, set
->secondary
.file
, NSC_MAXPATH
);
183 rc
.rc
= RDC_IOCTL(RDC_CONFIG
, rdccfg
, NULL
, 0, 0, 0, ustatus
);
186 rdc_set_error(&ustatus
, RDC_SPCS
, 0, 0);
187 strncpy(rc
.msg
, rdc_error(NULL
), RDC_ERR_SIZE
);
194 rdc_mtconfig(void *rdc
)
198 spcs_s_info_t ustatus
;
199 rdc_config_t
*rdccfg
= (rdc_config_t
*)rdc
;
201 ustatus
= spcs_s_ucreate();
203 if (self_check(rdccfg
->rdc_set
->primary
.intf
)) {
204 rdccfg
->options
|= RDC_OPT_PRIMARY
;
205 /* this needs changin if we do campus */
206 rdccfg
->rdc_set
->direct_file
[0] = 0;
208 rdccfg
->options
|= RDC_OPT_SECONDARY
;
211 set
= &rdccfg
->rdc_set
[0];
214 strncpy(rc
[0]->set
.phost
, set
->primary
.intf
, MAX_RDC_HOST_SIZE
);
215 strncpy(rc
[0]->set
.pfile
, set
->primary
.file
, NSC_MAXPATH
);
216 strncpy(rc
[0]->set
.pbmp
, set
->primary
.bitmap
, NSC_MAXPATH
);
217 strncpy(rc
[0]->set
.shost
, set
->secondary
.intf
, MAX_RDC_HOST_SIZE
);
218 strncpy(rc
[0]->set
.sfile
, set
->secondary
.file
, NSC_MAXPATH
);
219 strncpy(rc
[0]->set
.sbmp
, set
->secondary
.bitmap
, NSC_MAXPATH
);
221 rc
[0]->rc
= RDC_IOCTL(RDC_CONFIG
, rdccfg
, NULL
, 0, 0, 0, ustatus
);
224 rdc_set_error(&ustatus
, RDC_SPCS
, 0, 0);
225 strncpy(rc
[0]->msg
, rdc_error(NULL
), RDC_ERR_SIZE
);
228 sleep(1); /* give thr_join a chance to be called */
230 thr_exit((void **) *rc
);
234 populate_addrs(rdc_set_t
*urdc
, int isenable
)
238 char toname
[MAX_RDC_HOST_SIZE
];
239 char fromname
[MAX_RDC_HOST_SIZE
];
241 strncpy(fromname
, urdc
->primary
.intf
, MAX_RDC_HOST_SIZE
);
242 strncpy(toname
, urdc
->secondary
.intf
, MAX_RDC_HOST_SIZE
);
244 if ((fromname
[0] == '\0') || (fromname
[0] == '\0')) {
245 rdc_set_error(NULL
, RDC_INTERNAL
, RDC_FATAL
,
246 "NULL hostname recieved");
250 hp
= gethost_byname(fromname
);
251 strncpy(fromname
, hp
->h_name
, MAX_RDC_HOST_SIZE
);
252 hp
= gethost_byname(toname
);
253 strncpy(toname
, hp
->h_name
, MAX_RDC_HOST_SIZE
);
255 if (self_check(fromname
) && self_check(toname
)) {
256 rdc_set_error(NULL
, RDC_INTERNAL
, RDC_FATAL
, "");
260 svp
= get_addr(toname
, RDC_PROGRAM
, RDC_VERS_MIN
,
261 &conf
, NULL
, "rdc", &tinfo
, 0);
266 bzero(&svaddr
, sizeof (svaddr
));
269 urdc
->secondary
.addr
.len
= svaddr
.len
;
270 urdc
->secondary
.addr
.maxlen
= svaddr
.maxlen
;
271 urdc
->secondary
.addr
.buf
= (void*)svaddr
.buf
;
274 svp
= get_addr(fromname
, RDC_PROGRAM
, RDC_VERS_MIN
,
275 &conf
, NULL
, "rdc", &tinfo
, 0);
280 bzero(&svaddr
, sizeof (svaddr
));
283 urdc
->primary
.addr
.len
= svaddr
.len
;
284 urdc
->primary
.addr
.maxlen
= svaddr
.maxlen
;
285 urdc
->primary
.addr
.buf
= (void*)svaddr
.buf
;
288 convert_nconf_to_knconf(conf
, &knconf
);
289 urdc
->netconfig
= &knconf
;
291 urdc
->netconfig
= NULL
;
293 urdc
->syshostid
= (int32_t)gethostid();
299 rdc_free_config(rdcconfig_t
*rdc
, int all
)
305 if (all
== RDC_FREEONE
) {
307 } else while (rdcp
) {
316 rdc_free_rclist(rdc_rc_t
*rc
) {
329 rdc_alloc_config(const char *phost
, const char *pfile
,
330 const char *pbmp
, const char *shost
, const char *sfile
, const char *sbmp
,
331 const char *mode
, const char *group
, const char *ctag
, const char *options
,
336 rc
= (rdcconfig_t
*)calloc(1, sizeof (*rc
));
338 rdc_set_error(NULL
, RDC_OS
, RDC_FATAL
, NULL
);
342 strncpy(rc
->phost
, phost
, NSC_MAXPATH
);
344 strncpy(rc
->pfile
, pfile
, NSC_MAXPATH
);
346 strncpy(rc
->pbmp
, pbmp
, NSC_MAXPATH
);
348 strncpy(rc
->shost
, shost
, NSC_MAXPATH
);
350 strncpy(rc
->sfile
, sfile
, NSC_MAXPATH
);
352 strncpy(rc
->sbmp
, sbmp
, NSC_MAXPATH
);
354 strncpy(rc
->direct
, "ip", 2);
357 strncpy(rc
->mode
, mode
, NSC_MAXPATH
);
359 strncpy(rc
->ctag
, ctag
, NSC_MAXPATH
);
361 strncpy(rc
->options
, options
, NSC_MAXPATH
);
363 rc
->persist
= persist
;
371 populate_rc(rdc_rc_t
*rcp
, rdcconfig_t
*rdcp
)
374 strncpy(rcp
->msg
, rdc_error(NULL
), RDC_ERR_SIZE
);
375 strncpy(rcp
->set
.phost
, rdcp
->phost
, NSC_MAXPATH
);
376 strncpy(rcp
->set
.pfile
, rdcp
->pfile
, NSC_MAXPATH
);
377 strncpy(rcp
->set
.shost
, rdcp
->shost
, NSC_MAXPATH
);
378 strncpy(rcp
->set
.sfile
, rdcp
->sfile
, NSC_MAXPATH
);
385 * pointer to rdc_rc_t list of return values
388 rdc_enable(rdcconfig_t
*rdc
)
391 rdcconfig_t
*rdcp
= NULL
;
392 rdcconfig_t
*cfg_rdcs
= NULL
;
394 rdc_rc_t
*rcp
= NULL
;
398 if (!rc
) { /* error already set */
404 rdc_set_error(NULL
, RDC_INTERNAL
, RDC_NONFATAL
,
408 bzero(&rdccfg
, sizeof (rdc_config_t
));
409 rdccfg
.rdc_set
[0] = config2set(rdcp
);
410 rdccfg
.command
= RDC_CMD_ENABLE
;
411 rdccfg
.options
= RDC_OPT_SETBMP
;
412 if (strncmp(rdcp
->mode
, "sync", NSC_MAXPATH
) == 0) {
413 rdccfg
.options
|= RDC_OPT_SYNC
;
414 } else if (strncmp(rdc
->mode
, "async", NSC_MAXPATH
) == 0) {
415 rdccfg
.options
|= RDC_OPT_ASYNC
;
417 rdc_set_error(NULL
, RDC_INTERNAL
, RDC_NONFATAL
,
422 populate_addrs(&rdccfg
.rdc_set
[0], 1);
424 if (can_enable(rdcp
)) {
425 /* do the operation */
426 *rcp
= rdc_config(&rdccfg
);
428 } else { /* set up what rdc_config would've set up */
430 populate_rc(rcp
, rdcp
);
433 if ((rcp
->rc
== 0) && (!rdcp
->persist
)) {
435 * if we are not persisting, do this now,
436 * otherwise we will do it when
437 * we have a lock on the cfg in add_to_rdc_cfg
439 sv_enable(NULL
, rdcp
);
446 rcp
->next
= new_rc();
449 /* dont free here, return what you have */
455 * travel the rc chain and rdc chain checking results,
456 * building a new chain, and updating dscfg
461 cfg_rdcs
= chain_successful(rdcp
, rcp
);
463 if (add_to_rdc_cfg(cfg_rdcs
) < 0) {
464 /* XXX should disable or something here */
467 rdc_free_config(cfg_rdcs
, RDC_FREEALL
);
473 rdc_enable_clrbmp(rdcconfig_t
*rdc
)
476 rdcconfig_t
*rdcp
= NULL
;
477 rdcconfig_t
*cfg_rdcs
= NULL
;
479 rdc_rc_t
*rcp
= NULL
;
482 rc
= (rdc_rc_t
*)calloc(1, sizeof (rdc_rc_t
));
484 rdc_set_error(NULL
, RDC_OS
, RDC_FATAL
, NULL
);
490 rdc_set_error(NULL
, RDC_INTERNAL
, RDC_NONFATAL
,
494 bzero(&rdccfg
, sizeof (rdc_config_t
));
495 rdccfg
.rdc_set
[0] = config2set(rdcp
);
496 rdccfg
.command
= RDC_CMD_ENABLE
;
497 rdccfg
.options
= RDC_OPT_CLRBMP
;
498 if (strncmp(rdcp
->mode
, "sync", NSC_MAXPATH
) == 0) {
499 rdccfg
.options
|= RDC_OPT_SYNC
;
500 } else if (strncmp(rdc
->mode
, "async", NSC_MAXPATH
) == 0) {
501 rdccfg
.options
|= RDC_OPT_ASYNC
;
503 rdc_set_error(NULL
, RDC_INTERNAL
, RDC_NONFATAL
,
508 populate_addrs(&rdccfg
.rdc_set
[0], 1);
510 if (can_enable(rdcp
)) {
511 /* do the operation */
512 *rcp
= rdc_config(&rdccfg
);
514 } else { /* set up what rdc_config would've set up */
516 populate_rc(rcp
, rdcp
);
523 rcp
->next
= (rdc_rc_t
*)calloc(1, sizeof (rdc_rc_t
));
530 * travel the rc chain and rdc chain checking results,
531 * building a new chain, and updating dscfg
536 cfg_rdcs
= chain_successful(rdcp
, rcp
);
538 if (add_to_rdc_cfg(cfg_rdcs
) < 0) {
539 /* XXX should disable or something here */
542 rdc_free_config(cfg_rdcs
, RDC_FREEALL
);
549 rdc_disable(rdcconfig_t
*rdc
)
552 rdcconfig_t
*rdcp
= NULL
;
553 rdcconfig_t
*cfg_rdcs
= NULL
;
555 rdc_rc_t
*rcp
= NULL
;
566 bzero(&rdccfg
, sizeof (rdc_config_t
));
567 rdccfg
.rdc_set
[0] = config2set(rdcp
);
568 rdccfg
.command
= RDC_CMD_DISABLE
;
569 populate_addrs(&rdccfg
.rdc_set
[0], 0);
571 *rcp
= rdc_config(&rdccfg
);
577 rcp
->next
= new_rc();
586 cfg_rdcs
= chain_successful(rdcp
, rcp
);
588 remove_from_rdc_cfg(cfg_rdcs
);
590 rdc_free_config(cfg_rdcs
, RDC_FREEALL
);
596 rdc_log(rdcconfig_t
*rdc
)
599 rdcconfig_t
*rdcp
= NULL
;
601 rdc_rc_t
*rcp
= NULL
;
611 bzero(&rdccfg
, sizeof (rdc_config_t
));
612 rdccfg
.rdc_set
[0] = config2set(rdcp
);
613 rdccfg
.command
= RDC_CMD_LOG
;
614 populate_addrs(&rdccfg
.rdc_set
[0], 0);
616 *rcp
= rdc_config(&rdccfg
);
622 rcp
->next
= new_rc();
631 rdc_usync(rdcconfig_t
*rdc
)
633 rdc_config_t
*rdccfg
;
634 rdcconfig_t
*rdcp
= NULL
;
636 rdc_rc_t
*rcp
= NULL
;
643 /* freed in rdc_mtconfig */
644 rdccfg
= (rdc_config_t
*)calloc(1, sizeof (rdc_config_t
));
645 rdccfg
->rdc_set
[0] = config2set(rdcp
);
646 rdccfg
->command
= RDC_CMD_COPY
;
647 rdccfg
->options
= RDC_OPT_UPDATE
|RDC_OPT_FORWARD
;
648 populate_addrs(&rdccfg
->rdc_set
[0], 0);
649 trc
= thr_create(NULL
, 0, rdc_mtconfig
,
650 (void **) rdccfg
, THR_BOUND
, NULL
);
658 * collect status here from thr_join-status,
659 * and add to rdc_rc_t chain ?
660 * this will block, but caller could always thread too
662 while (thr_join(NULL
, NULL
, (void**) &tmprc
) == 0) {
664 rcp
= rc
= (rdc_rc_t
*)tmprc
;
666 rcp
->next
= (rdc_rc_t
*)tmprc
;
675 rdc_fsync(rdcconfig_t
*rdc
)
677 rdc_config_t
*rdccfg
;
678 rdcconfig_t
*rdcp
= NULL
;
680 rdc_rc_t
*rcp
= NULL
;
681 rdc_rc_t
*tmprc
= NULL
;
692 /* freed in rdc_mtconfig */
693 rdccfg
= (rdc_config_t
*)calloc(1, sizeof (rdc_config_t
));
694 rdccfg
->rdc_set
[0] = config2set(rdcp
);
695 rdccfg
->command
= RDC_CMD_COPY
;
696 rdccfg
->options
= RDC_OPT_FULL
|RDC_OPT_FORWARD
;
697 populate_addrs(&rdccfg
->rdc_set
[0], 0);
698 trc
= thr_create(NULL
, 0, rdc_mtconfig
,
699 (void **) rdccfg
, THR_BOUND
, NULL
);
707 * collect status here from thr_join-status,
708 * and add to rdc_rc_t chain ?
709 * this will block, but caller could always thread too
711 while (thr_join(NULL
, NULL
, (void**) &tmprc
) == 0) {
713 rcp
= rc
= (rdc_rc_t
*)tmprc
;
715 rcp
->next
= (rdc_rc_t
*)tmprc
;
724 rdc_rsync(rdcconfig_t
*rdc
)
726 rdc_config_t
*rdccfg
;
727 rdcconfig_t
*rdcp
= NULL
;
729 rdc_rc_t
*rcp
= NULL
;
730 rdc_rc_t
*tmprc
= NULL
;
741 tmprc
= cant_rsync(rdcp
);
752 /* freed in rdc_mtconfig */
753 rdccfg
= (rdc_config_t
*)calloc(1, sizeof (rdc_config_t
));
754 rdccfg
->rdc_set
[0] = config2set(rdcp
);
755 rdccfg
->command
= RDC_CMD_COPY
;
756 rdccfg
->options
= RDC_OPT_REVERSE
|RDC_OPT_FULL
;
757 populate_addrs(&rdccfg
->rdc_set
[0], 0);
758 trc
= thr_create(NULL
, 0, rdc_mtconfig
,
759 (void **) rdccfg
, THR_BOUND
, NULL
);
767 * collect status here from thr_join-status,
768 * and add to rdc_rc_t chain ?
769 * this will block, but caller could always thread too
771 while (thr_join(NULL
, NULL
, (void**) &tmprc
) == 0) {
773 rcp
= rc
= (rdc_rc_t
*)tmprc
;
775 rcp
->next
= (rdc_rc_t
*)tmprc
;
784 rdc_ursync(rdcconfig_t
*rdc
)
786 rdc_config_t
*rdccfg
;
787 rdcconfig_t
*rdcp
= NULL
;
789 rdc_rc_t
*rcp
= NULL
;
790 rdc_rc_t
*tmprc
= NULL
;
796 tmprc
= cant_rsync(rdcp
);
807 /* freed in rdc_mtconfig */
808 rdccfg
= (rdc_config_t
*)calloc(1, sizeof (rdc_config_t
));
809 rdccfg
->rdc_set
[0] = config2set(rdcp
);
810 rdccfg
->command
= RDC_CMD_COPY
;
811 rdccfg
->options
= RDC_OPT_REVERSE
| RDC_OPT_UPDATE
;
812 populate_addrs(&rdccfg
->rdc_set
[0], 0);
813 trc
= thr_create(NULL
, 0, rdc_mtconfig
,
814 (void **) rdccfg
, THR_BOUND
, NULL
);
823 * collect status here from thr_join-status,
824 * and add to rdc_rc_t chain ?
825 * this will block, but caller could always thread too
827 while (thr_join(NULL
, NULL
, (void**) &tmprc
) == 0) {
829 rcp
= rc
= (rdc_rc_t
*)tmprc
;
831 rcp
->next
= (rdc_rc_t
*)tmprc
;
840 rdc_wait(rdcconfig_t
*rdc
)
843 rdcconfig_t
*rdcp
= NULL
;
845 rdc_rc_t
*rcp
= NULL
;
855 bzero(&rdccfg
, sizeof (rdc_config_t
));
856 rdccfg
.rdc_set
[0] = config2set(rdcp
);
857 rdccfg
.command
= RDC_CMD_WAIT
;
858 populate_addrs(&rdccfg
.rdc_set
[0], 0);
860 *rcp
= rdc_config(&rdccfg
);
866 rcp
->next
= new_rc();
875 rdc_set_autosync(rdcconfig_t
*rdc
, int autosync
)
878 rdcconfig_t
*rdcp
= NULL
;
880 rdc_rc_t
*rcp
= NULL
;
890 bzero(&rdccfg
, sizeof (rdc_config_t
));
891 rdccfg
.rdc_set
[0] = config2set(rdcp
);
892 rdccfg
.command
= RDC_CMD_TUNABLE
;
893 rdccfg
.rdc_set
[0].autosync
= autosync
;
894 rdccfg
.rdc_set
[0].maxqitems
= -1;
895 rdccfg
.rdc_set
[0].maxqfbas
= -1;
896 populate_addrs(&rdccfg
.rdc_set
[0], 0);
898 *rcp
= rdc_config(&rdccfg
);
904 rcp
->next
= new_rc();
913 rdc_set_maxqfbas(rdcconfig_t
*rdc
, int maxqfbas
)
916 rdcconfig_t
*rdcp
= NULL
;
918 rdc_rc_t
*rcp
= NULL
;
928 bzero(&rdccfg
, sizeof (rdc_config_t
));
929 rdccfg
.rdc_set
[0] = config2set(rdcp
);
930 rdccfg
.command
= RDC_CMD_TUNABLE
;
931 rdccfg
.rdc_set
[0].autosync
= -1;
932 rdccfg
.rdc_set
[0].maxqitems
= -1;
933 rdccfg
.rdc_set
[0].maxqfbas
= maxqfbas
;
934 populate_addrs(&rdccfg
.rdc_set
[0], 0);
936 *rcp
= rdc_config(&rdccfg
);
942 rcp
->next
= new_rc();
951 rdc_set_maxqitems(rdcconfig_t
*rdc
, int maxqitems
)
954 rdcconfig_t
*rdcp
= NULL
;
956 rdc_rc_t
*rcp
= NULL
;
967 bzero(&rdccfg
, sizeof (rdc_config_t
));
968 rdccfg
.rdc_set
[0] = config2set(rdc
);
969 rdccfg
.command
= RDC_CMD_TUNABLE
;
970 rdccfg
.rdc_set
[0].autosync
= -1;
971 rdccfg
.rdc_set
[0].maxqitems
= maxqitems
;
972 rdccfg
.rdc_set
[0].maxqfbas
= -1;
973 populate_addrs(&rdccfg
.rdc_set
[0], 0);
975 *rcp
= rdc_config(&rdccfg
);
981 rcp
->next
= new_rc();
990 rdc_status(rdcconfig_t
*rdc
)
994 bzero(&rdccfg
, sizeof (rdc_config_t
));
995 rdccfg
.rdc_set
[0] = config2set(rdc
);
996 rdccfg
.command
= RDC_CMD_STATUS
;
997 populate_addrs(&rdccfg
.rdc_set
[0], 0);
1000 return (rdccfg
.rdc_set
[0]);
1004 rdc_get_autosync(rdcconfig_t
*rdc
)
1008 rdcset
= rdc_status(rdc
);
1009 return (rdcset
.autosync
);
1013 rdc_get_maxqfbas(rdcconfig_t
*rdc
)
1017 rdcset
= rdc_status(rdc
);
1018 return (rdcset
.maxqfbas
);
1023 rdc_get_maxqitems(rdcconfig_t
*rdc
)
1027 rdcset
= rdc_status(rdc
);
1028 return (rdcset
.maxqitems
);
1033 set_mode(rdcconfig_t
*rdc
)
1035 if (strcmp(rdc
->mode
, "async") == 0)
1036 return (RDC_OPT_ASYNC
);
1038 return (RDC_OPT_SYNC
);
1042 * reconfig bitmaps are single set only ops
1043 * for obvious reasons
1046 rdc_reconfig_pbmp(rdcconfig_t
*rdc
, char *pbmp
)
1048 rdc_config_t rdccfg
;
1052 if ((!rc
) || (!pbmp
))
1055 bzero(&rdccfg
, sizeof (rdc_config_t
));
1056 rdccfg
.rdc_set
[0] = config2set(rdc
);
1057 strncpy(rdccfg
.rdc_set
[0].primary
.bitmap
, pbmp
, NSC_MAXPATH
);
1058 rdccfg
.command
= RDC_CMD_RECONFIG
;
1059 rdccfg
.options
|= set_mode(rdc
);
1060 populate_addrs(&rdccfg
.rdc_set
[0], 0);
1062 if (can_reconfig_pbmp(rdc
, pbmp
))
1063 *rc
= rdc_config(&rdccfg
);
1065 populate_rc(rc
, rdc
);
1067 if ((rc
->rc
== 0) && (rdc
->persist
))
1068 if (replace_cfgfield(rdc
, "pbitmap", pbmp
) < 0) {
1070 strncpy(rc
->msg
, rdc_error(NULL
), RDC_ERR_SIZE
);
1076 rdc_reconfig_sbmp(rdcconfig_t
*rdc
, char *sbmp
)
1078 rdc_config_t rdccfg
;
1085 bzero(&rdccfg
, sizeof (rdc_config_t
));
1086 rdccfg
.rdc_set
[0] = config2set(rdc
);
1087 strncpy(rdccfg
.rdc_set
[0].secondary
.bitmap
, sbmp
, NSC_MAXPATH
);
1088 rdccfg
.command
= RDC_CMD_RECONFIG
;
1089 rdccfg
.options
|= set_mode(rdc
);
1090 populate_addrs(&rdccfg
.rdc_set
[0], 0);
1092 if (can_reconfig_sbmp(rdc
, sbmp
))
1093 *rc
= rdc_config(&rdccfg
);
1095 populate_rc(rc
, rdc
);
1097 if ((rc
->rc
== 0) && (rdc
->persist
))
1098 replace_cfgfield(rdc
, "sbitmap", sbmp
);
1104 rdc_reconfig_group(rdcconfig_t
*rdc
, char *group
)
1106 rdc_config_t rdccfg
;
1107 rdcconfig_t
*rdcp
= NULL
;
1108 rdcconfig_t
*cfg_rdcs
= NULL
;
1109 rdc_rc_t
*rc
= NULL
;
1110 rdc_rc_t
*rcp
= NULL
;
1120 bzero(&rdccfg
, sizeof (rdc_config_t
));
1122 strncpy(rdcp
->group
, group
, NSC_MAXPATH
);
1123 rdccfg
.rdc_set
[0] = config2set(rdcp
);
1124 rdccfg
.command
= RDC_CMD_RECONFIG
;
1125 rdccfg
.options
|= set_mode(rdcp
);
1126 populate_addrs(&rdccfg
.rdc_set
[0], 0);
1128 /* reconfig group rules enforced in kernel */
1129 *rcp
= rdc_config(&rdccfg
);
1135 rcp
->next
= new_rc();
1142 cfg_rdcs
= chain_successful(rdcp
, rcp
);
1143 replace_cfgfield(cfg_rdcs
, "group", group
);
1144 rdc_free_config(cfg_rdcs
, RDC_FREEALL
);
1150 rdc_reconfig_ctag(rdcconfig_t
*rdc
, char *ctag
)
1156 rdc_set_sync(rdcconfig_t
*rdc
)
1158 rdc_config_t rdccfg
;
1159 rdcconfig_t
*rdcp
= NULL
;
1160 rdcconfig_t
*cfg_rdcs
= NULL
;
1161 rdc_rc_t
*rc
= NULL
;
1162 rdc_rc_t
*rcp
= NULL
;
1172 bzero(&rdccfg
, sizeof (rdc_config_t
));
1173 rdccfg
.rdc_set
[0] = config2set(rdc
);
1174 rdccfg
.command
= RDC_CMD_RECONFIG
;
1175 rdccfg
.options
|= RDC_OPT_SYNC
;
1176 populate_addrs(&rdccfg
.rdc_set
[0], 0);
1178 *rcp
= rdc_config(&rdccfg
);
1184 rcp
->next
= new_rc();
1192 cfg_rdcs
= chain_successful(rdcp
, rcp
);
1193 replace_cfgfield(cfg_rdcs
, "mode", "sync");
1194 rdc_free_config(cfg_rdcs
, RDC_FREEALL
);
1200 rdc_set_async(rdcconfig_t
*rdc
)
1202 rdc_config_t rdccfg
;
1203 rdcconfig_t
*rdcp
= NULL
;
1204 rdcconfig_t
*cfg_rdcs
= NULL
;
1205 rdc_rc_t
*rc
= NULL
;
1206 rdc_rc_t
*rcp
= NULL
;
1216 bzero(&rdccfg
, sizeof (rdc_config_t
));
1217 rdccfg
.rdc_set
[0] = config2set(rdcp
);
1218 rdccfg
.command
= RDC_CMD_RECONFIG
;
1219 rdccfg
.options
|= RDC_OPT_ASYNC
;
1220 populate_addrs(&rdccfg
.rdc_set
[0], 0);
1222 *rcp
= rdc_config(&rdccfg
);
1228 rcp
->next
= new_rc();
1235 cfg_rdcs
= chain_successful(rdcp
, rcp
);
1236 replace_cfgfield(cfg_rdcs
, "mode", "async");
1237 rdc_free_config(cfg_rdcs
, RDC_FREEALL
);
1243 rdc_health(rdcconfig_t
*rdc
)
1245 rdc_config_t rdccfg
;
1246 rdcconfig_t
*rdcp
= NULL
;
1247 rdc_rc_t
*rc
= NULL
;
1248 rdc_rc_t
*rcp
= NULL
;
1258 bzero(&rdccfg
, sizeof (rdc_config_t
));
1259 rdccfg
.rdc_set
[0] = config2set(rdcp
);
1260 rdccfg
.command
= RDC_CMD_HEALTH
;
1261 populate_addrs(&rdccfg
.rdc_set
[0], 0);
1263 *rcp
= rdc_config(&rdccfg
);
1269 rcp
->next
= new_rc();
1280 rdc_reverse_role(rdcconfig_t
*rdc
)
1282 rdc_config_t rdccfg
;
1283 rdcconfig_t
*rdcp
= NULL
;
1284 rdcconfig_t
*cfg_rdcs
= NULL
;
1285 rdc_rc_t
*rc
= NULL
;
1286 rdc_rc_t
*rcp
= NULL
;
1296 bzero(&rdccfg
, sizeof (rdc_config_t
));
1297 rdccfg
.rdc_set
[0] = config2set(rdcp
);
1298 rdccfg
.command
= RDC_CMD_RECONFIG
;
1299 rdccfg
.options
|= RDC_OPT_REVERSE_ROLE
;
1300 rdccfg
.options
|= set_mode(rdcp
);
1301 populate_addrs(&rdccfg
.rdc_set
[0], 0);
1303 *rcp
= rdc_config(&rdccfg
);
1309 rcp
->next
= new_rc();
1316 cfg_rdcs
= chain_successful(rdcp
, rcp
);
1317 reverse_in_cfg(cfg_rdcs
);
1318 rdc_free_config(cfg_rdcs
, RDC_FREEALL
);