[stgt] [PATCH] iscsi: target redirect support
FUJITA Tomonori
fujita.tomonori at lab.ntt.co.jp
Tue Jun 15 05:06:49 CEST 2010
On Tue, 15 Jun 2010 11:53:33 +0900
FUJITA Tomonori <fujita.tomonori at lab.ntt.co.jp> wrote:
> > >From the code point of view, it all looks good except a missing
> > free()....
> >
> > On Mon, 2010-06-14 at 15:15 +0900, FUJITA Tomonori wrote:
> >
> > <snip>
> > > + p = strdup(target->redirect_info.addr);
> > > + if (!p)
> > > + return 0;
> > > + str = p;
> > > +
> > > + if (*p == '[') {
> > > + p++;
> > > + if (!(q = strchr(p, ']')))
> >
> > str needs to be freed before this return.
>
> Oops, thanks! I'll fix it and merge the updated patch.
The following patch was merged.
=
From: FUJITA Tomonori <fujita.tomonori at lab.ntt.co.jp>
Subject: [PATCH] iscsi: add 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
v2: Chandra Seetharaman pointed out the failure path memory leak.
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 | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 129 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..fe44b9f 100644
--- a/usr/iscsi/target.c
+++ b/usr/iscsi/target.c
@@ -192,6 +192,57 @@ 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, ']'))) {
+ free(str);
+ 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 +467,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 +537,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 +585,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 at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
More information about the stgt
mailing list