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