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, ¶ms, 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;