summaryrefslogtreecommitdiff
path: root/usr/src/cmd/isns/isnsd/dd.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/isns/isnsd/dd.c')
-rw-r--r--usr/src/cmd/isns/isnsd/dd.c1855
1 files changed, 1855 insertions, 0 deletions
diff --git a/usr/src/cmd/isns/isnsd/dd.c b/usr/src/cmd/isns/isnsd/dd.c
new file mode 100644
index 0000000000..039ca4b77a
--- /dev/null
+++ b/usr/src/cmd/isns/isnsd/dd.c
@@ -0,0 +1,1855 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "isns_server.h"
+#include "isns_msgq.h"
+#include "isns_htab.h"
+#include "isns_dd.h"
+#include "isns_cache.h"
+#include "isns_obj.h"
+#include "isns_pdu.h"
+#include "isns_dseng.h"
+#include "isns_scn.h"
+#include "isns_utils.h"
+
+/*
+ * extern global variables
+ */
+extern const int UID_ATTR_INDEX[MAX_OBJ_TYPE_FOR_SIZE];
+
+extern msg_queue_t *sys_q;
+extern msg_queue_t *scn_q;
+
+extern int cache_flag;
+
+/*
+ * extern functions.
+ */
+
+/*
+ * global variables
+ */
+
+/*
+ * local variables
+ */
+
+/*
+ * local functions.
+ */
+static matrix_t *new_matrix(uint32_t, uint32_t);
+
+static int
+cb_update_ds_attr(
+ void *p1,
+ void *p2
+)
+{
+ int ec = 0;
+
+ isns_obj_t *obj = (isns_obj_t *)p1;
+ lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
+ uint32_t tag = lcp->id[1];
+ uint32_t which;
+ isns_attr_t *attr;
+
+ uint32_t len;
+ uchar_t *name;
+ lookup_ctrl_t lc;
+ uint32_t uid;
+
+ switch (tag) {
+ case ISNS_DD_NAME_ATTR_ID:
+ which = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
+ break;
+ case ISNS_DD_FEATURES_ATTR_ID:
+ which = ATTR_INDEX_DD(ISNS_DD_FEATURES_ATTR_ID);
+ break;
+ case ISNS_DD_SET_NAME_ATTR_ID:
+ which = ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID);
+ break;
+ case ISNS_DD_SET_STATUS_ATTR_ID:
+ which = ATTR_INDEX_DDS(ISNS_DD_SET_STATUS_ATTR_ID);
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ attr = &obj->attrs[which];
+
+ switch (tag) {
+ case ISNS_DD_NAME_ATTR_ID:
+ case ISNS_DD_SET_NAME_ATTR_ID:
+ len = lcp->data[1].ui;
+ name = lcp->data[2].ptr;
+ lc.type = lcp->type;
+ lc.curr_uid = 0;
+ lc.id[0] = which;
+ lc.op[0] = OP_STRING;
+ lc.data[0].ptr = name;
+ lc.op[1] = 0;
+ /* check if the name is in use */
+ uid = is_obj_there(&lc);
+ if (uid != 0) {
+ if (uid != get_obj_uid(obj)) {
+ ec = ERR_NAME_IN_USE;
+ }
+ return (ec);
+ }
+ if (len > attr->len) {
+ uchar_t *tmp = (uchar_t *)malloc(len);
+ if (tmp != NULL) {
+ free(attr->value.ptr);
+ attr->value.ptr = tmp;
+ } else {
+ /* memory exhausted */
+ return (ISNS_RSP_INTERNAL_ERROR);
+ }
+ }
+ (void) strcpy((char *)attr->value.ptr, (char *)name);
+ attr->len = len;
+ break;
+ case ISNS_DD_FEATURES_ATTR_ID:
+ case ISNS_DD_SET_STATUS_ATTR_ID:
+ if (attr->tag != tag ||
+ attr->value.ui != lcp->data[1].ui) {
+ attr->tag = tag;
+ attr->len = 4;
+ attr->value.ui = lcp->data[1].ui;
+ } else {
+ return (ec);
+ }
+ break;
+ }
+
+ /* cache has been updated, set the flag */
+ SET_CACHE_UPDATED();
+
+ /* update data store */
+ if (sys_q != NULL) {
+ ec = write_data(DATA_UPDATE, obj);
+ }
+
+ return (ec);
+}
+
+static isns_obj_t *
+make_member_node(
+ const uint32_t uid,
+ isns_attr_t *attr1
+)
+{
+ isns_obj_t *obj = NULL;
+ isns_attr_t *attr;
+ isns_attr_t tmp;
+
+ switch (attr1->tag) {
+ case ISNS_DD_ISCSI_NAME_ATTR_ID:
+ obj = obj_calloc(OBJ_ISCSI);
+ attr = &obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID)];
+ tmp.tag = ISNS_ISCSI_NAME_ATTR_ID;
+ tmp.len = attr1->len;
+ tmp.value.ptr = attr1->value.ptr;
+ if (assign_attr(attr, &tmp) != 0) {
+ free_object(obj);
+ obj = NULL;
+ } else if (uid != 0) {
+ (void) set_obj_uid(obj, uid);
+ }
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ return (obj);
+}
+
+static isns_obj_t *
+make_member_dd(
+ const uint32_t uid
+)
+{
+ isns_obj_t *obj = NULL;
+ isns_attr_t name = { 0 };
+
+ obj = obj_calloc(OBJ_DD);
+ if (obj != NULL) {
+ (void) set_obj_uid(obj, uid);
+ name.tag = ISNS_DD_NAME_ATTR_ID;
+ if (assign_attr(
+ &obj->attrs[ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID)],
+ &name) != 0) {
+ free_object(obj);
+ obj = NULL;
+ }
+ }
+
+ return (obj);
+}
+
+static int
+get_member_info(
+ isns_obj_t *assoc,
+ uint32_t *m_type,
+ uint32_t *m_id,
+ int flag
+)
+{
+ int ec = 0;
+ lookup_ctrl_t lc = { 0 };
+
+ isns_obj_t *obj;
+ isns_attr_t *attr1, *attr2;
+ uint32_t tmp_id = 0;
+ int i = 0;
+
+ *m_type = 0;
+ *m_id = 0;
+
+ attr1 = &assoc->attrs[ATTR_INDEX_ASSOC_ISCSI(
+ ISNS_DD_ISCSI_INDEX_ATTR_ID)];
+ attr2 = &assoc->attrs[ATTR_INDEX_ASSOC_ISCSI(
+ ISNS_DD_ISCSI_NAME_ATTR_ID)];
+
+ lc.type = OBJ_ISCSI;
+ if (attr1->tag != 0 && attr1->value.ui != 0) {
+ *m_id = attr1->value.ui;
+ lc.id[i] = UID_ATTR_INDEX[OBJ_ISCSI];
+ lc.op[i] = OP_INTEGER;
+ lc.data[i].ui = *m_id;
+ i ++;
+ }
+ if (attr2->tag != 0) {
+ lc.id[i] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
+ lc.op[i] = OP_STRING;
+ lc.data[i].ptr = attr2->value.ptr;
+ i ++;
+ } else if (scn_q != NULL || sys_q != NULL) {
+ lc.id[i] = ISNS_ISCSI_NAME_ATTR_ID;
+ }
+
+ /* a member id or member name is required */
+ if (i == 0) {
+ if (flag != 0) {
+ /* add member */
+ return (ISNS_RSP_INVALID_REGIS);
+ } else {
+ /* remove member (isnsp msg request only) */
+ return (0);
+ }
+ }
+
+ ec = cache_lookup(&lc, &tmp_id, cb_clone_attrs);
+
+ if (ec == 0 && tmp_id == 0) {
+ if (flag != 0) {
+ /* add member */
+ if (attr1->tag == 0 || sys_q == NULL) {
+ /* object does not exist, create one */
+ obj = make_member_node(*m_id, attr2);
+ if (obj == NULL) {
+ ec = ISNS_RSP_INTERNAL_ERROR;
+ } else {
+ ec = register_assoc(obj, &tmp_id);
+ if (ec != 0) {
+ free_object(obj);
+ }
+ }
+ } else {
+ /* don't create it if uid is specified */
+ ec = ISNS_RSP_NO_SUCH_ENTRY;
+ }
+ } else {
+ /* remove member */
+ ec = ERR_NO_SUCH_ASSOCIATION;
+ }
+ }
+
+ if (attr1->tag == 0) {
+ attr1->tag = ISNS_DD_ISCSI_INDEX_ATTR_ID;
+ attr1->len = 4;
+ attr1->value.ui = tmp_id;
+ } else if (attr2->tag == 0) {
+ attr2->tag = ISNS_DD_ISCSI_NAME_ATTR_ID;
+ attr2->len = strlen((char *)lc.data[1].ptr);
+ attr2->len += 4 - (attr2->len % 4);
+ attr2->value.ptr = lc.data[1].ptr;
+ }
+
+ *m_type = OBJ_ISCSI;
+ *m_id = tmp_id;
+
+ return (ec);
+}
+
+static int
+get_dds_member_info(
+ uint32_t m_id
+)
+{
+ int ec = 0;
+ lookup_ctrl_t lc;
+
+ isns_obj_t *obj;
+ uint32_t tmp_id;
+
+ if (m_id != 0) {
+ SET_UID_LCP(&lc, OBJ_DD, m_id);
+ } else {
+ return (ISNS_RSP_INVALID_REGIS);
+ }
+
+ tmp_id = is_obj_there(&lc);
+
+ if (tmp_id == 0) {
+ /* object does not exist, create one */
+ obj = make_member_dd(m_id);
+ if (obj != NULL) {
+ ec = register_object(obj, NULL, NULL);
+ } else {
+ /* no memory */
+ ec = ISNS_RSP_INTERNAL_ERROR;
+ }
+ }
+
+ return (ec);
+}
+
+static int
+update_matrix(
+ matrix_t *matrix,
+ const uchar_t op,
+ const uint32_t puid,
+ const uint32_t m_id,
+ int ddd_flag
+)
+{
+ int ec = 0;
+
+ uint32_t new_x = 0, new_y = 0;
+ matrix_t *tmp_matrix;
+
+ uint32_t i, j, k = 0;
+ uint32_t x_info;
+ bmp_t *bmp, *tmp_bmp;
+
+ uint32_t primary = GET_PRIMARY(m_id);
+ uint32_t second = GET_SECOND(m_id);
+
+ if (primary >= matrix->x) {
+ if (op == '-') {
+ ec = ERR_NO_SUCH_ASSOCIATION;
+ goto update_matrix_done;
+ }
+ /* enlarge the matrix on x axis */
+ if (primary >= matrix->x * 2) {
+ new_x = primary + 1;
+ } else {
+ new_x = matrix->x * 2;
+ }
+ }
+
+ i = 0;
+ while (i < matrix->y) {
+ bmp = MATRIX_X_UNIT(matrix, i);
+ x_info = MATRIX_X_INFO(bmp);
+ if (x_info == puid) {
+ break;
+ } else if (x_info == 0 && k == 0) {
+ /* the first available slot */
+ k = i;
+ }
+ i ++;
+ }
+ if (i == matrix->y) {
+ if (op == '-') {
+ ec = ERR_NO_SUCH_ASSOCIATION;
+ goto update_matrix_done;
+ } else if (k == 0) {
+ new_y = matrix->y * 2;
+ } else {
+ i = k;
+ }
+ }
+
+ /*
+ * enlarge the matrix.
+ */
+ if (new_x != 0 || new_y != 0) {
+ if (new_x == 0) {
+ new_x = matrix->x;
+ }
+ if (new_y == 0) {
+ new_y = matrix->y;
+ }
+ tmp_matrix = new_matrix(new_x, new_y);
+ if (tmp_matrix != NULL) {
+ j = 0;
+ while (j < matrix->y) {
+ bmp = MATRIX_X_UNIT(matrix, j);
+ x_info = MATRIX_X_INFO(bmp);
+ if (x_info != 0) {
+ tmp_bmp = MATRIX_X_UNIT(tmp_matrix, j);
+ (void) memcpy((void *)tmp_bmp,
+ (void *)bmp, SIZEOF_X_UNIT(matrix));
+ }
+ j ++;
+ }
+ free(matrix->m);
+ matrix->x = tmp_matrix->x;
+ matrix->y = tmp_matrix->y;
+ matrix->m = tmp_matrix->m;
+ free(tmp_matrix);
+ } else {
+ ec = ISNS_RSP_INTERNAL_ERROR;
+ goto update_matrix_done;
+ }
+ }
+
+ bmp = MATRIX_X_UNIT(matrix, i);
+
+ MATRIX_X_INFO(bmp) = puid;
+ if (op == '+') {
+ if (TEST_MEMBERSHIP(bmp, primary, second) == 0) {
+ SET_MEMBERSHIP(bmp, primary, second);
+ SET_CACHE_UPDATED();
+ if (ddd_flag != 0) {
+ bmp = MATRIX_X_UNIT(matrix, 0);
+ ASSERT(MATRIX_X_INFO(bmp) ==
+ ISNS_DEFAULT_DD_ID);
+ CLEAR_MEMBERSHIP(bmp, primary, second);
+ }
+ } else {
+ ec = ERR_ALREADY_ASSOCIATED;
+ }
+ } else if (op == '-') {
+ if (TEST_MEMBERSHIP(bmp, primary, second) != 0) {
+ CLEAR_MEMBERSHIP(bmp, primary, second);
+ SET_CACHE_UPDATED();
+ if (ddd_flag != 0) {
+ i = 1;
+ while (i < matrix->y) {
+ bmp = MATRIX_X_UNIT(matrix, i);
+ x_info = MATRIX_X_INFO(bmp);
+ if (x_info != 0 &&
+ TEST_MEMBERSHIP(bmp,
+ primary, second) != 0) {
+ break;
+ }
+ i ++;
+ }
+ if (i == matrix->y) {
+ bmp = MATRIX_X_UNIT(matrix, 0);
+ ASSERT(MATRIX_X_INFO(bmp) ==
+ ISNS_DEFAULT_DD_ID);
+ SET_MEMBERSHIP(bmp, primary, second);
+ }
+ }
+ } else {
+ ec = ERR_NO_SUCH_ASSOCIATION;
+ }
+ }
+
+update_matrix_done:
+ return (ec);
+}
+
+/*ARGSUSED*/
+static int
+update_dd_matrix(
+ const uchar_t op,
+ const uint32_t dd_id,
+ const uint32_t m_type,
+ const uint32_t m_id
+)
+{
+ matrix_t *matrix;
+
+ ASSERT(m_type == OBJ_ISCSI);
+
+ matrix = cache_get_matrix(OBJ_DD);
+
+ return (update_matrix(matrix, op, dd_id, m_id, 1));
+}
+
+static int
+update_dds_matrix(
+ const uchar_t op,
+ const uint32_t dds_id,
+ const uint32_t m_id
+)
+{
+ matrix_t *dds_matrix = cache_get_matrix(OBJ_DDS);
+
+ return (update_matrix(dds_matrix, op, dds_id, m_id, 0));
+}
+
+static int
+clear_matrix(
+ matrix_t *matrix,
+ const uint32_t uid,
+ bmp_t **p,
+ uint32_t *n,
+ int ddd_flag
+)
+{
+ int ec = 0;
+ bmp_t *bmp;
+ uint32_t x_info;
+ int i, j;
+
+ uint32_t primary;
+ uint32_t second;
+
+ if (p != NULL) {
+ *p = NULL;
+ *n = 0;
+ }
+
+ i = 0;
+ while (i < matrix->y) {
+ bmp = MATRIX_X_UNIT(matrix, i);
+ x_info = MATRIX_X_INFO(bmp);
+ if (x_info == uid) {
+ if (p != NULL) {
+ /* dup it for caller */
+ *n = matrix->x;
+ *p = (bmp_t *)malloc(*n * sizeof (bmp_t));
+ if (*p != NULL) {
+ (void) memcpy(*p, &bmp[MATRIX_X_HEADER],
+ *n * sizeof (bmp_t));
+ } else {
+ ec = ISNS_RSP_INTERNAL_ERROR;
+ }
+ }
+ /* clean it */
+ (void) memset(bmp, 0, SIZEOF_X_UNIT(matrix));
+ break;
+ }
+ i ++;
+ }
+
+ if (ddd_flag != 0 && p != NULL) {
+ bmp = MATRIX_X_UNIT(matrix, 0);
+ ASSERT(MATRIX_X_INFO(bmp) == ISNS_DEFAULT_DD_ID);
+ /* Test the membership for each node which is a */
+ /* member in the dd that is being deleted. */
+ FOR_EACH_MEMBER(*p, *n, i, {
+ j = get_dd_id(i, 0);
+ if (j == 0) {
+ /* put it to the default dd */
+ primary = GET_PRIMARY(i);
+ second = GET_SECOND(i);
+ SET_MEMBERSHIP(bmp, primary, second);
+ }
+ });
+ }
+
+ return (ec);
+}
+
+static int
+get_matrix(
+ matrix_t *matrix,
+ const uint32_t uid,
+ bmp_t **p,
+ uint32_t *n
+)
+{
+ int ec = 0;
+ bmp_t *bmp;
+ uint32_t x_info;
+ int i;
+
+ *n = 0;
+ *p = NULL;
+
+ i = 0;
+ while (i < matrix->y) {
+ bmp = MATRIX_X_UNIT(matrix, i);
+ x_info = MATRIX_X_INFO(bmp);
+ if (x_info == uid) {
+ /* dup it for caller */
+ *n = matrix->x;
+ *p = (bmp_t *)malloc(*n * sizeof (bmp_t));
+ if (*p != NULL) {
+ (void) memcpy(*p, &bmp[MATRIX_X_HEADER],
+ *n * sizeof (bmp_t));
+ } else {
+ *n = 0;
+ ec = ISNS_RSP_INTERNAL_ERROR;
+ }
+ break;
+ }
+ i ++;
+ }
+
+ return (ec);
+}
+
+static int
+clear_dd_matrix(
+ const uint32_t dd_id,
+ bmp_t **p,
+ uint32_t *n
+)
+{
+ matrix_t *matrix = cache_get_matrix(OBJ_DD);
+
+ return (clear_matrix(matrix, dd_id, p, n, 1));
+}
+
+static int
+clear_dds_matrix(
+ const uint32_t dds_id
+)
+{
+ matrix_t *matrix = cache_get_matrix(OBJ_DDS);
+
+ return (clear_matrix(matrix, dds_id, NULL, NULL, 0));
+}
+
+int
+get_dd_matrix(
+ const uint32_t dd_id,
+ bmp_t **p,
+ uint32_t *n
+)
+{
+ matrix_t *matrix = cache_get_matrix(OBJ_DD);
+
+ return (get_matrix(matrix, dd_id, p, n));
+}
+
+int
+get_dds_matrix(
+ const uint32_t dds_id,
+ bmp_t **p,
+ uint32_t *n
+)
+{
+ matrix_t *matrix = cache_get_matrix(OBJ_DDS);
+
+ return (get_matrix(matrix, dds_id, p, n));
+}
+
+/*ARGSUSED*/
+static int
+cb_get_dds_status(
+ void *p1,
+ void *p2
+)
+{
+ isns_obj_t *obj = (isns_obj_t *)p1;
+
+ isns_attr_t *attr = &obj->attrs[
+ ATTR_INDEX_DDS(ISNS_DD_SET_STATUS_ATTR_ID)];
+
+ return (DDS_ENABLED(attr->value.ui) ? 1 : 0);
+}
+
+static int
+get_dds_status(
+ uint32_t dds_id
+)
+{
+ lookup_ctrl_t lc;
+
+ if (dds_id == 0) {
+ return (0);
+ }
+
+ SET_UID_LCP(&lc, OBJ_DDS, dds_id);
+
+ return (cache_lookup(&lc, NULL, cb_get_dds_status));
+}
+
+int
+is_dd_active(
+ uint32_t dd_id
+)
+{
+ int active = 0;
+
+ matrix_t *dds_matrix;
+ uint32_t primary;
+ uint32_t second;
+ uint32_t x_info;
+ bmp_t *bmp;
+ int i;
+
+ if (dd_id == 0) {
+ return (active);
+ }
+
+ dds_matrix = cache_get_matrix(OBJ_DDS);
+ primary = GET_PRIMARY(dd_id);
+ second = GET_SECOND(dd_id);
+
+ if (primary < dds_matrix->x) {
+ i = 0;
+ while (i < dds_matrix->y) {
+ bmp = MATRIX_X_UNIT(dds_matrix, i);
+ x_info = MATRIX_X_INFO(bmp);
+ if (x_info != 0 &&
+ TEST_MEMBERSHIP(bmp, primary, second) != 0) {
+ if (get_dds_status(x_info) != 0) {
+ active = 1;
+ break;
+ }
+ }
+ i ++;
+ }
+ }
+
+ return (active);
+}
+
+int
+get_scope(
+ uchar_t *node_name,
+ bmp_t **p,
+ uint32_t *n
+)
+{
+ int ec = 0;
+
+ lookup_ctrl_t lc;
+ uint32_t uid;
+
+ matrix_t *dd_matrix;
+ uint32_t primary;
+ uint32_t second;
+ uint32_t x_info;
+ bmp_t *bmp;
+ int i, j;
+
+ bmp_t *tmp_p;
+ uint32_t tmp_n;
+
+ bmp_t *short_p;
+ uint32_t short_n;
+
+ /* clear it */
+ *p = NULL;
+ *n = 0;
+
+ /* get the source object uid */
+ lc.curr_uid = 0;
+ lc.type = OBJ_ISCSI;
+ lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
+ lc.op[0] = OP_STRING;
+ lc.data[0].ptr = node_name;
+ lc.op[1] = 0;
+
+ uid = is_obj_there(&lc);
+
+ /* no such object */
+ if (uid == 0) {
+ return (ec);
+ }
+
+ dd_matrix = cache_get_matrix(OBJ_DD);
+ primary = GET_PRIMARY(uid);
+ second = GET_SECOND(uid);
+
+ if (primary < dd_matrix->x) {
+ i = 0;
+ while (i < dd_matrix->y) {
+ bmp = MATRIX_X_UNIT(dd_matrix, i);
+ x_info = MATRIX_X_INFO(bmp);
+ if (ec == 0 && x_info != 0 &&
+ TEST_MEMBERSHIP(bmp, primary, second) != 0) {
+ if (is_dd_active(x_info) != 0 &&
+ (ec = get_dd_matrix(x_info,
+ &tmp_p, &tmp_n)) == 0) {
+ if (*p == NULL) {
+ *p = tmp_p;
+ *n = tmp_n;
+ } else {
+ if (*n >= tmp_n) {
+ short_p = tmp_p;
+ short_n = tmp_n;
+ } else {
+ short_p = *p;
+ short_n = *n;
+ *p = tmp_p;
+ *n = tmp_n;
+ }
+ j = 0;
+ while (j < short_n) {
+ (*p)[j] |= short_p[j];
+ j ++;
+ }
+ free(short_p);
+ }
+ }
+ }
+ i ++;
+ }
+ }
+
+ primary ++;
+ if (ec == 0 && *p == NULL) {
+ *p = (bmp_t *)calloc(primary, sizeof (bmp_t));
+ if (*p != NULL) {
+ *n = primary;
+ } else {
+ *n = 0;
+ ec = ISNS_RSP_INTERNAL_ERROR;
+ }
+ }
+
+ if (*p != NULL) {
+ (*p)[primary - 1] |= (1 << second);
+ }
+
+ return (ec);
+}
+
+int
+cb_clone_attrs(
+ void *p1,
+ void *p2
+)
+{
+ int ec = 0;
+
+ isns_obj_t *obj = (isns_obj_t *)p1;
+ lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
+
+ isns_attr_t *attr;
+
+ int i = 1;
+
+ while (i < MAX_LOOKUP_CTRL &&
+ lcp->op[i] != 0) {
+ i ++;
+ }
+
+ while (ec == 0 &&
+ i < MAX_LOOKUP_CTRL &&
+ lcp->id[i] != 0) {
+ switch (lcp->id[i]) {
+ case ISNS_ISCSI_NAME_ATTR_ID:
+ attr = &obj->attrs[ATTR_INDEX_ISCSI(
+ ISNS_ISCSI_NAME_ATTR_ID)];
+ lcp->data[i].ptr = (uchar_t *)malloc(attr->len);
+ if (lcp->data[i].ptr != NULL) {
+ (void) strcpy((char *)lcp->data[i].ptr,
+ (char *)attr->value.ptr);
+ } else {
+ /* memory exhausted */
+ ec = ISNS_RSP_INTERNAL_ERROR;
+ }
+ break;
+ case ISNS_ISCSI_NODE_TYPE_ATTR_ID:
+ attr = &obj->attrs[ATTR_INDEX_ISCSI(
+ ISNS_ISCSI_NODE_TYPE_ATTR_ID)];
+ lcp->data[i].ui = attr->value.ui;
+ break;
+ case ISNS_PG_ISCSI_NAME_ATTR_ID:
+ attr = &obj->attrs[ATTR_INDEX_PG(
+ ISNS_PG_ISCSI_NAME_ATTR_ID)];
+ lcp->data[i].ptr = (uchar_t *)malloc(attr->len);
+ if (lcp->data[i].ptr != NULL) {
+ (void) strcpy((char *)lcp->data[i].ptr,
+ (char *)attr->value.ptr);
+ } else {
+ /* memory exhausted */
+ ec = ISNS_RSP_INTERNAL_ERROR;
+ }
+ break;
+ case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID:
+ attr = &obj->attrs[ATTR_INDEX_PG(
+ ISNS_PG_PORTAL_IP_ADDR_ATTR_ID)];
+ lcp->data[i].ip = (in6_addr_t *)malloc(attr->len);
+ if (lcp->data[i].ip != NULL) {
+ (void) memcpy(lcp->data[i].ip,
+ attr->value.ip, attr->len);
+ } else {
+ /* memory exhausted */
+ ec = ISNS_RSP_INTERNAL_ERROR;
+ }
+ break;
+ case ISNS_PG_PORTAL_PORT_ATTR_ID:
+ attr = &obj->attrs[ATTR_INDEX_PG(
+ ISNS_PG_PORTAL_PORT_ATTR_ID)];
+ lcp->data[i].ui = attr->value.ui;
+ break;
+ case ISNS_PORTAL_IP_ADDR_ATTR_ID:
+ attr = &obj->attrs[ATTR_INDEX_PORTAL(
+ ISNS_PORTAL_IP_ADDR_ATTR_ID)];
+ lcp->data[i].ip = (in6_addr_t *)malloc(attr->len);
+ if (lcp->data[i].ip != NULL) {
+ (void) memcpy(lcp->data[i].ip,
+ attr->value.ip, attr->len);
+ } else {
+ /* memory exhausted */
+ ec = ISNS_RSP_INTERNAL_ERROR;
+ }
+ break;
+ case ISNS_PORTAL_PORT_ATTR_ID:
+ case ISNS_ESI_PORT_ATTR_ID:
+ attr = &obj->attrs[ATTR_INDEX_PORTAL(lcp->id[i])];
+ if (attr->tag != 0 && attr->value.ui != 0) {
+ lcp->data[i].ui = attr->value.ui;
+ } else {
+ lcp->data[i].ui = 0;
+ }
+ break;
+ default:
+ ASSERT(0);
+ lcp->data[i].ui = 0;
+ break;
+ }
+ i ++;
+ }
+
+ return (ec);
+}
+
+static matrix_t *
+new_matrix(
+ uint32_t x,
+ uint32_t y
+)
+{
+ matrix_t *matrix;
+
+ matrix = (matrix_t *)malloc(sizeof (matrix_t));
+ if (matrix != NULL) {
+ matrix->x = x;
+ matrix->y = y;
+ matrix->m = (bmp_t *)calloc(y, SIZEOF_X_UNIT(matrix));
+ if (matrix->m == NULL) {
+ free(matrix);
+ matrix = NULL;
+ }
+ }
+
+ return (matrix);
+}
+
+int
+dd_matrix_init(
+ struct cache *c
+)
+{
+ matrix_t *x;
+ bmp_t *bmp;
+ uint32_t primary;
+ uint32_t second;
+
+ /*
+ * allocate an array of pointer for dd and dd-set matrix.
+ */
+ c->x = (matrix_t **)calloc(2, sizeof (matrix_t *));
+ if (c->x == NULL) {
+ return (1);
+ }
+
+ /*
+ * create dd matrix.
+ */
+ x = new_matrix(8, 64);
+ if (x != NULL) {
+ x->c = c;
+ c->x[0] = x;
+ } else {
+ return (1);
+ }
+
+ /*
+ * Mark the first array on the y axis for Default DD.
+ */
+ bmp = MATRIX_X_UNIT(x, 0);
+ MATRIX_X_INFO(bmp) = ISNS_DEFAULT_DD_ID;
+
+ /*
+ * create dd set matrix.
+ */
+ x = new_matrix(2, 16);
+ if (x != NULL) {
+ x->c = c;
+ c->x[1] = x;
+ } else {
+ return (1);
+ }
+
+ /*
+ * Mark the first array on the y axis for Default DD-set.
+ */
+ bmp = MATRIX_X_UNIT(x, 0);
+ MATRIX_X_INFO(bmp) = ISNS_DEFAULT_DD_SET_ID;
+
+ /*
+ * Add Default DD as a member of Default DD-set.
+ */
+ primary = GET_PRIMARY(ISNS_DEFAULT_DD_ID);
+ second = GET_SECOND(ISNS_DEFAULT_DD_ID);
+ SET_MEMBERSHIP(bmp, primary, second);
+
+ return (0);
+}
+
+static uint32_t
+get_ds_id(
+ matrix_t *matrix,
+ uint32_t m_id,
+ uint32_t curr_id
+)
+{
+ bmp_t *bmp;
+ uint32_t primary = GET_PRIMARY(m_id);
+ uint32_t second = GET_SECOND(m_id);
+ uint32_t dd_id = 0;
+ uint32_t uid;
+ int i = 0;
+
+ if (matrix->x > primary) {
+ while (i < matrix->y) {
+ bmp = MATRIX_X_UNIT(matrix, i);
+ uid = MATRIX_X_INFO(bmp);
+ if (uid > curr_id &&
+ TEST_MEMBERSHIP(bmp, primary, second) != 0) {
+ if (dd_id == 0 || uid < dd_id) {
+ dd_id = uid;
+ }
+ }
+ i ++;
+ }
+ }
+
+ return (dd_id);
+}
+
+uint32_t
+get_common_dd(
+ uint32_t m_id1,
+ uint32_t m_id2,
+ uint32_t curr_id
+)
+{
+ matrix_t *matrix;
+
+ bmp_t *bmp;
+ uint32_t primary1 = GET_PRIMARY(m_id1);
+ uint32_t second1 = GET_SECOND(m_id1);
+ uint32_t primary2 = GET_PRIMARY(m_id2);
+ uint32_t second2 = GET_SECOND(m_id2);
+ uint32_t dd_id = 0;
+ int i = 0;
+
+ matrix = cache_get_matrix(OBJ_DD);
+
+ if (matrix->x > primary1 && matrix->x > primary2) {
+ while (i < matrix->y) {
+ bmp = MATRIX_X_UNIT(matrix, i);
+ if (MATRIX_X_INFO(bmp) > curr_id &&
+ TEST_MEMBERSHIP(bmp, primary1, second1) != 0 &&
+ TEST_MEMBERSHIP(bmp, primary2, second2) != 0) {
+ dd_id = MATRIX_X_INFO(bmp);
+ break;
+ }
+ i ++;
+ }
+ }
+
+ return (dd_id);
+}
+
+uint32_t
+get_dd_id(
+ uint32_t m_id,
+ uint32_t curr_id
+)
+{
+ matrix_t *matrix = cache_get_matrix(OBJ_DD);
+
+ return (get_ds_id(matrix, m_id, curr_id));
+}
+
+uint32_t
+get_dds_id(
+ uint32_t m_id,
+ uint32_t curr_id
+)
+{
+ matrix_t *matrix = cache_get_matrix(OBJ_DDS);
+
+ return (get_ds_id(matrix, m_id, curr_id));
+}
+
+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
+)
+{
+ int ec = 0;
+
+ isns_obj_t *obj;
+ int id1, id2, id3;
+
+ if (type == OBJ_DD) {
+ id1 = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
+ id2 = ATTR_INDEX_DD(ISNS_DD_ID_ATTR_ID);
+ id3 = ATTR_INDEX_DD(ISNS_DD_FEATURES_ATTR_ID);
+ } else {
+ ASSERT(type == OBJ_DDS);
+ id1 = ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID);
+ id2 = ATTR_INDEX_DDS(ISNS_DD_SET_ID_ATTR_ID);
+ id3 = ATTR_INDEX_DDS(ISNS_DD_SET_STATUS_ATTR_ID);
+ }
+
+ obj = obj_calloc(type);
+ if (obj != NULL &&
+ (name_attr != NULL && name_attr->tag != 0 &&
+ assign_attr(&obj->attrs[id1], name_attr) == 0) &&
+ (uid_attr == NULL || uid_attr->value.ui == 0 ||
+ assign_attr(&obj->attrs[id2], uid_attr) == 0) &&
+ (status_attr == NULL || status_attr->value.ui == 0 ||
+ assign_attr(&obj->attrs[id3], status_attr) == 0)) {
+ *ds_p = obj;
+ } else {
+ /* no memory */
+ free_object(obj);
+ ec = ISNS_RSP_INTERNAL_ERROR;
+ }
+
+ return (ec);
+}
+
+int
+create_dd_object(
+ isns_tlv_t *op,
+ uint16_t op_len,
+ isns_obj_t **dd_p
+)
+{
+ int ec = 0;
+ uint8_t *value;
+ isns_attr_t name = { 0 };
+ isns_attr_t dd_id = { 0 }, features = { 0 };
+
+ name.tag = ISNS_DD_NAME_ATTR_ID;
+
+ while (op_len > 8 && ec == 0) {
+ value = &op->attr_value[0];
+ switch (op->attr_id) {
+ case ISNS_DD_ID_ATTR_ID:
+ if (op->attr_len == 4) {
+ dd_id.tag = ISNS_DD_ID_ATTR_ID;
+ dd_id.len = 4;
+ dd_id.value.ui = ntohl(*(uint32_t *)value);
+ } else if (op->attr_len != 0) {
+ ec = ISNS_RSP_MSG_FORMAT_ERROR;
+ }
+ break;
+ case ISNS_DD_NAME_ATTR_ID:
+ if (op->attr_len > 0 &&
+ op->attr_len <= 256) {
+ name.len = op->attr_len;
+ name.value.ptr = (uchar_t *)value;
+ } else if (op->attr_len != 0) {
+ ec = ISNS_RSP_MSG_FORMAT_ERROR;
+ }
+ break;
+ case ISNS_DD_ISCSI_INDEX_ATTR_ID:
+ case ISNS_DD_ISCSI_NAME_ATTR_ID:
+ break;
+ case ISNS_DD_FC_PORT_NAME_ATTR_ID:
+ case ISNS_DD_PORTAL_INDEX_ATTR_ID:
+ case ISNS_DD_PORTAL_IP_ADDR_ATTR_ID:
+ case ISNS_DD_PORTAL_PORT_ATTR_ID:
+ ec = ISNS_RSP_REGIS_NOT_SUPPORTED;
+ break;
+ case ISNS_DD_FEATURES_ATTR_ID:
+ if (op->attr_len == 4) {
+ features.tag = ISNS_DD_FEATURES_ATTR_ID;
+ features.len = op->attr_len;
+ features.value.ui = ntohl(*(uint32_t *)value);
+ } else if (op->attr_len != 0) {
+ ec = ISNS_RSP_MSG_FORMAT_ERROR;
+ }
+ break;
+ default:
+ ec = ISNS_RSP_INVALID_REGIS;
+ break;
+ }
+ NEXT_TLV(op, op_len);
+ }
+
+ if (ec == 0) {
+ ec = create_ds_object(OBJ_DD, dd_p,
+ &name, &dd_id, &features);
+ }
+
+ return (ec);
+}
+
+int
+create_dds_object(
+ isns_tlv_t *op,
+ uint16_t op_len,
+ isns_obj_t **dds_p
+)
+{
+ int ec = 0;
+ uint8_t *value;
+ isns_attr_t name = { 0 };
+ isns_attr_t dds_id = { 0 }, code = { 0 };
+
+ name.tag = ISNS_DD_SET_NAME_ATTR_ID;
+
+ while (op_len > 8 && ec == 0) {
+ value = &op->attr_value[0];
+ switch (op->attr_id) {
+ case ISNS_DD_SET_ID_ATTR_ID:
+ if (op->attr_len == 4) {
+ dds_id.tag = ISNS_DD_ID_ATTR_ID;
+ dds_id.len = 4;
+ dds_id.value.ui = ntohl(*(uint32_t *)value);
+ } else if (op->attr_len != 0) {
+ ec = ISNS_RSP_MSG_FORMAT_ERROR;
+ }
+ break;
+ case ISNS_DD_SET_NAME_ATTR_ID:
+ if (op->attr_len > 0 &&
+ op->attr_len <= 256) {
+ name.len = op->attr_len;
+ name.value.ptr = (uchar_t *)value;
+ } else if (op->attr_len != 0) {
+ ec = ISNS_RSP_MSG_FORMAT_ERROR;
+ }
+ break;
+ case ISNS_DD_SET_STATUS_ATTR_ID:
+ if (op->attr_len == 4) {
+ code.tag = ISNS_DD_SET_STATUS_ATTR_ID;
+ code.len = op->attr_len;
+ code.value.ui = ntohl(*(uint32_t *)value);
+ } else if (op->attr_len != 0) {
+ ec = ISNS_RSP_MSG_FORMAT_ERROR;
+ }
+ break;
+ case ISNS_DD_ID_ATTR_ID:
+ break;
+ default:
+ ec = ISNS_RSP_INVALID_REGIS;
+ break;
+ }
+ NEXT_TLV(op, op_len);
+ }
+
+ if (ec == 0) {
+ ec = create_ds_object(OBJ_DDS, dds_p,
+ &name, &dds_id, &code);
+ }
+
+ return (ec);
+}
+
+int
+adm_create_dd(
+ isns_obj_t **dd_p,
+ uchar_t *name,
+ uint32_t uid,
+ uint32_t features
+)
+{
+ uint32_t len;
+ isns_attr_t name_attr = { 0 };
+ isns_attr_t uid_attr = { 0 };
+ isns_attr_t features_attr = { 0 };
+
+ name_attr.tag = ISNS_DD_NAME_ATTR_ID;
+ if (name != NULL) {
+ /* need to include the null terminator */
+ /* and be on 4 bytes aligned */
+ len = strlen((char *)name) + 1;
+ len += 4 - (len % 4);
+ name_attr.len = len;
+ name_attr.value.ptr = name;
+ }
+
+ uid_attr.tag = ISNS_DD_ID_ATTR_ID;
+ uid_attr.len = 4;
+ uid_attr.value.ui = uid;
+
+ features_attr.tag = ISNS_DD_FEATURES_ATTR_ID;
+ features_attr.len = 4;
+ features_attr.value.ui = features;
+
+ return (create_ds_object(OBJ_DD, dd_p,
+ &name_attr, &uid_attr, &features_attr));
+}
+
+int
+adm_create_dds(
+ isns_obj_t **dds_p,
+ uchar_t *name,
+ uint32_t uid,
+ uint32_t code
+)
+{
+ uint32_t len;
+ isns_attr_t name_attr = { 0 };
+ isns_attr_t uid_attr = { 0 };
+ isns_attr_t code_attr = { 0 };
+
+ name_attr.tag = ISNS_DD_SET_NAME_ATTR_ID;
+ if (name != NULL) {
+ /* need to include the null terminator */
+ /* and be on 4 bytes aligned */
+ len = strlen((char *)name) + 1;
+ len += 4 - (len % 4);
+ name_attr.len = len;
+ name_attr.value.ptr = name;
+ }
+
+ uid_attr.tag = ISNS_DD_SET_ID_ATTR_ID;
+ uid_attr.len = 4;
+ uid_attr.value.ui = uid;
+
+ code_attr.tag = ISNS_DD_SET_STATUS_ATTR_ID;
+ code_attr.len = 4;
+ code_attr.value.ui = code;
+
+ return (create_ds_object(OBJ_DDS, dds_p,
+ &name_attr, &uid_attr, &code_attr));
+}
+
+static int
+update_ds_name(
+ isns_type_t type,
+ uint32_t uid,
+ uint32_t tag,
+ uint32_t len,
+ uchar_t *name
+)
+{
+ int ec = 0;
+
+ lookup_ctrl_t lc;
+
+ SET_UID_LCP(&lc, type, uid);
+
+ lc.id[1] = tag;
+ lc.data[1].ui = len;
+ lc.data[2].ptr = name;
+
+ ec = cache_rekey(&lc, &uid, cb_update_ds_attr);
+ if (uid == 0) {
+ ec = ISNS_RSP_INVALID_REGIS;
+ }
+
+ return (ec);
+}
+
+int
+update_dd_name(
+ uint32_t uid,
+ uint32_t len,
+ uchar_t *name
+)
+{
+ /*
+ * We do now allow changing the default DD and DD-set name.
+ */
+ if (uid == ISNS_DEFAULT_DD_ID) {
+ return (ISNS_RSP_OPTION_NOT_UNDERSTOOD);
+ }
+
+ return (update_ds_name(OBJ_DD, uid, ISNS_DD_NAME_ATTR_ID, len, name));
+}
+
+int
+update_dds_name(
+ uint32_t uid,
+ uint32_t len,
+ uchar_t *name
+)
+{
+ /*
+ * We do now allow changing the default DD and DD-set name.
+ */
+ if (uid == ISNS_DEFAULT_DD_ID) {
+ return (ISNS_RSP_OPTION_NOT_UNDERSTOOD);
+ }
+
+ return (update_ds_name(OBJ_DDS, uid,
+ ISNS_DD_SET_NAME_ATTR_ID, len, name));
+}
+
+static int
+update_ds_uint32(
+ isns_type_t type,
+ uint32_t uid,
+ uint32_t tag,
+ uint32_t value
+)
+{
+ int ec = 0;
+
+ lookup_ctrl_t lc;
+
+ SET_UID_LCP(&lc, type, uid);
+
+ lc.id[1] = tag;
+ lc.data[1].ui = value;
+
+ ec = cache_lookup(&lc, &uid, cb_update_ds_attr);
+ if (uid == 0) {
+ ec = ISNS_RSP_INVALID_REGIS;
+ }
+
+ return (ec);
+}
+
+int
+update_dd_features(
+ uint32_t uid,
+ uint32_t features
+)
+{
+ return (update_ds_uint32(OBJ_DD, uid,
+ ISNS_DD_FEATURES_ATTR_ID, features));
+}
+
+int
+update_dds_status(
+ uint32_t uid,
+ uint32_t enabled
+)
+{
+ return (update_ds_uint32(OBJ_DDS, uid,
+ ISNS_DD_SET_STATUS_ATTR_ID, enabled));
+}
+
+int
+add_dd_member(
+ isns_obj_t *assoc
+)
+{
+ int ec = 0;
+
+ uint32_t dd_id;
+ uint32_t m_id, m_type;
+
+ dd_id = get_parent_uid(assoc);
+ /*
+ * We do now allow placing any node to the default DD explicitly.
+ */
+ if (dd_id == ISNS_DEFAULT_DD_ID) {
+ return (ISNS_RSP_OPTION_NOT_UNDERSTOOD);
+ }
+
+ ec = get_member_info(assoc, &m_type, &m_id, 1);
+ if (ec == 0) {
+ ec = update_dd_matrix(
+ '+', /* add member */
+ dd_id,
+ m_type,
+ m_id);
+ }
+
+ if (ec == 0) {
+ if (sys_q != NULL) {
+ /* add the membership to data store */
+ ec = write_data(DATA_ADD, assoc);
+ }
+
+ /* trigger a management scn */
+ if (ec == 0 && scn_q != NULL) {
+ (void) make_scn(ISNS_MEMBER_ADDED, assoc);
+ }
+ }
+
+ return (ec);
+}
+
+int
+add_dds_member(
+ isns_obj_t *assoc
+)
+{
+ int ec = 0;
+
+ uint32_t m_id = assoc->attrs[ATTR_INDEX_ASSOC_DD(
+ ISNS_DD_ID_ATTR_ID)].value.ui;
+ uint32_t dds_id;
+
+ dds_id = get_parent_uid(assoc);
+ /*
+ * We do now allow changing the membership of the default DD
+ * and DD-set.
+ */
+ if (dds_id == ISNS_DEFAULT_DD_SET_ID ||
+ m_id == ISNS_DEFAULT_DD_ID) {
+ return (ISNS_RSP_OPTION_NOT_UNDERSTOOD);
+ }
+
+ ec = get_dds_member_info(m_id);
+ if (ec == 0) {
+ ec = update_dds_matrix(
+ '+', /* add member */
+ dds_id,
+ m_id);
+ }
+
+ if (ec == 0) {
+ if (sys_q != NULL) {
+ /* add the membership to data store */
+ ec = write_data(DATA_ADD, assoc);
+ }
+
+ /* trigger a management scn */
+ if (ec == 0 && scn_q != NULL) {
+ (void) make_scn(ISNS_MEMBER_ADDED, assoc);
+ }
+ }
+
+ return (ec);
+}
+
+int
+remove_dd_member(
+ isns_obj_t *assoc
+)
+{
+ int ec = 0;
+
+ uint32_t dd_id;
+ uint32_t m_type;
+ uint32_t m_id;
+
+ lookup_ctrl_t lc;
+
+ dd_id = get_parent_uid(assoc);
+ /*
+ * We do now allow removing the member from default DD explicitly.
+ */
+ if (dd_id == ISNS_DEFAULT_DD_ID) {
+ return (ISNS_RSP_OPTION_NOT_UNDERSTOOD);
+ }
+
+ ec = get_member_info(assoc, &m_type, &m_id, 0);
+ if (ec == 0) {
+ ec = update_dd_matrix(
+ '-', /* remove member */
+ dd_id,
+ m_type,
+ m_id);
+ if (ec == 0) {
+ /* update data store */
+ if (sys_q != NULL) {
+ /* remove it from data store */
+ ec = write_data(
+ DATA_DELETE_ASSOC, assoc);
+ }
+
+ /* trigger a management scn */
+ if (ec == 0 && scn_q != NULL) {
+ (void) make_scn(ISNS_MEMBER_REMOVED, assoc);
+ }
+
+ /* remove it from object container if */
+ /* it is not a registered object */
+ if (ec == 0) {
+ SET_UID_LCP(&lc, m_type, m_id);
+ ec = dereg_assoc(&lc);
+ }
+ }
+ }
+
+ return (ec);
+}
+
+int
+remove_dds_member(
+ uint32_t dds_id,
+ uint32_t m_id
+)
+{
+ int ec = 0;
+
+ isns_obj_t *clone;
+
+ /*
+ * We do now allow removing the member from default DD-set.
+ */
+ if (dds_id == ISNS_DEFAULT_DD_SET_ID) {
+ return (ISNS_RSP_OPTION_NOT_UNDERSTOOD);
+ }
+
+ if (m_id != 0) {
+ ec = update_dds_matrix(
+ '-', /* remove member */
+ dds_id,
+ m_id);
+ if (ec == 0) {
+ clone = obj_calloc(OBJ_ASSOC_DD);
+ if (clone != NULL) {
+ (void) set_obj_uid((void *)clone, m_id);
+ (void) set_parent_obj(clone, dds_id);
+ }
+ /* update data store */
+ if (sys_q != NULL) {
+ if (clone != NULL) {
+ /* remove it from data store */
+ ec = write_data(
+ DATA_DELETE_ASSOC, clone);
+ } else {
+ ec = ISNS_RSP_INTERNAL_ERROR;
+ }
+ }
+
+ /* trigger a management scn */
+ if (ec == 0 &&
+ scn_q != NULL &&
+ clone != NULL) {
+ (void) make_scn(ISNS_MEMBER_REMOVED, clone);
+ }
+ free_object(clone);
+ }
+ }
+
+ return (ec);
+}
+
+static int
+remove_member_wildchar(
+ matrix_t *matrix,
+ uint32_t m_id
+)
+{
+ int ec = 0;
+
+ bmp_t *bmp;
+ uint32_t x_info;
+ int i;
+
+ uint32_t primary = GET_PRIMARY(m_id);
+ uint32_t second = GET_SECOND(m_id);
+
+ isns_obj_t *clone;
+
+ if (primary >= matrix->x) {
+ return (ec);
+ }
+
+ i = 0;
+ while (ec == 0 && i < matrix->y) {
+ bmp = MATRIX_X_UNIT(matrix, i);
+ x_info = MATRIX_X_INFO(bmp);
+ if (x_info != 0 &&
+ TEST_MEMBERSHIP(bmp, primary, second) != 0) {
+ /* clean the membership */
+ CLEAR_MEMBERSHIP(bmp, primary, second);
+ /* update data store */
+ if (sys_q != NULL) {
+ clone = obj_calloc(OBJ_ASSOC_DD);
+ if (clone != NULL) {
+ (void) set_obj_uid((void *)clone, m_id);
+ (void) set_parent_obj(clone, x_info);
+ /* remove it from data store */
+ ec = write_data(
+ DATA_DELETE_ASSOC, clone);
+ free_object(clone);
+ } else {
+ ec = ISNS_RSP_INTERNAL_ERROR;
+ }
+ }
+ }
+ i ++;
+ }
+
+ return (ec);
+}
+
+int
+remove_dd_object(
+ uint32_t dd_id
+)
+{
+ matrix_t *dds_matrix;
+
+ bmp_t *p;
+ uint32_t n;
+ int ec;
+
+ lookup_ctrl_t lc;
+ uint32_t uid;
+
+ /*
+ * We do now allow removing the default DD.
+ */
+ if (dd_id == ISNS_DEFAULT_DD_ID) {
+ return (ISNS_RSP_OPTION_NOT_UNDERSTOOD);
+ }
+
+ SET_UID_LCP(&lc, OBJ_DD, dd_id);
+
+ /* de-register the object at first */
+ ec = dereg_object(&lc, 0);
+
+ /* clear it from all of dd-set */
+ dds_matrix = cache_get_matrix(OBJ_DDS);
+ (void) remove_member_wildchar(dds_matrix, dd_id);
+
+ /* clear its member bitmap */
+ (void) clear_dd_matrix(dd_id, &p, &n);
+
+ /* deregister the member nodes which are not-registered node */
+ /* and have no longer membership in other DD(s). */
+ if (p != NULL) {
+ SET_UID_LCP(&lc, OBJ_ISCSI, 0);
+ FOR_EACH_MEMBER(p, n, uid, {
+ lc.data[0].ui = uid;
+ (void) dereg_assoc(&lc);
+ });
+ free(p);
+ }
+
+ return (ec);
+}
+
+int
+remove_dds_object(
+ uint32_t dds_id
+)
+{
+ int ec;
+
+ lookup_ctrl_t lc;
+
+ /*
+ * We do now allow removing the default DD-set.
+ */
+ if (dds_id == ISNS_DEFAULT_DD_SET_ID) {
+ return (ISNS_RSP_OPTION_NOT_UNDERSTOOD);
+ }
+
+ (void) clear_dds_matrix(dds_id);
+
+ SET_UID_LCP(&lc, OBJ_DDS, dds_id);
+
+ ec = dereg_object(&lc, 0);
+
+ return (ec);
+}
+
+int
+update_ddd(
+ void *p,
+ const uchar_t op
+)
+{
+ isns_obj_t *obj;
+ uint32_t uid;
+
+ matrix_t *matrix;
+
+ obj = (isns_obj_t *)p;
+ if (obj->type != OBJ_ISCSI) {
+ return (0);
+ }
+
+ matrix = cache_get_matrix(OBJ_DD);
+ uid = get_obj_uid(obj);
+
+ return (update_matrix(matrix, op, ISNS_DEFAULT_DD_ID, uid, 0));
+}
+
+int
+verify_ddd(
+)
+{
+ int ec = 0;
+
+ lookup_ctrl_t lc;
+ isns_obj_t *obj;
+
+ uchar_t *name;
+ uint32_t uid;
+ uint32_t features;
+ uint32_t code;
+
+ /* Ensure the Default DD is registered. */
+ uid = ISNS_DEFAULT_DD_ID;
+
+ SET_UID_LCP(&lc, OBJ_DD, uid);
+
+ (void) cache_lock_write();
+
+ if (is_obj_there(&lc) == 0) {
+ name = (uchar_t *)DEFAULT_DD_NAME;
+ features = DEFAULT_DD_FEATURES;
+ ec = adm_create_dd(&obj, name, uid, features);
+ if (ec == 0) {
+ ec = register_object(obj, NULL, NULL);
+ if (ec != 0) {
+ free_object(obj);
+ goto verify_done;
+ }
+ } else {
+ goto verify_done;
+ }
+ }
+
+ /* Ensure the Default DD-set is registered. */
+ uid = ISNS_DEFAULT_DD_SET_ID;
+
+ SET_UID_LCP(&lc, OBJ_DDS, uid);
+
+ if (is_obj_there(&lc) == 0) {
+ name = (uchar_t *)DEFAULT_DD_SET_NAME;
+ code = DEFAULT_DD_SET_STATUS;
+ ec = adm_create_dds(&obj, name, uid, code);
+ if (ec == 0) {
+ ec = register_object(obj, NULL, NULL);
+ if (ec != 0) {
+ free_object(obj);
+ }
+ }
+ }
+
+verify_done:
+
+ ec = cache_unlock_sync(ec);
+
+ return (ec);
+}