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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 31 #include "isns_server.h" 32 #include "isns_msgq.h" 33 #include "isns_htab.h" 34 #include "isns_dd.h" 35 #include "isns_cache.h" 36 #include "isns_obj.h" 37 #include "isns_pdu.h" 38 #include "isns_dseng.h" 39 #include "isns_scn.h" 40 #include "isns_utils.h" 41 42 /* 43 * extern global variables 44 */ 45 extern const int UID_ATTR_INDEX[MAX_OBJ_TYPE_FOR_SIZE]; 46 47 extern msg_queue_t *sys_q; 48 extern msg_queue_t *scn_q; 49 50 extern int cache_flag; 51 52 /* 53 * extern functions. 54 */ 55 56 /* 57 * global variables 58 */ 59 60 /* 61 * local variables 62 */ 63 64 /* 65 * local functions. 66 */ 67 static matrix_t *new_matrix(uint32_t, uint32_t); 68 69 static int 70 cb_update_ds_attr( 71 void *p1, 72 void *p2 73 ) 74 { 75 int ec = 0; 76 77 isns_obj_t *obj = (isns_obj_t *)p1; 78 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 79 uint32_t tag = lcp->id[1]; 80 uint32_t which; 81 isns_attr_t *attr; 82 83 uint32_t len; 84 uchar_t *name; 85 lookup_ctrl_t lc; 86 uint32_t uid; 87 88 switch (tag) { 89 case ISNS_DD_NAME_ATTR_ID: 90 which = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID); 91 break; 92 case ISNS_DD_FEATURES_ATTR_ID: 93 which = ATTR_INDEX_DD(ISNS_DD_FEATURES_ATTR_ID); 94 break; 95 case ISNS_DD_SET_NAME_ATTR_ID: 96 which = ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID); 97 break; 98 case ISNS_DD_SET_STATUS_ATTR_ID: 99 which = ATTR_INDEX_DDS(ISNS_DD_SET_STATUS_ATTR_ID); 100 break; 101 default: 102 ASSERT(0); 103 break; 104 } 105 106 attr = &obj->attrs[which]; 107 108 switch (tag) { 109 case ISNS_DD_NAME_ATTR_ID: 110 case ISNS_DD_SET_NAME_ATTR_ID: 111 len = lcp->data[1].ui; 112 name = lcp->data[2].ptr; 113 lc.type = lcp->type; 114 lc.curr_uid = 0; 115 lc.id[0] = which; 116 lc.op[0] = OP_STRING; 117 lc.data[0].ptr = name; 118 lc.op[1] = 0; 119 /* check if the name is in use */ 120 uid = is_obj_there(&lc); 121 if (uid != 0) { 122 if (uid != get_obj_uid(obj)) { 123 ec = ERR_NAME_IN_USE; 124 } 125 return (ec); 126 } 127 if (len > attr->len) { 128 uchar_t *tmp = (uchar_t *)malloc(len); 129 if (tmp != NULL) { 130 free(attr->value.ptr); 131 attr->value.ptr = tmp; 132 } else { 133 /* memory exhausted */ 134 return (ISNS_RSP_INTERNAL_ERROR); 135 } 136 } 137 (void) strcpy((char *)attr->value.ptr, (char *)name); 138 attr->len = len; 139 break; 140 case ISNS_DD_FEATURES_ATTR_ID: 141 case ISNS_DD_SET_STATUS_ATTR_ID: 142 if (attr->tag != tag || 143 attr->value.ui != lcp->data[1].ui) { 144 attr->tag = tag; 145 attr->len = 4; 146 attr->value.ui = lcp->data[1].ui; 147 } else { 148 return (ec); 149 } 150 break; 151 } 152 153 /* cache has been updated, set the flag */ 154 SET_CACHE_UPDATED(); 155 156 /* update data store */ 157 if (sys_q != NULL) { 158 ec = write_data(DATA_UPDATE, obj); 159 } 160 161 return (ec); 162 } 163 164 static isns_obj_t * 165 make_member_node( 166 const uint32_t uid, 167 isns_attr_t *attr1 168 ) 169 { 170 isns_obj_t *obj = NULL; 171 isns_attr_t *attr; 172 isns_attr_t tmp; 173 174 switch (attr1->tag) { 175 case ISNS_DD_ISCSI_NAME_ATTR_ID: 176 obj = obj_calloc(OBJ_ISCSI); 177 attr = &obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID)]; 178 tmp.tag = ISNS_ISCSI_NAME_ATTR_ID; 179 tmp.len = attr1->len; 180 tmp.value.ptr = attr1->value.ptr; 181 if (assign_attr(attr, &tmp) != 0) { 182 free_object(obj); 183 obj = NULL; 184 } else if (uid != 0) { 185 (void) set_obj_uid(obj, uid); 186 } 187 break; 188 default: 189 ASSERT(0); 190 break; 191 } 192 193 return (obj); 194 } 195 196 static isns_obj_t * 197 make_member_dd( 198 const uint32_t uid 199 ) 200 { 201 isns_obj_t *obj = NULL; 202 isns_attr_t name = { 0 }; 203 204 obj = obj_calloc(OBJ_DD); 205 if (obj != NULL) { 206 (void) set_obj_uid(obj, uid); 207 name.tag = ISNS_DD_NAME_ATTR_ID; 208 if (assign_attr( 209 &obj->attrs[ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID)], 210 &name) != 0) { 211 free_object(obj); 212 obj = NULL; 213 } 214 } 215 216 return (obj); 217 } 218 219 static int 220 get_member_info( 221 isns_obj_t *assoc, 222 uint32_t *m_type, 223 uint32_t *m_id, 224 int flag 225 ) 226 { 227 int ec = 0; 228 lookup_ctrl_t lc = { 0 }; 229 230 isns_obj_t *obj; 231 isns_attr_t *attr1, *attr2; 232 uint32_t tmp_id = 0; 233 int i = 0; 234 235 *m_type = 0; 236 *m_id = 0; 237 238 attr1 = &assoc->attrs[ATTR_INDEX_ASSOC_ISCSI( 239 ISNS_DD_ISCSI_INDEX_ATTR_ID)]; 240 attr2 = &assoc->attrs[ATTR_INDEX_ASSOC_ISCSI( 241 ISNS_DD_ISCSI_NAME_ATTR_ID)]; 242 243 lc.type = OBJ_ISCSI; 244 if (attr1->tag != 0 && attr1->value.ui != 0) { 245 *m_id = attr1->value.ui; 246 lc.id[i] = UID_ATTR_INDEX[OBJ_ISCSI]; 247 lc.op[i] = OP_INTEGER; 248 lc.data[i].ui = *m_id; 249 i ++; 250 } 251 if (attr2->tag != 0) { 252 lc.id[i] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID); 253 lc.op[i] = OP_STRING; 254 lc.data[i].ptr = attr2->value.ptr; 255 i ++; 256 } else if (scn_q != NULL || sys_q != NULL) { 257 lc.id[i] = ISNS_ISCSI_NAME_ATTR_ID; 258 } 259 260 /* a member id or member name is required */ 261 if (i == 0) { 262 if (flag != 0) { 263 /* add member */ 264 return (ISNS_RSP_INVALID_REGIS); 265 } else { 266 /* remove member (isnsp msg request only) */ 267 return (0); 268 } 269 } 270 271 ec = cache_lookup(&lc, &tmp_id, cb_clone_attrs); 272 273 if (ec == 0 && tmp_id == 0) { 274 if (flag != 0) { 275 /* add member */ 276 if (attr1->tag == 0 || sys_q == NULL) { 277 /* object does not exist, create one */ 278 obj = make_member_node(*m_id, attr2); 279 if (obj == NULL) { 280 ec = ISNS_RSP_INTERNAL_ERROR; 281 } else { 282 ec = register_assoc(obj, &tmp_id); 283 if (ec != 0) { 284 free_object(obj); 285 } 286 } 287 } else { 288 /* don't create it if uid is specified */ 289 ec = ISNS_RSP_NO_SUCH_ENTRY; 290 } 291 } else { 292 /* remove member */ 293 ec = ERR_NO_SUCH_ASSOCIATION; 294 } 295 } 296 297 if (attr1->tag == 0) { 298 attr1->tag = ISNS_DD_ISCSI_INDEX_ATTR_ID; 299 attr1->len = 4; 300 attr1->value.ui = tmp_id; 301 } else if (attr2->tag == 0) { 302 attr2->tag = ISNS_DD_ISCSI_NAME_ATTR_ID; 303 attr2->len = strlen((char *)lc.data[1].ptr); 304 attr2->len += 4 - (attr2->len % 4); 305 attr2->value.ptr = lc.data[1].ptr; 306 } 307 308 *m_type = OBJ_ISCSI; 309 *m_id = tmp_id; 310 311 return (ec); 312 } 313 314 static int 315 get_dds_member_info( 316 uint32_t m_id 317 ) 318 { 319 int ec = 0; 320 lookup_ctrl_t lc; 321 322 isns_obj_t *obj; 323 uint32_t tmp_id; 324 325 if (m_id != 0) { 326 SET_UID_LCP(&lc, OBJ_DD, m_id); 327 } else { 328 return (ISNS_RSP_INVALID_REGIS); 329 } 330 331 tmp_id = is_obj_there(&lc); 332 333 if (tmp_id == 0) { 334 /* object does not exist, create one */ 335 obj = make_member_dd(m_id); 336 if (obj != NULL) { 337 ec = register_object(obj, NULL, NULL); 338 } else { 339 /* no memory */ 340 ec = ISNS_RSP_INTERNAL_ERROR; 341 } 342 } 343 344 return (ec); 345 } 346 347 static int 348 update_matrix( 349 matrix_t *matrix, 350 const uchar_t op, 351 const uint32_t puid, 352 const uint32_t m_id, 353 int ddd_flag 354 ) 355 { 356 int ec = 0; 357 358 uint32_t new_x = 0, new_y = 0; 359 matrix_t *tmp_matrix; 360 361 uint32_t i, j, k = 0; 362 uint32_t x_info; 363 bmp_t *bmp, *tmp_bmp; 364 365 uint32_t primary = GET_PRIMARY(m_id); 366 uint32_t second = GET_SECOND(m_id); 367 368 if (primary >= matrix->x) { 369 if (op == '-') { 370 ec = ERR_NO_SUCH_ASSOCIATION; 371 goto update_matrix_done; 372 } 373 /* enlarge the matrix on x axis */ 374 if (primary >= matrix->x * 2) { 375 new_x = primary + 1; 376 } else { 377 new_x = matrix->x * 2; 378 } 379 } 380 381 i = 0; 382 while (i < matrix->y) { 383 bmp = MATRIX_X_UNIT(matrix, i); 384 x_info = MATRIX_X_INFO(bmp); 385 if (x_info == puid) { 386 break; 387 } else if (x_info == 0 && k == 0) { 388 /* the first available slot */ 389 k = i; 390 } 391 i ++; 392 } 393 if (i == matrix->y) { 394 if (op == '-') { 395 ec = ERR_NO_SUCH_ASSOCIATION; 396 goto update_matrix_done; 397 } else if (k == 0) { 398 new_y = matrix->y * 2; 399 } else { 400 i = k; 401 } 402 } 403 404 /* 405 * enlarge the matrix. 406 */ 407 if (new_x != 0 || new_y != 0) { 408 if (new_x == 0) { 409 new_x = matrix->x; 410 } 411 if (new_y == 0) { 412 new_y = matrix->y; 413 } 414 tmp_matrix = new_matrix(new_x, new_y); 415 if (tmp_matrix != NULL) { 416 j = 0; 417 while (j < matrix->y) { 418 bmp = MATRIX_X_UNIT(matrix, j); 419 x_info = MATRIX_X_INFO(bmp); 420 if (x_info != 0) { 421 tmp_bmp = MATRIX_X_UNIT(tmp_matrix, j); 422 (void) memcpy((void *)tmp_bmp, 423 (void *)bmp, SIZEOF_X_UNIT(matrix)); 424 } 425 j ++; 426 } 427 free(matrix->m); 428 matrix->x = tmp_matrix->x; 429 matrix->y = tmp_matrix->y; 430 matrix->m = tmp_matrix->m; 431 free(tmp_matrix); 432 } else { 433 ec = ISNS_RSP_INTERNAL_ERROR; 434 goto update_matrix_done; 435 } 436 } 437 438 bmp = MATRIX_X_UNIT(matrix, i); 439 440 MATRIX_X_INFO(bmp) = puid; 441 if (op == '+') { 442 if (TEST_MEMBERSHIP(bmp, primary, second) == 0) { 443 SET_MEMBERSHIP(bmp, primary, second); 444 SET_CACHE_UPDATED(); 445 if (ddd_flag != 0) { 446 bmp = MATRIX_X_UNIT(matrix, 0); 447 ASSERT(MATRIX_X_INFO(bmp) == 448 ISNS_DEFAULT_DD_ID); 449 CLEAR_MEMBERSHIP(bmp, primary, second); 450 } 451 } else { 452 ec = ERR_ALREADY_ASSOCIATED; 453 } 454 } else if (op == '-') { 455 if (TEST_MEMBERSHIP(bmp, primary, second) != 0) { 456 CLEAR_MEMBERSHIP(bmp, primary, second); 457 SET_CACHE_UPDATED(); 458 if (ddd_flag != 0) { 459 i = 1; 460 while (i < matrix->y) { 461 bmp = MATRIX_X_UNIT(matrix, i); 462 x_info = MATRIX_X_INFO(bmp); 463 if (x_info != 0 && 464 TEST_MEMBERSHIP(bmp, 465 primary, second) != 0) { 466 break; 467 } 468 i ++; 469 } 470 if (i == matrix->y) { 471 bmp = MATRIX_X_UNIT(matrix, 0); 472 ASSERT(MATRIX_X_INFO(bmp) == 473 ISNS_DEFAULT_DD_ID); 474 SET_MEMBERSHIP(bmp, primary, second); 475 } 476 } 477 } else { 478 ec = ERR_NO_SUCH_ASSOCIATION; 479 } 480 } 481 482 update_matrix_done: 483 return (ec); 484 } 485 486 /*ARGSUSED*/ 487 static int 488 update_dd_matrix( 489 const uchar_t op, 490 const uint32_t dd_id, 491 const uint32_t m_type, 492 const uint32_t m_id 493 ) 494 { 495 matrix_t *matrix; 496 497 ASSERT(m_type == OBJ_ISCSI); 498 499 matrix = cache_get_matrix(OBJ_DD); 500 501 return (update_matrix(matrix, op, dd_id, m_id, 1)); 502 } 503 504 static int 505 update_dds_matrix( 506 const uchar_t op, 507 const uint32_t dds_id, 508 const uint32_t m_id 509 ) 510 { 511 matrix_t *dds_matrix = cache_get_matrix(OBJ_DDS); 512 513 return (update_matrix(dds_matrix, op, dds_id, m_id, 0)); 514 } 515 516 static int 517 clear_matrix( 518 matrix_t *matrix, 519 const uint32_t uid, 520 bmp_t **p, 521 uint32_t *n, 522 int ddd_flag 523 ) 524 { 525 int ec = 0; 526 bmp_t *bmp; 527 uint32_t x_info; 528 int i, j; 529 530 uint32_t primary; 531 uint32_t second; 532 533 if (p != NULL) { 534 *p = NULL; 535 *n = 0; 536 } 537 538 i = 0; 539 while (i < matrix->y) { 540 bmp = MATRIX_X_UNIT(matrix, i); 541 x_info = MATRIX_X_INFO(bmp); 542 if (x_info == uid) { 543 if (p != NULL) { 544 /* dup it for caller */ 545 *n = matrix->x; 546 *p = (bmp_t *)malloc(*n * sizeof (bmp_t)); 547 if (*p != NULL) { 548 (void) memcpy(*p, &bmp[MATRIX_X_HEADER], 549 *n * sizeof (bmp_t)); 550 } else { 551 ec = ISNS_RSP_INTERNAL_ERROR; 552 } 553 } 554 /* clean it */ 555 (void) memset(bmp, 0, SIZEOF_X_UNIT(matrix)); 556 break; 557 } 558 i ++; 559 } 560 561 if (ddd_flag != 0 && p != NULL) { 562 bmp = MATRIX_X_UNIT(matrix, 0); 563 ASSERT(MATRIX_X_INFO(bmp) == ISNS_DEFAULT_DD_ID); 564 /* Test the membership for each node which is a */ 565 /* member in the dd that is being deleted. */ 566 FOR_EACH_MEMBER(*p, *n, i, { 567 j = get_dd_id(i, 0); 568 if (j == 0) { 569 /* put it to the default dd */ 570 primary = GET_PRIMARY(i); 571 second = GET_SECOND(i); 572 SET_MEMBERSHIP(bmp, primary, second); 573 } 574 }); 575 } 576 577 return (ec); 578 } 579 580 static int 581 get_matrix( 582 matrix_t *matrix, 583 const uint32_t uid, 584 bmp_t **p, 585 uint32_t *n 586 ) 587 { 588 int ec = 0; 589 bmp_t *bmp; 590 uint32_t x_info; 591 int i; 592 593 *n = 0; 594 *p = NULL; 595 596 i = 0; 597 while (i < matrix->y) { 598 bmp = MATRIX_X_UNIT(matrix, i); 599 x_info = MATRIX_X_INFO(bmp); 600 if (x_info == uid) { 601 /* dup it for caller */ 602 *n = matrix->x; 603 *p = (bmp_t *)malloc(*n * sizeof (bmp_t)); 604 if (*p != NULL) { 605 (void) memcpy(*p, &bmp[MATRIX_X_HEADER], 606 *n * sizeof (bmp_t)); 607 } else { 608 *n = 0; 609 ec = ISNS_RSP_INTERNAL_ERROR; 610 } 611 break; 612 } 613 i ++; 614 } 615 616 return (ec); 617 } 618 619 static int 620 clear_dd_matrix( 621 const uint32_t dd_id, 622 bmp_t **p, 623 uint32_t *n 624 ) 625 { 626 matrix_t *matrix = cache_get_matrix(OBJ_DD); 627 628 return (clear_matrix(matrix, dd_id, p, n, 1)); 629 } 630 631 static int 632 clear_dds_matrix( 633 const uint32_t dds_id 634 ) 635 { 636 matrix_t *matrix = cache_get_matrix(OBJ_DDS); 637 638 return (clear_matrix(matrix, dds_id, NULL, NULL, 0)); 639 } 640 641 int 642 get_dd_matrix( 643 const uint32_t dd_id, 644 bmp_t **p, 645 uint32_t *n 646 ) 647 { 648 matrix_t *matrix = cache_get_matrix(OBJ_DD); 649 650 return (get_matrix(matrix, dd_id, p, n)); 651 } 652 653 int 654 get_dds_matrix( 655 const uint32_t dds_id, 656 bmp_t **p, 657 uint32_t *n 658 ) 659 { 660 matrix_t *matrix = cache_get_matrix(OBJ_DDS); 661 662 return (get_matrix(matrix, dds_id, p, n)); 663 } 664 665 /*ARGSUSED*/ 666 static int 667 cb_get_dds_status( 668 void *p1, 669 void *p2 670 ) 671 { 672 isns_obj_t *obj = (isns_obj_t *)p1; 673 674 isns_attr_t *attr = &obj->attrs[ 675 ATTR_INDEX_DDS(ISNS_DD_SET_STATUS_ATTR_ID)]; 676 677 return (DDS_ENABLED(attr->value.ui) ? 1 : 0); 678 } 679 680 static int 681 get_dds_status( 682 uint32_t dds_id 683 ) 684 { 685 lookup_ctrl_t lc; 686 687 if (dds_id == 0) { 688 return (0); 689 } 690 691 SET_UID_LCP(&lc, OBJ_DDS, dds_id); 692 693 return (cache_lookup(&lc, NULL, cb_get_dds_status)); 694 } 695 696 int 697 is_dd_active( 698 uint32_t dd_id 699 ) 700 { 701 int active = 0; 702 703 matrix_t *dds_matrix; 704 uint32_t primary; 705 uint32_t second; 706 uint32_t x_info; 707 bmp_t *bmp; 708 int i; 709 710 if (dd_id == 0) { 711 return (active); 712 } 713 714 dds_matrix = cache_get_matrix(OBJ_DDS); 715 primary = GET_PRIMARY(dd_id); 716 second = GET_SECOND(dd_id); 717 718 if (primary < dds_matrix->x) { 719 i = 0; 720 while (i < dds_matrix->y) { 721 bmp = MATRIX_X_UNIT(dds_matrix, i); 722 x_info = MATRIX_X_INFO(bmp); 723 if (x_info != 0 && 724 TEST_MEMBERSHIP(bmp, primary, second) != 0) { 725 if (get_dds_status(x_info) != 0) { 726 active = 1; 727 break; 728 } 729 } 730 i ++; 731 } 732 } 733 734 return (active); 735 } 736 737 int 738 get_scope( 739 uchar_t *node_name, 740 bmp_t **p, 741 uint32_t *n 742 ) 743 { 744 int ec = 0; 745 746 lookup_ctrl_t lc; 747 uint32_t uid; 748 749 matrix_t *dd_matrix; 750 uint32_t primary; 751 uint32_t second; 752 uint32_t x_info; 753 bmp_t *bmp; 754 int i, j; 755 756 bmp_t *tmp_p; 757 uint32_t tmp_n; 758 759 bmp_t *short_p; 760 uint32_t short_n; 761 762 /* clear it */ 763 *p = NULL; 764 *n = 0; 765 766 /* get the source object uid */ 767 lc.curr_uid = 0; 768 lc.type = OBJ_ISCSI; 769 lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID); 770 lc.op[0] = OP_STRING; 771 lc.data[0].ptr = node_name; 772 lc.op[1] = 0; 773 774 uid = is_obj_there(&lc); 775 776 /* no such object */ 777 if (uid == 0) { 778 return (ec); 779 } 780 781 dd_matrix = cache_get_matrix(OBJ_DD); 782 primary = GET_PRIMARY(uid); 783 second = GET_SECOND(uid); 784 785 if (primary < dd_matrix->x) { 786 i = 0; 787 while (i < dd_matrix->y) { 788 bmp = MATRIX_X_UNIT(dd_matrix, i); 789 x_info = MATRIX_X_INFO(bmp); 790 if (ec == 0 && x_info != 0 && 791 TEST_MEMBERSHIP(bmp, primary, second) != 0) { 792 if (is_dd_active(x_info) != 0 && 793 (ec = get_dd_matrix(x_info, 794 &tmp_p, &tmp_n)) == 0) { 795 if (*p == NULL) { 796 *p = tmp_p; 797 *n = tmp_n; 798 } else { 799 if (*n >= tmp_n) { 800 short_p = tmp_p; 801 short_n = tmp_n; 802 } else { 803 short_p = *p; 804 short_n = *n; 805 *p = tmp_p; 806 *n = tmp_n; 807 } 808 j = 0; 809 while (j < short_n) { 810 (*p)[j] |= short_p[j]; 811 j ++; 812 } 813 free(short_p); 814 } 815 } 816 } 817 i ++; 818 } 819 } 820 821 primary ++; 822 if (ec == 0 && *p == NULL) { 823 *p = (bmp_t *)calloc(primary, sizeof (bmp_t)); 824 if (*p != NULL) { 825 *n = primary; 826 } else { 827 *n = 0; 828 ec = ISNS_RSP_INTERNAL_ERROR; 829 } 830 } 831 832 if (*p != NULL) { 833 (*p)[primary - 1] |= (1 << second); 834 } 835 836 return (ec); 837 } 838 839 int 840 cb_clone_attrs( 841 void *p1, 842 void *p2 843 ) 844 { 845 int ec = 0; 846 847 isns_obj_t *obj = (isns_obj_t *)p1; 848 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2; 849 850 isns_attr_t *attr; 851 852 int i = 1; 853 854 while (i < MAX_LOOKUP_CTRL && 855 lcp->op[i] != 0) { 856 i ++; 857 } 858 859 while (ec == 0 && 860 i < MAX_LOOKUP_CTRL && 861 lcp->id[i] != 0) { 862 switch (lcp->id[i]) { 863 case ISNS_ISCSI_NAME_ATTR_ID: 864 attr = &obj->attrs[ATTR_INDEX_ISCSI( 865 ISNS_ISCSI_NAME_ATTR_ID)]; 866 lcp->data[i].ptr = (uchar_t *)malloc(attr->len); 867 if (lcp->data[i].ptr != NULL) { 868 (void) strcpy((char *)lcp->data[i].ptr, 869 (char *)attr->value.ptr); 870 } else { 871 /* memory exhausted */ 872 ec = ISNS_RSP_INTERNAL_ERROR; 873 } 874 break; 875 case ISNS_ISCSI_NODE_TYPE_ATTR_ID: 876 attr = &obj->attrs[ATTR_INDEX_ISCSI( 877 ISNS_ISCSI_NODE_TYPE_ATTR_ID)]; 878 lcp->data[i].ui = attr->value.ui; 879 break; 880 case ISNS_PG_ISCSI_NAME_ATTR_ID: 881 attr = &obj->attrs[ATTR_INDEX_PG( 882 ISNS_PG_ISCSI_NAME_ATTR_ID)]; 883 lcp->data[i].ptr = (uchar_t *)malloc(attr->len); 884 if (lcp->data[i].ptr != NULL) { 885 (void) strcpy((char *)lcp->data[i].ptr, 886 (char *)attr->value.ptr); 887 } else { 888 /* memory exhausted */ 889 ec = ISNS_RSP_INTERNAL_ERROR; 890 } 891 break; 892 case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID: 893 attr = &obj->attrs[ATTR_INDEX_PG( 894 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID)]; 895 lcp->data[i].ip = (in6_addr_t *)malloc(attr->len); 896 if (lcp->data[i].ip != NULL) { 897 (void) memcpy(lcp->data[i].ip, 898 attr->value.ip, attr->len); 899 } else { 900 /* memory exhausted */ 901 ec = ISNS_RSP_INTERNAL_ERROR; 902 } 903 break; 904 case ISNS_PG_PORTAL_PORT_ATTR_ID: 905 attr = &obj->attrs[ATTR_INDEX_PG( 906 ISNS_PG_PORTAL_PORT_ATTR_ID)]; 907 lcp->data[i].ui = attr->value.ui; 908 break; 909 case ISNS_PORTAL_IP_ADDR_ATTR_ID: 910 attr = &obj->attrs[ATTR_INDEX_PORTAL( 911 ISNS_PORTAL_IP_ADDR_ATTR_ID)]; 912 lcp->data[i].ip = (in6_addr_t *)malloc(attr->len); 913 if (lcp->data[i].ip != NULL) { 914 (void) memcpy(lcp->data[i].ip, 915 attr->value.ip, attr->len); 916 } else { 917 /* memory exhausted */ 918 ec = ISNS_RSP_INTERNAL_ERROR; 919 } 920 break; 921 case ISNS_PORTAL_PORT_ATTR_ID: 922 case ISNS_ESI_PORT_ATTR_ID: 923 attr = &obj->attrs[ATTR_INDEX_PORTAL(lcp->id[i])]; 924 if (attr->tag != 0 && attr->value.ui != 0) { 925 lcp->data[i].ui = attr->value.ui; 926 } else { 927 lcp->data[i].ui = 0; 928 } 929 break; 930 default: 931 ASSERT(0); 932 lcp->data[i].ui = 0; 933 break; 934 } 935 i ++; 936 } 937 938 return (ec); 939 } 940 941 static matrix_t * 942 new_matrix( 943 uint32_t x, 944 uint32_t y 945 ) 946 { 947 matrix_t *matrix; 948 949 matrix = (matrix_t *)malloc(sizeof (matrix_t)); 950 if (matrix != NULL) { 951 matrix->x = x; 952 matrix->y = y; 953 matrix->m = (bmp_t *)calloc(y, SIZEOF_X_UNIT(matrix)); 954 if (matrix->m == NULL) { 955 free(matrix); 956 matrix = NULL; 957 } 958 } 959 960 return (matrix); 961 } 962 963 int 964 dd_matrix_init( 965 struct cache *c 966 ) 967 { 968 matrix_t *x; 969 bmp_t *bmp; 970 uint32_t primary; 971 uint32_t second; 972 973 /* 974 * allocate an array of pointer for dd and dd-set matrix. 975 */ 976 c->x = (matrix_t **)calloc(2, sizeof (matrix_t *)); 977 if (c->x == NULL) { 978 return (1); 979 } 980 981 /* 982 * create dd matrix. 983 */ 984 x = new_matrix(8, 64); 985 if (x != NULL) { 986 x->c = c; 987 c->x[0] = x; 988 } else { 989 return (1); 990 } 991 992 /* 993 * Mark the first array on the y axis for Default DD. 994 */ 995 bmp = MATRIX_X_UNIT(x, 0); 996 MATRIX_X_INFO(bmp) = ISNS_DEFAULT_DD_ID; 997 998 /* 999 * create dd set matrix. 1000 */ 1001 x = new_matrix(2, 16); 1002 if (x != NULL) { 1003 x->c = c; 1004 c->x[1] = x; 1005 } else { 1006 return (1); 1007 } 1008 1009 /* 1010 * Mark the first array on the y axis for Default DD-set. 1011 */ 1012 bmp = MATRIX_X_UNIT(x, 0); 1013 MATRIX_X_INFO(bmp) = ISNS_DEFAULT_DD_SET_ID; 1014 1015 /* 1016 * Add Default DD as a member of Default DD-set. 1017 */ 1018 primary = GET_PRIMARY(ISNS_DEFAULT_DD_ID); 1019 second = GET_SECOND(ISNS_DEFAULT_DD_ID); 1020 SET_MEMBERSHIP(bmp, primary, second); 1021 1022 return (0); 1023 } 1024 1025 static uint32_t 1026 get_ds_id( 1027 matrix_t *matrix, 1028 uint32_t m_id, 1029 uint32_t curr_id 1030 ) 1031 { 1032 bmp_t *bmp; 1033 uint32_t primary = GET_PRIMARY(m_id); 1034 uint32_t second = GET_SECOND(m_id); 1035 uint32_t dd_id = 0; 1036 uint32_t uid; 1037 int i = 0; 1038 1039 if (matrix->x > primary) { 1040 while (i < matrix->y) { 1041 bmp = MATRIX_X_UNIT(matrix, i); 1042 uid = MATRIX_X_INFO(bmp); 1043 if (uid > curr_id && 1044 TEST_MEMBERSHIP(bmp, primary, second) != 0) { 1045 if (dd_id == 0 || uid < dd_id) { 1046 dd_id = uid; 1047 } 1048 } 1049 i ++; 1050 } 1051 } 1052 1053 return (dd_id); 1054 } 1055 1056 uint32_t 1057 get_common_dd( 1058 uint32_t m_id1, 1059 uint32_t m_id2, 1060 uint32_t curr_id 1061 ) 1062 { 1063 matrix_t *matrix; 1064 1065 bmp_t *bmp; 1066 uint32_t primary1 = GET_PRIMARY(m_id1); 1067 uint32_t second1 = GET_SECOND(m_id1); 1068 uint32_t primary2 = GET_PRIMARY(m_id2); 1069 uint32_t second2 = GET_SECOND(m_id2); 1070 uint32_t dd_id = 0; 1071 int i = 0; 1072 1073 matrix = cache_get_matrix(OBJ_DD); 1074 1075 if (matrix->x > primary1 && matrix->x > primary2) { 1076 while (i < matrix->y) { 1077 bmp = MATRIX_X_UNIT(matrix, i); 1078 if (MATRIX_X_INFO(bmp) > curr_id && 1079 TEST_MEMBERSHIP(bmp, primary1, second1) != 0 && 1080 TEST_MEMBERSHIP(bmp, primary2, second2) != 0) { 1081 dd_id = MATRIX_X_INFO(bmp); 1082 break; 1083 } 1084 i ++; 1085 } 1086 } 1087 1088 return (dd_id); 1089 } 1090 1091 uint32_t 1092 get_dd_id( 1093 uint32_t m_id, 1094 uint32_t curr_id 1095 ) 1096 { 1097 matrix_t *matrix = cache_get_matrix(OBJ_DD); 1098 1099 return (get_ds_id(matrix, m_id, curr_id)); 1100 } 1101 1102 uint32_t 1103 get_dds_id( 1104 uint32_t m_id, 1105 uint32_t curr_id 1106 ) 1107 { 1108 matrix_t *matrix = cache_get_matrix(OBJ_DDS); 1109 1110 return (get_ds_id(matrix, m_id, curr_id)); 1111 } 1112 1113 static int 1114 create_ds_object( 1115 isns_type_t type, 1116 isns_obj_t **ds_p, 1117 isns_attr_t *name_attr, 1118 isns_attr_t *uid_attr, 1119 isns_attr_t *status_attr 1120 ) 1121 { 1122 int ec = 0; 1123 1124 isns_obj_t *obj; 1125 int id1, id2, id3; 1126 1127 if (type == OBJ_DD) { 1128 id1 = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID); 1129 id2 = ATTR_INDEX_DD(ISNS_DD_ID_ATTR_ID); 1130 id3 = ATTR_INDEX_DD(ISNS_DD_FEATURES_ATTR_ID); 1131 } else { 1132 ASSERT(type == OBJ_DDS); 1133 id1 = ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID); 1134 id2 = ATTR_INDEX_DDS(ISNS_DD_SET_ID_ATTR_ID); 1135 id3 = ATTR_INDEX_DDS(ISNS_DD_SET_STATUS_ATTR_ID); 1136 } 1137 1138 obj = obj_calloc(type); 1139 if (obj != NULL && 1140 (name_attr != NULL && name_attr->tag != 0 && 1141 assign_attr(&obj->attrs[id1], name_attr) == 0) && 1142 (uid_attr == NULL || uid_attr->value.ui == 0 || 1143 assign_attr(&obj->attrs[id2], uid_attr) == 0) && 1144 (status_attr == NULL || status_attr->value.ui == 0 || 1145 assign_attr(&obj->attrs[id3], status_attr) == 0)) { 1146 *ds_p = obj; 1147 } else { 1148 /* no memory */ 1149 free_object(obj); 1150 ec = ISNS_RSP_INTERNAL_ERROR; 1151 } 1152 1153 return (ec); 1154 } 1155 1156 int 1157 create_dd_object( 1158 isns_tlv_t *op, 1159 uint16_t op_len, 1160 isns_obj_t **dd_p 1161 ) 1162 { 1163 int ec = 0; 1164 uint8_t *value; 1165 isns_attr_t name = { 0 }; 1166 isns_attr_t dd_id = { 0 }, features = { 0 }; 1167 1168 name.tag = ISNS_DD_NAME_ATTR_ID; 1169 1170 while (op_len > 8 && ec == 0) { 1171 value = &op->attr_value[0]; 1172 switch (op->attr_id) { 1173 case ISNS_DD_ID_ATTR_ID: 1174 if (op->attr_len == 4) { 1175 dd_id.tag = ISNS_DD_ID_ATTR_ID; 1176 dd_id.len = 4; 1177 dd_id.value.ui = ntohl(*(uint32_t *)value); 1178 } else if (op->attr_len != 0) { 1179 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1180 } 1181 break; 1182 case ISNS_DD_NAME_ATTR_ID: 1183 if (op->attr_len > 0 && 1184 op->attr_len <= 256) { 1185 name.len = op->attr_len; 1186 name.value.ptr = (uchar_t *)value; 1187 } else if (op->attr_len != 0) { 1188 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1189 } 1190 break; 1191 case ISNS_DD_ISCSI_INDEX_ATTR_ID: 1192 case ISNS_DD_ISCSI_NAME_ATTR_ID: 1193 break; 1194 case ISNS_DD_FC_PORT_NAME_ATTR_ID: 1195 case ISNS_DD_PORTAL_INDEX_ATTR_ID: 1196 case ISNS_DD_PORTAL_IP_ADDR_ATTR_ID: 1197 case ISNS_DD_PORTAL_PORT_ATTR_ID: 1198 ec = ISNS_RSP_REGIS_NOT_SUPPORTED; 1199 break; 1200 case ISNS_DD_FEATURES_ATTR_ID: 1201 if (op->attr_len == 4) { 1202 features.tag = ISNS_DD_FEATURES_ATTR_ID; 1203 features.len = op->attr_len; 1204 features.value.ui = ntohl(*(uint32_t *)value); 1205 } else if (op->attr_len != 0) { 1206 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1207 } 1208 break; 1209 default: 1210 ec = ISNS_RSP_INVALID_REGIS; 1211 break; 1212 } 1213 NEXT_TLV(op, op_len); 1214 } 1215 1216 if (ec == 0) { 1217 ec = create_ds_object(OBJ_DD, dd_p, 1218 &name, &dd_id, &features); 1219 } 1220 1221 return (ec); 1222 } 1223 1224 int 1225 create_dds_object( 1226 isns_tlv_t *op, 1227 uint16_t op_len, 1228 isns_obj_t **dds_p 1229 ) 1230 { 1231 int ec = 0; 1232 uint8_t *value; 1233 isns_attr_t name = { 0 }; 1234 isns_attr_t dds_id = { 0 }, code = { 0 }; 1235 1236 name.tag = ISNS_DD_SET_NAME_ATTR_ID; 1237 1238 while (op_len > 8 && ec == 0) { 1239 value = &op->attr_value[0]; 1240 switch (op->attr_id) { 1241 case ISNS_DD_SET_ID_ATTR_ID: 1242 if (op->attr_len == 4) { 1243 dds_id.tag = ISNS_DD_ID_ATTR_ID; 1244 dds_id.len = 4; 1245 dds_id.value.ui = ntohl(*(uint32_t *)value); 1246 } else if (op->attr_len != 0) { 1247 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1248 } 1249 break; 1250 case ISNS_DD_SET_NAME_ATTR_ID: 1251 if (op->attr_len > 0 && 1252 op->attr_len <= 256) { 1253 name.len = op->attr_len; 1254 name.value.ptr = (uchar_t *)value; 1255 } else if (op->attr_len != 0) { 1256 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1257 } 1258 break; 1259 case ISNS_DD_SET_STATUS_ATTR_ID: 1260 if (op->attr_len == 4) { 1261 code.tag = ISNS_DD_SET_STATUS_ATTR_ID; 1262 code.len = op->attr_len; 1263 code.value.ui = ntohl(*(uint32_t *)value); 1264 } else if (op->attr_len != 0) { 1265 ec = ISNS_RSP_MSG_FORMAT_ERROR; 1266 } 1267 break; 1268 case ISNS_DD_ID_ATTR_ID: 1269 break; 1270 default: 1271 ec = ISNS_RSP_INVALID_REGIS; 1272 break; 1273 } 1274 NEXT_TLV(op, op_len); 1275 } 1276 1277 if (ec == 0) { 1278 ec = create_ds_object(OBJ_DDS, dds_p, 1279 &name, &dds_id, &code); 1280 } 1281 1282 return (ec); 1283 } 1284 1285 int 1286 adm_create_dd( 1287 isns_obj_t **dd_p, 1288 uchar_t *name, 1289 uint32_t uid, 1290 uint32_t features 1291 ) 1292 { 1293 uint32_t len; 1294 isns_attr_t name_attr = { 0 }; 1295 isns_attr_t uid_attr = { 0 }; 1296 isns_attr_t features_attr = { 0 }; 1297 1298 name_attr.tag = ISNS_DD_NAME_ATTR_ID; 1299 if (name != NULL) { 1300 /* need to include the null terminator */ 1301 /* and be on 4 bytes aligned */ 1302 len = strlen((char *)name) + 1; 1303 len += 4 - (len % 4); 1304 name_attr.len = len; 1305 name_attr.value.ptr = name; 1306 } 1307 1308 uid_attr.tag = ISNS_DD_ID_ATTR_ID; 1309 uid_attr.len = 4; 1310 uid_attr.value.ui = uid; 1311 1312 features_attr.tag = ISNS_DD_FEATURES_ATTR_ID; 1313 features_attr.len = 4; 1314 features_attr.value.ui = features; 1315 1316 return (create_ds_object(OBJ_DD, dd_p, 1317 &name_attr, &uid_attr, &features_attr)); 1318 } 1319 1320 int 1321 adm_create_dds( 1322 isns_obj_t **dds_p, 1323 uchar_t *name, 1324 uint32_t uid, 1325 uint32_t code 1326 ) 1327 { 1328 uint32_t len; 1329 isns_attr_t name_attr = { 0 }; 1330 isns_attr_t uid_attr = { 0 }; 1331 isns_attr_t code_attr = { 0 }; 1332 1333 name_attr.tag = ISNS_DD_SET_NAME_ATTR_ID; 1334 if (name != NULL) { 1335 /* need to include the null terminator */ 1336 /* and be on 4 bytes aligned */ 1337 len = strlen((char *)name) + 1; 1338 len += 4 - (len % 4); 1339 name_attr.len = len; 1340 name_attr.value.ptr = name; 1341 } 1342 1343 uid_attr.tag = ISNS_DD_SET_ID_ATTR_ID; 1344 uid_attr.len = 4; 1345 uid_attr.value.ui = uid; 1346 1347 code_attr.tag = ISNS_DD_SET_STATUS_ATTR_ID; 1348 code_attr.len = 4; 1349 code_attr.value.ui = code; 1350 1351 return (create_ds_object(OBJ_DDS, dds_p, 1352 &name_attr, &uid_attr, &code_attr)); 1353 } 1354 1355 static int 1356 update_ds_name( 1357 isns_type_t type, 1358 uint32_t uid, 1359 uint32_t tag, 1360 uint32_t len, 1361 uchar_t *name 1362 ) 1363 { 1364 int ec = 0; 1365 1366 lookup_ctrl_t lc; 1367 1368 SET_UID_LCP(&lc, type, uid); 1369 1370 lc.id[1] = tag; 1371 lc.data[1].ui = len; 1372 lc.data[2].ptr = name; 1373 1374 ec = cache_rekey(&lc, &uid, cb_update_ds_attr); 1375 if (uid == 0) { 1376 ec = ISNS_RSP_INVALID_REGIS; 1377 } 1378 1379 return (ec); 1380 } 1381 1382 int 1383 update_dd_name( 1384 uint32_t uid, 1385 uint32_t len, 1386 uchar_t *name 1387 ) 1388 { 1389 /* 1390 * We do now allow changing the default DD and DD-set name. 1391 */ 1392 if (uid == ISNS_DEFAULT_DD_ID) { 1393 return (ISNS_RSP_OPTION_NOT_UNDERSTOOD); 1394 } 1395 1396 return (update_ds_name(OBJ_DD, uid, ISNS_DD_NAME_ATTR_ID, len, name)); 1397 } 1398 1399 int 1400 update_dds_name( 1401 uint32_t uid, 1402 uint32_t len, 1403 uchar_t *name 1404 ) 1405 { 1406 /* 1407 * We do now allow changing the default DD and DD-set name. 1408 */ 1409 if (uid == ISNS_DEFAULT_DD_ID) { 1410 return (ISNS_RSP_OPTION_NOT_UNDERSTOOD); 1411 } 1412 1413 return (update_ds_name(OBJ_DDS, uid, 1414 ISNS_DD_SET_NAME_ATTR_ID, len, name)); 1415 } 1416 1417 static int 1418 update_ds_uint32( 1419 isns_type_t type, 1420 uint32_t uid, 1421 uint32_t tag, 1422 uint32_t value 1423 ) 1424 { 1425 int ec = 0; 1426 1427 lookup_ctrl_t lc; 1428 1429 SET_UID_LCP(&lc, type, uid); 1430 1431 lc.id[1] = tag; 1432 lc.data[1].ui = value; 1433 1434 ec = cache_lookup(&lc, &uid, cb_update_ds_attr); 1435 if (uid == 0) { 1436 ec = ISNS_RSP_INVALID_REGIS; 1437 } 1438 1439 return (ec); 1440 } 1441 1442 int 1443 update_dd_features( 1444 uint32_t uid, 1445 uint32_t features 1446 ) 1447 { 1448 return (update_ds_uint32(OBJ_DD, uid, 1449 ISNS_DD_FEATURES_ATTR_ID, features)); 1450 } 1451 1452 int 1453 update_dds_status( 1454 uint32_t uid, 1455 uint32_t enabled 1456 ) 1457 { 1458 return (update_ds_uint32(OBJ_DDS, uid, 1459 ISNS_DD_SET_STATUS_ATTR_ID, enabled)); 1460 } 1461 1462 int 1463 add_dd_member( 1464 isns_obj_t *assoc 1465 ) 1466 { 1467 int ec = 0; 1468 1469 uint32_t dd_id; 1470 uint32_t m_id, m_type; 1471 1472 dd_id = get_parent_uid(assoc); 1473 /* 1474 * We do now allow placing any node to the default DD explicitly. 1475 */ 1476 if (dd_id == ISNS_DEFAULT_DD_ID) { 1477 return (ISNS_RSP_OPTION_NOT_UNDERSTOOD); 1478 } 1479 1480 ec = get_member_info(assoc, &m_type, &m_id, 1); 1481 if (ec == 0) { 1482 ec = update_dd_matrix( 1483 '+', /* add member */ 1484 dd_id, 1485 m_type, 1486 m_id); 1487 } 1488 1489 if (ec == 0) { 1490 if (sys_q != NULL) { 1491 /* add the membership to data store */ 1492 ec = write_data(DATA_ADD, assoc); 1493 } 1494 1495 /* trigger a management scn */ 1496 if (ec == 0 && scn_q != NULL) { 1497 (void) make_scn(ISNS_MEMBER_ADDED, assoc); 1498 } 1499 } 1500 1501 return (ec); 1502 } 1503 1504 int 1505 add_dds_member( 1506 isns_obj_t *assoc 1507 ) 1508 { 1509 int ec = 0; 1510 1511 uint32_t m_id = assoc->attrs[ATTR_INDEX_ASSOC_DD( 1512 ISNS_DD_ID_ATTR_ID)].value.ui; 1513 uint32_t dds_id; 1514 1515 dds_id = get_parent_uid(assoc); 1516 /* 1517 * We do now allow changing the membership of the default DD 1518 * and DD-set. 1519 */ 1520 if (dds_id == ISNS_DEFAULT_DD_SET_ID || 1521 m_id == ISNS_DEFAULT_DD_ID) { 1522 return (ISNS_RSP_OPTION_NOT_UNDERSTOOD); 1523 } 1524 1525 ec = get_dds_member_info(m_id); 1526 if (ec == 0) { 1527 ec = update_dds_matrix( 1528 '+', /* add member */ 1529 dds_id, 1530 m_id); 1531 } 1532 1533 if (ec == 0) { 1534 if (sys_q != NULL) { 1535 /* add the membership to data store */ 1536 ec = write_data(DATA_ADD, assoc); 1537 } 1538 1539 /* trigger a management scn */ 1540 if (ec == 0 && scn_q != NULL) { 1541 (void) make_scn(ISNS_MEMBER_ADDED, assoc); 1542 } 1543 } 1544 1545 return (ec); 1546 } 1547 1548 int 1549 remove_dd_member( 1550 isns_obj_t *assoc 1551 ) 1552 { 1553 int ec = 0; 1554 1555 uint32_t dd_id; 1556 uint32_t m_type; 1557 uint32_t m_id; 1558 1559 lookup_ctrl_t lc; 1560 1561 dd_id = get_parent_uid(assoc); 1562 /* 1563 * We do now allow removing the member from default DD explicitly. 1564 */ 1565 if (dd_id == ISNS_DEFAULT_DD_ID) { 1566 return (ISNS_RSP_OPTION_NOT_UNDERSTOOD); 1567 } 1568 1569 ec = get_member_info(assoc, &m_type, &m_id, 0); 1570 if (ec == 0) { 1571 ec = update_dd_matrix( 1572 '-', /* remove member */ 1573 dd_id, 1574 m_type, 1575 m_id); 1576 if (ec == 0) { 1577 /* update data store */ 1578 if (sys_q != NULL) { 1579 /* remove it from data store */ 1580 ec = write_data( 1581 DATA_DELETE_ASSOC, assoc); 1582 } 1583 1584 /* trigger a management scn */ 1585 if (ec == 0 && scn_q != NULL) { 1586 (void) make_scn(ISNS_MEMBER_REMOVED, assoc); 1587 } 1588 1589 /* remove it from object container if */ 1590 /* it is not a registered object */ 1591 if (ec == 0) { 1592 SET_UID_LCP(&lc, m_type, m_id); 1593 ec = dereg_assoc(&lc); 1594 } 1595 } 1596 } 1597 1598 return (ec); 1599 } 1600 1601 int 1602 remove_dds_member( 1603 uint32_t dds_id, 1604 uint32_t m_id 1605 ) 1606 { 1607 int ec = 0; 1608 1609 isns_obj_t *clone; 1610 1611 /* 1612 * We do now allow removing the member from default DD-set. 1613 */ 1614 if (dds_id == ISNS_DEFAULT_DD_SET_ID) { 1615 return (ISNS_RSP_OPTION_NOT_UNDERSTOOD); 1616 } 1617 1618 if (m_id != 0) { 1619 ec = update_dds_matrix( 1620 '-', /* remove member */ 1621 dds_id, 1622 m_id); 1623 if (ec == 0) { 1624 clone = obj_calloc(OBJ_ASSOC_DD); 1625 if (clone != NULL) { 1626 (void) set_obj_uid((void *)clone, m_id); 1627 (void) set_parent_obj(clone, dds_id); 1628 } 1629 /* update data store */ 1630 if (sys_q != NULL) { 1631 if (clone != NULL) { 1632 /* remove it from data store */ 1633 ec = write_data( 1634 DATA_DELETE_ASSOC, clone); 1635 } else { 1636 ec = ISNS_RSP_INTERNAL_ERROR; 1637 } 1638 } 1639 1640 /* trigger a management scn */ 1641 if (ec == 0 && 1642 scn_q != NULL && 1643 clone != NULL) { 1644 (void) make_scn(ISNS_MEMBER_REMOVED, clone); 1645 } 1646 free_object(clone); 1647 } 1648 } 1649 1650 return (ec); 1651 } 1652 1653 static int 1654 remove_member_wildchar( 1655 matrix_t *matrix, 1656 uint32_t m_id 1657 ) 1658 { 1659 int ec = 0; 1660 1661 bmp_t *bmp; 1662 uint32_t x_info; 1663 int i; 1664 1665 uint32_t primary = GET_PRIMARY(m_id); 1666 uint32_t second = GET_SECOND(m_id); 1667 1668 isns_obj_t *clone; 1669 1670 if (primary >= matrix->x) { 1671 return (ec); 1672 } 1673 1674 i = 0; 1675 while (ec == 0 && i < matrix->y) { 1676 bmp = MATRIX_X_UNIT(matrix, i); 1677 x_info = MATRIX_X_INFO(bmp); 1678 if (x_info != 0 && 1679 TEST_MEMBERSHIP(bmp, primary, second) != 0) { 1680 /* clean the membership */ 1681 CLEAR_MEMBERSHIP(bmp, primary, second); 1682 /* update data store */ 1683 if (sys_q != NULL) { 1684 clone = obj_calloc(OBJ_ASSOC_DD); 1685 if (clone != NULL) { 1686 (void) set_obj_uid((void *)clone, m_id); 1687 (void) set_parent_obj(clone, x_info); 1688 /* remove it from data store */ 1689 ec = write_data( 1690 DATA_DELETE_ASSOC, clone); 1691 free_object(clone); 1692 } else { 1693 ec = ISNS_RSP_INTERNAL_ERROR; 1694 } 1695 } 1696 } 1697 i ++; 1698 } 1699 1700 return (ec); 1701 } 1702 1703 int 1704 remove_dd_object( 1705 uint32_t dd_id 1706 ) 1707 { 1708 matrix_t *dds_matrix; 1709 1710 bmp_t *p; 1711 uint32_t n; 1712 int ec; 1713 1714 lookup_ctrl_t lc; 1715 uint32_t uid; 1716 1717 /* 1718 * We do now allow removing the default DD. 1719 */ 1720 if (dd_id == ISNS_DEFAULT_DD_ID) { 1721 return (ISNS_RSP_OPTION_NOT_UNDERSTOOD); 1722 } 1723 1724 SET_UID_LCP(&lc, OBJ_DD, dd_id); 1725 1726 /* de-register the object at first */ 1727 ec = dereg_object(&lc, 0); 1728 1729 /* clear it from all of dd-set */ 1730 dds_matrix = cache_get_matrix(OBJ_DDS); 1731 (void) remove_member_wildchar(dds_matrix, dd_id); 1732 1733 /* clear its member bitmap */ 1734 (void) clear_dd_matrix(dd_id, &p, &n); 1735 1736 /* deregister the member nodes which are not-registered node */ 1737 /* and have no longer membership in other DD(s). */ 1738 if (p != NULL) { 1739 SET_UID_LCP(&lc, OBJ_ISCSI, 0); 1740 FOR_EACH_MEMBER(p, n, uid, { 1741 lc.data[0].ui = uid; 1742 (void) dereg_assoc(&lc); 1743 }); 1744 free(p); 1745 } 1746 1747 return (ec); 1748 } 1749 1750 int 1751 remove_dds_object( 1752 uint32_t dds_id 1753 ) 1754 { 1755 int ec; 1756 1757 lookup_ctrl_t lc; 1758 1759 /* 1760 * We do now allow removing the default DD-set. 1761 */ 1762 if (dds_id == ISNS_DEFAULT_DD_SET_ID) { 1763 return (ISNS_RSP_OPTION_NOT_UNDERSTOOD); 1764 } 1765 1766 (void) clear_dds_matrix(dds_id); 1767 1768 SET_UID_LCP(&lc, OBJ_DDS, dds_id); 1769 1770 ec = dereg_object(&lc, 0); 1771 1772 return (ec); 1773 } 1774 1775 int 1776 update_ddd( 1777 void *p, 1778 const uchar_t op 1779 ) 1780 { 1781 isns_obj_t *obj; 1782 uint32_t uid; 1783 1784 matrix_t *matrix; 1785 1786 obj = (isns_obj_t *)p; 1787 if (obj->type != OBJ_ISCSI) { 1788 return (0); 1789 } 1790 1791 matrix = cache_get_matrix(OBJ_DD); 1792 uid = get_obj_uid(obj); 1793 1794 return (update_matrix(matrix, op, ISNS_DEFAULT_DD_ID, uid, 0)); 1795 } 1796 1797 int 1798 verify_ddd( 1799 ) 1800 { 1801 int ec = 0; 1802 1803 lookup_ctrl_t lc; 1804 isns_obj_t *obj; 1805 1806 uchar_t *name; 1807 uint32_t uid; 1808 uint32_t features; 1809 uint32_t code; 1810 1811 /* Ensure the Default DD is registered. */ 1812 uid = ISNS_DEFAULT_DD_ID; 1813 1814 SET_UID_LCP(&lc, OBJ_DD, uid); 1815 1816 (void) cache_lock_write(); 1817 1818 if (is_obj_there(&lc) == 0) { 1819 name = (uchar_t *)DEFAULT_DD_NAME; 1820 features = DEFAULT_DD_FEATURES; 1821 ec = adm_create_dd(&obj, name, uid, features); 1822 if (ec == 0) { 1823 ec = register_object(obj, NULL, NULL); 1824 if (ec != 0) { 1825 free_object(obj); 1826 goto verify_done; 1827 } 1828 } else { 1829 goto verify_done; 1830 } 1831 } 1832 1833 /* Ensure the Default DD-set is registered. */ 1834 uid = ISNS_DEFAULT_DD_SET_ID; 1835 1836 SET_UID_LCP(&lc, OBJ_DDS, uid); 1837 1838 if (is_obj_there(&lc) == 0) { 1839 name = (uchar_t *)DEFAULT_DD_SET_NAME; 1840 code = DEFAULT_DD_SET_STATUS; 1841 ec = adm_create_dds(&obj, name, uid, code); 1842 if (ec == 0) { 1843 ec = register_object(obj, NULL, NULL); 1844 if (ec != 0) { 1845 free_object(obj); 1846 } 1847 } 1848 } 1849 1850 verify_done: 1851 1852 ec = cache_unlock_sync(ec); 1853 1854 return (ec); 1855 } 1856