summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2010-03-22 17:45:14 -0500
committerMike Christie <michaelc@cs.wisc.edu>2010-03-22 17:45:14 -0500
commit7f6a05718a11a4bf0a241aa657b638bfb370b819 (patch)
treeed387ef085d6f181fe4017e850e22be4437128f8
parentc94bb3206d8816f9d13c8d971513202d94cbb9ea (diff)
downloadopen-iscsi-7f6a05718a11a4bf0a241aa657b638bfb370b819.tar.gz
iscsid: support discovery daemon auto logout
With this patch, if the sendtargets or isns daemon detects that a target is no longer sent it will logout the session.
-rw-r--r--README9
-rw-r--r--include/list.h12
-rw-r--r--usr/discoveryd.c233
-rw-r--r--usr/idbm.c14
-rw-r--r--usr/idbm.h3
-rw-r--r--usr/initiator.c15
-rw-r--r--usr/iscsi_sysfs.c2
-rw-r--r--usr/iscsiadm.c10
-rw-r--r--usr/session_mgmt.c66
-rw-r--r--usr/session_mgmt.h5
10 files changed, 237 insertions, 132 deletions
diff --git a/README b/README
index 3ff6726..eadb385 100644
--- a/README
+++ b/README
@@ -4,8 +4,7 @@
=================================================================
- May 20, 2009
-
+ March 22, 2010
Contents
========
@@ -852,8 +851,10 @@ being set. If an address or addresses are set, iscsid will perform discovery
to the address every poll_interval seconds, and it will log into any portals
found from the discovery source using the ifaces in /etc/iscsi/ifaces.
-Note: iscsid will login into new portals, but does not yet support logging
-out of portals that are no longer returned during discovery.
+Note that for iSNS the poll_interval does not have to be set. If not set,
+iscsid will only perform rediscovery when it gets a SCN from the server.
+SCNs are not supported when using the Microsoft or SLES iSNS server. If
+using one of them you should set the poll_interval.
See the iscsid.conf for more examples.
diff --git a/include/list.h b/include/list.h
index a59ca00..cccc3c3 100644
--- a/include/list.h
+++ b/include/list.h
@@ -90,4 +90,16 @@ static inline void list_del_init(struct list_head *entry)
INIT_LIST_HEAD(entry);
}
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
#endif
diff --git a/usr/discoveryd.c b/usr/discoveryd.c
index 4d01b7a..07c2b81 100644
--- a/usr/discoveryd.c
+++ b/usr/discoveryd.c
@@ -53,7 +53,9 @@
#define DISC_DEF_POLL_INVL 30
-static LIST_HEAD(isns_nodes);
+static LIST_HEAD(iscsi_targets);
+
+static LIST_HEAD(isns_initiators);
static LIST_HEAD(isns_refresh_list);
static char *isns_entity_id = NULL;
static uint32_t isns_refresh_interval;
@@ -64,6 +66,106 @@ static void isns_reg_refresh_by_eid_qry(void *data);
typedef void (do_disc_and_login_fn)(const char *def_iname, char *addr,
int port, int poll_inval);
+static int logout_stale_session(void *data, struct list_head *list,
+ struct session_info *info)
+{
+ struct list_head *stale_rec_list = data;
+ struct node_rec *rec;
+
+ list_for_each_entry(rec, stale_rec_list, list) {
+ if (iscsi_match_session(rec, info))
+ return iscsi_logout_portal(info, list);
+ }
+ return -1;
+}
+
+static void free_curr_targets(void)
+{
+ struct node_rec *rec, *tmp_rec;
+
+ list_for_each_entry_safe(rec, tmp_rec, &iscsi_targets, list) {
+ list_del(&rec->list);
+ free(rec);
+ }
+}
+
+/*
+ * update_sessions - login/logout sessions
+ * @new_rec_list: new target portals recs bound to ifaces
+ * @targetname: if set we only update sessions for this target
+ * @iname: if set we only update session for that initiator
+ *
+ * This will login/logout of portals. When it returns the recs on
+ * new_rec_list will be freed or put on the iscsi_targets list.
+ *
+ * FIXME: if we are hitting a per problem this may be it. With targets
+ * that do a target per lun this could get ugly.
+ */
+static void update_sessions(struct list_head *new_rec_list,
+ const char *targetname, const char *iname)
+{
+ struct node_rec *rec, *tmp_rec;
+ struct list_head stale_rec_list;
+ int nr_found;
+
+ INIT_LIST_HEAD(&stale_rec_list);
+ /*
+ * Check if a target portal is no longer being sent.
+ * Note: Due to how we reread ifaces this will also detect
+ * changes in ifaces being access through portals.
+ */
+ list_for_each_entry_safe(rec, tmp_rec, &iscsi_targets, list) {
+ log_debug(7, "Trying to match %s %s to %s %s %s",
+ targetname, iname, rec->name, rec->conn[0].address,
+ rec->iface.name);
+ if (targetname && strcmp(rec->name, targetname))
+ continue;
+
+ if (iname) {
+ if (strlen(rec->iface.iname) &&
+ strcmp(rec->iface.iname, iname))
+ continue;
+ else if (strcmp(iname, isns_config.ic_source_name))
+ continue;
+ }
+
+ log_debug(5, "Matched %s %s, checking if in new targets.",
+ targetname, iname);
+ if (!idbm_find_rec_in_list(new_rec_list, rec->name,
+ rec->conn[0].address,
+ rec->conn[0].port, &rec->iface)) {
+ log_debug(5, "Not found. Marking for logout");
+ list_move_tail(&rec->list, &stale_rec_list);
+ }
+ }
+
+ list_for_each_entry_safe(rec, tmp_rec, new_rec_list, list) {
+ if (!iscsi_check_for_running_session(rec))
+ iscsi_login_portal_nowait(rec);
+
+ if (!idbm_find_rec_in_list(&iscsi_targets, rec->name,
+ rec->conn[0].address,
+ rec->conn[0].port, &rec->iface)) {
+ log_debug(5, "%s %s %s %s not on curr target list. "
+ "Adding.", rec->name, rec->conn[0].address,
+ rec->iface.name, rec->iface.iname);
+ list_move_tail(&rec->list, &iscsi_targets);
+ } else {
+ list_del(&rec->list);
+ free(rec);
+ }
+ }
+
+ if (!list_empty(&stale_rec_list)) {
+ iscsi_logout_portals(&stale_rec_list, &nr_found, 0,
+ logout_stale_session);
+ list_for_each_entry_safe(rec, tmp_rec, &stale_rec_list, list) {
+ list_del(&rec->list);
+ free(rec);
+ }
+ }
+}
+
static void do_disc_to_addrs(const char *def_iname, char *disc_addrs,
int poll_inval,
do_disc_and_login_fn *do_disc_and_login)
@@ -130,58 +232,12 @@ static void __discoveryd_start(const char *def_iname, char *addr_cfg_str,
free(disc_addrs);
}
-/* iSNS */
-static void do_isns_disc_and_login(char *disc_addr, int port)
-{
- discovery_rec_t drec;
- struct list_head rec_list, setup_ifaces;
- int rc, nr_found;
- struct node_rec *rec, *tmp_rec;
- struct iface_rec *iface, *tmp_iface;
-
- log_debug(1, "iSNS: do_isns_disc_and_login to %s,%d.",
- disc_addr, port);
-
- INIT_LIST_HEAD(&rec_list);
- INIT_LIST_HEAD(&setup_ifaces);
-
- drec.type = DISCOVERY_TYPE_ISNS;
- strlcpy(drec.address, disc_addr, sizeof(drec.address));
- drec.port = port;
-
- iface_link_ifaces(&setup_ifaces);
- rc = idbm_bind_ifaces_to_nodes(discovery_isns, &drec,
- &setup_ifaces, &rec_list);
- if (rc) {
- log_error("Could not perform iSNS DevAttrQuery to %s.",
- disc_addr);
- goto free_ifaces;
- }
-
- list_for_each_entry_safe(rec, tmp_rec, &rec_list, list) {
- if (iscsi_check_for_running_session(rec)) {
- list_del(&rec->list);
- free(rec);
- }
-
- /* no need to retry since the disc daemon will retry */
- rec->session.initial_login_retry_max = 0;
- }
-
- iscsi_login_portals(NULL, &nr_found, &rec_list, iscsi_login_portal);
-
-free_ifaces:
- list_for_each_entry_safe(iface, tmp_iface, &setup_ifaces, list) {
- list_del(&iface->list);
- free(iface);
- }
-}
-
struct isns_node_list {
isns_source_t *source;
struct list_head list;
};
+/* iSNS */
static int isns_build_objs(isns_portal_info_t *portal_info,
isns_object_list_t *objs)
{
@@ -262,7 +318,7 @@ static int isns_build_objs(isns_portal_info_t *portal_info,
}
}
- list_for_each_entry(node, &isns_nodes, list) {
+ list_for_each_entry(node, &isns_initiators, list) {
inode = isns_create_storage_node2(node->source,
ISNS_ISCSI_INITIATOR_MASK,
NULL);
@@ -310,13 +366,12 @@ static int isns_query_node(void *data, struct iface_rec *iface,
return discovery_isns_query(NULL, iname, qry_data->targetname, recs);
}
-static int __isns_disc_new_portals(const char *targetname, const char *iname)
+static int isns_disc_new_portals(const char *targetname, const char *iname)
{
struct list_head ifaces, rec_list;
struct iface_rec *iface, *tmp_iface;
- struct node_rec *rec, *tmp_rec;
struct isns_qry_data qry_data;
- int nr_found = 0, rc;
+ int rc;
INIT_LIST_HEAD(&rec_list);
INIT_LIST_HEAD(&ifaces);
@@ -332,15 +387,7 @@ static int __isns_disc_new_portals(const char *targetname, const char *iname)
targetname);
goto free_ifaces;
}
-
- list_for_each_entry_safe(rec, tmp_rec, &rec_list, list) {
- if (iscsi_check_for_running_session(rec)) {
- list_del(&rec->list);
- free(rec);
- }
- }
-
- iscsi_login_portals(NULL, &nr_found, &rec_list, iscsi_login_portal);
+ update_sessions(&rec_list, targetname, iname);
rc = 0;
free_ifaces:
@@ -367,7 +414,7 @@ static void isns_reg_refresh_with_disc(void *data)
* Some servers do not support SCNs so we ping
* the server by doing discovery.
*/
- rc = __isns_disc_new_portals(NULL, NULL);
+ rc = isns_disc_new_portals(NULL, NULL);
if (rc) {
log_debug(4, "Registration refresh using DevAttrQuery "
"failed (retires %d) err %d", retries, rc);
@@ -641,7 +688,7 @@ static int isns_register_objs(isns_client_t *clnt, isns_object_list_t *objs,
if (rc)
goto free_reg;
- list_for_each_entry(node, &isns_nodes, list) {
+ list_for_each_entry(node, &isns_initiators, list) {
isns_simple_free(reg);
reg = isns_create_scn_registration2(clnt,
ISNS_SCN_OBJECT_UPDATED_MASK |
@@ -723,7 +770,7 @@ static isns_source_t *isns_lookup_node(char *iname)
{
struct isns_node_list *node;
- list_for_each_entry(node, &isns_nodes, list) {
+ list_for_each_entry(node, &isns_initiators, list) {
if (!strcmp(iname, isns_source_name(node->source)))
return node->source;
}
@@ -765,7 +812,7 @@ static int isns_create_node_list(const char *def_iname)
rc = ENOMEM;
goto fail;
}
- list_add_tail(&node->list, &isns_nodes);
+ list_add_tail(&node->list, &isns_initiators);
}
list_for_each_entry(iface, &ifaces, list) {
@@ -776,14 +823,14 @@ static int isns_create_node_list(const char *def_iname)
rc = ENOMEM;
goto fail;
}
- list_add_tail(&node->list, &isns_nodes);
+ list_add_tail(&node->list, &isns_initiators);
}
}
/* fix me */
rc = 0;
goto done;
fail:
- list_for_each_entry_safe(node, tmp_node, &isns_nodes, list) {
+ list_for_each_entry_safe(node, tmp_node, &isns_initiators, list) {
list_del(&node->list);
free(node);
}
@@ -796,37 +843,13 @@ done:
return rc;
}
-static void isns_disc_new_portals(const char *targetname, const char *iname)
-{
- pid_t pid;
-
- pid = fork();
- if (pid < 0) {
- log_error("Could not fork process to discover new portals.");
- return;
- } else if (pid > 0) {
- log_debug(1, "iSNS SCN handler for initiator %s (target %s). "
- "pid=%d", iname, targetname, pid);
- reap_inc();
- return;
- }
-
- __isns_disc_new_portals(targetname, iname);
- exit(0);
-}
-
static void isns_scn_callback(isns_db_t *db, uint32_t bitmap,
isns_object_template_t *node_type,
const char *node_name, const char *dst_name)
{
log_error("SCN for initiator: %s (Target: %s, Event: %s.)",
dst_name, node_name, isns_event_string(bitmap));
-
- if (bitmap & ISNS_SCN_OBJECT_REMOVED_MASK) {
- log_error("Auto removal not supported. Manually logout of "
- "portals on %s", node_name);
- } else if (bitmap & ISNS_SCN_OBJECT_ADDED_MASK)
- isns_disc_new_portals(node_name, dst_name);
+ isns_disc_new_portals(node_name, dst_name);
}
static void isns_clear_refresh_list(void)
@@ -876,7 +899,7 @@ static int isns_scn_recv(isns_server_t *svr, isns_socket_t *svr_sock,
continue;
}
- __isns_disc_new_portals(NULL, NULL);
+ isns_disc_new_portals(NULL, NULL);
if (!poll_inval)
break;
isns_register_nodes = 0;
@@ -931,13 +954,13 @@ static int isns_eventd(const char *def_iname, char *disc_addr, int port,
int rc = 0;
isns_create_node_list(def_iname);
- if (list_empty(&isns_nodes)) {
+ if (list_empty(&isns_initiators)) {
log_error("iSNS registration failed. Initiatorname not set.");
return EINVAL;
}
/* use def_iname or if not set the first iface's iname for the src */
- node = list_entry(isns_nodes.next, struct isns_node_list, list);
+ node = list_entry(isns_initiators.next, struct isns_node_list, list);
isns_assign_string(&isns_config.ic_source_name,
isns_source_name(node->source));
isns_config.ic_security = 0;
@@ -976,8 +999,9 @@ static int isns_eventd(const char *def_iname, char *disc_addr, int port,
isns_cancel_refresh_timers();
fail:
isns_clear_refresh_list();
+ free_curr_targets();
- list_for_each_entry_safe(node, tmp_node, &isns_nodes, list) {
+ list_for_each_entry_safe(node, tmp_node, &isns_initiators, list) {
list_del(&node->list);
free(node);
}
@@ -1011,9 +1035,8 @@ static void __do_st_disc_and_login(char *disc_addr, int port)
{
discovery_rec_t drec;
struct list_head rec_list, setup_ifaces;
- int rc, nr_found;
- struct node_rec *rec, *tmp_rec;
struct iface_rec *iface, *tmp_iface;
+ int rc;
INIT_LIST_HEAD(&rec_list);
INIT_LIST_HEAD(&setup_ifaces);
@@ -1045,17 +1068,7 @@ static void __do_st_disc_and_login(char *disc_addr, int port)
goto free_ifaces;
}
- list_for_each_entry_safe(rec, tmp_rec, &rec_list, list) {
- if (iscsi_check_for_running_session(rec)) {
- list_del(&rec->list);
- free(rec);
- }
-
- /* no need to retry since the disc daemon will retry */
- rec->session.initial_login_retry_max = 0;
- }
-
- iscsi_login_portals(NULL, &nr_found, &rec_list, iscsi_login_portal);
+ update_sessions(&rec_list, NULL, NULL);
free_ifaces:
list_for_each_entry_safe(iface, tmp_iface, &setup_ifaces, list) {
@@ -1075,6 +1088,8 @@ static void do_st_disc_and_login(const char *def_iname, char *disc_addr,
if (!poll_inval)
break;
} while (!sleep(poll_inval));
+
+ free_curr_targets();
}
void discoveryd_start(const char *def_iname)
diff --git a/usr/idbm.c b/usr/idbm.c
index f4b5a0f..1428365 100644
--- a/usr/idbm.c
+++ b/usr/idbm.c
@@ -2239,3 +2239,17 @@ void idbm_node_setup_defaults(node_rec_t *rec)
iface_setup_defaults(&rec->iface);
}
+
+struct node_rec *
+idbm_find_rec_in_list(struct list_head *rec_list, char *targetname, char *addr,
+ int port, struct iface_rec *iface)
+{
+ struct node_rec *rec;
+
+ list_for_each_entry(rec, rec_list, list) {
+ if (__iscsi_match_session(rec, targetname, addr, port, iface))
+ return rec;
+ }
+
+ return NULL;
+}
diff --git a/usr/idbm.h b/usr/idbm.h
index 7417967..57b9295 100644
--- a/usr/idbm.h
+++ b/usr/idbm.h
@@ -137,6 +137,9 @@ extern int idbm_rec_read(node_rec_t *out_rec, char *target_name,
extern int idbm_node_set_param(void *data, node_rec_t *rec);
extern int idbm_discovery_set_param(void *data, discovery_rec_t *rec);
extern void idbm_node_setup_defaults(node_rec_t *rec);
+extern struct node_rec *idbm_find_rec_in_list(struct list_head *rec_list,
+ char *targetname, char *addr,
+ int port, struct iface_rec *iface);
/* lower level idbm functions for use by iface.c */
extern void idbm_recinfo_config(recinfo_t *info, FILE *f);
diff --git a/usr/initiator.c b/usr/initiator.c
index 5c7270a..1c9d8b6 100644
--- a/usr/initiator.c
+++ b/usr/initiator.c
@@ -677,6 +677,13 @@ cleanup:
}
}
+ log_warning("Connection%d:%d to [target: %s, portal: %s,%d] "
+ "through [iface: %s] is shutdown.",
+ session->id, conn->id, session->nrec.name,
+ session->nrec.conn[conn->id].address,
+ session->nrec.conn[conn->id].port,
+ session->nrec.iface.name);
+
mgmt_ipc_write_rsp(qtask, err);
conn_delete_timers(conn);
__session_destroy(session);
@@ -1486,8 +1493,12 @@ setup_full_feature_phase(iscsi_conn_t *conn)
if (conn->id == 0)
session_scan_host(session, session->hostno, c->qtask);
- log_warning("connection%d:%d is operational now",
- session->id, conn->id);
+ log_warning("Connection%d:%d to [target: %s, portal: %s,%d] "
+ "through [iface: %s] is operational now",
+ session->id, conn->id, session->nrec.name,
+ session->nrec.conn[conn->id].address,
+ session->nrec.conn[conn->id].port,
+ session->nrec.iface.name);
} else {
session->sync_qtask = NULL;
diff --git a/usr/iscsi_sysfs.c b/usr/iscsi_sysfs.c
index 77069cd..31a8c88 100644
--- a/usr/iscsi_sysfs.c
+++ b/usr/iscsi_sysfs.c
@@ -768,6 +768,8 @@ int iscsi_sysfs_for_each_session(void *data, int *nr_found,
if (rc) {
log_error("could not find session info for %s",
namelist[i]->d_name);
+ /* raced. session was shutdown while looping */
+ rc = 0;
continue;
}
diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index fe9cad7..df55105 100644
--- a/usr/iscsiadm.c
+++ b/usr/iscsiadm.c
@@ -364,7 +364,7 @@ logout_by_startup(char *mode)
return EINVAL;
}
- return iscsi_logout_portals(mode, &nr_found, __logout_by_startup);
+ return iscsi_logout_portals(mode, &nr_found, 1, __logout_by_startup);
}
/*
@@ -404,7 +404,7 @@ login_by_startup(char *mode)
INIT_LIST_HEAD(&rec_list);
rc = idbm_for_each_rec(&nr_found, &rec_list, link_recs);
- err = iscsi_login_portals(mode, &nr_found, &rec_list,
+ err = iscsi_login_portals(mode, &nr_found, 1, &rec_list,
__login_by_startup);
if (err && !rc)
rc = err;
@@ -499,7 +499,7 @@ static int login_portals(struct node_rec *pattern_rec)
INIT_LIST_HEAD(&rec_list);
ret = for_each_rec(pattern_rec, &rec_list, link_recs);
- err = iscsi_login_portals(NULL, &nr_found, &rec_list,
+ err = iscsi_login_portals(NULL, &nr_found, 1, &rec_list,
iscsi_login_portal);
if (err && !ret)
ret = err;
@@ -883,7 +883,7 @@ exec_disc_op_on_recs(discovery_rec_t *drec, struct list_head *rec_list,
if (!do_login)
return 0;
- err = iscsi_login_portals(NULL, &found, rec_list,
+ err = iscsi_login_portals(NULL, &found, 1, rec_list,
iscsi_login_portal);
if (err && !rc)
rc = err;
@@ -1265,7 +1265,7 @@ static int exec_node_op(int op, int do_login, int do_logout,
if (do_logout) {
int nr_found;
- if (iscsi_logout_portals(rec, &nr_found,
+ if (iscsi_logout_portals(rec, &nr_found, 1,
iscsi_logout_matched_portal))
rc = -1;
goto out;
diff --git a/usr/session_mgmt.c b/usr/session_mgmt.c
index 99543b3..46189e1 100644
--- a/usr/session_mgmt.c
+++ b/usr/session_mgmt.c
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
+#include <unistd.h>
#include "idbm.h"
#include "list.h"
@@ -53,6 +54,23 @@ struct iscsid_async_req {
int fd;
};
+/**
+ * iscsid_reqs_close - close open async requests
+ * @list: list of async reqs
+ *
+ * This just closes the socket to the daemon.
+ */
+static void iscsid_reqs_close(struct list_head *list)
+{
+ struct iscsid_async_req *tmp, *curr;
+
+ list_for_each_entry_safe(curr, tmp, list, list) {
+ close(curr->fd);
+ list_del(&curr->list);
+ free(curr);
+ }
+}
+
static int iscsid_login_reqs_wait(struct list_head *list)
{
struct iscsid_async_req *tmp, *curr;
@@ -123,17 +141,38 @@ int iscsi_login_portal(void *data, struct list_head *list, struct node_rec *rec)
}
/**
+ * iscsi_login_portal_nowait - request iscsid to login to portal
+ * @rec: portal rec to log into
+ *
+ * This sends the login request, but does not wait for the result.
+ */
+int iscsi_login_portal_nowait(struct node_rec *rec)
+{
+ struct list_head list;
+ int err;
+
+ INIT_LIST_HEAD(&list);
+
+ err = iscsi_login_portal(NULL, &list, rec);
+ if (err > 0)
+ return err;
+ iscsid_reqs_close(&list);
+ return 0;
+}
+
+/**
* iscsi_login_portals - login into portals on @rec_list,
* @data: data to pass to login_fn
* @nr_found: returned with number of portals logged into
+ * @wait: bool indicating if the fn should wait for the result
* @rec_list: list of portals to log into
* @login_fn: list iter function
*
* This will loop over the list of portals and login. It
* will attempt to login asynchronously, and then wait for
- * them to complete.
+ * them to complete if wait is set.
*/
-int iscsi_login_portals(void *data, int *nr_found,
+int iscsi_login_portals(void *data, int *nr_found, int wait,
struct list_head *rec_list,
int (* login_fn)(void *, struct list_head *,
struct node_rec *))
@@ -153,9 +192,12 @@ int iscsi_login_portals(void *data, int *nr_found,
(*nr_found)++;
}
- err = iscsid_login_reqs_wait(&login_list);
- if (err && !ret)
- ret = err;
+ if (wait) {
+ err = iscsid_login_reqs_wait(&login_list);
+ if (err && !ret)
+ ret = err;
+ } else
+ iscsid_reqs_close(&login_list);
list_for_each_entry_safe(curr_rec, tmp, rec_list, list) {
list_del(&curr_rec->list);
@@ -256,13 +298,14 @@ int iscsi_logout_portal(struct session_info *info, struct list_head *list)
* iscsi_logout_portals - logout portals
* @data: data to pass to iter logout_fn
* @nr_found: number of sessions logged out
+ * @wait: bool indicating if the fn should wait for the result
* @logout_fn: logout iter function
*
* This will loop over the list of sessions and run the logout fn
* on them. It will attempt to logout asynchronously, and then wait for
- * them to complete.
+ * them to complete if wait is set.
*/
-int iscsi_logout_portals(void *data, int *nr_found,
+int iscsi_logout_portals(void *data, int *nr_found, int wait,
int (*logout_fn)(void *, struct list_head *,
struct session_info *))
{
@@ -294,9 +337,12 @@ int iscsi_logout_portals(void *data, int *nr_found,
(*nr_found)++;
}
- err = iscsid_logout_reqs_wait(&logout_list);
- if (err)
- ret = err;
+ if (wait) {
+ err = iscsid_logout_reqs_wait(&logout_list);
+ if (err)
+ ret = err;
+ } else
+ iscsid_reqs_close(&logout_list);
session_info_free_list(&session_list);
return ret;
diff --git a/usr/session_mgmt.h b/usr/session_mgmt.h
index c310d49..b800fd7 100644
--- a/usr/session_mgmt.h
+++ b/usr/session_mgmt.h
@@ -7,13 +7,14 @@ struct session_info;
extern int iscsi_login_portal(void *data, struct list_head *list,
struct node_rec *rec);
-extern int iscsi_login_portals(void *data, int *nr_found,
+extern int iscsi_login_portal_nowait(struct node_rec *rec);
+extern int iscsi_login_portals(void *data, int *nr_found, int wait,
struct list_head *rec_list,
int (* login_fn)(void *, struct list_head *,
struct node_rec *));
extern int iscsi_logout_portal(struct session_info *info,
struct list_head *list);
-extern int iscsi_logout_portals(void *data, int *nr_found,
+extern int iscsi_logout_portals(void *data, int *nr_found, int wait,
int (*logout_fn)(void *, struct list_head *,
struct session_info *));
extern int iscsi_check_for_running_session(struct node_rec *rec);