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 * 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 * 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 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 * 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 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 * 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 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 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 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 * 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 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 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 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 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 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 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 * 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 * 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 * 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 * 1150 rdc_reconfig_ctag(rdcconfig_t *rdc, char *ctag) 1151 { 1152 return (NULL); 1153 } 1154 1155 rdc_rc_t * 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 * 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 * 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 * 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