[PATCH 1/1] iscsi: add support to use multiple portals for iscsi

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Tomo, list,

Please find attached a patch to add multiple-portal support to tgtd.
This allows a user to specify multiple different portals for tgtd to listen on.

Example:
tgtd --iscsi portal=10.1.1.1:3260,10.1.1.2:3261,[::1]:3262


This is useful for systems where you have very many NICs and ip
addresses but you only want TGTD to bind to some of the addresses.


(
In addition to multiple portal support I would want to also add
support to add and remove portals at runtime using the tgtadm command.
This would avoid the very disruptive 'stop tgtd, restart tgtd' that
you have to do today when chaning the portals used by tgtd.
)

regards
ronnie sahlberg

Attachment: 0001-Add-support-for-multiple-portals.patch.gz
Description: GNU Zip compressed data

From a0da7338636798417a232b8482244c84728d6596 Mon Sep 17 00:00:00 2001
From: Ronnie Sahlberg <ronniesahlberg@xxxxxxxxx>
Date: Sat, 9 Apr 2011 12:41:05 +1000
Subject: [PATCH] Add support for multiple portals,
 keep a list of the portals that are in use, and have this list
 default to [0::0] and 0.0.0.0 wilcards for ipv6/ipv4 in case the user
 does not specify a portal.

This allows
tgtd --iscsi portal=10.1.1.1:3260,portal=10.1.1.2:3261,portal=10.1.1.2:3262

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@xxxxxxxxx>
---
 usr/iscsi/iscsi_tcp.c |   30 +++++++++++++++++++++++++++---
 usr/iscsi/iscsid.c    |   43 +++++++++++++++++++++++++++++++------------
 usr/iscsi/iscsid.h    |   11 +++++++++--
 usr/iscsi/isns.c      |   15 ++++++++++-----
 4 files changed, 77 insertions(+), 22 deletions(-)

diff --git a/usr/iscsi/iscsi_tcp.c b/usr/iscsi/iscsi_tcp.c
index 0fbb671..358deb6 100644
--- a/usr/iscsi/iscsi_tcp.c
+++ b/usr/iscsi/iscsi_tcp.c
@@ -169,20 +169,20 @@ static void iscsi_tcp_event_handler(int fd, int events, void *data)
 	}
 }
 
-static int iscsi_tcp_init(void)
+static int iscsi_tcp_init_portal(struct iscsi_portal *portal)
 {
 	struct addrinfo hints, *res, *res0;
 	char servname[64];
 	int ret, fd, opt, nr_sock = 0;
 
 	memset(servname, 0, sizeof(servname));
-	snprintf(servname, sizeof(servname), "%d", iscsi_listen_port);
+	snprintf(servname, sizeof(servname), "%d", portal->port);
 
 	memset(&hints, 0, sizeof(hints));
 	hints.ai_socktype = SOCK_STREAM;
 	hints.ai_flags = AI_PASSIVE;
 
-	ret = getaddrinfo(iscsi_portal_addr, servname, &hints, &res0);
+	ret = getaddrinfo(portal->addr, servname, &hints, &res0);
 	if (ret) {
 		eprintf("unable to get address info, %m\n");
 		return -errno;
@@ -237,6 +237,7 @@ static int iscsi_tcp_init(void)
 		else {
 			listen_fds[nr_sock] = fd;
 			nr_sock++;
+			portal->fd = fd;
 		}
 	}
 
@@ -245,6 +246,29 @@ static int iscsi_tcp_init(void)
 	return !nr_sock;
 }
 
+static int iscsi_tcp_init(void)
+{
+	struct iscsi_portal *portal;
+
+	/* if the user did not set a portal we default to wildcard
+	   for ipv4 and ipv6
+	*/
+	if (!iscsi_portal_list) {
+		iscsi_add_portal("0::0", 0);
+		iscsi_add_portal("0.0.0.0", 0);
+	}
+
+	for (portal = iscsi_portal_list; portal; portal = portal->next) {
+		int ret;
+
+		ret = iscsi_tcp_init_portal(portal);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static void iscsi_tcp_exit(void)
 {
 	int i;
diff --git a/usr/iscsi/iscsid.c b/usr/iscsi/iscsid.c
index e8140e0..8cce52b 100644
--- a/usr/iscsi/iscsid.c
+++ b/usr/iscsi/iscsid.c
@@ -43,8 +43,7 @@
 
 #define MAX_QUEUE_CMD	128
 
-int iscsi_listen_port = ISCSI_LISTEN_PORT;
-char *iscsi_portal_addr;
+struct iscsi_portal *iscsi_portal_list;
 
 enum {
 	IOSTATE_FREE,
@@ -74,6 +73,19 @@ enum {
 	IOSTATE_TX_END,
 };
 
+void iscsi_add_portal(char *addr, int port)
+{
+	struct iscsi_portal *new_portal;
+
+	new_portal = malloc(sizeof(struct iscsi_portal));
+	new_portal->next = iscsi_portal_list;
+	new_portal->addr = strdup(addr);
+	new_portal->port = port ? port : ISCSI_LISTEN_PORT;
+	new_portal->fd   = -1;
+
+	iscsi_portal_list = new_portal;
+};
+
 void conn_read_pdu(struct iscsi_connection *conn)
 {
 	conn->rx_iostate = IOSTATE_RX_BHS;
@@ -827,7 +839,7 @@ static void text_scan_text(struct iscsi_connection *conn)
 			struct sockaddr_storage ss;
 			socklen_t slen, blen;
 			char *p, buf[NI_MAXHOST + 128];
-			int ret;
+			int ret, port;
 
 			if (value[0] == 0)
 				continue;
@@ -861,7 +873,15 @@ static void text_scan_text(struct iscsi_connection *conn)
 			if (ss.ss_family == AF_INET6)
 				 *p++ = ']';
 
-			sprintf(p, ":%d,1", iscsi_listen_port);
+			if (ss.ss_family == AF_INET6) {
+				port = ntohs(((struct sockaddr_in6 *)
+						&ss)->sin6_port);
+			} else {
+				port = ntohs(((struct sockaddr_in *)
+						&ss)->sin_port);
+			}
+
+			sprintf(p, ":%d,1", port);
 			target_list_build(conn, buf,
 					  strcmp(value, "All") ? value : NULL);
 		} else
@@ -2374,13 +2394,13 @@ static int iscsi_param_parser(char *p)
 	while (*p) {
 		if (!strncmp(p, "portal", 6)) {
 			char *addr, *q;
-			int len;
+			int len, port = 0;
 
 			addr = p + 7;
 
 			q = strchr(addr, ':');
 			if (q)
-				iscsi_listen_port = atoi(q + 1);
+				port = atoi(q + 1);
 			else
 				q = strchr(addr, ',');
 
@@ -2389,13 +2409,12 @@ static int iscsi_param_parser(char *p)
 			else
 				len = strlen(addr);
 
-			if (iscsi_portal_addr) {
-				free(iscsi_portal_addr);
-				iscsi_portal_addr = NULL;
-			}
 			if (len) {
-				iscsi_portal_addr = zalloc(len + 1);
-				memcpy(iscsi_portal_addr, addr, len);
+				char *tmp;
+				tmp = zalloc(len + 1);
+				memcpy(tmp, addr, len);
+				iscsi_add_portal(tmp, port);
+				free(tmp);
 			}
 		}
 
diff --git a/usr/iscsi/iscsid.h b/usr/iscsi/iscsid.h
index e496712..5e3db12 100644
--- a/usr/iscsi/iscsid.h
+++ b/usr/iscsi/iscsid.h
@@ -266,8 +266,14 @@ enum task_flags {
 	TASK_in_scsi,
 };
 
-extern int iscsi_listen_port;
-extern char *iscsi_portal_addr;
+struct iscsi_portal {
+	struct iscsi_portal *next;
+	char *addr;
+	int port;
+	int fd;
+};
+
+extern struct iscsi_portal *iscsi_portal_list;
 
 #define set_task_pending(t)	((t)->flags |= (1 << TASK_pending))
 #define clear_task_pending(t)	((t)->flags &= ~(1 << TASK_pending))
@@ -302,6 +308,7 @@ extern int iscsi_tx_handler(struct iscsi_connection *conn);
 extern void iscsi_rx_handler(struct iscsi_connection *conn);
 extern int iscsi_scsi_cmd_execute(struct iscsi_task *task);
 extern int iscsi_transportid(int tid, uint64_t itn_id, char *buf, int size);
+extern void iscsi_add_portal(char *addr, int port);
 
 /* iscsid.c iscsi_task */
 extern void iscsi_free_task(struct iscsi_task *task);
diff --git a/usr/iscsi/isns.c b/usr/iscsi/isns.c
index 19531de..0afd251 100644
--- a/usr/iscsi/isns.c
+++ b/usr/iscsi/isns.c
@@ -71,6 +71,7 @@ static char *rxbuf;
 static uint16_t transaction;
 static char eid[ISCSI_NAME_LEN];
 static uint8_t ip[16]; /* IET supoprts only one portal */
+static uint16_t port;
 static struct sockaddr_storage ss;
 
 /*
@@ -147,10 +148,14 @@ static int isns_get_ip(int fd)
 		ip[14] = 0xff & (addr >> 16);
 		ip[13] = 0xff & (addr >> 8);
 		ip[12] = 0xff & addr;
+
+		port = (((struct sockaddr_in *) &lss)->sin_port);
 		break;
 	case AF_INET6:
 		for (i = 0; i < ARRAY_SIZE(ip); i++)
 			ip[i] = ((struct sockaddr_in6 *) &lss)->sin6_addr.s6_addr[i];
+
+		port = (((struct sockaddr_in6 *) &lss)->sin6_port);
 		break;
 	}
 
@@ -417,7 +422,7 @@ int isns_target_register(char *name)
 	struct isns_hdr *hdr = (struct isns_hdr *) buf;
 	struct isns_tlv *tlv;
 	struct iscsi_target *target;
-	uint32_t port = htonl(iscsi_listen_port);
+	uint32_t p    = htonl(port);
 	uint32_t node = htonl(ISNS_NODE_TARGET);
 	uint32_t type = htonl(2);
 	int err;
@@ -447,7 +452,7 @@ int isns_target_register(char *name)
 		length += isns_tlv_set(&tlv, ISNS_ATTR_PORTAL_IP_ADDRESS,
 				       sizeof(ip), &ip);
 		length += isns_tlv_set(&tlv, ISNS_ATTR_PORTAL_PORT,
-				       sizeof(port), &port);
+				       sizeof(p), &p);
 		flags = ISNS_FLAG_REPLACE;
 
 		if (scn_listen_port) {
@@ -958,14 +963,14 @@ static void isns_timeout_fn(void *data)
 int isns_init(void)
 {
 	int err;
-	char port[8];
+	char p[8];
 	struct addrinfo hints, *res;
 	struct iscsi_target *target;
 
-	snprintf(port, sizeof(port), "%d", isns_port);
+	snprintf(p, sizeof(p), "%d", isns_port);
 	memset(&hints, 0, sizeof(hints));
 	hints.ai_socktype = SOCK_STREAM;
-	err = getaddrinfo(isns_addr, (char *) &port, &hints, &res);
+	err = getaddrinfo(isns_addr, (char *) &p, &hints, &res);
 	if (err) {
 		eprintf("getaddrinfo error %s\n", isns_addr);
 		return -1;
-- 
1.7.3.1


[Index of Archives]     [Linux SCSI]     [Linux RAID]     [Linux Clusters]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]

  Powered by Linux