Hello,

We have a setup, where we are using the iSCSI redirect functionality, where 
we connect to a highly available persistent address, and get redirected to 
a different address/portal.
Our setup allows modifying the persistent IP address of the iSCSI targets, 
amongst active I/O to the iSCSI sessions to the redirected 
addresses/portals.
The requirement is to ensure non-disruptive I/O when any portal crashes. 
(persistent address/portal is assumed to be still available)

Consider a scenario where sessions are redirected to different 
addresses/portals and now the persistent portal address is modified on the 
target.

Without this patch:
When the redirected portal crashes, iscsid would tries to recover the 
session by reconnecting to the incorrect/stale in-memory 'failback_saddr' 
portal.
Since, this IP is modified on the fly, iscsid tries reconnecting to a wrong 
portal.

With the patch:
Patch notifiies iscsid about the change in the persistent address of all 
the sessions via the iscsiadm utility.
All in-memory session structures' failback addresses are updated with the 
new persistent address.

We have unit-tested the patch in our setup and we can see sessions 
recovering amongst current portal failures.
Usage:

iscsiadm -m session -n updated_persistent_ip_address -v 192.168.5.5

Would be great if someone can review the attached patch.  Any 
feedback/suggestions/questions greatly appreciated.

Thanks,
Satyajit

-- 
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to open-iscsi+unsubscr...@googlegroups.com.
To post to this group, send email to open-iscsi@googlegroups.com.
Visit this group at https://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.
commit dcee6c1e4b9f98472f814a69632a42a98bb71559
Author: Satyajit Deshmukh <satyajit.s.deshm...@gmail.com>
Date:   Wed Feb 8 01:19:06 2017 -0800

    iscsiadm utility to update persistent address of all sessions, to a given address. Usage: iscsiadm -m session -n updated_persistent_ip_address -v 192.168.5.5

diff --git a/usr/initiator.h b/usr/initiator.h
index 4f96d6b..49ce189 100644
--- a/usr/initiator.h
+++ b/usr/initiator.h
@@ -281,7 +281,7 @@ extern int iscsi_add_text(struct iscsi_hdr *hdr, char *data, int max_data_length
 extern enum iscsi_login_status iscsi_login(iscsi_session_t *session, int cid,
 		   char *buffer, size_t bufsize, uint8_t * status_class,
 		   uint8_t * status_detail);
-extern int iscsi_update_address(iscsi_conn_t *conn, char *address);
+extern int iscsi_update_address(iscsi_conn_t *conn, char *address, int update_persistent_address);
 extern int iscsi_login_begin(iscsi_session_t *session,
 			     iscsi_login_context_t *c);
 extern int iscsi_login_req(iscsi_session_t *session, iscsi_login_context_t *c);
diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index 4b2bd34..c66790b 100644
--- a/usr/iscsiadm.c
+++ b/usr/iscsiadm.c
@@ -3713,6 +3713,14 @@ free_info:
 			}
 
 			rc = session_info_print(info_level, NULL, do_show);
+
+			/* Update persistent portal if old and new ip portal is provided. */
+			list_for_each_entry(param, &params, list) {
+				if (!strcmp("updated_persistent_ip_address", param->name)) {
+					update_persistent_ip_address(param->value);
+					break;
+				}
+      }
 		}
 		break;
 	default:
diff --git a/usr/login.c b/usr/login.c
index 294ad0b..e605827 100644
--- a/usr/login.c
+++ b/usr/login.c
@@ -184,7 +184,7 @@ resolve_address(char *host, char *port, struct sockaddr_storage *ss)
  * provided
  */
 int
-iscsi_update_address(iscsi_conn_t *conn, char *address)
+iscsi_update_address(iscsi_conn_t *conn, char *address, int update_persistent_address)
 {
 	char *port, *tag;
 	char default_port[NI_MAXSERV];
@@ -222,7 +222,11 @@ iscsi_update_address(iscsi_conn_t *conn, char *address)
 		return 0;
 	}
 
-	conn->saddr = addr;
+  if (!update_persistent_address)
+    conn->saddr = addr;
+  else
+    conn->failback_saddr = addr;
+
 	if (tag)
 		session->portal_group_tag = atoi(tag);
 	return 1;
@@ -265,7 +269,7 @@ get_security_text_keys(iscsi_session_t *session, int cid, char **data,
 		 * ip_address and port to the new TargetAddress for
 		 * leading connection
 		 */
-		if (iscsi_update_address(&session->conn[cid], value)) {
+		if (iscsi_update_address(&session->conn[cid], value, 0)) {
 			text = value_end;
 		} else {
 			log_error("Login redirection failed, "
@@ -337,7 +341,7 @@ get_op_params_text_keys(iscsi_session_t *session, int cid,
 		text = value_end;
 	} else if (iscsi_find_key_value("TargetAddress", text, end, &value,
 					 &value_end)) {
-		if (iscsi_update_address(conn, value))
+		if (iscsi_update_address(conn, value, 0))
 			text = value_end;
 		else {
 			log_error("Login redirection failed, "
diff --git a/usr/mgmt_ipc.c b/usr/mgmt_ipc.c
index c16bce9..9e4d3d9 100644
--- a/usr/mgmt_ipc.c
+++ b/usr/mgmt_ipc.c
@@ -37,6 +37,8 @@
 #include "iscsi_ipc.h"
 #include "iscsi_err.h"
 #include "iscsi_util.h"
+#include "session_info.h"
+#include "initiator.h"
 
 #define PEERUSER_MAX	64
 #define EXTMSG_MAX	(64 * 1024)
@@ -346,6 +348,35 @@ mgmt_ipc_notify_del_portal(queue_task_t *qtask)
 	return mgmt_ipc_notify_common(qtask, iscsi_discovery_del_portal);
 }
 
+static int update_persistent_address(void *data, struct session_info *info)
+{
+	int rc, sid = info->sid;
+	char *persistent_address = (char *)data;
+	struct iscsi_session *session = session_find_by_sid(sid);
+	if (iscsi_update_address(&session->conn[0], persistent_address, 1)) {
+		log_info("Successfully updated persistent address to %s for session %d", persistent_address, sid);
+		rc = 0;
+	} else {
+		log_error("Failed to update persistent address to %s for session %d", persistent_address, sid);
+		rc = -1;
+	}
+	return rc;
+}
+
+static int
+mgmt_ipc_notify_upd_perst_addr(queue_task_t *qtask)
+{
+	char *persistent_ip_address = qtask->req.u.updated_persistent_ip_address;
+	int nr_found = 0, err;
+	err = iscsi_sysfs_for_each_session(persistent_ip_address, &nr_found, update_persistent_address, 0);
+
+	if (!err)
+		log_info("Successfully updated persistent portals for %d sessions.", nr_found);
+
+	mgmt_ipc_write_rsp(qtask, err);
+	return ISCSI_SUCCESS;
+}
+
 static int
 mgmt_peeruser(int sock, char *user)
 {
@@ -530,6 +561,7 @@ static mgmt_ipc_fn_t *	mgmt_ipc_functions[__MGMT_IPC_MAX_COMMAND] = {
 [MGMT_IPC_NOTIFY_DEL_NODE]	= mgmt_ipc_notify_del_node,
 [MGMT_IPC_NOTIFY_ADD_PORTAL]	= mgmt_ipc_notify_add_portal,
 [MGMT_IPC_NOTIFY_DEL_PORTAL]	= mgmt_ipc_notify_del_portal,
+[MGMT_IPC_NOTIFY_UPD_PERST_ADDR]	= mgmt_ipc_notify_upd_perst_addr,
 };
 
 void mgmt_ipc_handle(int accept_fd)
diff --git a/usr/mgmt_ipc.h b/usr/mgmt_ipc.h
index 55972ed..d0b18b6 100644
--- a/usr/mgmt_ipc.h
+++ b/usr/mgmt_ipc.h
@@ -46,6 +46,7 @@ typedef enum iscsiadm_cmd {
 	MGMT_IPC_NOTIFY_DEL_NODE	= 17,
 	MGMT_IPC_NOTIFY_ADD_PORTAL	= 18,
 	MGMT_IPC_NOTIFY_DEL_PORTAL	= 19,
+	MGMT_IPC_NOTIFY_UPD_PERST_ADDR	= 20,
 
 	__MGMT_IPC_MAX_COMMAND
 } iscsiadm_cmd_e;
@@ -77,6 +78,7 @@ typedef struct iscsiadm_req {
 			char value[IFNAMSIZ + 1];
 
 		} set_host_param;
+		char updated_persistent_ip_address[NI_MAXHOST];
 	} u;
 } iscsiadm_req_t;
 
diff --git a/usr/session_info.c b/usr/session_info.c
index 9dc6e25..f17d674 100644
--- a/usr/session_info.c
+++ b/usr/session_info.c
@@ -146,6 +146,23 @@ static int print_iscsi_state(int sid, char *prefix, int tmo)
 	return 0;
 }
 
+void update_persistent_ip_address(char *persistent_ip_address)
+{
+	iscsiadm_req_t req;
+	iscsiadm_rsp_t rsp;
+	int err;
+
+	memset(&req, 0, sizeof(iscsiadm_req_t));
+	req.command = MGMT_IPC_NOTIFY_UPD_PERST_ADDR;
+	strcpy(req.u.updated_persistent_ip_address, persistent_ip_address);
+
+	err = iscsid_exec_req(&req, &rsp, 1, ISCSID_REQ_TIMEOUT);
+	if (!err)
+		printf("Updated all sessions' persistent IP address to %s\n", persistent_ip_address);
+	else
+		printf("Failed with %d to update sessions with newer persistent portal address.\n", err);
+}
+
 static void print_iscsi_params(int sid, char *prefix)
 {
 	struct iscsi_session_operational_config session_conf;

Reply via email to