[stgt] [PATCH] Make thread per <connection/target> a user configurable option

Chandra Seetharaman sekharan at us.ibm.com
Sat Oct 16 03:26:36 CEST 2010


Hi All,
--
Note: This applies cleanly on the thread branch on top of the patches I 
sent yesterday.
--
With the thread-per-connection patches that I sent yesterday, there are
three levels of threading that can be achieved 
 1. No threads at all
 2. One thread per target
 3. One thread per connection to a target.

These are stacked up, i.e when 3 is set 2 is assumed.

This patch allows user to select one of the thread type from above. Thread
type can be specified at the time of creation of a target.

Ex:
# Do not use threads at all
# tgtadm --lld iscsi --op new --mode target --tid 1 -T mytarget.1:01 -x none
 
# Use Thread per target. This is default too. IOW, both the commands below
# achieve the same result.
# tgtadm --lld iscsi --op new --mode target --tid 1 -T mytarget.1:01 -x thread
# tgtadm --lld iscsi --op new --mode target --tid 1 -T mytarget.1:01
 
# Use one thread per connection (on top of one thread per target)
# tgtadm --lld iscsi --op new --mode target --tid 1 -T mytarget.1:01 -x conn
 
Signed-off-by: Chandra Seetharaman <sekharan at us.ibm.com>

---
 doc/tgtadm.8.xml      |    6 +++++-
 usr/iscsi/iscsi_tcp.c |   48 ++++++++++++++++++++++++------------------------
 usr/iscsi/iscsid.c    |    8 ++++++--
 usr/iscsi/iscsid.h    |    2 +-
 usr/iscsi/target.c    |    2 +-
 usr/target.c          |   51 ++++++++++++++++++++++++++++++++++++++++++++++++--
 usr/target.h          |    2 ++
 usr/tgtadm.c          |   17 ++++++++++++-----
 usr/tgtd.h            |    6 ++++++
 9 files changed, 106 insertions(+), 36 deletions(-)

Index: tgt-thread/usr/tgtd.h
===================================================================
--- tgt-thread.orig/usr/tgtd.h
+++ tgt-thread/usr/tgtd.h
@@ -32,6 +32,12 @@ enum tgt_system_state {
 	TGT_SYSTEM_READY,
 };
 
+enum tgt_thread_type {
+	NO_PTHREAD = 0,
+	PTHREAD_PER_TARGET,
+	PTHREAD_PER_CONN,
+};
+
 enum scsi_target_state {
 	SCSI_TARGET_OFFLINE = 1,
 	SCSI_TARGET_READY,
Index: tgt-thread/usr/target.h
===================================================================
--- tgt-thread.orig/usr/target.h
+++ tgt-thread/usr/target.h
@@ -43,6 +43,8 @@ struct target {
 	struct tgt_account account;
 
 	struct bs_finish *bsf;
+
+	enum tgt_thread_type thr_type;
 };
 
 struct it_nexus {
Index: tgt-thread/usr/iscsi/iscsid.h
===================================================================
--- tgt-thread.orig/usr/iscsi/iscsid.h
+++ tgt-thread/usr/iscsi/iscsid.h
@@ -331,7 +331,7 @@ int iscsi_target_update(int mode, int op
 int target_redirected(struct iscsi_target *target,
 	struct iscsi_connection *conn, char *buf, int *reason);
 
-int iscsi_pthread_per_target(void);
+enum tgt_thread_type iscsi_pthread_per_target(struct target *target);
 
 /* param.c */
 int param_index_by_name(char *name, struct iscsi_key *keys);
Index: tgt-thread/usr/target.c
===================================================================
--- tgt-thread.orig/usr/target.c
+++ tgt-thread/usr/target.c
@@ -1639,6 +1639,47 @@ static char *target_state_name(enum scsi
 	return name;
 }
 
+static struct {
+	enum tgt_thread_type value;
+	char *name;
+} thread_type[] = {
+	{NO_PTHREAD, "none"},
+	{PTHREAD_PER_TARGET, "target"},
+	{PTHREAD_PER_CONN, "conn"},
+};
+
+static enum tgt_thread_type target_thread_type(char *name)
+{
+	int i;
+	enum tgt_thread_type type = -1;
+
+	for (i = 0; i < ARRAY_SIZE(thread_type); i++) {
+		if (!strcmp(thread_type[i].name, name)) {
+			type = thread_type[i].value;
+			break;
+		}
+	}
+	if (type == -1) {
+		eprintf("Unknown thread type <%s>, setting to default\n", name);
+		type = PTHREAD_PER_TARGET;
+	}
+	return type;
+}
+
+static char *target_thr_type_name(enum tgt_thread_type type)
+{
+	int i;
+	char *name = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(thread_type); i++) {
+		if (thread_type[i].value == type) {
+			name = thread_type[i].name;
+			break;
+		}
+	}
+	return name;
+}
+
 int tgt_set_target_state(int tid, char *str)
 {
 	int i, err = TGTADM_INVALID_REQUEST;
@@ -1720,11 +1761,13 @@ int tgt_target_show_all(char *buf, int r
 			 "Target %d: %s\n"
 			 _TAB1 "System information:\n"
 			 _TAB2 "Driver: %s\n"
-			 _TAB2 "State: %s\n",
+			 _TAB2 "State: %s\n"
+			 _TAB2 "Thread type: %s\n",
 			 target->tid,
 			 target->name,
 			 tgt_drivers[target->lid]->name,
-			 target_state_name(target->target_state));
+			 target_state_name(target->target_state),
+			 target_thr_type_name(target->thr_type));
 
 		shprintf(total, buf, rest, _TAB1 "I_T nexus information:\n");
 
@@ -1816,6 +1859,7 @@ int tgt_target_create(int lld, int tid, 
 	struct target *target, *pos;
 	char *p, *q, *targetname = NULL;
 	struct backingstore_template *bst;
+	int type = PTHREAD_PER_TARGET;
 
 	p = args;
 	while ((q = strsep(&p, ","))) {
@@ -1827,6 +1871,8 @@ int tgt_target_create(int lld, int tid, 
 
 			if (!strcmp("targetname", q))
 				targetname = str;
+			else if (!strcmp("thread", q))
+				type = target_thread_type(str);
 			else
 				eprintf("Unknow option %s\n", q);
 		}
@@ -1869,6 +1915,7 @@ int tgt_target_create(int lld, int tid, 
 	target->account.max_inaccount = DEFAULT_NR_ACCOUNT;
 
 	target->tid = tid;
+	target->thr_type = type;
 
 	INIT_LIST_HEAD(&target->device_list);
 
Index: tgt-thread/usr/tgtadm.c
===================================================================
--- tgt-thread.orig/usr/tgtadm.c
+++ tgt-thread/usr/tgtadm.c
@@ -103,6 +103,7 @@ struct option const long_options[] = {
 	{"bstype", required_argument, NULL, 'E'},
 	{"bsoflags", required_argument, NULL, 'f'},
 	{"targetname", required_argument, NULL, 'T'},
+	{"thread", required_argument, NULL, 'x'},
 	{"initiator-address", required_argument, NULL, 'I'},
 	{"user", required_argument, NULL, 'u'},
 	{"password", required_argument, NULL, 'p'},
@@ -116,7 +117,7 @@ struct option const long_options[] = {
 	{NULL, 0, NULL, 0},
 };
 
-static char *short_options = "dhL:o:m:t:s:c:l:n:v:b:E:f:T:I:u:p:H:P:B:Y:O:C:";
+static char *short_options = "dhL:o:m:t:s:c:l:n:v:b:x:E:f:T:I:u:p:H:P:B:Y:O:C:";
 
 static void usage(int status)
 {
@@ -127,7 +128,7 @@ static void usage(int status)
 		printf("\
 Linux SCSI Target Framework Administration Utility, version %s\n\
 \n\
-  --lld <driver> --mode target --op new --tid <id> --targetname <name>\n\
+  --lld <driver> --mode target --op new --tid <id> --targetname <name> [ --thread <type> ]\n\
                         add a new target with <id> and <name>. <id> must not be zero.\n\
   --lld <driver> --mode target --op delete --tid <id>\n\
                         delete the specific target with <id>. The target must\n\
@@ -423,7 +424,7 @@ int main(int argc, char **argv)
 	uint32_t cid, hostno;
 	uint64_t sid, lun;
 	char *name, *value, *path, *targetname, *params, *address, *targetOps;
-	char *bstype;
+	char *bstype, *thread_type;
 	char *bsoflags;
 	char *user, *password;
 	char *buf;
@@ -439,7 +440,7 @@ int main(int argc, char **argv)
 	ac_dir = ACCOUNT_TYPE_INCOMING;
 	rest = BUFSIZE;
 	name = value = path = targetname = address = targetOps = bstype = NULL;
-	bsoflags = user = password = NULL;
+	bsoflags = user = password = thread_type = NULL;
 
 	buf = valloc(bufsz);
 	if (!buf) {
@@ -531,6 +532,9 @@ int main(int argc, char **argv)
 		case 'h':
 			usage(0);
 			break;
+		case 'x':
+			thread_type = optarg;
+			break;
 		default:
 			usage(1);
 		}
@@ -583,7 +587,7 @@ int main(int argc, char **argv)
 		}
 		switch (op) {
 		case OP_NEW:
-			rc = verify_mode_params(argc, argv, "LmotTC");
+			rc = verify_mode_params(argc, argv, "LmotTCx");
 			if (rc) {
 				eprintf("target mode: option '-%c' is not "
 					  "allowed/supported\n", rc);
@@ -780,6 +784,9 @@ int main(int argc, char **argv)
 	if (targetname)
 		shprintf(total, params, rest, "%stargetname=%s",
 			 rest == BUFSIZE ? "" : ",", targetname);
+	if (thread_type)
+		shprintf(total, params, rest, "%sthread=%s",
+			 rest == BUFSIZE ? "" : ",", thread_type);
 	if (address)
 		shprintf(total, params, rest, "%sinitiator-address=%s",
 			 rest == BUFSIZE ? "" : ",", address);
Index: tgt-thread/usr/iscsi/iscsi_tcp.c
===================================================================
--- tgt-thread.orig/usr/iscsi/iscsi_tcp.c
+++ tgt-thread/usr/iscsi/iscsi_tcp.c
@@ -35,6 +35,7 @@
 
 #include "iscsid.h"
 #include "tgtd.h"
+#include "target.h"
 #include "util.h"
 
 static void iscsi_tcp_event_handler(int fd, int events, void *data);
@@ -42,10 +43,6 @@ static void iscsi_tcp_event_handler(int 
 static int listen_fds[8];
 static struct iscsi_transport iscsi_tcp;
 
-#define NO_PTHREAD		0
-#define PTHREAD_PER_TARGET	1
-#define PTHREAD_PER_CONN	2
-
 struct iscsi_tcp_connection {
 	int fd;
 	int pthread;
@@ -293,32 +290,35 @@ static void iscsi_tcp_conn_nexus_init(st
 {
 	struct iscsi_tcp_connection *tcp_conn = TCP_CONN(conn);
 	struct thread_info *ti;
-	int ret;
+	struct target *t = target_lookup(conn->tid);
+	int ret, type;
 
-	if (iscsi_pthread_per_target()) {
+	if ((type = iscsi_pthread_per_target(t)) != NO_PTHREAD) {
 		/* remove the conn from the main thread. */
 		tgt_event_del(tcp_conn->fd);
 
-		ti = &conn->session->target->ti;
-
 		tcp_conn->pthread = PTHREAD_PER_TARGET;
+		ti = &conn->session->target->ti;
 
-		conn->conn_ti.bsf = NULL;
-		conn->conn_ti.stop_pthread = 0;
-		conn->conn_ti.start_pthread = 0;
-		INIT_LIST_HEAD(&conn->conn_ti.t_list);
-		pthread_rwlock_init(&conn->conn_ti.rwlock, NULL);
-
-		conn->conn_ti.efd = epoll_create(128);
-		if (conn->conn_ti.efd < 0)
-			goto thread_per_target;
-
-		ret = pthread_create(&conn->thread, NULL, thread_fn, &conn->conn_ti);
-		if (!ret) {
-			eprintf("created thread %u for connection %p\n",
-				(unsigned) conn->thread, conn);
-			ti = &conn->conn_ti;
-			tcp_conn->pthread = PTHREAD_PER_CONN;
+		if (type == PTHREAD_PER_CONN) {
+			conn->conn_ti.bsf = NULL;
+			conn->conn_ti.stop_pthread = 0;
+			conn->conn_ti.start_pthread = 0;
+			INIT_LIST_HEAD(&conn->conn_ti.t_list);
+			pthread_rwlock_init(&conn->conn_ti.rwlock, NULL);
+
+			conn->conn_ti.efd = epoll_create(128);
+			if (conn->conn_ti.efd < 0)
+				goto thread_per_target;
+
+			ret = pthread_create(&conn->thread, NULL,
+						thread_fn, &conn->conn_ti);
+			if (!ret) {
+				eprintf("created thread %u for connection %p\n",
+					(unsigned) conn->thread, conn);
+				ti = &conn->conn_ti;
+				tcp_conn->pthread = PTHREAD_PER_CONN;
+			}
 		}
 thread_per_target:
 		do_tgt_event_add(ti, tcp_conn->fd, EPOLLIN,
Index: tgt-thread/usr/iscsi/iscsid.c
===================================================================
--- tgt-thread.orig/usr/iscsi/iscsid.c
+++ tgt-thread/usr/iscsi/iscsid.c
@@ -39,6 +39,7 @@
 #include "driver.h"
 #include "scsi.h"
 #include "tgtadm.h"
+#include "target.h"
 #include "crc32c.h"
 
 #define MAX_QUEUE_CMD	128
@@ -76,9 +77,12 @@ enum {
 
 int iscsi_rdma_enabled;
 
-int iscsi_pthread_per_target(void)
+enum tgt_thread_type iscsi_pthread_per_target(struct target *t)
 {
-	return sig_fd >= 0 && !iscsi_rdma_enabled;
+	if (sig_fd >= 0 && !iscsi_rdma_enabled)
+		return t->thr_type;
+	else
+		return NO_PTHREAD;
 }
 
 void conn_read_pdu(struct iscsi_connection *conn)
Index: tgt-thread/usr/iscsi/target.c
===================================================================
--- tgt-thread.orig/usr/iscsi/target.c
+++ tgt-thread/usr/iscsi/target.c
@@ -443,7 +443,7 @@ int iscsi_target_create(struct target *t
 
 	isns_target_register(tgt_targetname(tid));
 
-	if (iscsi_pthread_per_target()) {
+	if (iscsi_pthread_per_target(t) != NO_PTHREAD) {
 		int ret;
 
 		INIT_LIST_HEAD(&target->ti.t_list);
Index: tgt-thread/doc/tgtadm.8.xml
===================================================================
--- tgt-thread.orig/doc/tgtadm.8.xml
+++ tgt-thread/doc/tgtadm.8.xml
@@ -21,6 +21,7 @@
 		<arg choice="opt">-m --mode <mode></arg>
 		<arg choice="opt">-t --tid <id></arg>
 		<arg choice="opt">-T --targetname <targetname></arg>
+		<arg choice="opt">-x --thread <thread></arg>
 		<arg choice="opt">-Y --device-type <type></arg>
 		<arg choice="opt">-l --lun <lun></arg>
 		<arg choice="opt">-b --backing-store <path></arg>
@@ -72,7 +73,7 @@ Possible device-types are:
     changer : emulate a media changer device
       </screen>
 
-      <varlistentry><term><option>--lld <driver> --op new --mode target --tid <id> --targetname <name></option></term>
+      <varlistentry><term><option>--lld <driver> --op new --mode target --tid <id> --targetname <name> --thread <thread_type></option> </term>
         <listitem>
           <para>
 	    Add a new target with <id> and <name>.
@@ -390,6 +391,9 @@ two empty DVD-R disks.
 # Create a target
 tgtadm --lld iscsi --mode target --op new --tid 1 --targetname iqn.2007-03:virtual-dvd:`hostname`
 
+# Create a target with thread type as connection. Other options are "none" and "thread"(default)
+tgtadm --lld iscsi --mode target --op new --tid 1 --targetname iqn.2007-03:virtual-dvd:`hostname` --thread conn
+
 # Create a DVD drive and give it a nice name
 # The dvd starts out without a backing store file, i.e. no disk loaded
 tgtadm --op new --mode logicalunit --tid 1 --lun 1 --device-type cd


--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the stgt mailing list