dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / isns / isnsd / scn.c
blob82027e417170e46617cfc55a607439bd256b4a90
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
32 #include "isns_server.h"
33 #include "isns_msgq.h"
34 #include "isns_cache.h"
35 #include "isns_cfg.h"
36 #include "isns_obj.h"
37 #include "isns_dseng.h"
38 #include "isns_log.h"
39 #include "isns_scn.h"
40 #include "isns_pdu.h"
43 * global variables.
47 * local variables.
49 static scn_registry_t *scn_registry = NULL;
50 static int scn_dispatched = 0;
53 * external variables.
55 extern uint8_t mgmt_scn;
56 extern msg_queue_t *sys_q;
57 extern msg_queue_t *scn_q;
58 extern const int UID_ATTR_INDEX[MAX_OBJ_TYPE_FOR_SIZE];
60 #ifdef DEBUG
61 extern void dump_pdu1(isns_pdu_t *);
62 #endif
64 static int sf_gen(scn_raw_t *);
65 static int sf_error(scn_raw_t *);
67 static scn_raw_t *make_raw_entity(isns_obj_t *);
68 static scn_raw_t *make_raw_iscsi(isns_obj_t *);
69 static scn_raw_t *make_raw_portal(isns_obj_t *);
70 static scn_raw_t *make_raw_assoc_iscsi(isns_obj_t *);
71 static scn_raw_t *make_raw_assoc_dd(isns_obj_t *);
72 static scn_raw_t *(*const make_raw[MAX_OBJ_TYPE_FOR_SIZE])(isns_obj_t *) = {
73 NULL,
74 &make_raw_entity,
75 &make_raw_iscsi,
76 &make_raw_portal,
77 NULL, /* OBJ_PG */
78 NULL, /* OBJ_DD */
79 NULL, /* OBJ_DDS */
80 NULL, /* MAX_OBJ_TYPE */
81 NULL, /* OBJ_DUMMY1 */
82 NULL, /* OBJ_DUMMY2 */
83 NULL, /* OBJ_DUMMY3 */
84 NULL, /* OBJ_DUMMY4 */
85 &make_raw_assoc_iscsi,
86 &make_raw_assoc_dd
89 static scn_text_t *scn_gen_entity(scn_raw_t *);
90 static scn_text_t *scn_gen_iscsi(scn_raw_t *);
91 static scn_text_t *scn_gen_portal(scn_raw_t *);
92 static scn_text_t *scn_gen_assoc_dd(scn_raw_t *);
93 static scn_text_t *(*const scn_gen[MAX_OBJ_TYPE_FOR_SIZE])(scn_raw_t *) = {
94 NULL,
95 &scn_gen_entity,
96 &scn_gen_iscsi,
97 &scn_gen_portal,
98 NULL, /* OBJ_PG */
99 NULL, /* OBJ_DD */
100 NULL, /* OBJ_DDS */
101 NULL, /* MAX_OBJ_TYPE */
102 NULL, /* OBJ_DUMMY1 */
103 NULL, /* OBJ_DUMMY2 */
104 NULL, /* OBJ_DUMMY3 */
105 NULL, /* OBJ_DUMMY4 */
106 &scn_gen_iscsi,
107 &scn_gen_assoc_dd
110 #define SCN_TEST(E, BITMAP, UID1, UID2, NT) \
111 (((E) & (BITMAP)) && \
112 (!((BITMAP) & (ISNS_INIT_SELF_INFO_ONLY | \
113 ISNS_TARGET_SELF_INFO_ONLY)) || \
114 ((UID1) == (UID2)) || \
115 (((BITMAP) & ISNS_INIT_SELF_INFO_ONLY) && \
116 ((NT) & ISNS_INITIATOR_NODE_TYPE)) || \
117 (((BITMAP) & ISNS_TARGET_SELF_INFO_ONLY) && \
118 ((NT) & ISNS_TARGET_NODE_TYPE))))
121 * local functions.
125 * ****************************************************************************
127 * free_portal_1:
128 * Free one SCN portal or decrease the reference count if the portal
129 * is referenced by other SCN entry(s).
131 * p - the portal.
133 * ****************************************************************************
135 static void
136 free_portal_1(
137 scn_portal_t *p
140 if (p->ref <= 1) {
141 if (p->sz == sizeof (in6_addr_t)) {
142 free(p->ip.in6);
144 free(p);
145 } else {
146 p->ref --;
151 * ****************************************************************************
153 * free_portal:
154 * Free the unused portals, which are extracted for new SCN entry,
155 * after the new SCN entry is added.
157 * p - the portal.
159 * ****************************************************************************
161 static void
162 free_portal(
163 scn_portal_t *p
166 scn_portal_t *n;
168 while (p != NULL) {
169 n = p->next;
170 free_portal_1(p);
171 p = n;
176 * ****************************************************************************
178 * free_portal_list:
179 * Free the list of portals while a SCN entry is being destroyed.
181 * l - the portal list.
183 * ****************************************************************************
185 static void
186 free_portal_list(
187 scn_list_t *l
190 scn_list_t *n;
191 scn_portal_t *p;
193 while (l != NULL) {
194 n = l->next;
195 p = l->data.portal;
196 free_portal_1(p);
197 free(l);
198 l = n;
203 * ****************************************************************************
205 * free_scn_text:
206 * Free one SCN or decrease the ref count after the SCN is emitted.
208 * text - the SCN.
210 * ****************************************************************************
212 static void
213 free_scn_text(
214 scn_text_t *text
217 if (text->ref <= 1) {
218 free(text->iscsi);
219 free(text);
220 } else {
221 text->ref --;
226 * ****************************************************************************
228 * free_scn_list:
229 * Free the the list of SCN.
231 * scn - the list.
233 * ****************************************************************************
235 static void
236 free_scn_list(
237 scn_t *scn
240 scn_t *next_scn;
241 scn_list_t *list;
242 scn_list_t *next_list;
244 while (scn != NULL) {
245 next_scn = scn->next;
246 list = scn->data.list;
247 while (list != NULL) {
248 next_list = list->next;
249 free_scn_text(list->data.text);
250 free(list);
251 list = next_list;
253 free(scn);
254 scn = next_scn;
259 * ****************************************************************************
261 * free_scn:
262 * Free all of SCNs which are dispatched to every entry.
264 * ****************************************************************************
266 static void
267 free_scn(
270 scn_registry_t *p;
272 p = scn_registry;
274 while (p != NULL) {
275 free_scn_list(p->scn);
276 p->scn = NULL;
277 p = p->next;
282 * ****************************************************************************
284 * free_entry:
285 * Free one SCN entry.
287 * e - the SCN entry.
289 * ****************************************************************************
291 static void
292 free_entry(
293 scn_registry_t *e
296 free_scn_list(e->scn);
297 free_portal_list(e->portal.l);
298 free(e->name);
299 free(e);
303 * ****************************************************************************
305 * free_raw:
306 * Free the raw data after the SCN is generated from it.
308 * raw - the raw SCN data.
310 * ****************************************************************************
312 static void
313 free_raw(
314 scn_raw_t *raw
317 if (raw->ref == 0) {
318 free(raw->iscsi);
320 if (raw->ip != NULL) {
321 free(raw->ip);
323 free(raw);
327 * ****************************************************************************
329 * scn_add_portal:
330 * Add portals to the portal list of a SCN entry.
332 * e - the SCN entry.
333 * p - the portals.
334 * return - 0: successful, otherwise failed.
336 * ****************************************************************************
338 static int
339 scn_add_portal(
340 scn_registry_t *e,
341 scn_portal_t *p
344 scn_portal_t *x;
345 scn_list_t *l, *m;
347 scn_list_t **lp;
349 int found_it;
351 lp = &e->portal.l;
352 while (p != NULL) {
353 m = (scn_list_t *)malloc(sizeof (scn_list_t));
354 if (m == NULL) {
355 return (1);
357 found_it = 0;
358 e = scn_registry;
359 while (e && !found_it) {
360 l = e->portal.l;
361 while (l && !found_it) {
362 x = l->data.portal;
363 if (x->uid == p->uid) {
364 found_it = 1;
366 l = l->next;
368 e = e->next;
371 if (!found_it) {
372 x = p;
374 m->data.portal = x;
375 x->ref ++;
376 m->next = *lp;
377 *lp = m;
379 p = p->next;
382 return (0);
386 * ****************************************************************************
388 * scn_remove_portal:
389 * Remove a portal from the portal list of every SCN entry.
391 * uid - the portal object uid.
392 * return - always successful (0).
394 * ****************************************************************************
396 static int
397 scn_remove_portal(
398 uint32_t uid
401 scn_registry_t **ep, *e;
403 scn_portal_t *x;
404 scn_list_t **lp, *l;
406 ep = &scn_registry;
407 e = *ep;
409 while (e != NULL) {
410 lp = &e->portal.l;
411 l = *lp;
412 while (l != NULL) {
413 x = l->data.portal;
414 if (x->uid == uid) {
415 /* remove it */
416 *lp = l->next;
417 free_portal_1(x);
418 free(l);
419 } else {
420 lp = &l->next;
422 l = *lp;
425 if (e->portal.l == NULL) {
426 /* no portal for this entry, destroy it */
427 *ep = e->next;
428 free_entry(e);
429 } else {
430 ep = &e->next;
432 e = *ep;
435 return (0);
439 * ****************************************************************************
441 * scn_list_add:
442 * Add one SCN entry to the SCN entry list.
444 * e - the SCN entry.
445 * return - always successful (0).
447 * ****************************************************************************
449 static int
450 scn_list_add(
451 scn_registry_t *e
454 scn_registry_t **pp;
455 scn_portal_t *p;
457 p = e->portal.p;
458 e->portal.l = NULL;
460 pp = &scn_registry;
461 while (*pp) {
462 if ((*pp)->uid == e->uid) {
463 /* replace the bitmap */
464 (*pp)->bitmap = e->bitmap;
465 free_portal(p);
466 free_entry(e);
467 return (0);
468 } else if ((*pp)->uid < e->uid) {
469 break;
471 pp = &(*pp)->next;
474 (void) scn_add_portal(e, p);
476 if (e->portal.l != NULL || sys_q == NULL) {
477 /* insert it to the list */
478 e->next = *pp;
479 *pp = e;
480 } else {
481 /* no portal, ignore it */
482 free_entry(e);
485 /* free the unused portal(s) */
486 free_portal(p);
488 return (0);
492 * ****************************************************************************
494 * scn_list_remove:
495 * Remove one SCN entry from the SCN entry list.
497 * uid - the SCN entry unique ID.
498 * return - always successful (0).
500 * ****************************************************************************
502 static int
503 scn_list_remove(
504 uint32_t uid
507 scn_registry_t **ep, *e;
509 ep = &scn_registry;
510 e = *ep;
511 while (e) {
512 if (e->uid == uid) {
513 /* destroy it */
514 *ep = e->next;
515 free_entry(e);
516 break;
517 } else if (e->uid < uid) {
518 break;
520 ep = &e->next;
521 e = *ep;
524 return (0);
528 * ****************************************************************************
530 * cb_get_scn_port:
531 * The callback function which returns the SCN port of a portal object.
533 * p1 - the portal object.
534 * p2 - the lookup control data.
535 * return - the SCN port number.
537 * ****************************************************************************
539 static int
540 cb_get_scn_port(
541 void *p1,
542 /*ARGSUSED*/
543 void *p2
546 isns_obj_t *obj = (isns_obj_t *)p1;
548 isns_attr_t *attr = &obj->attrs[
549 ATTR_INDEX_PORTAL(ISNS_SCN_PORT_ATTR_ID)];
551 int port = 0;
553 if (attr->tag != 0 && attr->value.ui != 0) {
554 port = (int)attr->value.ui;
557 return (port);
561 * ****************************************************************************
563 * new_scn_portal:
564 * Make a new SCN portal.
566 * ref - the ref count.
567 * uid - the portal object UID.
568 * ip - the ip address.
569 * port - the port number.
570 * return - the SCN portal.
572 * ****************************************************************************
574 static scn_portal_t *
575 new_scn_portal(
576 uint32_t ref,
577 uint32_t uid,
578 in6_addr_t *ip,
579 uint32_t port
582 scn_portal_t *p;
584 p = (scn_portal_t *)malloc(sizeof (scn_portal_t));
585 if (p != NULL) {
586 p->uid = uid;
587 /* convert the ipv6 to ipv4 */
588 if (((int *)ip)[0] == 0x00 &&
589 ((int *)ip)[1] == 0x00 &&
590 ((uchar_t *)ip)[8] == 0x00 &&
591 ((uchar_t *)ip)[9] == 0x00 &&
592 ((uchar_t *)ip)[10] == 0xFF &&
593 ((uchar_t *)ip)[11] == 0xFF) {
594 p->sz = sizeof (in_addr_t);
595 p->ip.in = ((uint32_t *)ip)[3];
596 free(ip);
597 } else {
598 p->sz = sizeof (in6_addr_t);
599 p->ip.in6 = ip;
601 p->port = port;
602 p->ref = ref;
603 p->so = 0;
604 p->next = NULL;
607 return (p);
611 * ****************************************************************************
613 * extract scn_portal:
614 * Extract the SCN portal(s) for a storage node.
616 * name - the storage node name.
617 * return - the SCN portal list.
619 * ****************************************************************************
621 static scn_portal_t *
622 extract_scn_portal(
623 uchar_t *name
626 scn_portal_t *list = NULL;
627 scn_portal_t *p;
629 lookup_ctrl_t lc_pg, lc_p;
630 uint32_t pg_uid, uid;
632 in6_addr_t *ip;
633 uint32_t port;
635 lc_pg.type = OBJ_PG;
636 lc_pg.curr_uid = 0;
637 lc_pg.id[0] = ATTR_INDEX_PG(ISNS_PG_ISCSI_NAME_ATTR_ID);
638 lc_pg.op[0] = OP_STRING;
639 lc_pg.data[0].ptr = name;
640 lc_pg.op[1] = 0;
642 lc_pg.id[1] = ISNS_PG_PORTAL_IP_ADDR_ATTR_ID;
643 lc_pg.id[2] = ISNS_PG_PORTAL_PORT_ATTR_ID;
645 lc_p.type = OBJ_PORTAL;
646 lc_p.curr_uid = 0;
647 lc_p.id[0] = ATTR_INDEX_PORTAL(ISNS_PORTAL_IP_ADDR_ATTR_ID);
648 lc_p.op[0] = OP_MEMORY_IP6;
649 lc_p.id[1] = ATTR_INDEX_PORTAL(ISNS_PORTAL_PORT_ATTR_ID);
650 lc_p.op[1] = OP_INTEGER;
651 lc_p.op[2] = 0;
653 while (cache_lookup(&lc_pg, &pg_uid, cb_clone_attrs) == 0 &&
654 pg_uid != 0) {
655 ip = lc_pg.data[1].ip;
656 port = lc_pg.data[2].ui;
657 if (ip != NULL) {
658 lc_p.data[0].ip = ip;
659 lc_p.data[1].ui = port;
660 port = cache_lookup(&lc_p, &uid, cb_get_scn_port);
661 if (port != 0 && uid != 0) {
662 /* ref starts from 1 */
663 p = new_scn_portal(1, uid, ip, port);
664 if (p != NULL) {
665 p->next = list;
666 list = p;
667 } else {
668 free(ip);
669 free(p);
671 } else {
672 /* portal not registered or no scn port */
673 free(ip);
676 lc_pg.curr_uid = pg_uid;
679 return (list);
683 * ****************************************************************************
685 * cb_update_scn_bitmap:
686 * The callback function which updates the SCN Bitmap attribute of
687 * a storage node object.
689 * p1 - the storage node object.
690 * p2 - the lookup control data.
691 * return - error code.
693 * ****************************************************************************
695 static int
696 cb_update_scn_bitmap(
697 void *p1,
698 void *p2
701 int ec = 0;
703 isns_obj_t *obj = (isns_obj_t *)p1;
704 lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
706 int id = ATTR_INDEX_ISCSI(ISNS_ISCSI_SCN_BITMAP_ATTR_ID);
707 isns_attr_t *attr = &obj->attrs[id];
709 uint32_t bitmap = lcp->data[2].ui;
711 if (bitmap != 0) {
712 attr->tag = ISNS_ISCSI_SCN_BITMAP_ATTR_ID;
713 attr->len = 4;
714 } else if (attr->tag == 0) {
715 return (ec);
716 } else {
717 attr->tag = 0;
718 attr->len = 0;
720 attr->value.ui = bitmap;
722 if (sys_q != NULL) {
723 ec = write_data(DATA_UPDATE, obj);
726 return (ec);
730 * ****************************************************************************
732 * cb_get_node_type:
733 * The callback function which returns the node type attribute of
734 * a storage node object.
736 * p1 - the storage node object.
737 * p2 - the lookup control data.
738 * return - error code.
740 * ****************************************************************************
742 static int
743 cb_get_node_type(
744 void *p1,
745 /* LINTED E_FUNC_ARG_UNUSED */
746 void *p2
749 isns_obj_t *obj = (isns_obj_t *)p1;
750 isns_attr_t *attr = &obj->attrs[
751 ATTR_INDEX_ISCSI(ISNS_ISCSI_NODE_TYPE_ATTR_ID)];
752 int nt = (int)attr->value.ui;
754 return (nt);
758 * ****************************************************************************
760 * cb_get_node_type:
761 * The callback function which returns the storage node object UID
762 * from a portal group object.
764 * p1 - the pg object.
765 * p2 - the lookup control data.
766 * return - the storage node object UID.
768 * ****************************************************************************
770 static int
771 cb_pg_node(
772 void *p1,
773 /* LINTED E_FUNC_ARG_UNUSED */
774 void *p2
777 uint32_t ref;
779 ref = get_ref_t(p1, OBJ_ISCSI);
781 return ((int)ref);
785 * ****************************************************************************
787 * make_raw_entity:
788 * Make raw SCN data with a Network Entity object.
790 * obj - the network entity object.
791 * return - the raw SCN data.
793 * ****************************************************************************
795 static scn_raw_t *
796 make_raw_entity(
797 /*ARGSUSED*/
798 isns_obj_t *obj
801 scn_raw_t *raw;
803 raw = (scn_raw_t *)malloc(sizeof (scn_raw_t));
804 if (raw != NULL) {
805 raw->type = obj->type;
806 raw->uid = get_obj_uid(obj);
807 raw->iscsi = NULL;
808 raw->ref = 0;
809 raw->ilen = 0;
810 raw->nt = 0;
811 raw->ip = NULL;
812 raw->dd_id = 0;
813 raw->dds_id = 0;
814 } else {
815 isnslog(LOG_DEBUG, "make_raw_entity", "malloc failed.");
818 return (raw);
822 * ****************************************************************************
824 * make_raw_iscsi:
825 * Make raw SCN data with a Storage Node object.
827 * obj - the storage node object.
828 * return - the raw SCN data.
830 * ****************************************************************************
832 static scn_raw_t *
833 make_raw_iscsi(
834 isns_obj_t *obj
837 uint32_t uid;
838 uint32_t nt;
839 uchar_t *iscsi;
840 uint32_t ilen;
842 isns_attr_t *attr;
844 scn_raw_t *raw;
846 uid = get_obj_uid(obj);
847 attr = &obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NODE_TYPE_ATTR_ID)];
848 nt = attr->value.ui;
849 attr = &obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID)];
851 raw = (scn_raw_t *)malloc(sizeof (scn_raw_t));
852 ilen = attr->len;
853 iscsi = (uchar_t *)malloc(ilen);
854 if (raw != NULL && iscsi != NULL) {
855 /* copy the iscsi storage node name */
856 (void) strcpy((char *)iscsi, (char *)attr->value.ptr);
858 raw->type = obj->type;
859 raw->uid = uid;
860 raw->iscsi = iscsi;
861 raw->ref = 0;
862 raw->ilen = ilen;
863 raw->nt = nt;
864 raw->ip = NULL;
865 raw->dd_id = 0;
866 raw->dds_id = 0;
867 } else {
868 free(raw);
869 free(iscsi);
870 raw = NULL;
871 isnslog(LOG_DEBUG, "make_raw_iscsi", "malloc failed.");
874 return (raw);
878 * ****************************************************************************
880 * make_raw_portal:
881 * Make raw SCN data with a Portal object.
883 * obj - the portal object.
884 * return - the raw SCN data.
886 * ****************************************************************************
888 static scn_raw_t *
889 make_raw_portal(
890 isns_obj_t *obj
893 isns_attr_t *attr;
894 in6_addr_t *ip;
895 uint32_t port;
897 scn_raw_t *raw;
899 raw = (scn_raw_t *)malloc(sizeof (scn_raw_t));
900 ip = (in6_addr_t *)malloc(sizeof (in6_addr_t));
901 if (raw != NULL && ip != NULL) {
902 attr = &obj->attrs[
903 ATTR_INDEX_PORTAL(ISNS_PORTAL_IP_ADDR_ATTR_ID)];
904 (void) memcpy(ip, attr->value.ip, sizeof (in6_addr_t));
905 attr = &obj->attrs[
906 ATTR_INDEX_PORTAL(ISNS_PORTAL_PORT_ATTR_ID)];
907 port = attr->value.ui;
909 raw->type = obj->type;
910 raw->uid = 0;
911 raw->iscsi = NULL;
912 raw->ref = 0;
913 raw->ilen = 0;
914 raw->nt = 0;
915 raw->ip = ip;
916 raw->port = port;
917 raw->dd_id = 0;
918 raw->dds_id = 0;
919 } else {
920 free(ip);
921 free(raw);
922 raw = NULL;
923 isnslog(LOG_DEBUG, "make_raw_portal", "malloc failed.");
926 return (raw);
930 * ****************************************************************************
932 * make_raw_assoc_iscsi:
933 * Make raw SCN data with a Discovery Domain member association.
935 * obj - the member association object.
936 * return - the raw SCN data.
938 * ****************************************************************************
940 static scn_raw_t *
941 make_raw_assoc_iscsi(
942 isns_obj_t *obj
945 uint32_t uid;
946 uint32_t dd_id;
947 uint32_t nt;
949 lookup_ctrl_t lc;
950 isns_attr_t *attr;
952 scn_raw_t *raw;
953 uchar_t *iscsi;
954 uint32_t ilen;
956 uid = get_obj_uid(obj);
957 dd_id = get_parent_uid(obj);
959 SET_UID_LCP(&lc, OBJ_ISCSI, uid);
961 nt = cache_lookup(&lc, NULL, cb_get_node_type);
963 attr = &obj->attrs[ATTR_INDEX_ASSOC_ISCSI(ISNS_DD_ISCSI_NAME_ATTR_ID)];
965 raw = (scn_raw_t *)malloc(sizeof (scn_raw_t));
966 ilen = attr->len;
967 iscsi = (uchar_t *)malloc(ilen);
968 if (raw != NULL && iscsi != NULL) {
969 /* copy the iscsi storage node name */
970 (void) strcpy((char *)iscsi, (char *)attr->value.ptr);
972 raw->type = obj->type;
973 raw->uid = uid;
974 raw->iscsi = iscsi;
975 raw->ref = 0;
976 raw->ilen = ilen;
977 raw->nt = nt;
978 raw->ip = NULL;
979 raw->dd_id = dd_id;
980 raw->dds_id = 0;
981 } else {
982 free(raw);
983 free(iscsi);
984 raw = NULL;
985 isnslog(LOG_DEBUG, "make_raw_assoc_iscsi", "malloc failed.");
988 return (raw);
992 * ****************************************************************************
994 * make_raw_assoc_dd:
995 * Make raw SCN data with a Discovery Domain Set member association.
997 * obj - the member association object.
998 * return - the raw SCN data.
1000 * ****************************************************************************
1002 static scn_raw_t *
1003 make_raw_assoc_dd(
1004 isns_obj_t *obj
1007 scn_raw_t *raw;
1009 raw = (scn_raw_t *)malloc(sizeof (scn_raw_t));
1010 if (raw != NULL) {
1011 raw->type = obj->type;
1012 raw->uid = 0;
1013 raw->iscsi = NULL;
1014 raw->ref = 0;
1015 raw->ilen = 0;
1016 raw->nt = 0;
1017 raw->ip = NULL;
1018 raw->dd_id = get_obj_uid(obj);
1019 raw->dds_id = get_parent_uid(obj);
1020 } else {
1021 isnslog(LOG_DEBUG, "make_raw_assoc_dd", "malloc failed.");
1024 return (raw);
1028 * ****************************************************************************
1030 * scn_gen_entity:
1031 * Generate SCN with the raw SCN data from a Network Entity object.
1033 * raw - the raw SCN data.
1034 * return - the SCN.
1036 * ****************************************************************************
1038 static scn_text_t *
1039 scn_gen_entity(
1040 /* LINTED E_FUNC_ARG_UNUSED */
1041 scn_raw_t *raw
1044 return (NULL);
1048 * ****************************************************************************
1050 * scn_gen_iscsi:
1051 * Generate SCN with the raw SCN data from a Storage Node object.
1053 * raw - the raw SCN data.
1054 * return - the SCN.
1056 * ****************************************************************************
1058 static scn_text_t *
1059 scn_gen_iscsi(
1060 scn_raw_t *raw
1063 scn_text_t *text;
1065 text = (scn_text_t *)malloc(sizeof (scn_text_t));
1066 if (text != NULL) {
1067 text->flag = 0;
1068 text->ref = 1; /* start with 1 */
1069 text->uid = raw->uid;
1070 text->iscsi = raw->iscsi;
1071 raw->ref ++;
1072 text->ilen = raw->ilen;
1073 text->nt = raw->nt;
1074 text->dd_id = raw->dd_id;
1075 text->dds_id = raw->dds_id;
1076 text->next = NULL;
1077 } else {
1078 isnslog(LOG_DEBUG, "scn_gen_iscsi", "malloc failed.");
1080 return (text);
1084 * ****************************************************************************
1086 * scn_gen_portal:
1087 * Generate SCN with the raw SCN data from a Portal object.
1089 * raw - the raw SCN data.
1090 * return - the SCN.
1092 * ****************************************************************************
1094 static scn_text_t *
1095 scn_gen_portal(
1096 scn_raw_t *raw
1099 in6_addr_t *ip;
1100 uint32_t port;
1102 uint32_t pg_uid, uid;
1103 lookup_ctrl_t pg_lc, lc;
1105 uint32_t nt;
1106 uchar_t *name;
1107 int ilen;
1109 scn_text_t *text, *l = NULL;
1111 ip = raw->ip;
1112 port = raw->port;
1114 pg_lc.curr_uid = 0;
1115 pg_lc.type = OBJ_PG;
1116 pg_lc.id[0] = ATTR_INDEX_PG(ISNS_PG_PORTAL_IP_ADDR_ATTR_ID);
1117 pg_lc.op[0] = OP_MEMORY_IP6;
1118 pg_lc.data[0].ip = ip;
1119 pg_lc.id[1] = ATTR_INDEX_PG(ISNS_PG_PORTAL_PORT_ATTR_ID);
1120 pg_lc.op[1] = OP_INTEGER;
1121 pg_lc.data[1].ui = port;
1122 pg_lc.op[2] = 0;
1124 SET_UID_LCP(&lc, OBJ_ISCSI, 0);
1126 lc.id[1] = ISNS_ISCSI_NAME_ATTR_ID;
1127 lc.id[2] = ISNS_ISCSI_NODE_TYPE_ATTR_ID;
1128 lc.data[1].ptr = NULL;
1130 /* get a pg which is associated to the portal */
1131 uid = cache_lookup(&pg_lc, &pg_uid, cb_pg_node);
1132 while (pg_uid != 0) {
1133 if (uid != 0) {
1134 lc.data[0].ui = uid;
1135 (void) cache_lookup(&lc, NULL, cb_clone_attrs);
1136 name = lc.data[1].ptr;
1137 if (name != NULL) {
1138 nt = lc.data[2].ui;
1139 text = (scn_text_t *)malloc(
1140 sizeof (scn_text_t));
1141 if (text != NULL) {
1142 text->flag = 0;
1143 text->ref = 1; /* start with 1 */
1144 text->uid = uid;
1145 text->iscsi = name;
1146 ilen = strlen((char *)name);
1147 ilen += 4 - (ilen % 4);
1148 text->ilen = ilen;
1149 text->nt = nt;
1150 text->dd_id = 0;
1151 text->dds_id = 0;
1152 text->next = l;
1153 l = text;
1154 } else {
1155 free(name);
1156 isnslog(LOG_DEBUG, "scn_gen_portal",
1157 "malloc failed.");
1159 lc.data[1].ptr = NULL;
1160 } else {
1161 isnslog(LOG_WARNING, "scn_gen_portal",
1162 "cannot get node name.");
1166 /* get the next pg */
1167 pg_lc.curr_uid = pg_uid;
1168 uid = cache_lookup(&pg_lc, &pg_uid, cb_pg_node);
1171 /* update the iscsi storage node object */
1172 raw->event = ISNS_OBJECT_UPDATED;
1174 return (l);
1178 * ****************************************************************************
1180 * scn_gen_assoc_dd:
1181 * Generate SCN with the raw SCN data from a DD membership object.
1183 * raw - the raw SCN data.
1184 * return - the SCN.
1186 * ****************************************************************************
1188 static scn_text_t *
1189 scn_gen_assoc_dd(
1190 /* LINTED E_FUNC_ARG_UNUSED */
1191 scn_raw_t *raw
1194 return (NULL);
1198 * ****************************************************************************
1200 * make_scn:
1201 * Make a SCN with an event and an object.
1203 * event - the event.
1204 * obj - the object.
1205 * return - always successful (0).
1207 * ****************************************************************************
1210 make_scn(
1211 uint32_t event,
1212 isns_obj_t *obj
1215 scn_raw_t *raw = NULL;
1217 scn_raw_t *(*f)(isns_obj_t *) = make_raw[obj->type];
1219 if (f != NULL) {
1220 /* make raw scn data */
1221 raw = f(obj);
1223 if (raw != NULL) {
1224 /* trigger an scn event */
1225 raw->event = event;
1226 (void) queue_msg_set(scn_q, SCN_SET, (void *)raw);
1229 return (0);
1233 * data structure of the SCN state transition table.
1235 typedef struct scn_tbl {
1236 int state;
1237 uint32_t event;
1238 isns_type_t type;
1239 int (*sf)(scn_raw_t *);
1240 int next_state;
1241 } scn_tbl_t;
1244 * the SCN state transition table.
1246 static const scn_tbl_t stbl[] = {
1247 { -1, 0, OBJ_PG, NULL, 0 },
1248 { -1, 0, OBJ_DD, NULL, 0 },
1249 { -1, 0, OBJ_DDS, NULL, 0 },
1251 { 0, ISNS_OBJECT_ADDED, OBJ_ENTITY, NULL, 1 },
1252 { 1, ISNS_OBJECT_ADDED, OBJ_ISCSI, sf_gen, 1 },
1253 { 1, ISNS_OBJECT_ADDED, 0, NULL, 1 },
1255 { 0, ISNS_OBJECT_UPDATED, OBJ_ENTITY, sf_gen, 2 },
1256 { 2, ISNS_OBJECT_UPDATED, 0, NULL, 2 },
1257 { 2, ISNS_OBJECT_ADDED, OBJ_ISCSI, sf_gen, 2 },
1258 { 2, ISNS_OBJECT_ADDED, 0, NULL, 2 },
1260 { 0, ISNS_OBJECT_REMOVED, OBJ_ENTITY, NULL, 3 },
1261 { 0, ISNS_OBJECT_REMOVED, 0, sf_gen, 4 },
1262 { 3, ISNS_OBJECT_REMOVED, OBJ_ISCSI, sf_gen, 3 },
1263 { 3, ISNS_OBJECT_REMOVED, 0, NULL, 3 },
1264 { 4, ISNS_OBJECT_REMOVED, 0, sf_gen, 4 },
1266 { 0, ISNS_MEMBER_ADDED, OBJ_ASSOC_ISCSI, sf_gen, 5 },
1267 { 5, ISNS_MEMBER_ADDED, OBJ_ASSOC_ISCSI, sf_gen, 5 },
1269 { 0, ISNS_MEMBER_ADDED, OBJ_ASSOC_DD, sf_gen, 6 },
1270 { 6, ISNS_MEMBER_ADDED, OBJ_ASSOC_DD, sf_gen, 6 },
1272 { 0, ISNS_MEMBER_REMOVED, OBJ_ASSOC_ISCSI, sf_gen, 7 },
1273 { 7, ISNS_MEMBER_REMOVED, OBJ_ASSOC_ISCSI, sf_gen, 7 },
1275 { 0, ISNS_MEMBER_REMOVED, OBJ_ASSOC_DD, sf_gen, 8 },
1276 { 8, ISNS_MEMBER_REMOVED, OBJ_ASSOC_DD, sf_gen, 8 },
1278 { -1, 0, 0, sf_error, -1 }
1282 * ****************************************************************************
1284 * scn_disp1:
1285 * Dispatch one SCN to one SCN entry.
1287 * event - the event.
1288 * p - the SCN entry.
1289 * t - the SCN.
1290 * return - always successful (0).
1292 * ****************************************************************************
1294 static int
1295 scn_disp1(
1296 uint32_t event,
1297 scn_registry_t *p,
1298 scn_text_t *t
1301 scn_t *s, *r = NULL;
1302 scn_list_t *l, **lp;
1304 s = p->scn;
1306 while (s != NULL) {
1307 if (s->event == event) {
1308 l = s->data.list;
1309 do {
1310 if (l->data.text->uid == t->uid) {
1311 /* duplicated */
1312 return (0);
1314 lp = &l->next;
1315 l = *lp;
1316 } while (l != NULL);
1317 break;
1319 r = s;
1320 s = s->next;
1323 l = (scn_list_t *)malloc(sizeof (scn_list_t));
1324 if (l != NULL) {
1325 if (s == NULL) {
1326 s = (scn_t *)malloc(sizeof (scn_t));
1327 if (s != NULL) {
1328 s->event = event;
1329 s->next = NULL;
1330 if (r != NULL) {
1331 r->next = s;
1332 } else {
1333 p->scn = s;
1335 lp = &s->data.list;
1336 } else {
1337 free(l);
1338 isnslog(LOG_DEBUG, "scn_disp1",
1339 "malloc scn failed.\n");
1340 return (0);
1344 t->ref ++;
1345 l->data.text = t;
1346 l->next = NULL;
1347 *lp = l;
1348 } else {
1349 isnslog(LOG_DEBUG, "scn_disp1",
1350 "malloc list failed.\n");
1353 return (0);
1357 * ****************************************************************************
1359 * scn_disp1:
1360 * Dispatch one SCN to every SCN entry and update the dispatch status.
1362 * event - the event.
1363 * text - the SCN.
1364 * return - always successful (0).
1366 * ****************************************************************************
1368 static int
1369 scn_disp(
1370 uint32_t event,
1371 scn_text_t *text
1374 scn_registry_t *registry, *p;
1375 uint32_t dd_id = 0;
1377 scn_text_t *t;
1379 uint32_t e;
1381 registry = scn_registry;
1383 t = text;
1384 while (t != NULL) {
1385 e = event;
1386 if (t->flag == 0) {
1387 if (e & ISNS_MEMBER_ADDED) {
1388 e |= ISNS_OBJECT_ADDED;
1389 } else if (e & ISNS_MEMBER_REMOVED) {
1390 e |= ISNS_OBJECT_REMOVED;
1393 p = registry;
1394 while (p != NULL) {
1395 if (SCN_TEST(e, p->bitmap, p->uid, t->uid, t->nt)) {
1396 if (p->bitmap & ISNS_MGMT_REG) {
1397 /* management scn are not bound */
1398 /* by discovery domain service. */
1399 dd_id = 1;
1400 } else {
1401 dd_id = 0;
1402 /* lock the cache for reading */
1403 (void) cache_lock_read();
1404 /* verify common dd */
1405 do {
1406 dd_id = get_common_dd(
1407 p->uid,
1408 t->uid,
1409 dd_id);
1410 } while (dd_id > 0 &&
1411 is_dd_active(dd_id) == 0);
1412 /* unlock the cache */
1413 (void) cache_unlock_nosync();
1415 if (dd_id != 0) {
1416 (void) scn_disp1(e, p, t);
1419 p = p->next;
1421 t = t->next;
1424 while (text != NULL) {
1425 t = text->next;
1426 /* clean up the scn text(s) which nobody cares about. */
1427 free_scn_text(text);
1428 text = t;
1431 if (dd_id != 0) {
1432 /* scn(s) are dispatched. */
1433 scn_dispatched = 1;
1436 return (0);
1440 * ****************************************************************************
1442 * sf_gen:
1443 * State transition function which generates and dispatches SCN(s).
1445 * raw - the raw SCN data.
1446 * return - always successful (0).
1448 * ****************************************************************************
1450 static int
1451 sf_gen(
1452 scn_raw_t *raw
1455 uint32_t event;
1457 scn_text_t *(*gen)(scn_raw_t *);
1458 scn_text_t *text = NULL;
1460 gen = scn_gen[raw->type];
1461 if (gen != NULL) {
1462 text = gen(raw);
1465 event = raw->event;
1466 if (text != NULL) {
1467 (void) scn_disp(event, text);
1470 return (0);
1474 * ****************************************************************************
1476 * sf_error:
1477 * State transition function for an error state. It free any SCN(s)
1478 * which have been generated and dispatched previously.
1480 * raw - the raw SCN data.
1481 * return - always successful (0).
1483 * ****************************************************************************
1485 static int
1486 sf_error(
1487 /* LINTED E_FUNC_ARG_UNUSED */
1488 scn_raw_t *raw
1491 free_scn();
1493 return (0);
1497 * ****************************************************************************
1499 * scn_transition:
1500 * Performs the state transition when a SCN event occurs.
1502 * state - the previous state.
1503 * raw - the raw SCN data.
1504 * return - the next state.
1506 * ****************************************************************************
1508 static int
1509 scn_transition(
1510 int state,
1511 scn_raw_t *raw
1514 uint32_t event = raw->event;
1515 isns_type_t type = raw->type;
1517 int new_state = state;
1519 const scn_tbl_t *tbl;
1521 tbl = &stbl[0];
1522 for (;;) {
1523 if ((tbl->state == -1 || tbl->state == state) &&
1524 (tbl->event == 0 || tbl->event == event) &&
1525 (tbl->type == 0 || tbl->type == type)) {
1526 if (tbl->next_state != 0) {
1527 new_state = tbl->next_state;
1529 if (tbl->sf != NULL) {
1530 tbl->sf(raw);
1532 break;
1534 tbl ++;
1537 if (new_state == -1) {
1538 isnslog(LOG_DEBUG, "scn_transition",
1539 "prev state: %d new event: 0x%x new object: %d.\n",
1540 state, event, type);
1541 new_state = 0;
1544 state = new_state;
1546 return (state);
1550 * ****************************************************************************
1552 * connect_to:
1553 * Create socket connection with peer network portal.
1555 * sz - the size of the ip addr.
1556 * in - the ipv4 address.
1557 * in6 - the ipv6 address.
1558 * port2- the port info.
1559 * return - the socket descriptor.
1561 * ****************************************************************************
1564 connect_to(
1565 int sz,
1566 in_addr_t in,
1567 /* LINTED E_FUNC_ARG_UNUSED */
1568 in6_addr_t *in6,
1569 uint32_t port2
1572 int so = -1;
1574 union {
1575 struct sockaddr sin;
1576 struct sockaddr_in in;
1577 struct sockaddr_in6 in6;
1578 } ca = { 0 };
1580 int tcp;
1581 uint16_t port;
1583 tcp = (port2 & 0x10000) == 0 ? 1 : 0;
1584 port = (uint16_t)(port2 & 0xFFFF);
1585 if (sz == sizeof (in_addr_t)) {
1586 if (tcp != 0) {
1587 so = socket(AF_INET, SOCK_STREAM, 0);
1588 if (so != -1) {
1589 ca.in.sin_family = AF_INET;
1590 ca.in.sin_port = htons(port);
1591 ca.in.sin_addr.s_addr = in;
1592 if (connect(so, &ca.sin, sizeof (ca.in)) !=
1593 0) {
1594 isnslog(LOG_DEBUG, "connect_to",
1595 "connect() failed %%m.");
1596 (void) close(so);
1597 so = -1;
1599 } else {
1600 isnslog(LOG_DEBUG, "connect_to",
1601 "socket() failed %%m.");
1603 } else {
1604 /* FIXME: UDP support */
1605 isnslog(LOG_DEBUG, "connect_to", "No UDP support.");
1607 } else {
1608 /* FIXME: IPv6 support */
1609 isnslog(LOG_DEBUG, "connect_to", "No IPv6 support.");
1612 return (so);
1616 * ****************************************************************************
1618 * emit_scn:
1619 * Emit the SCN to any portal of the peer storage node.
1621 * list - the list of portal.
1622 * pdu - the SCN packet.
1623 * pl - the SCN packet payload length.
1624 * return - always successful (0).
1626 * ****************************************************************************
1628 static int
1629 emit_scn(
1630 scn_list_t *list,
1631 isns_pdu_t *pdu,
1632 size_t pl
1635 int so = 0;
1636 scn_list_t *l;
1637 scn_portal_t *p;
1639 isns_pdu_t *rsp = NULL;
1640 size_t rsp_sz;
1642 pdu->version = htons((uint16_t)ISNSP_VERSION);
1643 pdu->func_id = htons((uint16_t)ISNS_SCN);
1644 pdu->xid = htons(get_server_xid());
1646 l = list;
1647 while (l != NULL) {
1648 p = l->data.portal;
1649 so = connect_to(p->sz, p->ip.in, p->ip.in6, p->port);
1650 if (so != -1) {
1651 if (isns_send_pdu(so, pdu, pl) == 0) {
1652 /* This may help Solaris iSCSI Initiator */
1653 /* not to panic frequently. */
1654 (void) isns_rcv_pdu(so, &rsp, &rsp_sz,
1655 ISNS_RCV_SHORT_TIMEOUT);
1656 } else {
1657 isnslog(LOG_DEBUG, "emit_scn",
1658 "sending packet failed.");
1660 (void) close(so);
1661 /* p->so = so; */
1662 break;
1664 l = l->next;
1667 if (rsp != NULL) {
1668 #ifdef DEBUG
1669 dump_pdu1(rsp);
1670 #endif
1671 free(rsp);
1674 return (0);
1678 * ****************************************************************************
1680 * scn_trigger1:
1681 * Trigger one SCN for one SCN entry.
1683 * t - the time that SCN is being triggered.
1684 * p - the SCN entry.
1685 * return - always successful (0).
1687 * ****************************************************************************
1689 static int
1690 scn_trigger1(
1691 time_t t,
1692 scn_registry_t *p
1695 int ec;
1697 isns_pdu_t *pdu = NULL;
1698 size_t sz;
1699 size_t pl;
1701 scn_t *s;
1702 scn_list_t *l;
1703 scn_text_t *x;
1705 union {
1706 uint32_t i32;
1707 uint64_t i64;
1708 } u;
1710 #ifdef DEBUG
1711 char buff[1024] = { 0 };
1712 char *logbuff = buff;
1713 #endif
1715 ec = pdu_reset_scn(&pdu, &pl, &sz);
1716 if (pdu == NULL) {
1717 goto scn_done;
1720 /* add destination attribute */
1721 ec = pdu_add_tlv(&pdu, &pl, &sz,
1722 ISNS_ISCSI_NAME_ATTR_ID,
1723 p->nlen,
1724 (void *)p->name, 0);
1725 if (ec != 0) {
1726 goto scn_done;
1729 #ifdef DEBUG
1730 sprintf(logbuff, "==>%s ", p->name);
1731 logbuff += strlen(logbuff);
1732 #endif
1734 /* add timestamp */
1735 u.i64 = BE_64((uint64_t)t);
1736 ec = pdu_add_tlv(&pdu, &pl, &sz,
1737 ISNS_TIMESTAMP_ATTR_ID,
1739 (void *)&u.i64, 1);
1741 s = p->scn;
1742 while (s != NULL && ec == 0) {
1743 u.i32 = htonl(s->event);
1744 ec = pdu_add_tlv(&pdu, &pl, &sz,
1745 ISNS_ISCSI_SCN_BITMAP_ATTR_ID,
1747 (void *)&u.i32, 1);
1748 #ifdef DEBUG
1749 sprintf(logbuff, "EVENT [%d] ", s->event);
1750 logbuff += strlen(logbuff);
1751 #endif
1752 l = s->data.list;
1753 while (l != NULL && ec == 0) {
1754 x = l->data.text;
1755 if (x->flag == 0) {
1756 ec = pdu_add_tlv(&pdu, &pl, &sz,
1757 ISNS_ISCSI_NAME_ATTR_ID,
1758 x->ilen, (void *)x->iscsi, 0);
1759 #ifdef DEBUG
1760 sprintf(logbuff, "FROM [%s] ", x->iscsi);
1761 logbuff += strlen(logbuff);
1762 #endif
1763 if (ec == 0 &&
1764 (p->bitmap &
1765 (ISNS_MEMBER_ADDED |
1766 ISNS_MEMBER_REMOVED))) {
1767 /* management SCN */
1768 u.i32 = htonl(x->dd_id);
1769 ec = pdu_add_tlv(&pdu, &pl, &sz,
1770 ISNS_DD_ID_ATTR_ID,
1771 4, (void *)&u.i32, 1);
1772 #ifdef DEBUG
1773 sprintf(logbuff, "IN DD [%d] ",
1774 x->dd_id);
1775 logbuff += strlen(logbuff);
1776 #endif
1778 } else {
1779 /* add(remove) dd to(from) dd-set */
1780 u.i32 = htonl(x->dd_id);
1781 ec = pdu_add_tlv(&pdu, &pl, &sz,
1782 ISNS_DD_ID_ATTR_ID,
1783 4, (void *)&u.i32, 1);
1784 u.i32 = htonl(x->dds_id);
1785 if (ec == 0) {
1786 ec = pdu_add_tlv(&pdu, &pl, &sz,
1787 ISNS_DD_ID_ATTR_ID,
1788 4, (void *)&u.i32, 1);
1790 #ifdef DEBUG
1791 sprintf(logbuff, "FROM [%d] ", x->dd_id);
1792 logbuff += strlen(logbuff);
1793 sprintf(logbuff, "IN [%d] ", x->dds_id);
1794 logbuff += strlen(logbuff);
1795 #endif
1797 l = l->next;
1799 s = s->next;
1802 scn_done:
1803 if (ec == 0) {
1804 #ifdef DEBUG
1805 isnslog(LOG_DEBUG, "scn_trigger1", buff);
1806 #endif
1807 ec = emit_scn(p->portal.l, pdu, pl);
1808 } else {
1809 isnslog(LOG_DEBUG, "scn_trigger1", " failed.\n");
1812 free(pdu);
1814 return (0);
1818 * ****************************************************************************
1820 * scn_trigger:
1821 * Trigger one SCN for every SCN entry.
1823 * return - always successful (0).
1825 * ****************************************************************************
1827 static int
1828 scn_trigger(
1831 time_t t;
1832 scn_registry_t *p;
1834 t = time(NULL);
1836 p = scn_registry;
1837 while (p != NULL) {
1838 if (p->scn != NULL) {
1839 (void) scn_trigger1(t, p);
1841 p = p->next;
1844 return (0);
1848 * global functions.
1852 * ****************************************************************************
1854 * scn_list_load:
1855 * Load one SCN entry and add it to the SCN entry list.
1857 * uid - the Storage Node object UID.
1858 * node - the Storage Node name.
1859 * nlen - the length of the name.
1860 * bitmap - the SCN bitmap.
1861 * return - error code.
1863 * ****************************************************************************
1866 scn_list_load(
1867 uint32_t uid,
1868 uchar_t *node,
1869 uint32_t nlen,
1870 uint32_t bitmap
1873 int ec = 0;
1875 scn_registry_t *list;
1876 uchar_t *name;
1878 list = (scn_registry_t *)malloc(sizeof (scn_registry_t));
1879 name = (uchar_t *)malloc(nlen);
1881 if (list != NULL && name != NULL) {
1882 list->uid = uid;
1883 (void) strcpy((char *)name, (char *)node);
1884 list->name = name;
1885 list->nlen = nlen;
1886 list->bitmap = bitmap;
1887 list->portal.l = NULL;
1888 list->scn = NULL;
1889 list->next = NULL;
1890 ASSERT(scn_q == NULL);
1891 (void) scn_list_add(list);
1892 } else {
1893 free(list);
1894 free(name);
1895 ec = ISNS_RSP_INTERNAL_ERROR;
1898 return (ec);
1902 * ****************************************************************************
1904 * verify_scn_portal:
1905 * Extract and verify portals for every SCN entry(s) after they are
1906 * loaded from data store, for those which do not have a SCN portal,
1907 * remove it from the SCN entry list.
1909 * return - 1: error occurs, otherwise 0.
1911 * ****************************************************************************
1914 verify_scn_portal(
1917 scn_registry_t **pp, *e;
1918 scn_portal_t *p;
1920 pp = &scn_registry;
1921 while (*pp != NULL) {
1922 e = *pp;
1923 p = extract_scn_portal(e->name);
1924 if (p != NULL) {
1925 if (scn_add_portal(e, p) != 0) {
1926 return (1);
1929 if (e->portal.l != NULL) {
1930 pp = &e->next;
1931 } else {
1932 /* remove this entry */
1933 *pp = e->next;
1934 free_entry(e);
1936 /* free the unused portal(s) */
1937 free_portal(p);
1940 return (0);
1944 * ****************************************************************************
1946 * add_scn_entry:
1947 * Add a SCN entry.
1949 * node - the Storage Node name.
1950 * nlen - the length of the name.
1951 * bitmap - the SCN bitmap.
1952 * return - error code.
1954 * ****************************************************************************
1957 add_scn_entry(
1958 uchar_t *node,
1959 uint32_t nlen,
1960 uint32_t bitmap
1963 int ec = 0;
1965 uint32_t mgmt;
1966 scn_portal_t *p;
1968 lookup_ctrl_t lc;
1969 uint32_t uid;
1970 scn_registry_t *e;
1971 uchar_t *name;
1973 mgmt = bitmap & (
1974 ISNS_MGMT_REG |
1975 ISNS_MEMBER_REMOVED |
1976 ISNS_MEMBER_ADDED);
1978 if ((mgmt > 0 &&
1979 (mgmt_scn == 0 ||
1980 mgmt < ISNS_MGMT_REG ||
1981 is_control_node(node) == 0)) ||
1982 (p = extract_scn_portal(node)) == NULL) {
1983 return (ISNS_RSP_SCN_REGIS_REJECTED);
1986 e = (scn_registry_t *)malloc(sizeof (scn_registry_t));
1987 name = (uchar_t *)malloc(nlen);
1988 if (e != NULL && name != NULL) {
1989 lc.type = OBJ_ISCSI;
1990 lc.curr_uid = 0;
1991 lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
1992 lc.data[0].ptr = node;
1993 lc.op[0] = OP_STRING;
1994 lc.op[1] = 0;
1995 lc.data[2].ui = bitmap;
1996 ec = cache_lookup(&lc, &uid, cb_update_scn_bitmap);
1997 if (uid == 0) {
1998 ec = ISNS_RSP_SCN_REGIS_REJECTED;
2000 if (ec == 0) {
2001 e->uid = uid;
2002 (void) strcpy((char *)name, (char *)node);
2003 e->name = name;
2004 e->nlen = nlen;
2005 e->bitmap = bitmap;
2006 e->portal.p = p;
2007 e->scn = NULL;
2008 e->next = NULL;
2009 (void) queue_msg_set(scn_q, SCN_ADD, (void *)e);
2011 } else {
2012 ec = ISNS_RSP_INTERNAL_ERROR;
2015 if (ec != 0) {
2016 free(e);
2017 free(name);
2018 free_portal(p);
2021 return (ec);
2025 * ****************************************************************************
2027 * remove_scn_entry:
2028 * Remove a SCN entry.
2030 * node - the Storage Node name.
2031 * return - error code.
2033 * ****************************************************************************
2036 remove_scn_entry(
2037 uchar_t *node
2040 int ec = 0;
2042 lookup_ctrl_t lc;
2043 uint32_t uid;
2045 lc.type = OBJ_ISCSI;
2046 lc.curr_uid = 0;
2047 lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
2048 lc.data[0].ptr = node;
2049 lc.op[0] = OP_STRING;
2050 lc.op[1] = 0;
2051 lc.data[2].ui = 0;
2052 ec = cache_lookup(&lc, &uid, cb_update_scn_bitmap);
2053 if (ec == 0 && uid != 0) {
2054 (void) queue_msg_set(scn_q, SCN_REMOVE, (void *)uid);
2057 return (ec);
2061 * ****************************************************************************
2063 * remove_scn_portal:
2064 * Remove a portal from every SCN entry.
2066 * uid - the Portal object UID.
2067 * return - alrays successful (0).
2069 * ****************************************************************************
2072 remove_scn_portal(
2073 uint32_t uid
2076 (void) queue_msg_set(scn_q, SCN_REMOVE_P, (void *)uid);
2078 return (0);
2082 * ****************************************************************************
2084 * scn_proc:
2085 * The entry point of the SCN thread. It listens on the SCN message
2086 * queue and process every SCN related stuff.
2088 * arg - nothing.
2089 * return - NULL.
2091 * ****************************************************************************
2093 void *
2094 scn_proc(
2095 /* LINTED E_FUNC_ARG_UNUSED */
2096 void *arg
2099 int state = 0;
2101 scn_raw_t *raw;
2102 msg_text_t *msg;
2104 for (;;) {
2105 msg = queue_msg_get(scn_q);
2106 switch (msg->id) {
2107 case SCN_ADD:
2108 (void) scn_list_add((scn_registry_t *)msg->data);
2109 break;
2110 case SCN_REMOVE:
2111 (void) scn_list_remove((uint32_t)msg->data);
2112 break;
2113 case SCN_REMOVE_P:
2114 (void) scn_remove_portal((uint32_t)msg->data);
2115 break;
2116 case SCN_SET:
2117 raw = (scn_raw_t *)msg->data;
2118 state = scn_transition(state, raw);
2119 /* free the raw data */
2120 free_raw(raw);
2121 break;
2122 case SCN_TRIGGER:
2123 if (scn_dispatched != 0) {
2124 (void) scn_trigger();
2126 case SCN_IGNORE:
2127 /* clean the scn(s) */
2128 free_scn();
2129 /* reset the state */
2130 state = 0;
2131 /* reset the scn_dispatched flag */
2132 scn_dispatched = 0;
2133 break;
2134 case SCN_STOP:
2135 queue_msg_free(msg);
2136 return (NULL);
2137 default:
2138 break;
2140 queue_msg_free(msg);