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
cb_update_ds_attr(void * p1,void * p2)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 *
make_member_node(const uint32_t uid,isns_attr_t * attr1)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 *
make_member_dd(const uint32_t uid)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
get_member_info(isns_obj_t * assoc,uint32_t * m_type,uint32_t * m_id,int flag)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
get_dds_member_info(uint32_t m_id)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
update_matrix(matrix_t * matrix,const uchar_t op,const uint32_t puid,const uint32_t m_id,int ddd_flag)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
update_dd_matrix(const uchar_t op,const uint32_t dd_id,const uint32_t m_type,const uint32_t m_id)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
update_dds_matrix(const uchar_t op,const uint32_t dds_id,const uint32_t m_id)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
clear_matrix(matrix_t * matrix,const uint32_t uid,bmp_t ** p,uint32_t * n,int ddd_flag)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
get_matrix(matrix_t * matrix,const uint32_t uid,bmp_t ** p,uint32_t * n)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
clear_dd_matrix(const uint32_t dd_id,bmp_t ** p,uint32_t * n)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
clear_dds_matrix(const uint32_t dds_id)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
get_dd_matrix(const uint32_t dd_id,bmp_t ** p,uint32_t * n)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
get_dds_matrix(const uint32_t dds_id,bmp_t ** p,uint32_t * n)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
cb_get_dds_status(void * p1,void * p2)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
get_dds_status(uint32_t dds_id)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
is_dd_active(uint32_t dd_id)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
get_scope(uchar_t * node_name,bmp_t ** p,uint32_t * n)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
cb_clone_attrs(void * p1,void * p2)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 *
new_matrix(uint32_t x,uint32_t y)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
dd_matrix_init(struct cache * c)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
get_ds_id(matrix_t * matrix,uint32_t m_id,uint32_t curr_id)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
get_common_dd(uint32_t m_id1,uint32_t m_id2,uint32_t curr_id)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
get_dd_id(uint32_t m_id,uint32_t curr_id)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
get_dds_id(uint32_t m_id,uint32_t curr_id)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
create_ds_object(isns_type_t type,isns_obj_t ** ds_p,isns_attr_t * name_attr,isns_attr_t * uid_attr,isns_attr_t * status_attr)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
create_dd_object(isns_tlv_t * op,uint16_t op_len,isns_obj_t ** dd_p)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
create_dds_object(isns_tlv_t * op,uint16_t op_len,isns_obj_t ** dds_p)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
adm_create_dd(isns_obj_t ** dd_p,uchar_t * name,uint32_t uid,uint32_t features)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
adm_create_dds(isns_obj_t ** dds_p,uchar_t * name,uint32_t uid,uint32_t code)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
update_ds_name(isns_type_t type,uint32_t uid,uint32_t tag,uint32_t len,uchar_t * name)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
update_dd_name(uint32_t uid,uint32_t len,uchar_t * name)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
update_dds_name(uint32_t uid,uint32_t len,uchar_t * name)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
update_ds_uint32(isns_type_t type,uint32_t uid,uint32_t tag,uint32_t value)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
update_dd_features(uint32_t uid,uint32_t features)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
update_dds_status(uint32_t uid,uint32_t enabled)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
add_dd_member(isns_obj_t * assoc)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
add_dds_member(isns_obj_t * assoc)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
remove_dd_member(isns_obj_t * assoc)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
remove_dds_member(uint32_t dds_id,uint32_t m_id)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
remove_member_wildchar(matrix_t * matrix,uint32_t m_id)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
remove_dd_object(uint32_t dd_id)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
remove_dds_object(uint32_t dds_id)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
update_ddd(void * p,const uchar_t op)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
verify_ddd()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