[stgt] [PATCH] iscsi: target redirect support

Chandra Seetharaman sekharan at us.ibm.com
Mon Jun 14 20:06:23 CEST 2010


Hi Tomo,

Nice feature to have. Will test it out and respond.

BTW, just to confirm... the redirector is one instance of tgtd running
on a node, and at the redirected address/port a tgtd is running which
serves the target, right ?

Thanks,

chandra

On Mon, 2010-06-14 at 15:15 +0900, FUJITA Tomonori wrote:
> Let's keep up with IET. :)
> 
> =
> From: FUJITA Tomonori <fujita.tomonori at lab.ntt.co.jp>
> Subject: [PATCH] iscsi: target redirect support
> 
> root at rose:~# tgtadm --op update --mode target --tid 1 --name RedirectAddress --value 10.76.0.30
> root at rose:~# tgtadm --op update --mode target --tid 1 --name RedirectPort --value 3260
> root at rose:~# tgtadm --op update --mode target --tid 1 --name RedirectReason --value Temporary
> root at rose:~# tgtadm --op show --mode target --tid 1
> RedirectAddress=10.76.0.30
> RedirectPort=3260
> RedirectReason=Temporary
> 
> If you want "Target moved permanently",
> 
> root at rose:~# tgtadm --op update --mode target --tid 1 --name RedirectReason --value Permanent
> 
> Signed-off-by: FUJITA Tomonori <fujita.tomonori at lab.ntt.co.jp>
> ---
>  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:


--
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