This patch is a prototype for dynamic reconfiguration (USERSPACE TODO ITEM #3).
This patch defines some parameters update interface in iscsiadm session mode.

Examples of the user interface in this patch is as follows.

 # iscsiadm -m session -o update -n PARAM_NAME -v VALUE
 => Update node DB and session parameter in all running sessions.

 # iscsiadm -m session -o nonpersistent -n PARAM_NAME -v VALUE
 => Update session parameter in all running sessions (not update node DB).

 # iscsiadm -m session -o update -n PARAM_NAME -v VALUE -r SESSION_ID
 => Update node DB and session parameter in a specified session.

 # iscsiadm -m session -o nonpersistent -n PARAM_NAME -v VALUE -r SESSION_ID
 => Update session parameter in a specified session (not update node DB).

This patch makes following parameters to be modifiable in running session.

 node.session.timeo.replacement_timeout
 node.session.iscsi.FastAbort
 node.session.err_timeo.abort_timeout
 node.session.err_timeo.lu_reset_timeout
 node.conn[0].timeo.noop_out_timeout
 node.conn[0].timeo.noop_out_interval


There is a concern about the user interface in this patch.
Currently following option is drop down to node ops in iscsiadm. 

 # iscsiadm -m session -o update -n PARAM_NAME -v VALUE 

So I'm worried about modifying a session parameter unintentionally. 
But I can't come up with the better user interface.

Any comments are welcome.

Signed-off-by: Tomoaki Nishimura <t-nishim...@hf.jp.nec.com>
---
 usr/iscsiadm.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 usr/mgmt_ipc.c |  33 ++++++++++
 usr/mgmt_ipc.h |   1 +
 3 files changed, 222 insertions(+), 4 deletions(-)

diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index f886d39..a7b6109 100644
--- a/usr/iscsiadm.c
+++ b/usr/iscsiadm.c
@@ -29,6 +29,7 @@
 #include <signal.h>
 #include <time.h>
 #include <sys/stat.h>
+#include <dirent.h>
 
 #include "initiator.h"
 #include "discovery.h"
@@ -3209,6 +3210,166 @@ ping_exit:
        return rc;
 }
 
+static int
+session_set_rec_from_params(node_rec_t *rec, struct list_head *params)
+{
+       int rc;
+       struct user_param *param;
+       char id[256];
+
+       rc = verify_node_params(params, rec);
+       if (rc)
+               return rc;
+
+       snprintf(id, sizeof(id), "session%d", rec->session.sid);
+       sysfs_get_int(id, "iscsi_session", "recovery_tmo",
+                       &rec->session.timeo.replacement_timeout);
+       sysfs_get_int(id, "iscsi_session", "fast_abort",
+                       &rec->session.iscsi.FastAbort);
+       sysfs_get_int(id, "iscsi_session", "abort_tmo",
+                       &rec->session.err_timeo.abort_timeout);
+       sysfs_get_int(id, "iscsi_session", "lu_reset_tmo",
+                       &rec->session.err_timeo.lu_reset_timeout);
+
+       snprintf(id, sizeof(id), "connection%d:0", rec->session.sid);
+       sysfs_get_int(id, "iscsi_connection", "ping_tmo",
+                       &rec->conn[0].timeo.noop_out_timeout);
+       sysfs_get_int(id, "iscsi_connection", "recv_tmo",
+                       &rec->conn[0].timeo.noop_out_interval);
+
+       list_for_each_entry(param, params, list) {
+               if (strcmp(param->name,
+                       "node.session.timeo.replacement_timeout") == 0) {
+                       rec->session.timeo.replacement_timeout =
+                               strtoul(param->value, NULL, 10);
+               } else if (strcmp(param->name,
+                       "node.session.iscsi.FastAbort") == 0) {
+                       if (strcmp(param->value, "Yes") == 0) {
+                               rec->session.iscsi.FastAbort = 1;
+                       } else if (strcmp(param->value, "No") == 0) {
+                               rec->session.iscsi.FastAbort = 0;
+                       }
+               } else if (strcmp(param->name,
+                       "node.session.err_timeo.abort_timeout") == 0) {
+                       rec->session.err_timeo.abort_timeout =
+                               strtoul(param->value, NULL, 10);
+               } else if (strcmp(param->name,
+                       "node.session.err_timeo.lu_reset_timeout") == 0) {
+                       rec->session.err_timeo.lu_reset_timeout =
+                               strtoul(param->value, NULL, 10);
+               } else if (strcmp(param->name,
+                       "node.conn[0].timeo.noop_out_timeout") == 0) {
+                       rec->conn[0].timeo.noop_out_timeout =
+                               strtoul(param->value, NULL, 10);
+               } else if (strcmp(param->name,
+                       "node.conn[0].timeo.noop_out_interval") == 0) {
+                       rec->conn[0].timeo.noop_out_interval =
+                               strtoul(param->value, NULL, 10);
+               } else {
+                       printf("%s is not supported in session update\n",
+                               param->name);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+static int session_update(node_rec_t *node_rec, struct session_info *info)
+{
+       int rc;
+       iscsiadm_req_t req;
+       iscsiadm_req_t rsp;
+
+       if (!iscsi_match_session(node_rec, info))
+               return -1;
+       /*
+       rc = iscsid_req_by_rec(MGMT_IPC_SESSION_UPDATE, rec);
+       */
+       req.command = MGMT_IPC_SESSION_UPDATE;
+       req.u.session.sid = info->sid;
+       memcpy(&req.u.session.rec, node_rec, sizeof(node_rec_t));
+
+       rc = iscsid_exec_req(&req, &rsp, 1);
+       if (rc)
+               return rc;
+
+       printf("Session update [sid: %d, target: %s, portal: %s,%d]\n",
+               info->sid, info->targetname, info->persistent_address,
+               info->port);
+
+       return 0;
+}
+
+static int trans_filter(const struct dirent *dir)
+{
+       return strcmp(dir->d_name, ".") && strcmp(dir->d_name, "..");
+}
+
+static int session_update_all(struct list_head *params)
+{
+       struct dirent **namelist;
+       int rc = 0, n, i;
+       struct session_info *info;
+       struct node_rec *rec = NULL;
+
+       info = calloc(1, sizeof(*info));
+       if (!info)
+               return ISCSI_ERR_NOMEM;
+
+       n = scandir("/sys/class/iscsi_session", &namelist, trans_filter,
+                                                               alphasort);
+       if (n <= 0)
+               goto free_info;
+
+       for (i = 0; i < n; i++) {
+               rc = iscsi_sysfs_get_sessioninfo_by_id(info,
+                                                       namelist[i]->d_name);
+               if (rc) {
+                       log_error("could not find session info for %s",
+                                                       namelist[i]->d_name);
+                       /* raced. session was shutdown while looping */
+                       rc = 0;
+                       continue;
+               }
+
+               rec = idbm_create_rec(info->targetname,
+                                       info->tpgt,
+                                       info->persistent_address,
+                                       info->persistent_port,
+                                       &info->iface, 1);
+               if (!rec) {
+                       log_error("create rec for %s failed",
+                                                       namelist[i]->d_name);
+                       goto free_info;
+               }
+               rec->session.info = info;
+               rec->session.sid = info->sid;
+
+               rc = session_set_rec_from_params(rec, params);
+               if (rc) {
+                       log_error("set params for %s failed, error %d",
+                                               namelist[i]->d_name, rc);
+                       goto free_info;
+               }
+               rc = session_update(rec, info);
+               free(rec);
+               if (rc) {
+                       log_error("update session for %s failed, error %d",
+                                               namelist[i]->d_name, rc);
+                       goto free_info;
+               }
+       }
+
+
+       for (i = 0; i < n; i++)
+               free(namelist[i]);
+       free(namelist);
+
+free_info:
+       free(info);
+       return rc;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -3647,14 +3808,37 @@ main(int argc, char **argv)
                                rec->session.multiple = 1;
                        }
 
-                       /* drop down to node ops */
-                       rc = exec_node_op(op, do_login, do_logout, do_show,
-                                         do_rescan, do_stats, info_level,
-                                         rec, &params);
+                       if (!(op & OP_NONPERSISTENT)) {
+                               rc = exec_node_op(op, do_login, do_logout,
+                                                       do_show, do_rescan,
+                                                       do_stats, info_level,
+                                                       rec, &params);
+                               if (rc)
+                                       goto free_info;
+                       }
+                       if (op == OP_UPDATE || op == OP_NONPERSISTENT) {
+                               rc = session_set_rec_from_params(rec, &params);
+                               if (rc)
+                                       goto free_info;
+                               rc = session_update(rec, info);
+                       }
 free_info:
                        free(info);
                        goto out;
                } else {
+                       if (op == OP_UPDATE || op == OP_NONPERSISTENT) {
+                               if (!(op & OP_NONPERSISTENT)) {
+                                       rc = exec_node_op(op, do_login,
+                                                       do_logout, do_show,
+                                                       do_rescan, do_stats,
+                                                       info_level, rec,
+                                                       &params);
+                                       if (rc)
+                                               goto out;
+                               }
+                               rc = session_update_all(&params);
+                               goto out;
+                       }
                        if (op == OP_NEW) {
                                log_error("session mode: Operation 'new' only "
                                          "allowed with specific session IDs");
diff --git a/usr/mgmt_ipc.c b/usr/mgmt_ipc.c
index ee037d9..b96946d 100644
--- a/usr/mgmt_ipc.c
+++ b/usr/mgmt_ipc.c
@@ -295,6 +295,38 @@ mgmt_ipc_notify_common(queue_task_t *qtask, int 
(*handler)(int, char **))
        return ISCSI_SUCCESS;
 }
 
+static int mgmt_ipc_session_update(queue_task_t *qtask)
+{
+       int sid = qtask->req.u.session.sid;
+       node_rec_t *rec = &qtask->req.u.session.rec;
+       iscsi_session_t *session;
+       struct iscsi_conn *conn;
+       int rc;
+
+       session = session_find_by_sid(sid);
+       if (!session)
+               return ISCSI_ERR_SESS_NOT_FOUND;
+
+       session->replacement_timeout = rec->session.timeo.replacement_timeout;
+       session->fast_abort = rec->session.iscsi.FastAbort;
+       session->abort_timeout = rec->session.err_timeo.abort_timeout;
+       session->lu_reset_timeout = rec->session.err_timeo.lu_reset_timeout;
+
+       conn = &session->conn[0];
+       conn->noop_out_timeout = rec->conn[0].timeo.noop_out_timeout;
+       conn->noop_out_interval = rec->conn[0].timeo.noop_out_interval;
+
+       rc = iscsi_session_set_params(conn);
+       if (rc) {
+               log_error("iscsi_session_set_params(): IPC error %d session"
+                       " [%02d]" , rc, sid);
+               return ISCSI_ERR_INTERNAL;
+       }
+
+       mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
+       return ISCSI_SUCCESS;
+}
+
 /* Replace these dummies as you implement them
    elsewhere */
 static int
@@ -529,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_SESSION_UPDATE]      = mgmt_ipc_session_update,
 };
 
 void mgmt_ipc_handle(int accept_fd)
diff --git a/usr/mgmt_ipc.h b/usr/mgmt_ipc.h
index 55972ed..1a06403 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_SESSION_UPDATE         = 20,
 
        __MGMT_IPC_MAX_COMMAND
 } iscsiadm_cmd_e;
-- 
1.9.3

-- 
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 http://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.

Reply via email to