From cb6f2ce252cb7009252f94aae8d1f774c800243c Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Thu, 18 Oct 2012 10:48:52 +0200 Subject: [PATCH] iSCSI Redirect support This patch adds support for persistant portals like they are common to storage arrays with different interfaces or physical members. --- include/iscsi.h | 1 + lib/connect.c | 12 ++++++++++++ lib/login.c | 7 +++++++ 3 files changed, 20 insertions(+) diff --git a/include/iscsi.h b/include/iscsi.h index 60df33d..309c081 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -231,6 +231,7 @@ enum scsi_status { SCSI_STATUS_GOOD = 0, SCSI_STATUS_CHECK_CONDITION = 2, SCSI_STATUS_RESERVATION_CONFLICT = 0x18, + SCSI_STATUS_REDIRECT = 0x101, SCSI_STATUS_CANCELLED = 0x0f000000, SCSI_STATUS_ERROR = 0x0f000001 }; diff --git a/lib/connect.c b/lib/connect.c index db24a3a..eb9b7c7 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -35,6 +35,10 @@ struct connect_task { int lun; }; +static void +iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data _U_, + void *private_data); + static void iscsi_testunitready_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data) @@ -82,6 +86,14 @@ iscsi_login_cb(struct iscsi_context *iscsi, int status, void *command_data _U_, { struct connect_task *ct = private_data; + if (status == 0x101 && iscsi->target_address) { + iscsi_disconnect(iscsi); + if (iscsi_connect_async(iscsi, iscsi->target_address, iscsi_connect_cb, iscsi->connect_data) != 0) { + return; + } + return; + } + if (status != 0) { ct->cb(iscsi, SCSI_STATUS_ERROR, NULL, ct->private_data); return; diff --git a/lib/login.c b/lib/login.c index b685743..d841a4b 100644 --- a/lib/login.c +++ b/lib/login.c @@ -1088,6 +1088,13 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, size -= len + 1; } + if (status == 0x101 && iscsi->target_address) { + DPRINTF(iscsi,2,"target requests redirect to %s",iscsi->target_address); + pdu->callback(iscsi, SCSI_STATUS_REDIRECT, NULL, + pdu->private_data); + return 0; + } + if (status != 0) { iscsi_set_error(iscsi, "Failed to log in to target. Status: %s(%d)", login_error_str(status), status);