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 { 318 rdc_rc_t *rcp, *rcq; 319 320 rcp = rc; 321 while (rcp) { 322 rcq = rcp->next; 323 free(rcp); 324 rcp = rcq; 325 } 326 327 } 328 /*ARGSUSED*/ 329 rdcconfig_t * 330 rdc_alloc_config(const char *phost, const char *pfile, 331 const char *pbmp, const char *shost, const char *sfile, const char *sbmp, 332 const char *mode, const char *group, const char *ctag, const char *options, 333 int persist) 334 { 335 rdcconfig_t *rc; 336 337 rc = (rdcconfig_t *)calloc(1, sizeof (*rc)); 338 if (!rc) { 339 rdc_set_error(NULL, RDC_OS, RDC_FATAL, NULL); 340 return (NULL); 341 } 342 if (phost) 343 strncpy(rc->phost, phost, NSC_MAXPATH); 344 if (pfile) 345 strncpy(rc->pfile, pfile, NSC_MAXPATH); 346 if (pbmp) 347 strncpy(rc->pbmp, pbmp, NSC_MAXPATH); 348 if (shost) 349 strncpy(rc->shost, shost, NSC_MAXPATH); 350 if (sfile) 351 strncpy(rc->sfile, sfile, NSC_MAXPATH); 352 if (sbmp) 353 strncpy(rc->sbmp, sbmp, NSC_MAXPATH); 354 355 strncpy(rc->direct, "ip", 2); 356 357 if (mode) 358 strncpy(rc->mode, mode, NSC_MAXPATH); 359 if (ctag) 360 strncpy(rc->ctag, ctag, NSC_MAXPATH); 361 if (options) 362 strncpy(rc->options, options, NSC_MAXPATH); 363 364 rc->persist = persist; 365 rc->next = NULL; 366 367 return (rc); 368 369 } 370 371 void 372 populate_rc(rdc_rc_t *rcp, rdcconfig_t *rdcp) 373 { 374 rcp->rc = -1; 375 strncpy(rcp->msg, rdc_error(NULL), RDC_ERR_SIZE); 376 strncpy(rcp->set.phost, rdcp->phost, NSC_MAXPATH); 377 strncpy(rcp->set.pfile, rdcp->pfile, NSC_MAXPATH); 378 strncpy(rcp->set.shost, rdcp->shost, NSC_MAXPATH); 379 strncpy(rcp->set.sfile, rdcp->sfile, NSC_MAXPATH); 380 } 381 382 /* 383 * rdc_enable 384 * return values 385 * NULL on error 386 * pointer to rdc_rc_t list of return values 387 */ 388 rdc_rc_t * 389 rdc_enable(rdcconfig_t *rdc) 390 { 391 rdc_config_t rdccfg; 392 rdcconfig_t *rdcp = NULL; 393 rdcconfig_t *cfg_rdcs = NULL; 394 rdc_rc_t *rc = NULL; 395 rdc_rc_t *rcp = NULL; 396 397 rdcp = rdc; 398 rc = new_rc(); 399 if (!rc) { /* error already set */ 400 return (NULL); 401 } 402 rcp = rc; 403 while (rdcp) { 404 if (!rdcp->mode) { 405 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL, 406 RDC_EINVAL); 407 return (NULL); 408 } 409 bzero(&rdccfg, sizeof (rdc_config_t)); 410 rdccfg.rdc_set[0] = config2set(rdcp); 411 rdccfg.command = RDC_CMD_ENABLE; 412 rdccfg.options = RDC_OPT_SETBMP; 413 if (strncmp(rdcp->mode, "sync", NSC_MAXPATH) == 0) { 414 rdccfg.options |= RDC_OPT_SYNC; 415 } else if (strncmp(rdc->mode, "async", NSC_MAXPATH) == 0) { 416 rdccfg.options |= RDC_OPT_ASYNC; 417 } else { 418 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL, 419 RDC_EINVAL); 420 return (NULL); 421 } 422 423 populate_addrs(&rdccfg.rdc_set[0], 1); 424 425 if (can_enable(rdcp)) { 426 /* do the operation */ 427 *rcp = rdc_config(&rdccfg); 428 429 } else { /* set up what rdc_config would've set up */ 430 431 populate_rc(rcp, rdcp); 432 433 } 434 if ((rcp->rc == 0) && (!rdcp->persist)) { 435 /* 436 * if we are not persisting, do this now, 437 * otherwise we will do it when 438 * we have a lock on the cfg in add_to_rdc_cfg 439 */ 440 sv_enable(NULL, rdcp); 441 } 442 443 rdcp = rdcp->next; 444 if (!rdcp) 445 break; 446 447 rcp->next = new_rc(); 448 rcp = rcp->next; 449 if (!rcp) { 450 /* dont free here, return what you have */ 451 break; 452 } 453 } 454 455 /* 456 * travel the rc chain and rdc chain checking results, 457 * building a new chain, and updating dscfg 458 */ 459 rcp = rc; 460 rdcp = rdc; 461 462 cfg_rdcs = chain_successful(rdcp, rcp); 463 464 if (add_to_rdc_cfg(cfg_rdcs) < 0) { 465 /* XXX should disable or something here */ 466 return (rc); 467 } 468 rdc_free_config(cfg_rdcs, RDC_FREEALL); 469 return (rc); 470 471 } 472 473 rdc_rc_t * 474 rdc_enable_clrbmp(rdcconfig_t *rdc) 475 { 476 rdc_config_t rdccfg; 477 rdcconfig_t *rdcp = NULL; 478 rdcconfig_t *cfg_rdcs = NULL; 479 rdc_rc_t *rc = NULL; 480 rdc_rc_t *rcp = NULL; 481 482 rdcp = rdc; 483 rc = (rdc_rc_t *)calloc(1, sizeof (rdc_rc_t)); 484 if (!rc) { 485 rdc_set_error(NULL, RDC_OS, RDC_FATAL, NULL); 486 return (NULL); 487 } 488 rcp = rc; 489 while (rdcp) { 490 if (!rdcp->mode) { 491 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL, 492 RDC_EINVAL); 493 return (NULL); 494 } 495 bzero(&rdccfg, sizeof (rdc_config_t)); 496 rdccfg.rdc_set[0] = config2set(rdcp); 497 rdccfg.command = RDC_CMD_ENABLE; 498 rdccfg.options = RDC_OPT_CLRBMP; 499 if (strncmp(rdcp->mode, "sync", NSC_MAXPATH) == 0) { 500 rdccfg.options |= RDC_OPT_SYNC; 501 } else if (strncmp(rdc->mode, "async", NSC_MAXPATH) == 0) { 502 rdccfg.options |= RDC_OPT_ASYNC; 503 } else { 504 rdc_set_error(NULL, RDC_INTERNAL, RDC_NONFATAL, 505 RDC_EINVAL); 506 return (NULL); 507 } 508 509 populate_addrs(&rdccfg.rdc_set[0], 1); 510 511 if (can_enable(rdcp)) { 512 /* do the operation */ 513 *rcp = rdc_config(&rdccfg); 514 515 } else { /* set up what rdc_config would've set up */ 516 517 populate_rc(rcp, rdcp); 518 519 } 520 rdcp = rdcp->next; 521 if (!rdcp) 522 break; 523 524 rcp->next = (rdc_rc_t *)calloc(1, sizeof (rdc_rc_t)); 525 rcp = rcp->next; 526 if (!rcp) 527 break; 528 } 529 530 /* 531 * travel the rc chain and rdc chain checking results, 532 * building a new chain, and updating dscfg 533 */ 534 rcp = rc; 535 rdcp = rdc; 536 537 cfg_rdcs = chain_successful(rdcp, rcp); 538 539 if (add_to_rdc_cfg(cfg_rdcs) < 0) { 540 /* XXX should disable or something here */ 541 return (rc); 542 } 543 rdc_free_config(cfg_rdcs, RDC_FREEALL); 544 545 return (rc); 546 547 } 548 549 rdc_rc_t * 550 rdc_disable(rdcconfig_t *rdc) 551 { 552 rdc_config_t rdccfg; 553 rdcconfig_t *rdcp = NULL; 554 rdcconfig_t *cfg_rdcs = NULL; 555 rdc_rc_t *rc = NULL; 556 rdc_rc_t *rcp = NULL; 557 558 rdcp = rdc; 559 rc = new_rc(); 560 if (!rc) { 561 return (NULL); 562 } 563 rcp = rc; 564 565 while (rdcp) { 566 567 bzero(&rdccfg, sizeof (rdc_config_t)); 568 rdccfg.rdc_set[0] = config2set(rdcp); 569 rdccfg.command = RDC_CMD_DISABLE; 570 populate_addrs(&rdccfg.rdc_set[0], 0); 571 572 *rcp = rdc_config(&rdccfg); 573 574 rdcp = rdcp->next; 575 if (!rdcp) 576 break; 577 578 rcp->next = new_rc(); 579 rcp = rcp->next; 580 if (!rcp) 581 return (rc); 582 583 } 584 rcp = rc; 585 rdcp = rdc; 586 587 cfg_rdcs = chain_successful(rdcp, rcp); 588 589 remove_from_rdc_cfg(cfg_rdcs); 590 591 rdc_free_config(cfg_rdcs, RDC_FREEALL); 592 593 return (rc); 594 } 595 596 rdc_rc_t * 597 rdc_log(rdcconfig_t *rdc) 598 { 599 rdc_config_t rdccfg; 600 rdcconfig_t *rdcp = NULL; 601 rdc_rc_t *rc = NULL; 602 rdc_rc_t *rcp = NULL; 603 604 rdcp = rdc; 605 rc = new_rc(); 606 if (!rc) { 607 return (NULL); 608 } 609 rcp = rc; 610 611 while (rdcp) { 612 bzero(&rdccfg, sizeof (rdc_config_t)); 613 rdccfg.rdc_set[0] = config2set(rdcp); 614 rdccfg.command = RDC_CMD_LOG; 615 populate_addrs(&rdccfg.rdc_set[0], 0); 616 617 *rcp = rdc_config(&rdccfg); 618 619 rdcp = rdcp->next; 620 if (!rdcp) 621 break; 622 623 rcp->next = new_rc(); 624 rcp = rcp->next; 625 if (!rcp) 626 break; 627 } 628 return (rc); 629 } 630 631 rdc_rc_t * 632 rdc_usync(rdcconfig_t *rdc) 633 { 634 rdc_config_t *rdccfg; 635 rdcconfig_t *rdcp = NULL; 636 rdc_rc_t *rc = NULL; 637 rdc_rc_t *rcp = NULL; 638 rdc_rc_t *tmprc; 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 (void) 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 683 rdcp = rdc; 684 rc = new_rc(); 685 if (!rc) { 686 return (NULL); 687 } 688 rcp = rc; 689 690 while (rdcp) { 691 /* freed in rdc_mtconfig */ 692 rdccfg = (rdc_config_t *)calloc(1, sizeof (rdc_config_t)); 693 rdccfg->rdc_set[0] = config2set(rdcp); 694 rdccfg->command = RDC_CMD_COPY; 695 rdccfg->options = RDC_OPT_FULL|RDC_OPT_FORWARD; 696 populate_addrs(&rdccfg->rdc_set[0], 0); 697 (void) thr_create(NULL, 0, rdc_mtconfig, 698 (void **) rdccfg, THR_BOUND, NULL); 699 rdcp = rdcp->next; 700 if (!rdcp) 701 break; 702 703 } 704 705 /* 706 * collect status here from thr_join-status, 707 * and add to rdc_rc_t chain ? 708 * this will block, but caller could always thread too 709 */ 710 while (thr_join(NULL, NULL, (void**) &tmprc) == 0) { 711 if (rc == NULL) { 712 rcp = rc = (rdc_rc_t *)tmprc; 713 } else { 714 rcp->next = (rdc_rc_t *)tmprc; 715 rcp = rcp->next; 716 } 717 } 718 719 return (rc); 720 } 721 722 rdc_rc_t * 723 rdc_rsync(rdcconfig_t *rdc) 724 { 725 rdc_config_t *rdccfg; 726 rdcconfig_t *rdcp = NULL; 727 rdc_rc_t *rc = NULL; 728 rdc_rc_t *rcp = NULL; 729 rdc_rc_t *tmprc = NULL; 730 731 rdcp = rdc; 732 rc = new_rc(); 733 if (!rc) { 734 return (NULL); 735 } 736 rcp = rc; 737 738 while (rdcp) { 739 tmprc = cant_rsync(rdcp); 740 if (tmprc != NULL) { 741 if (rc == NULL) { 742 rcp = rc = tmprc; 743 } else { 744 rcp->next = tmprc; 745 rcp = rcp->next; 746 } 747 goto next; 748 } 749 750 /* freed in rdc_mtconfig */ 751 rdccfg = (rdc_config_t *)calloc(1, sizeof (rdc_config_t)); 752 rdccfg->rdc_set[0] = config2set(rdcp); 753 rdccfg->command = RDC_CMD_COPY; 754 rdccfg->options = RDC_OPT_REVERSE|RDC_OPT_FULL; 755 populate_addrs(&rdccfg->rdc_set[0], 0); 756 (void) thr_create(NULL, 0, rdc_mtconfig, 757 (void **) rdccfg, THR_BOUND, NULL); 758 next: 759 rdcp = rdcp->next; 760 if (!rdcp) 761 break; 762 } 763 764 /* 765 * collect status here from thr_join-status, 766 * and add to rdc_rc_t chain ? 767 * this will block, but caller could always thread too 768 */ 769 while (thr_join(NULL, NULL, (void**) &tmprc) == 0) { 770 if (rc == NULL) { 771 rcp = rc = (rdc_rc_t *)tmprc; 772 } else { 773 rcp->next = (rdc_rc_t *)tmprc; 774 rcp = rcp->next; 775 } 776 } 777 778 return (rc); 779 } 780 781 rdc_rc_t * 782 rdc_ursync(rdcconfig_t *rdc) 783 { 784 rdc_config_t *rdccfg; 785 rdcconfig_t *rdcp = NULL; 786 rdc_rc_t *rc = NULL; 787 rdc_rc_t *rcp = NULL; 788 rdc_rc_t *tmprc = NULL; 789 790 rdcp = rdc; 791 792 while (rdcp) { 793 tmprc = cant_rsync(rdcp); 794 if (tmprc != NULL) { 795 if (rc == NULL) { 796 rcp = rc = tmprc; 797 } else { 798 rcp->next = tmprc; 799 rcp = rcp->next; 800 } 801 goto next; 802 } 803 804 /* freed in rdc_mtconfig */ 805 rdccfg = (rdc_config_t *)calloc(1, sizeof (rdc_config_t)); 806 rdccfg->rdc_set[0] = config2set(rdcp); 807 rdccfg->command = RDC_CMD_COPY; 808 rdccfg->options = RDC_OPT_REVERSE | RDC_OPT_UPDATE; 809 populate_addrs(&rdccfg->rdc_set[0], 0); 810 (void) thr_create(NULL, 0, rdc_mtconfig, 811 (void **) rdccfg, THR_BOUND, NULL); 812 next: 813 rdcp = rdcp->next; 814 if (!rdcp) 815 break; 816 817 } 818 819 /* 820 * collect status here from thr_join-status, 821 * and add to rdc_rc_t chain ? 822 * this will block, but caller could always thread too 823 */ 824 while (thr_join(NULL, NULL, (void**) &tmprc) == 0) { 825 if (rc == NULL) { 826 rcp = rc = (rdc_rc_t *)tmprc; 827 } else { 828 rcp->next = (rdc_rc_t *)tmprc; 829 rcp = rcp->next; 830 } 831 } 832 833 return (rc); 834 } 835 836 rdc_rc_t * 837 rdc_wait(rdcconfig_t *rdc) 838 { 839 rdc_config_t rdccfg; 840 rdcconfig_t *rdcp = NULL; 841 rdc_rc_t *rc = NULL; 842 rdc_rc_t *rcp = NULL; 843 844 rdcp = rdc; 845 rc = new_rc(); 846 if (!rc) { 847 return (NULL); 848 } 849 rcp = rc; 850 851 while (rdcp) { 852 bzero(&rdccfg, sizeof (rdc_config_t)); 853 rdccfg.rdc_set[0] = config2set(rdcp); 854 rdccfg.command = RDC_CMD_WAIT; 855 populate_addrs(&rdccfg.rdc_set[0], 0); 856 857 *rcp = rdc_config(&rdccfg); 858 859 rdcp = rdcp->next; 860 if (!rdcp) 861 break; 862 863 rcp->next = new_rc(); 864 rcp = rcp->next; 865 if (!rcp) 866 break; 867 } 868 return (rc); 869 } 870 871 rdc_rc_t * 872 rdc_set_autosync(rdcconfig_t *rdc, int autosync) 873 { 874 rdc_config_t rdccfg; 875 rdcconfig_t *rdcp = NULL; 876 rdc_rc_t *rc = NULL; 877 rdc_rc_t *rcp = NULL; 878 879 rdcp = rdc; 880 rc = new_rc(); 881 if (!rc) { 882 return (NULL); 883 } 884 rcp = rc; 885 886 while (rdcp) { 887 bzero(&rdccfg, sizeof (rdc_config_t)); 888 rdccfg.rdc_set[0] = config2set(rdcp); 889 rdccfg.command = RDC_CMD_TUNABLE; 890 rdccfg.rdc_set[0].autosync = autosync; 891 rdccfg.rdc_set[0].maxqitems = -1; 892 rdccfg.rdc_set[0].maxqfbas = -1; 893 populate_addrs(&rdccfg.rdc_set[0], 0); 894 895 *rcp = rdc_config(&rdccfg); 896 897 rdcp = rdcp->next; 898 if (!rdcp) 899 break; 900 901 rcp->next = new_rc(); 902 rcp = rcp->next; 903 if (!rcp) 904 break; 905 } 906 return (rc); 907 } 908 909 rdc_rc_t * 910 rdc_set_maxqfbas(rdcconfig_t *rdc, int maxqfbas) 911 { 912 rdc_config_t rdccfg; 913 rdcconfig_t *rdcp = NULL; 914 rdc_rc_t *rc = NULL; 915 rdc_rc_t *rcp = NULL; 916 917 rdcp = rdc; 918 rc = new_rc(); 919 if (!rc) { 920 return (NULL); 921 } 922 rcp = rc; 923 924 while (rdcp) { 925 bzero(&rdccfg, sizeof (rdc_config_t)); 926 rdccfg.rdc_set[0] = config2set(rdcp); 927 rdccfg.command = RDC_CMD_TUNABLE; 928 rdccfg.rdc_set[0].autosync = -1; 929 rdccfg.rdc_set[0].maxqitems = -1; 930 rdccfg.rdc_set[0].maxqfbas = maxqfbas; 931 populate_addrs(&rdccfg.rdc_set[0], 0); 932 933 *rcp = rdc_config(&rdccfg); 934 935 rdcp = rdcp->next; 936 if (!rdcp) 937 break; 938 939 rcp->next = new_rc(); 940 rcp = rcp->next; 941 if (!rcp) 942 break; 943 } 944 return (rc); 945 } 946 947 rdc_rc_t * 948 rdc_set_maxqitems(rdcconfig_t *rdc, int maxqitems) 949 { 950 rdc_config_t rdccfg; 951 rdcconfig_t *rdcp = NULL; 952 rdc_rc_t *rc = NULL; 953 rdc_rc_t *rcp = NULL; 954 955 rdcp = rdc; 956 rc = new_rc(); 957 958 if (!rc) { 959 return (NULL); 960 } 961 rcp = rc; 962 963 while (rdcp) { 964 bzero(&rdccfg, sizeof (rdc_config_t)); 965 rdccfg.rdc_set[0] = config2set(rdc); 966 rdccfg.command = RDC_CMD_TUNABLE; 967 rdccfg.rdc_set[0].autosync = -1; 968 rdccfg.rdc_set[0].maxqitems = maxqitems; 969 rdccfg.rdc_set[0].maxqfbas = -1; 970 populate_addrs(&rdccfg.rdc_set[0], 0); 971 972 *rcp = rdc_config(&rdccfg); 973 974 rdcp = rdcp->next; 975 if (!rdcp) 976 break; 977 978 rcp->next = new_rc(); 979 rcp = rcp->next; 980 if (!rcp) 981 break; 982 } 983 return (rc); 984 } 985 986 rdc_set_t 987 rdc_status(rdcconfig_t *rdc) 988 { 989 rdc_config_t rdccfg; 990 991 bzero(&rdccfg, sizeof (rdc_config_t)); 992 rdccfg.rdc_set[0] = config2set(rdc); 993 rdccfg.command = RDC_CMD_STATUS; 994 populate_addrs(&rdccfg.rdc_set[0], 0); 995 rdc_config(&rdccfg); 996 997 return (rdccfg.rdc_set[0]); 998 } 999 1000 int 1001 rdc_get_autosync(rdcconfig_t *rdc) 1002 { 1003 rdc_set_t rdcset; 1004 1005 rdcset = rdc_status(rdc); 1006 return (rdcset.autosync); 1007 } 1008 1009 int 1010 rdc_get_maxqfbas(rdcconfig_t *rdc) 1011 { 1012 rdc_set_t rdcset; 1013 1014 rdcset = rdc_status(rdc); 1015 return (rdcset.maxqfbas); 1016 1017 } 1018 1019 int 1020 rdc_get_maxqitems(rdcconfig_t *rdc) 1021 { 1022 rdc_set_t rdcset; 1023 1024 rdcset = rdc_status(rdc); 1025 return (rdcset.maxqitems); 1026 1027 } 1028 1029 int 1030 set_mode(rdcconfig_t *rdc) 1031 { 1032 if (strcmp(rdc->mode, "async") == 0) 1033 return (RDC_OPT_ASYNC); 1034 else 1035 return (RDC_OPT_SYNC); 1036 } 1037 1038 /* 1039 * reconfig bitmaps are single set only ops 1040 * for obvious reasons 1041 */ 1042 rdc_rc_t * 1043 rdc_reconfig_pbmp(rdcconfig_t *rdc, char *pbmp) 1044 { 1045 rdc_config_t rdccfg; 1046 rdc_rc_t *rc; 1047 1048 rc = new_rc(); 1049 if ((!rc) || (!pbmp)) 1050 return (NULL); 1051 1052 bzero(&rdccfg, sizeof (rdc_config_t)); 1053 rdccfg.rdc_set[0] = config2set(rdc); 1054 strncpy(rdccfg.rdc_set[0].primary.bitmap, pbmp, NSC_MAXPATH); 1055 rdccfg.command = RDC_CMD_RECONFIG; 1056 rdccfg.options |= set_mode(rdc); 1057 populate_addrs(&rdccfg.rdc_set[0], 0); 1058 1059 if (can_reconfig_pbmp(rdc, pbmp)) 1060 *rc = rdc_config(&rdccfg); 1061 else 1062 populate_rc(rc, rdc); 1063 1064 if ((rc->rc == 0) && (rdc->persist)) 1065 if (replace_cfgfield(rdc, "pbitmap", pbmp) < 0) { 1066 rc->rc = -1; 1067 strncpy(rc->msg, rdc_error(NULL), RDC_ERR_SIZE); 1068 } 1069 return (rc); 1070 } 1071 1072 rdc_rc_t * 1073 rdc_reconfig_sbmp(rdcconfig_t *rdc, char *sbmp) 1074 { 1075 rdc_config_t rdccfg; 1076 rdc_rc_t *rc; 1077 1078 rc = new_rc(); 1079 if (!rc) 1080 return (NULL); 1081 1082 bzero(&rdccfg, sizeof (rdc_config_t)); 1083 rdccfg.rdc_set[0] = config2set(rdc); 1084 strncpy(rdccfg.rdc_set[0].secondary.bitmap, sbmp, NSC_MAXPATH); 1085 rdccfg.command = RDC_CMD_RECONFIG; 1086 rdccfg.options |= set_mode(rdc); 1087 populate_addrs(&rdccfg.rdc_set[0], 0); 1088 1089 if (can_reconfig_sbmp(rdc, sbmp)) 1090 *rc = rdc_config(&rdccfg); 1091 else 1092 populate_rc(rc, rdc); 1093 1094 if ((rc->rc == 0) && (rdc->persist)) 1095 replace_cfgfield(rdc, "sbitmap", sbmp); 1096 1097 return (rc); 1098 } 1099 1100 rdc_rc_t * 1101 rdc_reconfig_group(rdcconfig_t *rdc, char *group) 1102 { 1103 rdc_config_t rdccfg; 1104 rdcconfig_t *rdcp = NULL; 1105 rdcconfig_t *cfg_rdcs = NULL; 1106 rdc_rc_t *rc = NULL; 1107 rdc_rc_t *rcp = NULL; 1108 1109 rdcp = rdc; 1110 rc = new_rc(); 1111 if (!rc) { 1112 return (NULL); 1113 } 1114 rcp = rc; 1115 1116 while (rdcp) { 1117 bzero(&rdccfg, sizeof (rdc_config_t)); 1118 /* just in case */ 1119 strncpy(rdcp->group, group, NSC_MAXPATH); 1120 rdccfg.rdc_set[0] = config2set(rdcp); 1121 rdccfg.command = RDC_CMD_RECONFIG; 1122 rdccfg.options |= set_mode(rdcp); 1123 populate_addrs(&rdccfg.rdc_set[0], 0); 1124 1125 /* reconfig group rules enforced in kernel */ 1126 *rcp = rdc_config(&rdccfg); 1127 1128 rdcp = rdcp->next; 1129 if (!rdcp) 1130 break; 1131 1132 rcp->next = new_rc(); 1133 rcp = rcp->next; 1134 if (!rcp) 1135 break; 1136 } 1137 rcp = rc; 1138 rdcp = rdc; 1139 cfg_rdcs = chain_successful(rdcp, rcp); 1140 replace_cfgfield(cfg_rdcs, "group", group); 1141 rdc_free_config(cfg_rdcs, RDC_FREEALL); 1142 1143 return (rc); 1144 } 1145 /*ARGSUSED*/ 1146 rdc_rc_t * 1147 rdc_reconfig_ctag(rdcconfig_t *rdc, char *ctag) 1148 { 1149 return (NULL); 1150 } 1151 1152 rdc_rc_t * 1153 rdc_set_sync(rdcconfig_t *rdc) 1154 { 1155 rdc_config_t rdccfg; 1156 rdcconfig_t *rdcp = NULL; 1157 rdcconfig_t *cfg_rdcs = NULL; 1158 rdc_rc_t *rc = NULL; 1159 rdc_rc_t *rcp = NULL; 1160 1161 rdcp = rdc; 1162 rc = new_rc(); 1163 if (!rc) { 1164 return (NULL); 1165 } 1166 rcp = rc; 1167 1168 while (rdcp) { 1169 bzero(&rdccfg, sizeof (rdc_config_t)); 1170 rdccfg.rdc_set[0] = config2set(rdc); 1171 rdccfg.command = RDC_CMD_RECONFIG; 1172 rdccfg.options |= RDC_OPT_SYNC; 1173 populate_addrs(&rdccfg.rdc_set[0], 0); 1174 1175 *rcp = rdc_config(&rdccfg); 1176 1177 rdcp = rdcp->next; 1178 if (!rdcp) 1179 break; 1180 1181 rcp->next = new_rc(); 1182 rcp = rcp->next; 1183 if (!rcp) 1184 break; 1185 } 1186 1187 rcp = rc; 1188 rdcp = rdc; 1189 cfg_rdcs = chain_successful(rdcp, rcp); 1190 replace_cfgfield(cfg_rdcs, "mode", "sync"); 1191 rdc_free_config(cfg_rdcs, RDC_FREEALL); 1192 1193 return (rc); 1194 } 1195 1196 rdc_rc_t * 1197 rdc_set_async(rdcconfig_t *rdc) 1198 { 1199 rdc_config_t rdccfg; 1200 rdcconfig_t *rdcp = NULL; 1201 rdcconfig_t *cfg_rdcs = NULL; 1202 rdc_rc_t *rc = NULL; 1203 rdc_rc_t *rcp = NULL; 1204 1205 rdcp = rdc; 1206 rc = new_rc(); 1207 if (!rc) { 1208 return (NULL); 1209 } 1210 rcp = rc; 1211 1212 while (rdcp) { 1213 bzero(&rdccfg, sizeof (rdc_config_t)); 1214 rdccfg.rdc_set[0] = config2set(rdcp); 1215 rdccfg.command = RDC_CMD_RECONFIG; 1216 rdccfg.options |= RDC_OPT_ASYNC; 1217 populate_addrs(&rdccfg.rdc_set[0], 0); 1218 1219 *rcp = rdc_config(&rdccfg); 1220 1221 rdcp = rdcp->next; 1222 if (!rdcp) 1223 break; 1224 1225 rcp->next = new_rc(); 1226 rcp = rcp->next; 1227 if (!rcp) 1228 break; 1229 } 1230 rcp = rc; 1231 rdcp = rdc; 1232 cfg_rdcs = chain_successful(rdcp, rcp); 1233 replace_cfgfield(cfg_rdcs, "mode", "async"); 1234 rdc_free_config(cfg_rdcs, RDC_FREEALL); 1235 1236 return (rc); 1237 } 1238 1239 rdc_rc_t * 1240 rdc_health(rdcconfig_t *rdc) 1241 { 1242 rdc_config_t rdccfg; 1243 rdcconfig_t *rdcp = NULL; 1244 rdc_rc_t *rc = NULL; 1245 rdc_rc_t *rcp = NULL; 1246 1247 rdcp = rdc; 1248 rc = new_rc(); 1249 if (!rc) { 1250 return (NULL); 1251 } 1252 rcp = rc; 1253 1254 while (rdcp) { 1255 bzero(&rdccfg, sizeof (rdc_config_t)); 1256 rdccfg.rdc_set[0] = config2set(rdcp); 1257 rdccfg.command = RDC_CMD_HEALTH; 1258 populate_addrs(&rdccfg.rdc_set[0], 0); 1259 1260 *rcp = rdc_config(&rdccfg); 1261 1262 rdcp = rdcp->next; 1263 if (!rdcp) 1264 break; 1265 1266 rcp->next = new_rc(); 1267 rcp = rcp->next; 1268 1269 if (!rcp) 1270 break; 1271 1272 } 1273 return (rc); 1274 } 1275 1276 rdc_rc_t * 1277 rdc_reverse_role(rdcconfig_t *rdc) 1278 { 1279 rdc_config_t rdccfg; 1280 rdcconfig_t *rdcp = NULL; 1281 rdcconfig_t *cfg_rdcs = NULL; 1282 rdc_rc_t *rc = NULL; 1283 rdc_rc_t *rcp = NULL; 1284 1285 rdcp = rdc; 1286 rc = new_rc(); 1287 if (!rc) { 1288 return (NULL); 1289 } 1290 rcp = rc; 1291 1292 while (rdcp) { 1293 bzero(&rdccfg, sizeof (rdc_config_t)); 1294 rdccfg.rdc_set[0] = config2set(rdcp); 1295 rdccfg.command = RDC_CMD_RECONFIG; 1296 rdccfg.options |= RDC_OPT_REVERSE_ROLE; 1297 rdccfg.options |= set_mode(rdcp); 1298 populate_addrs(&rdccfg.rdc_set[0], 0); 1299 1300 *rcp = rdc_config(&rdccfg); 1301 1302 rdcp = rdcp->next; 1303 if (!rdcp) 1304 break; 1305 1306 rcp->next = new_rc(); 1307 rcp = rcp->next; 1308 if (!rcp) 1309 break; 1310 } 1311 rcp = rc; 1312 rdcp = rdc; 1313 cfg_rdcs = chain_successful(rdcp, rcp); 1314 reverse_in_cfg(cfg_rdcs); 1315 rdc_free_config(cfg_rdcs, RDC_FREEALL); 1316 1317 return (rc); 1318 }