scn.c revision fcf3ce441efd61da9bb2884968af01cb7c1452cc
/*
* 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
* 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 <unistd.h>
#include "isns_server.h"
#include "isns_msgq.h"
#include "isns_cache.h"
#include "isns_cfg.h"
#include "isns_obj.h"
#include "isns_dseng.h"
#include "isns_log.h"
#include "isns_scn.h"
#include "isns_pdu.h"
/*
* global variables.
*/
/*
* local variables.
*/
static int scn_dispatched = 0;
/*
* external variables.
*/
extern msg_queue_t *sys_q;
extern msg_queue_t *scn_q;
extern const int UID_ATTR_INDEX[MAX_OBJ_TYPE_FOR_SIZE];
#ifdef DEBUG
extern void dump_pdu1(isns_pdu_t *);
#endif
NULL,
NULL, /* OBJ_PG */
NULL, /* OBJ_DD */
NULL, /* OBJ_DDS */
NULL, /* MAX_OBJ_TYPE */
NULL, /* OBJ_DUMMY1 */
NULL, /* OBJ_DUMMY2 */
NULL, /* OBJ_DUMMY3 */
NULL, /* OBJ_DUMMY4 */
};
NULL,
NULL, /* OBJ_PG */
NULL, /* OBJ_DD */
NULL, /* OBJ_DDS */
NULL, /* MAX_OBJ_TYPE */
NULL, /* OBJ_DUMMY1 */
NULL, /* OBJ_DUMMY2 */
NULL, /* OBJ_DUMMY3 */
NULL, /* OBJ_DUMMY4 */
};
(((E) & (BITMAP)) && \
(!((BITMAP) & (ISNS_INIT_SELF_INFO_ONLY | \
ISNS_TARGET_SELF_INFO_ONLY)) || \
(((BITMAP) & ISNS_INIT_SELF_INFO_ONLY) && \
((NT) & ISNS_INITIATOR_NODE_TYPE)) || \
(((BITMAP) & ISNS_TARGET_SELF_INFO_ONLY) && \
((NT) & ISNS_TARGET_NODE_TYPE))))
/*
* local functions.
*/
/*
* ****************************************************************************
*
* free_portal_1:
* Free one SCN portal or decrease the reference count if the portal
* is referenced by other SCN entry(s).
*
* p - the portal.
*
* ****************************************************************************
*/
static void
scn_portal_t *p
)
{
if (p->ref <= 1) {
if (p->sz == sizeof (in6_addr_t)) {
}
free(p);
} else {
p->ref --;
}
}
/*
* ****************************************************************************
*
* free_portal:
* Free the unused portals, which are extracted for new SCN entry,
* after the new SCN entry is added.
*
* p - the portal.
*
* ****************************************************************************
*/
static void
scn_portal_t *p
)
{
scn_portal_t *n;
while (p != NULL) {
n = p->next;
free_portal_1(p);
p = n;
}
}
/*
* ****************************************************************************
*
* free_portal_list:
* Free the list of portals while a SCN entry is being destroyed.
*
* l - the portal list.
*
* ****************************************************************************
*/
static void
scn_list_t *l
)
{
scn_list_t *n;
scn_portal_t *p;
while (l != NULL) {
n = l->next;
free_portal_1(p);
free(l);
l = n;
}
}
/*
* ****************************************************************************
*
* free_scn_text:
* Free one SCN or decrease the ref count after the SCN is emitted.
*
* text - the SCN.
*
* ****************************************************************************
*/
static void
)
{
} else {
}
}
/*
* ****************************************************************************
*
* free_scn_list:
* Free the the list of SCN.
*
* scn - the list.
*
* ****************************************************************************
*/
static void
)
{
}
}
}
/*
* ****************************************************************************
*
* free_scn:
* Free all of SCNs which are dispatched to every entry.
*
* ****************************************************************************
*/
static void
)
{
scn_registry_t *p;
p = scn_registry;
while (p != NULL) {
free_scn_list(p->scn);
p = p->next;
}
}
/*
* ****************************************************************************
*
* free_entry:
* Free one SCN entry.
*
* e - the SCN entry.
*
* ****************************************************************************
*/
static void
)
{
free_scn_list(e->scn);
free_portal_list(e->portal.l);
free(e);
}
/*
* ****************************************************************************
*
* free_raw:
* Free the raw data after the SCN is generated from it.
*
* raw - the raw SCN data.
*
* ****************************************************************************
*/
static void
)
{
}
}
}
/*
* ****************************************************************************
*
* scn_add_portal:
* Add portals to the portal list of a SCN entry.
*
* e - the SCN entry.
* p - the portals.
* return - 0: successful, otherwise failed.
*
* ****************************************************************************
*/
static int
scn_registry_t *e,
scn_portal_t *p
)
{
scn_portal_t *x;
scn_list_t *l, *m;
scn_list_t **lp;
int found_it;
while (p != NULL) {
if (m == NULL) {
return (1);
}
found_it = 0;
e = scn_registry;
while (e && !found_it) {
l = e->portal.l;
while (l && !found_it) {
found_it = 1;
}
l = l->next;
}
e = e->next;
}
if (!found_it) {
x = p;
}
x->ref ++;
*lp = m;
p = p->next;
}
return (0);
}
/*
* ****************************************************************************
*
* scn_remove_portal:
* Remove a portal from the portal list of every SCN entry.
*
* uid - the portal object uid.
* return - always successful (0).
*
* ****************************************************************************
*/
static int
)
{
scn_registry_t **ep, *e;
scn_portal_t *x;
scn_list_t **lp, *l;
ep = &scn_registry;
e = *ep;
while (e != NULL) {
l = *lp;
while (l != NULL) {
/* remove it */
free_portal_1(x);
free(l);
} else {
}
l = *lp;
}
/* no portal for this entry, destroy it */
free_entry(e);
} else {
}
e = *ep;
}
return (0);
}
/*
* ****************************************************************************
*
* scn_list_add:
* Add one SCN entry to the SCN entry list.
*
* e - the SCN entry.
* return - always successful (0).
*
* ****************************************************************************
*/
static int
)
{
scn_registry_t **pp;
scn_portal_t *p;
p = e->portal.p;
pp = &scn_registry;
while (*pp) {
/* replace the bitmap */
free_portal(p);
free_entry(e);
return (0);
break;
}
}
(void) scn_add_portal(e, p);
/* insert it to the list */
*pp = e;
} else {
/* no portal, ignore it */
free_entry(e);
}
/* free the unused portal(s) */
free_portal(p);
return (0);
}
/*
* ****************************************************************************
*
* scn_list_remove:
* Remove one SCN entry from the SCN entry list.
*
* uid - the SCN entry unique ID.
* return - always successful (0).
*
* ****************************************************************************
*/
static int
)
{
scn_registry_t **ep, *e;
ep = &scn_registry;
e = *ep;
while (e) {
/* destroy it */
free_entry(e);
break;
break;
}
e = *ep;
}
return (0);
}
/*
* ****************************************************************************
*
* cb_get_scn_port:
* The callback function which returns the SCN port of a portal object.
*
* p1 - the portal object.
* p2 - the lookup control data.
* return - the SCN port number.
*
* ****************************************************************************
*/
static int
void *p1,
/*ARGSUSED*/
void *p2
)
{
int port = 0;
}
return (port);
}
/*
* ****************************************************************************
*
* new_scn_portal:
* Make a new SCN portal.
*
* ref - the ref count.
* uid - the portal object UID.
* ip - the ip address.
* port - the port number.
* return - the SCN portal.
*
* ****************************************************************************
*/
static scn_portal_t *
in6_addr_t *ip,
)
{
scn_portal_t *p;
if (p != NULL) {
/* convert the ipv6 to ipv4 */
if (((int *)ip)[0] == 0x00 &&
} else {
p->sz = sizeof (in6_addr_t);
}
p->so = 0;
}
return (p);
}
/*
* ****************************************************************************
*
* extract scn_portal:
* Extract the SCN portal(s) for a storage node.
*
* name - the storage node name.
* return - the SCN portal list.
*
* ****************************************************************************
*/
static scn_portal_t *
)
{
scn_portal_t *p;
in6_addr_t *ip;
pg_uid != 0) {
/* ref starts from 1 */
if (p != NULL) {
list = p;
} else {
free(p);
}
} else {
/* portal not registered or no scn port */
}
}
}
return (list);
}
/*
* ****************************************************************************
*
* cb_update_scn_bitmap:
* The callback function which updates the SCN Bitmap attribute of
* a storage node object.
*
* p1 - the storage node object.
* p2 - the lookup control data.
* return - error code.
*
* ****************************************************************************
*/
static int
void *p1,
void *p2
)
{
int ec = 0;
if (bitmap != 0) {
return (ec);
} else {
}
}
return (ec);
}
/*
* ****************************************************************************
*
* cb_get_node_type:
* The callback function which returns the node type attribute of
* a storage node object.
*
* p1 - the storage node object.
* p2 - the lookup control data.
* return - error code.
*
* ****************************************************************************
*/
static int
void *p1,
/* LINTED E_FUNC_ARG_UNUSED */
void *p2
)
{
return (nt);
}
/*
* ****************************************************************************
*
* cb_get_node_type:
* The callback function which returns the storage node object UID
* from a portal group object.
*
* p1 - the pg object.
* p2 - the lookup control data.
* return - the storage node object UID.
*
* ****************************************************************************
*/
static int
void *p1,
/* LINTED E_FUNC_ARG_UNUSED */
void *p2
)
{
return ((int)ref);
}
/*
* ****************************************************************************
*
* make_raw_entity:
* Make raw SCN data with a Network Entity object.
*
* obj - the network entity object.
* return - the raw SCN data.
*
* ****************************************************************************
*/
static scn_raw_t *
/*ARGSUSED*/
)
{
} else {
}
return (raw);
}
/*
* ****************************************************************************
*
* make_raw_iscsi:
* Make raw SCN data with a Storage Node object.
*
* obj - the storage node object.
* return - the raw SCN data.
*
* ****************************************************************************
*/
static scn_raw_t *
)
{
/* copy the iscsi storage node name */
} else {
}
return (raw);
}
/*
* ****************************************************************************
*
* make_raw_portal:
* Make raw SCN data with a Portal object.
*
* obj - the portal object.
* return - the raw SCN data.
*
* ****************************************************************************
*/
static scn_raw_t *
)
{
in6_addr_t *ip;
} else {
}
return (raw);
}
/*
* ****************************************************************************
*
* make_raw_assoc_iscsi:
* Make raw SCN data with a Discovery Domain member association.
*
* obj - the member association object.
* return - the raw SCN data.
*
* ****************************************************************************
*/
static scn_raw_t *
)
{
/* copy the iscsi storage node name */
} else {
}
return (raw);
}
/*
* ****************************************************************************
*
* make_raw_assoc_dd:
* Make raw SCN data with a Discovery Domain Set member association.
*
* obj - the member association object.
* return - the raw SCN data.
*
* ****************************************************************************
*/
static scn_raw_t *
)
{
} else {
}
return (raw);
}
/*
* ****************************************************************************
*
* scn_gen_entity:
* Generate SCN with the raw SCN data from a Network Entity object.
*
* raw - the raw SCN data.
* return - the SCN.
*
* ****************************************************************************
*/
static scn_text_t *
/* LINTED E_FUNC_ARG_UNUSED */
)
{
return (NULL);
}
/*
* ****************************************************************************
*
* scn_gen_iscsi:
* Generate SCN with the raw SCN data from a Storage Node object.
*
* raw - the raw SCN data.
* return - the SCN.
*
* ****************************************************************************
*/
static scn_text_t *
)
{
} else {
}
return (text);
}
/*
* ****************************************************************************
*
* scn_gen_portal:
* Generate SCN with the raw SCN data from a Portal object.
*
* raw - the raw SCN data.
* return - the SCN.
*
* ****************************************************************************
*/
static scn_text_t *
)
{
in6_addr_t *ip;
int ilen;
/* get a pg which is associated to the portal */
while (pg_uid != 0) {
if (uid != 0) {
sizeof (scn_text_t));
l = text;
} else {
"malloc failed.");
}
} else {
"cannot get node name.");
}
}
/* get the next pg */
}
/* update the iscsi storage node object */
return (l);
}
/*
* ****************************************************************************
*
* scn_gen_assoc_dd:
* Generate SCN with the raw SCN data from a DD membership object.
*
* raw - the raw SCN data.
* return - the SCN.
*
* ****************************************************************************
*/
static scn_text_t *
/* LINTED E_FUNC_ARG_UNUSED */
)
{
return (NULL);
}
/*
* ****************************************************************************
*
* make_scn:
* Make a SCN with an event and an object.
*
* event - the event.
* obj - the object.
* return - always successful (0).
*
* ****************************************************************************
*/
int
)
{
if (f != NULL) {
/* make raw scn data */
}
/* trigger an scn event */
}
return (0);
}
/*
* data structure of the SCN state transition table.
*/
typedef struct scn_tbl {
int state;
int next_state;
} scn_tbl_t;
/*
* the SCN state transition table.
*/
};
/*
* ****************************************************************************
*
* scn_disp1:
* Dispatch one SCN to one SCN entry.
*
* event - the event.
* p - the SCN entry.
* t - the SCN.
* return - always successful (0).
*
* ****************************************************************************
*/
static int
scn_registry_t *p,
scn_text_t *t
)
{
scn_list_t *l, **lp;
s = p->scn;
while (s != NULL) {
do {
/* duplicated */
return (0);
}
l = *lp;
} while (l != NULL);
break;
}
r = s;
s = s->next;
}
if (l != NULL) {
if (s == NULL) {
if (s != NULL) {
if (r != NULL) {
r->next = s;
} else {
p->scn = s;
}
} else {
free(l);
"malloc scn failed.\n");
return (0);
}
}
t->ref ++;
*lp = l;
} else {
"malloc list failed.\n");
}
return (0);
}
/*
* ****************************************************************************
*
* scn_disp1:
* Dispatch one SCN to every SCN entry and update the dispatch status.
*
* event - the event.
* text - the SCN.
* return - always successful (0).
*
* ****************************************************************************
*/
static int
)
{
scn_registry_t *registry, *p;
scn_text_t *t;
uint32_t e;
t = text;
while (t != NULL) {
e = event;
if (t->flag == 0) {
if (e & ISNS_MEMBER_ADDED) {
e |= ISNS_OBJECT_ADDED;
} else if (e & ISNS_MEMBER_REMOVED) {
e |= ISNS_OBJECT_REMOVED;
}
}
p = registry;
while (p != NULL) {
if (p->bitmap & ISNS_MGMT_REG) {
/* management scn are not bound */
/* by discovery domain service. */
dd_id = 1;
} else {
dd_id = 0;
/* lock the cache for reading */
(void) cache_lock_read();
/* verify common dd */
do {
p->uid,
t->uid,
dd_id);
} while (dd_id > 0 &&
is_dd_active(dd_id) == 0);
/* unlock the cache */
(void) cache_unlock_nosync();
}
if (dd_id != 0) {
(void) scn_disp1(e, p, t);
}
}
p = p->next;
}
t = t->next;
}
/* clean up the scn text(s) which nobody cares about. */
text = t;
}
if (dd_id != 0) {
/* scn(s) are dispatched. */
scn_dispatched = 1;
}
return (0);
}
/*
* ****************************************************************************
*
* sf_gen:
* State transition function which generates and dispatches SCN(s).
*
* raw - the raw SCN data.
* return - always successful (0).
*
* ****************************************************************************
*/
static int
)
{
}
}
return (0);
}
/*
* ****************************************************************************
*
* sf_error:
* State transition function for an error state. It free any SCN(s)
* which have been generated and dispatched previously.
*
* raw - the raw SCN data.
* return - always successful (0).
*
* ****************************************************************************
*/
static int
/* LINTED E_FUNC_ARG_UNUSED */
)
{
free_scn();
return (0);
}
/*
* ****************************************************************************
*
* scn_transition:
* Performs the state transition when a SCN event occurs.
*
* state - the previous state.
* raw - the raw SCN data.
* return - the next state.
*
* ****************************************************************************
*/
static int
int state,
)
{
for (;;) {
if (tbl->next_state != 0) {
}
}
break;
}
tbl ++;
}
if (new_state == -1) {
"prev state: %d new event: 0x%x new object: %d.\n",
new_state = 0;
}
return (state);
}
/*
* ****************************************************************************
*
* connect_to:
* Create socket connection with peer network portal.
*
* sz - the size of the ip addr.
* in - the ipv4 address.
* in6 - the ipv6 address.
* port2- the port info.
* return - the socket descriptor.
*
* ****************************************************************************
*/
int
int sz,
/* LINTED E_FUNC_ARG_UNUSED */
)
{
int so = -1;
union {
struct sockaddr_in in;
struct sockaddr_in6 in6;
} ca = { 0 };
int tcp;
if (tcp != 0) {
if (so != -1) {
0) {
"connect() failed %%m.");
so = -1;
}
} else {
"socket() failed %%m.");
}
} else {
/* FIXME: UDP support */
}
} else {
/* FIXME: IPv6 support */
}
return (so);
}
/*
* ****************************************************************************
*
* emit_scn:
* Emit the SCN to any portal of the peer storage node.
*
* list - the list of portal.
* pdu - the SCN packet.
* pl - the SCN packet payload length.
* return - always successful (0).
*
* ****************************************************************************
*/
static int
)
{
int so = 0;
scn_list_t *l;
scn_portal_t *p;
l = list;
while (l != NULL) {
if (so != -1) {
/* This may help Solaris iSCSI Initiator */
/* not to panic frequently. */
} else {
"sending packet failed.");
}
/* p->so = so; */
break;
}
l = l->next;
}
#ifdef DEBUG
#endif
}
return (0);
}
/*
* ****************************************************************************
*
* scn_trigger1:
* Trigger one SCN for one SCN entry.
*
* t - the time that SCN is being triggered.
* p - the SCN entry.
* return - always successful (0).
*
* ****************************************************************************
*/
static int
time_t t,
)
{
int ec;
scn_t *s;
scn_list_t *l;
scn_text_t *x;
union {
} u;
#ifdef DEBUG
char buff[1024] = { 0 };
#endif
goto scn_done;
}
/* add destination attribute */
p->nlen,
(void *)p->name, 0);
if (ec != 0) {
goto scn_done;
}
#ifdef DEBUG
#endif
/* add timestamp */
8,
(void *)&u.i64, 1);
s = p->scn;
4,
(void *)&u.i32, 1);
#ifdef DEBUG
#endif
if (x->flag == 0) {
#ifdef DEBUG
#endif
if (ec == 0 &&
(p->bitmap &
ISNS_MEMBER_REMOVED))) {
/* management SCN */
#ifdef DEBUG
x->dd_id);
#endif
}
} else {
/* add(remove) dd to(from) dd-set */
if (ec == 0) {
}
#ifdef DEBUG
#endif
}
l = l->next;
}
s = s->next;
}
if (ec == 0) {
#ifdef DEBUG
#endif
} else {
}
return (0);
}
/*
* ****************************************************************************
*
* scn_trigger:
* Trigger one SCN for every SCN entry.
*
* return - always successful (0).
*
* ****************************************************************************
*/
static int
)
{
time_t t;
scn_registry_t *p;
p = scn_registry;
while (p != NULL) {
(void) scn_trigger1(t, p);
}
p = p->next;
}
return (0);
}
/*
* global functions.
*/
/*
* ****************************************************************************
*
* scn_list_load:
* Load one SCN entry and add it to the SCN entry list.
*
* uid - the Storage Node object UID.
* node - the Storage Node name.
* nlen - the length of the name.
* bitmap - the SCN bitmap.
* return - error code.
*
* ****************************************************************************
*/
int
)
{
int ec = 0;
(void) scn_list_add(list);
} else {
}
return (ec);
}
/*
* ****************************************************************************
*
* verify_scn_portal:
* Extract and verify portals for every SCN entry(s) after they are
* loaded from data store, for those which do not have a SCN portal,
* remove it from the SCN entry list.
*
* return - 1: error occurs, otherwise 0.
*
* ****************************************************************************
*/
int
)
{
scn_registry_t **pp, *e;
scn_portal_t *p;
pp = &scn_registry;
e = *pp;
p = extract_scn_portal(e->name);
if (p != NULL) {
if (scn_add_portal(e, p) != 0) {
return (1);
}
}
} else {
/* remove this entry */
free_entry(e);
}
/* free the unused portal(s) */
free_portal(p);
}
return (0);
}
/*
* ****************************************************************************
*
* add_scn_entry:
* Add a SCN entry.
*
* node - the Storage Node name.
* nlen - the length of the name.
* bitmap - the SCN bitmap.
* return - error code.
*
* ****************************************************************************
*/
int
)
{
int ec = 0;
scn_portal_t *p;
scn_registry_t *e;
if ((mgmt > 0 &&
(mgmt_scn == 0 ||
mgmt < ISNS_MGMT_REG ||
is_control_node(node) == 0)) ||
return (ISNS_RSP_SCN_REGIS_REJECTED);
}
if (uid == 0) {
}
if (ec == 0) {
e->portal.p = p;
}
} else {
}
if (ec != 0) {
free(e);
free_portal(p);
}
return (ec);
}
/*
* ****************************************************************************
*
* remove_scn_entry:
* Remove a SCN entry.
*
* node - the Storage Node name.
* return - error code.
*
* ****************************************************************************
*/
int
)
{
int ec = 0;
}
return (ec);
}
/*
* ****************************************************************************
*
* remove_scn_portal:
* Remove a portal from every SCN entry.
*
* uid - the Portal object UID.
* return - alrays successful (0).
*
* ****************************************************************************
*/
int
)
{
return (0);
}
/*
* ****************************************************************************
*
* scn_proc:
* The entry point of the SCN thread. It listens on the SCN message
* queue and process every SCN related stuff.
*
* arg - nothing.
* return - NULL.
*
* ****************************************************************************
*/
void *
/* LINTED E_FUNC_ARG_UNUSED */
void *arg
)
{
int state = 0;
for (;;) {
case SCN_ADD:
break;
case SCN_REMOVE:
break;
case SCN_REMOVE_P:
break;
case SCN_SET:
/* free the raw data */
break;
case SCN_TRIGGER:
if (scn_dispatched != 0) {
(void) scn_trigger();
}
case SCN_IGNORE:
/* clean the scn(s) */
free_scn();
/* reset the state */
state = 0;
/* reset the scn_dispatched flag */
scn_dispatched = 0;
break;
case SCN_STOP:
return (NULL);
default:
break;
}
}
}