Add user interface for dynamic reconfiguration (USERSPACE TODO ITEM #3).
Note1:
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).
Note2:
This patch makes following parameters to be modifiable in running sessions.
node.session.timeo.replacement_timeout
node.session.iscsi.FastAbort
node.session.err_timeo.abort_timeout
node.session.err_timeo.lu_reset_timeout
node.session.err_timeo.tgt_reset_timeout
node.conn[0].timeo.noop_out_timeout
node.conn[0].timeo.noop_out_interval
v2:
- Bug fixes and Misc cleanups.
v3:
- Add iscsi_session_update_params() in initiator_common.c and replace
iscsi_session_set_params() with iscsi_session_update_params() in
mgmt_ipc_session_update().
- Make it possible to set node.session.timeo.replacement_timeout to "-1".
Signed-off-by: Tomoaki Nishimura <[email protected]>
---
usr/config.h | 3 +
usr/initiator.h | 2 +
usr/initiator_common.c | 88 ++++++++++++++++++++++++++++
usr/iscsiadm.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++--
usr/mgmt_ipc.c | 56 ++++++++++++++++++
usr/mgmt_ipc.h | 1 +
6 files changed, 300 insertions(+), 4 deletions(-)
diff --git a/usr/config.h b/usr/config.h
index fd31a54..93a84ac 100644
--- a/usr/config.h
+++ b/usr/config.h
@@ -39,6 +39,9 @@
/* max len of interface */
#define ISCSI_MAX_IFACE_LEN 65
+/* flag of excluded session update */
+#define NO_UPDATE -2
+
/* the following structures store the options set in the config file.
* a structure is defined for each logically-related group of options.
* if you are adding a new option, first check if it should belong
diff --git a/usr/initiator.h b/usr/initiator.h
index c34625b..cefcfbc 100644
--- a/usr/initiator.h
+++ b/usr/initiator.h
@@ -359,5 +359,7 @@ extern int iscsi_set_net_config(struct iscsi_transport *t,
iscsi_session_t *session,
struct iface_rec *iface);
extern void iscsi_session_init_params(struct iscsi_session *session);
+extern int iscsi_session_update_params(struct iscsi_conn *conn,
+ node_rec_t *rec);
#endif /* INITIATOR_H */
diff --git a/usr/initiator_common.c b/usr/initiator_common.c
index 8ff993d..bfa1ed7 100644
--- a/usr/initiator_common.c
+++ b/usr/initiator_common.c
@@ -637,6 +637,94 @@ TODO handle this
return 0;
}
+#define MAX_UPDATE_PARAMS 7
+
+int iscsi_session_update_params(struct iscsi_conn *conn, node_rec_t *rec)
+{
+ struct iscsi_session *session = conn->session;
+ int i, rc;
+ struct connparam {
+ int param;
+ int type;
+ void *value;
+ int conn_only;
+ } conntbl[MAX_UPDATE_PARAMS] = {
+ {
+ .param = ISCSI_PARAM_SESS_RECOVERY_TMO,
+ .value = &rec->session.timeo.replacement_timeout,
+ .type = ISCSI_INT,
+ .conn_only = 0,
+ }, {
+ .param = ISCSI_PARAM_FAST_ABORT,
+ .value = &rec->session.iscsi.FastAbort,
+ .type = ISCSI_INT,
+ .conn_only = 0,
+ }, {
+ .param = ISCSI_PARAM_ABORT_TMO,
+ .value = &rec->session.err_timeo.abort_timeout,
+ .type = ISCSI_INT,
+ .conn_only = 0,
+ }, {
+ .param = ISCSI_PARAM_LU_RESET_TMO,
+ .value = &rec->session.err_timeo.lu_reset_timeout,
+ .type = ISCSI_INT,
+ .conn_only = 0,
+ }, {
+ .param = ISCSI_PARAM_TGT_RESET_TMO,
+ .value = &rec->session.err_timeo.tgt_reset_timeout,
+ .type = ISCSI_INT,
+ .conn_only = 0,
+ }, {
+ .param = ISCSI_PARAM_PING_TMO,
+ .value = &rec->conn[conn->id].timeo.noop_out_timeout,
+ .type = ISCSI_INT,
+ .conn_only = 1,
+ }, {
+ .param = ISCSI_PARAM_RECV_TMO,
+ .value = &rec->conn[conn->id].timeo.noop_out_interval,
+ .type = ISCSI_INT,
+ .conn_only = 1,
+ },
+ };
+
+ for (i = 0; i < MAX_UPDATE_PARAMS; i++) {
+ if (conntbl[i].type == ISCSI_INT) {
+ if (*((int *)conntbl[i].value) == NO_UPDATE)
+ continue;
+ }
+
+ if (!(session->param_mask & (1ULL << conntbl[i].param)))
+ continue;
+
+ rc = ipc->set_param(session->t->handle, session->id,
+ conn->id, conntbl[i].param, conntbl[i].value,
+ conntbl[i].type);
+ if (rc && rc != -ENOSYS) {
+ log_error("can't set operational parameter %d for "
+ "connection %d:%d, retcode %d (%d)",
+ conntbl[i].param, session->id, conn->id,
+ rc, errno);
+ return -EPERM;
+ }
+
+ if (rc == -ENOSYS) {
+ switch (conntbl[i].param) {
+ case ISCSI_PARAM_PING_TMO:
+ /*
+ * older kernels may not support nops
+ * in kernel
+ */
+ conn->userspace_nop = 1;
+ break;
+ }
+ }
+ print_param_value(conntbl[i].param, conntbl[i].value,
+ conntbl[i].type);
+ }
+
+ return 0;
+}
+
int iscsi_set_net_config(struct iscsi_transport *t, iscsi_session_t *session,
struct iface_rec *iface)
{
diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index f886d39..c967aff 100644
--- a/usr/iscsiadm.c
+++ b/usr/iscsiadm.c
@@ -58,6 +58,10 @@
static char program_name[] = "iscsiadm";
static char config_file[TARGET_NAME_MAXLEN];
extern struct iscsi_ipc *ipc;
+static struct iscsi_rec_params {
+ struct node_rec *rec;
+ struct list_head *params;
+};
enum iscsiadm_mode {
MODE_DISCOVERY,
@@ -3209,6 +3213,125 @@ ping_exit:
return rc;
}
+static int verify_session_update_params(struct list_head *params)
+{
+ int i;
+ struct user_param *param;
+ char key[NAME_MAXVAL];
+
+ list_for_each_entry(param, params, list) {
+ if (strcmp(param->name, SESSION_REPLACEMENT_TMO) == 0)
+ continue;
+ else if (strcmp(param->name, SESSION_ABORT_TMO) == 0)
+ continue;
+ else if (strcmp(param->name, SESSION_FAST_ABORT) == 0)
+ continue;
+ else if (strcmp(param->name, SESSION_LU_RESET_TMO) == 0)
+ continue;
+ else if (strcmp(param->name, SESSION_TGT_RESET_TMO) == 0)
+ continue;
+ else {
+ for (i = 0; i < ISCSI_CONN_MAX; i++) {
+
+ sprintf(key, CONN_NOP_INT, i);
+ if (strcmp(param->name, key) == 0)
+ continue;
+
+ sprintf(key, CONN_NOP_TMO, i);
+ if (strcmp(param->name, key) == 0)
+ continue;
+
+ printf("%s is unsupported in session update.\n",
+ param->name);
+ return ISCSI_ERR;
+ }
+ }
+ }
+
+ return ISCSI_SUCCESS;
+}
+
+static void init_rec_for_session_update(node_rec_t *rec)
+{
+ int i;
+
+ rec->session.timeo.replacement_timeout = NO_UPDATE;
+ rec->session.err_timeo.abort_timeout = NO_UPDATE;
+ rec->session.iscsi.FastAbort = NO_UPDATE;
+ rec->session.err_timeo.lu_reset_timeout = NO_UPDATE;
+ rec->session.err_timeo.tgt_reset_timeout = NO_UPDATE;
+ for (i = 0; i < ISCSI_CONN_MAX; i++) {
+ rec->conn[i].timeo.noop_out_interval = NO_UPDATE;
+ rec->conn[i].timeo.noop_out_timeout = NO_UPDATE;
+ }
+}
+
+static int
+session_update(struct iscsi_rec_params *rec_params, struct session_info *info)
+{
+ int rc;
+ node_rec_t *node_rec;
+ struct list_head *params = rec_params->params;
+ iscsiadm_req_t req;
+ iscsiadm_rsp_t rsp;
+
+ if (!rec_params->rec) {
+ rec_params->rec = idbm_create_rec(info->targetname, info->tpgt,
+ info->persistent_address,
+ info->persistent_port, &info->iface, 1);
+ if (!rec_params->rec)
+ return ISCSI_ERR_NOMEM;
+ }
+ node_rec = rec_params->rec;
+
+ rc = verify_session_update_params(params);
+ if (rc)
+ return rc;
+
+ init_rec_for_session_update(node_rec);
+
+ rc = idbm_node_set_rec_from_param(params, node_rec, 1);
+ if (rc) {
+ log_error("Set rec from params failed.\n");
+ return rc;
+ }
+
+ 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 rc;
+}
+
+static int session_update_all(struct list_head *params)
+{
+ int rc, num_found = 0;
+ struct iscsi_rec_params rec_params;
+
+ rec_params.rec = NULL;
+ rec_params.params = params;
+
+ rc = iscsi_sysfs_for_each_session(&rec_params, &num_found,
+ session_update, 0);
+ if (rc) {
+ log_error("Could not execute operation on all sessions: %s",
+ iscsi_err_to_str(rc));
+ return rc;
+ } else if (!num_found) {
+ log_error("No session found.");
+ return ISCSI_ERR_NO_OBJS_FOUND;
+ }
+
+ return ISCSI_SUCCESS;
+}
+
int
main(int argc, char **argv)
{
@@ -3230,6 +3353,7 @@ main(int argc, char **argv)
uint64_t index = ULLONG_MAX;
struct user_param *param;
struct list_head params;
+ struct iscsi_rec_params rec_params;
INIT_LIST_HEAD(¶ms);
INIT_LIST_HEAD(&ifaces);
@@ -3647,14 +3771,36 @@ 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, ¶ms);
+ if (!(op & OP_NONPERSISTENT)) {
+ rc = exec_node_op(op, do_login, do_logout,
+ do_show, do_rescan,
+ do_stats, info_level,
+ rec, ¶ms);
+ if (rc)
+ goto free_info;
+ }
+ if (op == OP_UPDATE || op == OP_NONPERSISTENT) {
+ rec_params.rec = rec;
+ rec_params.params = ¶ms;
+ rc = session_update(&rec_params, 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,
+ ¶ms);
+ if (rc)
+ goto out;
+ }
+ rc = session_update_all(¶ms);
+ 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..034ea36 100644
--- a/usr/mgmt_ipc.c
+++ b/usr/mgmt_ipc.c
@@ -295,6 +295,61 @@ mgmt_ipc_notify_common(queue_task_t *qtask, int
(*handler)(int, char **))
return ISCSI_SUCCESS;
}
+#define MAX_UPDATE_PARAMS 7
+
+static int mgmt_ipc_session_update(queue_task_t *qtask)
+{
+ int rc, i, sid = qtask->req.u.session.sid;
+ node_rec_t *rec = &qtask->req.u.session.rec;
+ iscsi_session_t *session;
+ struct iscsi_conn *conn;
+
+ session = session_find_by_sid(sid);
+ if (!session)
+ return ISCSI_ERR_SESS_NOT_FOUND;
+
+ for (i = 0; i < ISCSI_CONN_MAX; i++) {
+ conn = &session->conn[i];
+
+ rc = iscsi_session_update_params(conn, rec);
+ if (rc) {
+ log_error("iscsi_session_update_params(): IPC error %d"
+ " session [%02d]" , rc, sid);
+ return ISCSI_ERR_INTERNAL;
+ }
+
+ if (rec->conn[i].timeo.noop_out_timeout != NO_UPDATE)
+ conn->noop_out_timeout =
+ rec->conn[i].timeo.noop_out_timeout;
+
+ if (rec->conn[i].timeo.noop_out_interval != NO_UPDATE)
+ conn->noop_out_interval =
+ rec->conn[i].timeo.noop_out_interval;
+
+ }
+
+ if (rec->session.timeo.replacement_timeout != NO_UPDATE)
+ session->replacement_timeout =
+ rec->session.timeo.replacement_timeout;
+
+ if (rec->session.iscsi.FastAbort != NO_UPDATE)
+ session->fast_abort = rec->session.iscsi.FastAbort;
+
+ if (rec->session.err_timeo.abort_timeout != NO_UPDATE)
+ session->abort_timeout = rec->session.err_timeo.abort_timeout;
+
+ if (rec->session.err_timeo.lu_reset_timeout != NO_UPDATE)
+ session->lu_reset_timeout =
+ rec->session.err_timeo.lu_reset_timeout;
+
+ if (rec->session.err_timeo.tgt_reset_timeout != NO_UPDATE)
+ session->tgt_reset_timeout =
+ rec->session.err_timeo.tgt_reset_timeout;
+
+ mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
+ return ISCSI_SUCCESS;
+}
+
/* Replace these dummies as you implement them
elsewhere */
static int
@@ -529,6 +584,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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.