[PATCH] iscsi: target redirect support

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

 



Let's keep up with IET. :)

=
From: FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx>
Subject: [PATCH] iscsi: target redirect support

root@rose:~# tgtadm --op update --mode target --tid 1 --name RedirectAddress --value 10.76.0.30
root@rose:~# tgtadm --op update --mode target --tid 1 --name RedirectPort --value 3260
root@rose:~# tgtadm --op update --mode target --tid 1 --name RedirectReason --value Temporary
root@rose:~# tgtadm --op show --mode target --tid 1
RedirectAddress=10.76.0.30
RedirectPort=3260
RedirectReason=Temporary

If you want "Target moved permanently",

root@rose:~# tgtadm --op update --mode target --tid 1 --name RedirectReason --value Permanent

Signed-off-by: FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx>
---
 usr/iscsi/iscsid.c |   12 ++++++
 usr/iscsi/iscsid.h |    8 ++++
 usr/iscsi/target.c |  108 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 127 insertions(+), 1 deletions(-)

diff --git a/usr/iscsi/iscsid.c b/usr/iscsi/iscsid.c
index b4e0969..e66323c 100644
--- a/usr/iscsi/iscsid.c
+++ b/usr/iscsi/iscsid.c
@@ -489,8 +489,20 @@ static void login_start(struct iscsi_connection *conn)
 			conn->state = STATE_EXIT;
 			return;
 		}
+
 		conn->tid = target->tid;
 
+		if (target_redirected(target, conn)) {
+			char buf[NI_MAXHOST + NI_MAXSERV + 4];
+			snprintf(buf, sizeof(buf), "%s:%s", target->redirect_info.addr,
+				 target->redirect_info.port);
+			text_key_add(conn, "TargetAddress", buf);
+			rsp->status_class = ISCSI_STATUS_CLS_REDIRECT;
+			rsp->status_detail = target->redirect_info.reason;
+			conn->state = STATE_EXIT;
+			return;
+		}
+
 		if (tgt_get_target_state(target->tid) != SCSI_TARGET_READY) {
 			rsp->status_class = ISCSI_STATUS_CLS_TARGET_ERR;
 			rsp->status_detail = ISCSI_LOGIN_STATUS_TARGET_ERROR;
diff --git a/usr/iscsi/iscsid.h b/usr/iscsi/iscsid.h
index 1e70d81..7e501a4 100644
--- a/usr/iscsi/iscsid.h
+++ b/usr/iscsi/iscsid.h
@@ -21,6 +21,7 @@
 
 #include <stdint.h>
 #include <inttypes.h>
+#include <netdb.h>
 
 #include "transport.h"
 #include "list.h"
@@ -243,6 +244,12 @@ struct iscsi_target {
 	int max_nr_sessions;
 	int nr_sessions;
 
+	struct redirect_info {
+		char addr[NI_MAXHOST + 1];
+		char port[NI_MAXSERV + 1];
+		uint8_t reason;
+	} redirect_info;
+
 	struct list_head isns_list;
 
 	int efd;
@@ -316,6 +323,7 @@ extern int iscsi_target_show(int mode, int tid, uint64_t sid, uint32_t cid,
 			     uint64_t lun, char *buf, int rest);
 int iscsi_target_update(int mode, int op, int tid, uint64_t sid, uint64_t lun,
 			uint32_t cid, char *name);
+int target_redirected(struct iscsi_target *target, struct iscsi_connection *conn);
 
 int iscsi_pthread_per_target(void);
 
diff --git a/usr/iscsi/target.c b/usr/iscsi/target.c
index b547626..c86d851 100644
--- a/usr/iscsi/target.c
+++ b/usr/iscsi/target.c
@@ -192,6 +192,55 @@ int ip_acl(int tid, struct iscsi_connection *conn)
 	return -EPERM;
 }
 
+int target_redirected(struct iscsi_target *target, struct iscsi_connection *conn)
+{
+	struct sockaddr_storage from;
+	struct addrinfo hints, *res;
+	socklen_t len;
+	int ret;
+	char *p, *q, *str;
+
+	if (!strlen(target->redirect_info.addr))
+		return 0;
+
+	if (target->redirect_info.reason != ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP &&
+	    target->redirect_info.reason != ISCSI_LOGIN_STATUS_TGT_MOVED_PERM)
+		return 0;
+
+	len = sizeof(from);
+	ret = conn->tp->ep_getpeername(conn, (struct sockaddr *)&from, &len);
+	if (ret < 0)
+		return 0;
+
+	p = strdup(target->redirect_info.addr);
+	if (!p)
+		return 0;
+	str = p;
+
+	if (*p == '[') {
+		p++;
+		if (!(q = strchr(p, ']')))
+			return 0;
+		*(q++) = '\0';
+	}
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags = AI_NUMERICHOST;
+
+	ret = getaddrinfo(p, NULL, &hints, &res);
+	if (ret < 0) {
+		free(str);
+		return 0;
+	}
+
+	ret = address_match(res->ai_addr, (struct sockaddr *)&from);
+	freeaddrinfo(res);
+	free(str);
+
+	return !ret;
+}
+
 void target_list_build(struct iscsi_connection *conn, char *addr, char *name)
 {
 	struct iscsi_target *target;
@@ -416,6 +465,29 @@ int iscsi_target_update(int mode, int op, int tid, uint64_t sid, uint64_t lun,
 
 		dprintf("%s:%s\n", name, str);
 
+		if (!strncmp(name, "RedirectAddress", 15)) {
+			snprintf(target->redirect_info.addr,
+				 sizeof(target->redirect_info.addr), "%s", str);
+			err = TGTADM_SUCCESS;
+			break;
+		} else if (!strncmp(name, "RedirectPort", 12)) {
+			snprintf(target->redirect_info.port,
+				 sizeof(target->redirect_info.port), "%s", str);
+			err = TGTADM_SUCCESS;
+			break;
+		} else if (!strncmp(name, "RedirectReason", 14)) {
+			if (!strncmp(str, "Temporary", 9)) {
+				target->redirect_info.reason =
+					ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP;
+				err = TGTADM_SUCCESS;
+			} else if (!strncmp(str, "Permanent", 9)) {
+				target->redirect_info.reason =
+					ISCSI_LOGIN_STATUS_TGT_MOVED_PERM;
+				err = TGTADM_SUCCESS;
+			} else
+				break;
+		}
+
 		idx = param_index_by_name(name, session_keys);
 		if (idx >= 0) {
 			err = iscsi_session_param_update(target, idx, str);
@@ -463,6 +535,37 @@ static int iscsi_target_show_session(struct iscsi_target* target, uint64_t sid,
 	return total;
 }
 
+#define __buffer_check(buf, total, len, rest)	\
+({						\
+	buf += len;				\
+	total += len;				\
+	rest -= len;				\
+	if (!rest)				\
+		return total;			\
+})
+
+static int show_redirect_info(struct iscsi_target* target, char *buf, int rest)
+{
+	int len, total = 0;
+
+	len = snprintf(buf, rest, "RedirectAddress=%s\n", target->redirect_info.addr);
+	__buffer_check(buf, total, len, rest);
+	len = snprintf(buf, rest, "RedirectPort=%s\n", target->redirect_info.port);
+	__buffer_check(buf, total, len, rest);
+	if (target->redirect_info.reason == ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP) {
+		len = snprintf(buf, rest, "RedirectReason=Temporary\n");
+		__buffer_check(buf, total, len, rest);
+	} else if (target->redirect_info.reason == ISCSI_LOGIN_STATUS_TGT_MOVED_PERM) {
+		len = snprintf(buf, rest, "RedirectReason=Permanent\n");
+		__buffer_check(buf, total, len, rest);
+	} else {
+		len = snprintf(buf, rest, "RedirectReason=Unknown\n");
+		__buffer_check(buf, total, len, rest);
+	}
+
+	return total;
+}
+
 int iscsi_target_show(int mode, int tid, uint64_t sid, uint32_t cid, uint64_t lun,
 		      char *buf, int rest)
 {
@@ -480,7 +583,10 @@ int iscsi_target_show(int mode, int tid, uint64_t sid, uint32_t cid, uint64_t lu
 		total = isns_show(buf, rest);
 		break;
 	case MODE_TARGET:
-		len = show_iscsi_param(buf, target->session_param, rest);
+		if (strlen(target->redirect_info.addr))
+			len = show_redirect_info(target, buf, rest);
+		else
+			len = show_iscsi_param(buf, target->session_param, rest);
 		total += len;
 		break;
 	case MODE_SESSION:
-- 
1.6.5

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


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

  Powered by Linux