[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