summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--etc/iscsid.conf5
-rw-r--r--usr/config.h1
-rw-r--r--usr/idbm.c3
-rw-r--r--usr/idbm_fields.h1
-rw-r--r--usr/iscsi_util.c13
-rw-r--r--usr/iscsi_util.h1
-rw-r--r--usr/session_mgmt.c66
7 files changed, 86 insertions, 4 deletions
diff --git a/etc/iscsid.conf b/etc/iscsid.conf
index e8087c8..4e8c08d 100644
--- a/etc/iscsid.conf
+++ b/etc/iscsid.conf
@@ -278,6 +278,11 @@ discovery.sendtargets.iscsi.MaxRecvDataSegmentLength = 32768
# The default is to never use DataDigests or HeaderDigests.
#
+# For multipath configurations, you may want more than one session to be
+# created on each iface record. If node.session.nr_sessions is greater
+# than 1, performing a 'login' for that node will ensure that the
+# appropriate number of sessions is created.
+node.session.nr_sessions = 1
#************
# Workarounds
diff --git a/usr/config.h b/usr/config.h
index e361d7c..1736382 100644
--- a/usr/config.h
+++ b/usr/config.h
@@ -189,6 +189,7 @@ typedef struct session_rec {
int cmds_max;
int queue_depth;
int initial_login_retry_max;
+ int nr_sessions;
struct iscsi_auth_config auth;
struct iscsi_session_timeout_config timeo;
struct iscsi_error_timeout_config err_timeo;
diff --git a/usr/idbm.c b/usr/idbm.c
index 551d724..93b5882 100644
--- a/usr/idbm.c
+++ b/usr/idbm.c
@@ -248,6 +248,8 @@ idbm_recinfo_node(node_rec_t *r, recinfo_t *ri)
session.cmds_max, IDBM_SHOW, num, 1);
__recinfo_int(SESSION_QDEPTH, ri, r,
session.queue_depth, IDBM_SHOW, num, 1);
+ __recinfo_int(SESSION_NR_SESSIONS, ri, r,
+ session.nr_sessions, IDBM_SHOW, num, 1);
__recinfo_int_o2(SESSION_AUTH_METHOD, ri, r, session.auth.authmethod,
IDBM_SHOW, "None", "CHAP", num, 1);
__recinfo_str(SESSION_USERNAME, ri, r,
@@ -2402,6 +2404,7 @@ void idbm_node_setup_defaults(node_rec_t *rec)
rec->session.xmit_thread_priority = XMIT_THREAD_PRIORITY;
rec->session.initial_cmdsn = 0;
rec->session.queue_depth = QUEUE_DEPTH;
+ rec->session.nr_sessions = 1;
rec->session.initial_login_retry_max = DEF_INITIAL_LOGIN_RETRIES_MAX;
rec->session.reopen_max = 32;
rec->session.auth.authmethod = 0;
diff --git a/usr/idbm_fields.h b/usr/idbm_fields.h
index eaa55d1..824a7a9 100644
--- a/usr/idbm_fields.h
+++ b/usr/idbm_fields.h
@@ -21,6 +21,7 @@
#define SESSION_CMDS_MAX "node.session.cmds_max"
#define SESSION_XMIT_THREAD_PRIORITY "node.session.xmit_thread_priority"
#define SESSION_QDEPTH "node.session.queue_depth"
+#define SESSION_NR_SESSIONS "node.session.nr_sessions"
#define SESSION_AUTH_METHOD "node.session.auth.authmethod"
#define SESSION_USERNAME "node.session.auth.username"
#define SESSION_PASSWORD "node.session.auth.password"
diff --git a/usr/iscsi_util.c b/usr/iscsi_util.c
index a99db9f..9502d37 100644
--- a/usr/iscsi_util.c
+++ b/usr/iscsi_util.c
@@ -331,3 +331,16 @@ int iscsi_match_session(void *data, struct session_info *info)
info->persistent_port, &info->iface,
info->sid);
}
+
+int iscsi_match_session_count(void *data, struct session_info *info)
+{
+ /*
+ * iscsi_sysfs_for_each_session expects:
+ * 0==match -1==nomatch >0==error
+ * but iscsi_match_session returns:
+ * 1==match 0==nomatch
+ */
+ if (iscsi_match_session(data, info))
+ return 0;
+ return -1;
+}
diff --git a/usr/iscsi_util.h b/usr/iscsi_util.h
index 9428867..13a5eb2 100644
--- a/usr/iscsi_util.h
+++ b/usr/iscsi_util.h
@@ -14,6 +14,7 @@ extern int increase_max_files(void);
extern char *str_to_ipport(char *str, int *port, int *tgpt);
extern int iscsi_match_session(void *data, struct session_info *info);
+extern int iscsi_match_session_count(void *data, struct session_info *info);
extern int __iscsi_match_session(struct node_rec *rec, char *targetname,
char *address, int port,
struct iface_rec *iface,
diff --git a/usr/session_mgmt.c b/usr/session_mgmt.c
index afdd077..7918954 100644
--- a/usr/session_mgmt.c
+++ b/usr/session_mgmt.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2010 Mike Christie
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
-
+ * Copyright (C) 2011 Dell Inc.
* maintained by open-iscsi@googlegroups.com
*
* This program is free software; you can redistribute it and/or modify
@@ -93,18 +93,19 @@ static int iscsid_login_reqs_wait(struct list_head *list)
}
/**
- * iscsi_login_portal - request iscsid to login to portal
+ * __iscsi_login_portal - request iscsid to login to portal
* @data: If set, copies the session.multiple value to the portal record
* so it is propagated to iscsid.
* @list: If async, list to add session to
* @rec: portal rec to log into
*/
-int iscsi_login_portal(void *data, struct list_head *list, struct node_rec *rec)
+static int
+__iscsi_login_portal(void *data, struct list_head *list, struct node_rec *rec)
{
struct iscsid_async_req *async_req = NULL;
int rc = 0, fd;
- if (data) {
+ if (data && !rec->session.multiple) {
struct node_rec *pattern_rec = data;
rec->session.multiple = pattern_rec->session.multiple;
}
@@ -147,6 +148,63 @@ int iscsi_login_portal(void *data, struct list_head *list, struct node_rec *rec)
}
/**
+ * iscsi_login_portal - request iscsid to login to portal multiple
+ * times, based on the session.nr_sessions in the portal record.
+ * @data: If set, session.multiple will cause an additional session to
+ * be created regardless of the value of session.nr_sessions
+ * @list: If async, list to add session to
+ * @rec: portal rec to log into
+ */
+int iscsi_login_portal(void *data, struct list_head *list, struct node_rec *rec)
+{
+ struct node_rec *pattern_rec = data;
+ int rc = 0, session_count = 0, i;
+
+ /*
+ * If pattern_rec->session.multiple is set, just add a single new
+ * session by passing things along to __iscsi_login_portal
+ */
+ if (pattern_rec && pattern_rec->session.multiple)
+ return __iscsi_login_portal(data, list, rec);
+
+ /*
+ * Count the current number of sessions, and only create those
+ * that are missing.
+ */
+ rc = iscsi_sysfs_for_each_session(rec, &session_count,
+ iscsi_match_session_count);
+ if (rc) {
+ log_error("Could not count current number of sessions");
+ goto done;
+ }
+ if (session_count >= rec->session.nr_sessions) {
+ log_debug(1, "%s: %d session%s requested, but %d "
+ "already present.",
+ rec->iface.name, rec->session.nr_sessions,
+ rec->session.nr_sessions == 1 ? "" : "s",
+ session_count);
+ rc = 0;
+ goto done;
+ }
+
+ /*
+ * Ensure the record's 'multiple' flag is set so __iscsi_login_portal
+ * will allow multiple logins.
+ */
+ rec->session.multiple = 1;
+ for (i = session_count; i < rec->session.nr_sessions; ++i) {
+ log_debug(1, "%s: Creating session %d/%d", rec->iface.name,
+ i + 1, rec->session.nr_sessions);
+ int err = __iscsi_login_portal(pattern_rec, list, rec);
+ if (err && !rc)
+ rc = err;
+ }
+
+done:
+ return rc;
+}
+
+/**
* iscsi_login_portal_nowait - request iscsid to login to portal
* @rec: portal rec to log into
*