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
27 #include <sys/types.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <strings.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <netdb.h>
34 #include <sys/stream.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <ctype.h>
39 #include <thread.h>
40 #include <pthread.h>
41
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>
46
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>
54
55 #include <sys/unistat/spcs_dtrinkets.h>
56 #include <sys/unistat/spcs_etrinkets.h>
57
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>
63 #include <rpc/rpc.h>
64
65 struct netbuf svaddr, *svp;
66 struct netconfig nconf, *conf;
67 struct knetconfig knconf;
68
69 /*
70 * libdscfg type stuff here
71 */
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);
77
78 rdcconfig_t *
rdc_dup_config(rdcconfig_t * orig)79 rdc_dup_config(rdcconfig_t *orig)
80 {
81 rdcconfig_t *rc;
82
83 rc = (rdcconfig_t *)calloc(1, sizeof (*rc));
84 if (!rc) {
85 rdc_set_error(NULL, RDC_OS, RDC_FATAL, NULL);
86 return (NULL);
87 }
88
89 *rc = *orig;
90 rc->next = NULL; /* don't want to hook into wrong chaing */
91 return (rc);
92 }
93
94 /*
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
98 * chain.
99 */
100 rdcconfig_t *
chain_successful(rdcconfig_t * rdcs,rdc_rc_t * rcs)101 chain_successful(rdcconfig_t *rdcs, rdc_rc_t *rcs)
102 {
103 rdc_rc_t *rcp;
104 rdcconfig_t *rdcp;
105 rdcconfig_t *ret = NULL;
106 rdcconfig_t *retp = NULL;
107
108 rcp = rcs;
109 rdcp = rdcs;
110
111 while (rcp) {
112 if (rcp->rc == 0) {
113 if ((ret == NULL) && (rdcp->persist)) {
114 retp = ret = rdc_dup_config(rdcp);
115
116 } else if ((ret) && (rdcp->persist)) {
117 retp->next = rdc_dup_config(rdcp);
118 retp = retp->next;
119 }
120 }
121 rcp = rcp->next;
122 rdcp = rdcp->next;
123 }
124 return (ret);
125
126 }
127
128 rdc_set_t
config2set(rdcconfig_t * rdc)129 config2set(rdcconfig_t *rdc)
130 {
131 rdc_set_t urdc;
132
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);
141
142 return (urdc);
143 }
144
145 rdc_rc_t *
new_rc()146 new_rc()
147 {
148 rdc_rc_t *rc;
149
150 rc = (rdc_rc_t *)calloc(1, sizeof (*rc));
151 if (rc == NULL) {
152 rdc_set_error(NULL, RDC_OS, RDC_FATAL, NULL);
153 return (NULL);
154 }
155 return (rc);
156 }
157
158 rdc_rc_t
rdc_config(rdc_config_t * rdccfg)159 rdc_config(rdc_config_t *rdccfg)
160 {
161 rdc_rc_t rc;
162 rdc_set_t *set;
163 spcs_s_info_t ustatus;
164
165 bzero(&rc, sizeof (rc));
166 ustatus = spcs_s_ucreate();
167
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;
172 } else {
173 rdccfg->options |= RDC_OPT_SECONDARY;
174 }
175
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);
182
183 rc.rc = RDC_IOCTL(RDC_CONFIG, rdccfg, NULL, 0, 0, 0, ustatus);
184
185 if (rc.rc < 0) {
186 rdc_set_error(&ustatus, RDC_SPCS, 0, 0);
187 strncpy(rc.msg, rdc_error(NULL), RDC_ERR_SIZE);
188 }
189
190 return (rc);
191 }
192
193 void *
rdc_mtconfig(void * rdc)194 rdc_mtconfig(void *rdc)
195 {
196 rdc_rc_t *rc[1];
197 rdc_set_t *set;
198 spcs_s_info_t ustatus;
199 rdc_config_t *rdccfg = (rdc_config_t *)rdc;
200
201 ustatus = spcs_s_ucreate();
202
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;
207 } else {
208 rdccfg->options |= RDC_OPT_SECONDARY;
209 }
210
211 set = &rdccfg->rdc_set[0];
212 *rc = new_rc();
213
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);
220
221 rc[0]->rc = RDC_IOCTL(RDC_CONFIG, rdccfg, NULL, 0, 0, 0, ustatus);
222
223 if (rc[0]->rc < 0) {
224 rdc_set_error(&ustatus, RDC_SPCS, 0, 0);
225 strncpy(rc[0]->msg, rdc_error(NULL), RDC_ERR_SIZE);
226 }
227
228 sleep(1); /* give thr_join a chance to be called */
229 free(rdccfg);
230 thr_exit((void **) *rc);
231 return (NULL);
232 }
233 int
populate_addrs(rdc_set_t * urdc,int isenable)234 populate_addrs(rdc_set_t *urdc, int isenable)
235 {
236 struct t_info tinfo;
237 struct hostent *hp;
238 char toname[MAX_RDC_HOST_SIZE];
239 char fromname[MAX_RDC_HOST_SIZE];
240
241 strncpy(fromname, urdc->primary.intf, MAX_RDC_HOST_SIZE);
242 strncpy(toname, urdc->secondary.intf, MAX_RDC_HOST_SIZE);
243
244 if ((fromname[0] == '\0') || (fromname[0] == '\0')) {
245 rdc_set_error(NULL, RDC_INTERNAL, RDC_FATAL,
246 "NULL hostname recieved");
247 return (-1);
248 }
249
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);
254
255 if (self_check(fromname) && self_check(toname)) {
256 rdc_set_error(NULL, RDC_INTERNAL, RDC_FATAL, "");
257 }
258
259 if (isenable) {
260 svp = get_addr(toname, RDC_PROGRAM, RDC_VERS_MIN,
261 &conf, NULL, "rdc", &tinfo, 0);
262 if (svp == NULL)
263 return (-1);
264 svaddr = *svp;
265 } else {
266 bzero(&svaddr, sizeof (svaddr));
267 }
268
269 urdc->secondary.addr.len = svaddr.len;
270 urdc->secondary.addr.maxlen = svaddr.maxlen;
271 urdc->secondary.addr.buf = (void*)svaddr.buf;
272
273 if (isenable) {
274 svp = get_addr(fromname, RDC_PROGRAM, RDC_VERS_MIN,
275 &conf, NULL, "rdc", &tinfo, 0);
276 if (svp == NULL)
277 return (-1);
278 svaddr = *svp;
279 } else {
280 bzero(&svaddr, sizeof (svaddr));
281 }
282
283 urdc->primary.addr.len = svaddr.len;
284 urdc->primary.addr.maxlen = svaddr.maxlen;
285 urdc->primary.addr.buf = (void*)svaddr.buf;
286
287 if (isenable) {
288 convert_nconf_to_knconf(conf, &knconf);
289 urdc->netconfig = &knconf;
290 } else {
291 urdc->netconfig = NULL;
292 }
293 urdc->syshostid = (int32_t)gethostid();
294
295 return (1);
296
297 }
298 void
rdc_free_config(rdcconfig_t * rdc,int all)299 rdc_free_config(rdcconfig_t *rdc, int all)
300 {
301 rdcconfig_t *rdcp;
302 rdcconfig_t *rdcq;
303
304 rdcp = rdc;
305 if (all == RDC_FREEONE) {
306 free(rdcp);
307 } else while (rdcp) {
308 rdcq = rdcp->next;
309 free(rdcp);
310 rdcp = rdcq;
311 }
312 rdc = NULL;
313 }
314
315 void
rdc_free_rclist(rdc_rc_t * rc)316 rdc_free_rclist(rdc_rc_t *rc) {
317 rdc_rc_t *rcp, *rcq;
318
319 rcp = rc;
320 while (rcp) {
321 rcq = rcp->next;
322 free(rcp);
323 rcp = rcq;
324 }
325
326 }
327 /*ARGSUSED*/
328 rdcconfig_t *
rdc_alloc_config(const char * phost,const char * pfile,const char * pbmp,const char * shost,const char * sfile,const char * sbmp,const char * mode,const char * group,const char * ctag,const char * options,int persist)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,
332 int persist)
333 {
334 rdcconfig_t *rc;
335
336 rc = (rdcconfig_t *)calloc(1, sizeof (*rc));
337 if (!rc) {
338 rdc_set_error(NULL, RDC_OS, RDC_FATAL, NULL);
339 return (NULL);
340 }
341 if (phost)
342 strncpy(rc->phost, phost, NSC_MAXPATH);
343 if (pfile)
344 strncpy(rc->pfile, pfile, NSC_MAXPATH);
345 if (pbmp)
346 strncpy(rc->pbmp, pbmp, NSC_MAXPATH);
347 if (shost)
348 strncpy(rc->shost, shost, NSC_MAXPATH);
349 if (sfile)
350 strncpy(rc->sfile, sfile, NSC_MAXPATH);
351 if (sbmp)
352 strncpy(rc->sbmp, sbmp, NSC_MAXPATH);
353
354 strncpy(rc->direct, "ip", 2);
355
356 if (mode)
357 strncpy(rc->mode, mode, NSC_MAXPATH);
358 if (ctag)
359 strncpy(rc->ctag, ctag, NSC_MAXPATH);
360 if (options)
361 strncpy(rc->options, options, NSC_MAXPATH);
362
363 rc->persist = persist;
364 rc->next = NULL;
365
366 return (rc);
367
368 }
369
370 void
populate_rc(rdc_rc_t * rcp,rdcconfig_t * rdcp)371 populate_rc(rdc_rc_t *rcp, rdcconfig_t *rdcp)
372 {
373 rcp->rc = -1;
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);
379 }
380
381 /*
382 * rdc_enable
383 * return values
384 * NULL on error
385 * pointer to rdc_rc_t list of return values
386 */
387 rdc_rc_t *
rdc_enable(rdcconfig_t * rdc)388 rdc_enable(rdcconfig_t *rdc)
389 {
390 rdc_config_t rdccfg;
391 rdcconfig_t *rdcp = NULL;
392 rdcconfig_t *cfg_rdcs = NULL;
393 rdc_rc_t *rc = NULL;
394 rdc_rc_t *rcp = NULL;
395
396 rdcp = rdc;
397 rc = new_rc();
398 if (!rc) { /* error already set */
399 return (NULL);
400 }
401 rcp = rc;
402 while (rdcp) {
403 if (!rdcp->mode) {
404 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
405 RDC_EINVAL);
406 return (NULL);
407 }
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;
416 } else {
417 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
418 RDC_EINVAL);
419 return (NULL);
420 }
421
422 populate_addrs(&rdccfg.rdc_set[0], 1);
423
424 if (can_enable(rdcp)) {
425 /* do the operation */
426 *rcp = rdc_config(&rdccfg);
427
428 } else { /* set up what rdc_config would've set up */
429
430 populate_rc(rcp, rdcp);
431
432 }
433 if ((rcp->rc == 0) && (!rdcp->persist)) {
434 /*
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
438 */
439 sv_enable(NULL, rdcp);
440 }
441
442 rdcp = rdcp->next;
443 if (!rdcp)
444 break;
445
446 rcp->next = new_rc();
447 rcp = rcp->next;
448 if (!rcp) {
449 /* dont free here, return what you have */
450 break;
451 }
452 }
453
454 /*
455 * travel the rc chain and rdc chain checking results,
456 * building a new chain, and updating dscfg
457 */
458 rcp = rc;
459 rdcp = rdc;
460
461 cfg_rdcs = chain_successful(rdcp, rcp);
462
463 if (add_to_rdc_cfg(cfg_rdcs) < 0) {
464 /* XXX should disable or something here */
465 return (rc);
466 }
467 rdc_free_config(cfg_rdcs, RDC_FREEALL);
468 return (rc);
469
470 }
471
472 rdc_rc_t *
rdc_enable_clrbmp(rdcconfig_t * rdc)473 rdc_enable_clrbmp(rdcconfig_t *rdc)
474 {
475 rdc_config_t rdccfg;
476 rdcconfig_t *rdcp = NULL;
477 rdcconfig_t *cfg_rdcs = NULL;
478 rdc_rc_t *rc = NULL;
479 rdc_rc_t *rcp = NULL;
480
481 rdcp = rdc;
482 rc = (rdc_rc_t *)calloc(1, sizeof (rdc_rc_t));
483 if (!rc) {
484 rdc_set_error(NULL, RDC_OS, RDC_FATAL, NULL);
485 return (NULL);
486 }
487 rcp = rc;
488 while (rdcp) {
489 if (!rdcp->mode) {
490 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
491 RDC_EINVAL);
492 return (NULL);
493 }
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;
502 } else {
503 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL,
504 RDC_EINVAL);
505 return (NULL);
506 }
507
508 populate_addrs(&rdccfg.rdc_set[0], 1);
509
510 if (can_enable(rdcp)) {
511 /* do the operation */
512 *rcp = rdc_config(&rdccfg);
513
514 } else { /* set up what rdc_config would've set up */
515
516 populate_rc(rcp, rdcp);
517
518 }
519 rdcp = rdcp->next;
520 if (!rdcp)
521 break;
522
523 rcp->next = (rdc_rc_t *)calloc(1, sizeof (rdc_rc_t));
524 rcp = rcp->next;
525 if (!rcp)
526 break;
527 }
528
529 /*
530 * travel the rc chain and rdc chain checking results,
531 * building a new chain, and updating dscfg
532 */
533 rcp = rc;
534 rdcp = rdc;
535
536 cfg_rdcs = chain_successful(rdcp, rcp);
537
538 if (add_to_rdc_cfg(cfg_rdcs) < 0) {
539 /* XXX should disable or something here */
540 return (rc);
541 }
542 rdc_free_config(cfg_rdcs, RDC_FREEALL);
543
544 return (rc);
545
546 }
547
548 rdc_rc_t *
rdc_disable(rdcconfig_t * rdc)549 rdc_disable(rdcconfig_t *rdc)
550 {
551 rdc_config_t rdccfg;
552 rdcconfig_t *rdcp = NULL;
553 rdcconfig_t *cfg_rdcs = NULL;
554 rdc_rc_t *rc = NULL;
555 rdc_rc_t *rcp = NULL;
556
557 rdcp = rdc;
558 rc = new_rc();
559 if (!rc) {
560 return (NULL);
561 }
562 rcp = rc;
563
564 while (rdcp) {
565
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);
570
571 *rcp = rdc_config(&rdccfg);
572
573 rdcp = rdcp->next;
574 if (!rdcp)
575 break;
576
577 rcp->next = new_rc();
578 rcp = rcp->next;
579 if (!rcp)
580 return (rc);
581
582 }
583 rcp = rc;
584 rdcp = rdc;
585
586 cfg_rdcs = chain_successful(rdcp, rcp);
587
588 remove_from_rdc_cfg(cfg_rdcs);
589
590 rdc_free_config(cfg_rdcs, RDC_FREEALL);
591
592 return (rc);
593 }
594
595 rdc_rc_t *
rdc_log(rdcconfig_t * rdc)596 rdc_log(rdcconfig_t *rdc)
597 {
598 rdc_config_t rdccfg;
599 rdcconfig_t *rdcp = NULL;
600 rdc_rc_t *rc = NULL;
601 rdc_rc_t *rcp = NULL;
602
603 rdcp = rdc;
604 rc = new_rc();
605 if (!rc) {
606 return (NULL);
607 }
608 rcp = rc;
609
610 while (rdcp) {
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);
615
616 *rcp = rdc_config(&rdccfg);
617
618 rdcp = rdcp->next;
619 if (!rdcp)
620 break;
621
622 rcp->next = new_rc();
623 rcp = rcp->next;
624 if (!rcp)
625 break;
626 }
627 return (rc);
628 }
629
630 rdc_rc_t *
rdc_usync(rdcconfig_t * rdc)631 rdc_usync(rdcconfig_t *rdc)
632 {
633 rdc_config_t *rdccfg;
634 rdcconfig_t *rdcp = NULL;
635 rdc_rc_t *rc = NULL;
636 rdc_rc_t *rcp = NULL;
637 rdc_rc_t *tmprc;
638 int trc;
639
640 rdcp = rdc;
641
642 while (rdcp) {
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);
651 rdcp = rdcp->next;
652 if (!rdcp)
653 break;
654
655 }
656
657 /*
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
661 */
662 while (thr_join(NULL, NULL, (void**) &tmprc) == 0) {
663 if (rc == NULL) {
664 rcp = rc = (rdc_rc_t *)tmprc;
665 } else {
666 rcp->next = (rdc_rc_t *)tmprc;
667 rcp = rcp->next;
668 }
669 }
670
671 return (rc);
672 }
673
674 rdc_rc_t *
rdc_fsync(rdcconfig_t * rdc)675 rdc_fsync(rdcconfig_t *rdc)
676 {
677 rdc_config_t *rdccfg;
678 rdcconfig_t *rdcp = NULL;
679 rdc_rc_t *rc = NULL;
680 rdc_rc_t *rcp = NULL;
681 rdc_rc_t *tmprc = NULL;
682 int trc;
683
684 rdcp = rdc;
685 rc = new_rc();
686 if (!rc) {
687 return (NULL);
688 }
689 rcp = rc;
690
691 while (rdcp) {
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);
700 rdcp = rdcp->next;
701 if (!rdcp)
702 break;
703
704 }
705
706 /*
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
710 */
711 while (thr_join(NULL, NULL, (void**) &tmprc) == 0) {
712 if (rc == NULL) {
713 rcp = rc = (rdc_rc_t *)tmprc;
714 } else {
715 rcp->next = (rdc_rc_t *)tmprc;
716 rcp = rcp->next;
717 }
718 }
719
720 return (rc);
721 }
722
723 rdc_rc_t *
rdc_rsync(rdcconfig_t * rdc)724 rdc_rsync(rdcconfig_t *rdc)
725 {
726 rdc_config_t *rdccfg;
727 rdcconfig_t *rdcp = NULL;
728 rdc_rc_t *rc = NULL;
729 rdc_rc_t *rcp = NULL;
730 rdc_rc_t *tmprc = NULL;
731 int trc;
732
733 rdcp = rdc;
734 rc = new_rc();
735 if (!rc) {
736 return (NULL);
737 }
738 rcp = rc;
739
740 while (rdcp) {
741 tmprc = cant_rsync(rdcp);
742 if (tmprc != NULL) {
743 if (rc == NULL) {
744 rcp = rc = tmprc;
745 } else {
746 rcp->next = tmprc;
747 rcp = rcp->next;
748 }
749 goto next;
750 }
751
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);
760 next:
761 rdcp = rdcp->next;
762 if (!rdcp)
763 break;
764 }
765
766 /*
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
770 */
771 while (thr_join(NULL, NULL, (void**) &tmprc) == 0) {
772 if (rc == NULL) {
773 rcp = rc = (rdc_rc_t *)tmprc;
774 } else {
775 rcp->next = (rdc_rc_t *)tmprc;
776 rcp = rcp->next;
777 }
778 }
779
780 return (rc);
781 }
782
783 rdc_rc_t *
rdc_ursync(rdcconfig_t * rdc)784 rdc_ursync(rdcconfig_t *rdc)
785 {
786 rdc_config_t *rdccfg;
787 rdcconfig_t *rdcp = NULL;
788 rdc_rc_t *rc = NULL;
789 rdc_rc_t *rcp = NULL;
790 rdc_rc_t *tmprc = NULL;
791 int trc;
792
793 rdcp = rdc;
794
795 while (rdcp) {
796 tmprc = cant_rsync(rdcp);
797 if (tmprc != NULL) {
798 if (rc == NULL) {
799 rcp = rc = tmprc;
800 } else {
801 rcp->next = tmprc;
802 rcp = rcp->next;
803 }
804 goto next;
805 }
806
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);
815 next:
816 rdcp = rdcp->next;
817 if (!rdcp)
818 break;
819
820 }
821
822 /*
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
826 */
827 while (thr_join(NULL, NULL, (void**) &tmprc) == 0) {
828 if (rc == NULL) {
829 rcp = rc = (rdc_rc_t *)tmprc;
830 } else {
831 rcp->next = (rdc_rc_t *)tmprc;
832 rcp = rcp->next;
833 }
834 }
835
836 return (rc);
837 }
838
839 rdc_rc_t *
rdc_wait(rdcconfig_t * rdc)840 rdc_wait(rdcconfig_t *rdc)
841 {
842 rdc_config_t rdccfg;
843 rdcconfig_t *rdcp = NULL;
844 rdc_rc_t *rc = NULL;
845 rdc_rc_t *rcp = NULL;
846
847 rdcp = rdc;
848 rc = new_rc();
849 if (!rc) {
850 return (NULL);
851 }
852 rcp = rc;
853
854 while (rdcp) {
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);
859
860 *rcp = rdc_config(&rdccfg);
861
862 rdcp = rdcp->next;
863 if (!rdcp)
864 break;
865
866 rcp->next = new_rc();
867 rcp = rcp->next;
868 if (!rcp)
869 break;
870 }
871 return (rc);
872 }
873
874 rdc_rc_t *
rdc_set_autosync(rdcconfig_t * rdc,int autosync)875 rdc_set_autosync(rdcconfig_t *rdc, int autosync)
876 {
877 rdc_config_t rdccfg;
878 rdcconfig_t *rdcp = NULL;
879 rdc_rc_t *rc = NULL;
880 rdc_rc_t *rcp = NULL;
881
882 rdcp = rdc;
883 rc = new_rc();
884 if (!rc) {
885 return (NULL);
886 }
887 rcp = rc;
888
889 while (rdcp) {
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);
897
898 *rcp = rdc_config(&rdccfg);
899
900 rdcp = rdcp->next;
901 if (!rdcp)
902 break;
903
904 rcp->next = new_rc();
905 rcp = rcp->next;
906 if (!rcp)
907 break;
908 }
909 return (rc);
910 }
911
912 rdc_rc_t *
rdc_set_maxqfbas(rdcconfig_t * rdc,int maxqfbas)913 rdc_set_maxqfbas(rdcconfig_t *rdc, int maxqfbas)
914 {
915 rdc_config_t rdccfg;
916 rdcconfig_t *rdcp = NULL;
917 rdc_rc_t *rc = NULL;
918 rdc_rc_t *rcp = NULL;
919
920 rdcp = rdc;
921 rc = new_rc();
922 if (!rc) {
923 return (NULL);
924 }
925 rcp = rc;
926
927 while (rdcp) {
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);
935
936 *rcp = rdc_config(&rdccfg);
937
938 rdcp = rdcp->next;
939 if (!rdcp)
940 break;
941
942 rcp->next = new_rc();
943 rcp = rcp->next;
944 if (!rcp)
945 break;
946 }
947 return (rc);
948 }
949
950 rdc_rc_t *
rdc_set_maxqitems(rdcconfig_t * rdc,int maxqitems)951 rdc_set_maxqitems(rdcconfig_t *rdc, int maxqitems)
952 {
953 rdc_config_t rdccfg;
954 rdcconfig_t *rdcp = NULL;
955 rdc_rc_t *rc = NULL;
956 rdc_rc_t *rcp = NULL;
957
958 rdcp = rdc;
959 rc = new_rc();
960
961 if (!rc) {
962 return (NULL);
963 }
964 rcp = rc;
965
966 while (rdcp) {
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);
974
975 *rcp = rdc_config(&rdccfg);
976
977 rdcp = rdcp->next;
978 if (!rdcp)
979 break;
980
981 rcp->next = new_rc();
982 rcp = rcp->next;
983 if (!rcp)
984 break;
985 }
986 return (rc);
987 }
988
989 rdc_set_t
rdc_status(rdcconfig_t * rdc)990 rdc_status(rdcconfig_t *rdc)
991 {
992 rdc_config_t rdccfg;
993
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);
998 rdc_config(&rdccfg);
999
1000 return (rdccfg.rdc_set[0]);
1001 }
1002
1003 int
rdc_get_autosync(rdcconfig_t * rdc)1004 rdc_get_autosync(rdcconfig_t *rdc)
1005 {
1006 rdc_set_t rdcset;
1007
1008 rdcset = rdc_status(rdc);
1009 return (rdcset.autosync);
1010 }
1011
1012 int
rdc_get_maxqfbas(rdcconfig_t * rdc)1013 rdc_get_maxqfbas(rdcconfig_t *rdc)
1014 {
1015 rdc_set_t rdcset;
1016
1017 rdcset = rdc_status(rdc);
1018 return (rdcset.maxqfbas);
1019
1020 }
1021
1022 int
rdc_get_maxqitems(rdcconfig_t * rdc)1023 rdc_get_maxqitems(rdcconfig_t *rdc)
1024 {
1025 rdc_set_t rdcset;
1026
1027 rdcset = rdc_status(rdc);
1028 return (rdcset.maxqitems);
1029
1030 }
1031
1032 int
set_mode(rdcconfig_t * rdc)1033 set_mode(rdcconfig_t *rdc)
1034 {
1035 if (strcmp(rdc->mode, "async") == 0)
1036 return (RDC_OPT_ASYNC);
1037 else
1038 return (RDC_OPT_SYNC);
1039 }
1040
1041 /*
1042 * reconfig bitmaps are single set only ops
1043 * for obvious reasons
1044 */
1045 rdc_rc_t *
rdc_reconfig_pbmp(rdcconfig_t * rdc,char * pbmp)1046 rdc_reconfig_pbmp(rdcconfig_t *rdc, char *pbmp)
1047 {
1048 rdc_config_t rdccfg;
1049 rdc_rc_t *rc;
1050
1051 rc = new_rc();
1052 if ((!rc) || (!pbmp))
1053 return (NULL);
1054
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);
1061
1062 if (can_reconfig_pbmp(rdc, pbmp))
1063 *rc = rdc_config(&rdccfg);
1064 else
1065 populate_rc(rc, rdc);
1066
1067 if ((rc->rc == 0) && (rdc->persist))
1068 if (replace_cfgfield(rdc, "pbitmap", pbmp) < 0) {
1069 rc->rc = -1;
1070 strncpy(rc->msg, rdc_error(NULL), RDC_ERR_SIZE);
1071 }
1072 return (rc);
1073 }
1074
1075 rdc_rc_t *
rdc_reconfig_sbmp(rdcconfig_t * rdc,char * sbmp)1076 rdc_reconfig_sbmp(rdcconfig_t *rdc, char *sbmp)
1077 {
1078 rdc_config_t rdccfg;
1079 rdc_rc_t *rc;
1080
1081 rc = new_rc();
1082 if (!rc)
1083 return (NULL);
1084
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);
1091
1092 if (can_reconfig_sbmp(rdc, sbmp))
1093 *rc = rdc_config(&rdccfg);
1094 else
1095 populate_rc(rc, rdc);
1096
1097 if ((rc->rc == 0) && (rdc->persist))
1098 replace_cfgfield(rdc, "sbitmap", sbmp);
1099
1100 return (rc);
1101 }
1102
1103 rdc_rc_t *
rdc_reconfig_group(rdcconfig_t * rdc,char * group)1104 rdc_reconfig_group(rdcconfig_t *rdc, char *group)
1105 {
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;
1111
1112 rdcp = rdc;
1113 rc = new_rc();
1114 if (!rc) {
1115 return (NULL);
1116 }
1117 rcp = rc;
1118
1119 while (rdcp) {
1120 bzero(&rdccfg, sizeof (rdc_config_t));
1121 /* just in case */
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);
1127
1128 /* reconfig group rules enforced in kernel */
1129 *rcp = rdc_config(&rdccfg);
1130
1131 rdcp = rdcp->next;
1132 if (!rdcp)
1133 break;
1134
1135 rcp->next = new_rc();
1136 rcp = rcp->next;
1137 if (!rcp)
1138 break;
1139 }
1140 rcp = rc;
1141 rdcp = rdc;
1142 cfg_rdcs = chain_successful(rdcp, rcp);
1143 replace_cfgfield(cfg_rdcs, "group", group);
1144 rdc_free_config(cfg_rdcs, RDC_FREEALL);
1145
1146 return (rc);
1147 }
1148 /*ARGSUSED*/
1149 rdc_rc_t *
rdc_reconfig_ctag(rdcconfig_t * rdc,char * ctag)1150 rdc_reconfig_ctag(rdcconfig_t *rdc, char *ctag)
1151 {
1152 return (NULL);
1153 }
1154
1155 rdc_rc_t *
rdc_set_sync(rdcconfig_t * rdc)1156 rdc_set_sync(rdcconfig_t *rdc)
1157 {
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;
1163
1164 rdcp = rdc;
1165 rc = new_rc();
1166 if (!rc) {
1167 return (NULL);
1168 }
1169 rcp = rc;
1170
1171 while (rdcp) {
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);
1177
1178 *rcp = rdc_config(&rdccfg);
1179
1180 rdcp = rdcp->next;
1181 if (!rdcp)
1182 break;
1183
1184 rcp->next = new_rc();
1185 rcp = rcp->next;
1186 if (!rcp)
1187 break;
1188 }
1189
1190 rcp = rc;
1191 rdcp = rdc;
1192 cfg_rdcs = chain_successful(rdcp, rcp);
1193 replace_cfgfield(cfg_rdcs, "mode", "sync");
1194 rdc_free_config(cfg_rdcs, RDC_FREEALL);
1195
1196 return (rc);
1197 }
1198
1199 rdc_rc_t *
rdc_set_async(rdcconfig_t * rdc)1200 rdc_set_async(rdcconfig_t *rdc)
1201 {
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;
1207
1208 rdcp = rdc;
1209 rc = new_rc();
1210 if (!rc) {
1211 return (NULL);
1212 }
1213 rcp = rc;
1214
1215 while (rdcp) {
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);
1221
1222 *rcp = rdc_config(&rdccfg);
1223
1224 rdcp = rdcp->next;
1225 if (!rdcp)
1226 break;
1227
1228 rcp->next = new_rc();
1229 rcp = rcp->next;
1230 if (!rcp)
1231 break;
1232 }
1233 rcp = rc;
1234 rdcp = rdc;
1235 cfg_rdcs = chain_successful(rdcp, rcp);
1236 replace_cfgfield(cfg_rdcs, "mode", "async");
1237 rdc_free_config(cfg_rdcs, RDC_FREEALL);
1238
1239 return (rc);
1240 }
1241
1242 rdc_rc_t *
rdc_health(rdcconfig_t * rdc)1243 rdc_health(rdcconfig_t *rdc)
1244 {
1245 rdc_config_t rdccfg;
1246 rdcconfig_t *rdcp = NULL;
1247 rdc_rc_t *rc = NULL;
1248 rdc_rc_t *rcp = NULL;
1249
1250 rdcp = rdc;
1251 rc = new_rc();
1252 if (!rc) {
1253 return (NULL);
1254 }
1255 rcp = rc;
1256
1257 while (rdcp) {
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);
1262
1263 *rcp = rdc_config(&rdccfg);
1264
1265 rdcp = rdcp->next;
1266 if (!rdcp)
1267 break;
1268
1269 rcp->next = new_rc();
1270 rcp = rcp->next;
1271
1272 if (!rcp)
1273 break;
1274
1275 }
1276 return (rc);
1277 }
1278
1279 rdc_rc_t *
rdc_reverse_role(rdcconfig_t * rdc)1280 rdc_reverse_role(rdcconfig_t *rdc)
1281 {
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;
1287
1288 rdcp = rdc;
1289 rc = new_rc();
1290 if (!rc) {
1291 return (NULL);
1292 }
1293 rcp = rc;
1294
1295 while (rdcp) {
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);
1302
1303 *rcp = rdc_config(&rdccfg);
1304
1305 rdcp = rdcp->next;
1306 if (!rdcp)
1307 break;
1308
1309 rcp->next = new_rc();
1310 rcp = rcp->next;
1311 if (!rcp)
1312 break;
1313 }
1314 rcp = rc;
1315 rdcp = rdc;
1316 cfg_rdcs = chain_successful(rdcp, rcp);
1317 reverse_in_cfg(cfg_rdcs);
1318 rdc_free_config(cfg_rdcs, RDC_FREEALL);
1319
1320 return (rc);
1321 }
1322