NOP-In/response timeouts improvements

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@3411 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2011-04-25 23:50:49 +00:00
parent 279ed8fd9f
commit 64065a21e9
8 changed files with 82 additions and 32 deletions

View File

@@ -294,20 +294,20 @@ Each target subdirectory contains the following entries:
- QueuedCommands - defines maximum number of commands queued to any
session of this target. Default is 32 commands.
- RspTimeout - defines the maximum time in seconds a command can wait for
response from initiator, otherwise the corresponding connection will
be closed. For performance reasons it is implemented as a timer,
which once in RspTimeout time checks the oldest command waiting for
response and, if it's older than RspTimeout, then it closes the
connection. Hence, a stalled connection will be closed in time
between RspTimeout and 2*RspTimeout. Default is 30 seconds.
- NopInInterval - defines interval between NOP-In requests, which the
target will send on idle connections to check if the initiator is
still alive. If there is no NOP-Out reply from the initiator in
RspTimeout time, the corresponding connection will be closed. Default
is 30 seconds. If it's set to 0, then NOP-In requests are disabled.
- NopInTimeout - defines the maximum time in seconds a NOP-In request
can wait for response from initiator, otherwise the corresponding
connection will be closed. Default is 30 seconds.
- RspTimeout - defines the maximum time in seconds a command can wait for
response from initiator, otherwise the corresponding connection will
be closed. Default is 90 seconds.
- enabled - using this attribute you can enable or disable iSCSI-SCST
accept new connections to this target. It allows to finish
configuring it before it starts accepting new connections. 0 by

View File

@@ -136,20 +136,20 @@ Each target subdirectory contains the following entries:
- QueuedCommands - defines maximum number of commands queued to any
session of this target. Default is 32 commands.
- RspTimeout - defines the maximum time in seconds a command can wait for
response from initiator, otherwise the corresponding connection will
be closed. For performance reasons it is implemented as a timer,
which once in RspTimeout time checks the oldest command waiting for
response and, if it's older than RspTimeout, then it closes the
connection. Hence, a stalled connection will be closed in time
between RspTimeout and 2*RspTimeout. Default is 30 seconds.
- NopInInterval - defines interval between NOP-In requests, which the
target will send on idle connections to check if the initiator is
still alive. If there is no NOP-Out reply from the initiator in
RspTimeout time, the corresponding connection will be closed. Default
is 30 seconds. If it's set to 0, then NOP-In requests are disabled.
- NopInTimeout - defines the maximum time in seconds a NOP-In request
can wait for response from initiator, otherwise the corresponding
connection will be closed. Default is 30 seconds.
- RspTimeout - defines the maximum time in seconds a command can wait for
response from initiator, otherwise the corresponding connection will
be closed. Default is 90 seconds.
- enabled - using this attribute you can enable or disable iSCSI-SCST
accept new connections to this target. It allows to finish
configuring it before it starts accepting new connections. 0 by

View File

@@ -70,6 +70,7 @@ enum {
key_queued_cmnds,
key_rsp_timeout,
key_nop_in_interval,
key_nop_in_timeout,
key_max_sessions,
target_key_last,
};
@@ -187,7 +188,7 @@ struct iscsi_kern_initiator_info {
#define MIN_NR_QUEUED_CMNDS 1
#define MAX_NR_QUEUED_CMNDS 256
#define DEFAULT_RSP_TIMEOUT 30
#define DEFAULT_RSP_TIMEOUT 90
#define MIN_RSP_TIMEOUT 2
#define MAX_RSP_TIMEOUT 65535
@@ -195,6 +196,10 @@ struct iscsi_kern_initiator_info {
#define MIN_NOP_IN_INTERVAL 0
#define MAX_NOP_IN_INTERVAL 65535
#define DEFAULT_NOP_IN_TIMEOUT 30
#define MIN_NOP_IN_TIMEOUT 2
#define MAX_NOP_IN_TIMEOUT 65535
#define NETLINK_ISCSI_SCST 25
#define REGISTER_USERD _IOWR('s', 0, struct iscsi_kern_register_info)

View File

@@ -530,14 +530,14 @@ static void conn_rsp_timer_fn(unsigned long arg)
cmnd = list_entry(conn->write_timeout_list.next,
struct iscsi_cmnd, write_timeout_list_entry);
timeout_time = j + conn->rsp_timeout + ISCSI_ADD_SCHED_TIME;
timeout_time = j + iscsi_get_timeout(cmnd) + ISCSI_ADD_SCHED_TIME;
if (unlikely(time_after_eq(j, cmnd->write_start +
conn->rsp_timeout))) {
if (unlikely(time_after_eq(j, iscsi_get_timeout_time(cmnd)))) {
if (!conn->closing) {
PRINT_ERROR("Timeout sending data/waiting "
PRINT_ERROR("Timeout %ld sec sending data/waiting "
"for reply to/from initiator "
"%s (SID %llx), closing connection",
iscsi_get_timeout(cmnd)/HZ,
conn->session->initiator_name,
(long long unsigned int)
conn->session->sid);
@@ -883,8 +883,9 @@ static int iscsi_conn_alloc(struct iscsi_session *session,
conn);
#endif
conn->last_rcv_time = jiffies;
conn->rsp_timeout = session->tgt_params.rsp_timeout * HZ;
conn->data_rsp_timeout = session->tgt_params.rsp_timeout * HZ;
conn->nop_in_interval = session->tgt_params.nop_in_interval * HZ;
conn->nop_in_timeout = session->tgt_params.nop_in_timeout * HZ;
if (conn->nop_in_interval > 0) {
TRACE_DBG("Schedule Nop-In work for conn %p", conn);
schedule_delayed_work(&conn->nop_in_delayed_work,

View File

@@ -63,6 +63,7 @@ struct iscsi_tgt_params {
int queued_cmnds;
unsigned int rsp_timeout;
unsigned int nop_in_interval;
unsigned int nop_in_timeout;
};
struct iscsi_thread {
@@ -213,7 +214,7 @@ struct iscsi_conn {
/* Protected by write_list_lock */
struct timer_list rsp_timer;
unsigned int rsp_timeout; /* in jiffies */
unsigned int data_rsp_timeout; /* in jiffies */
/*
* All 2 protected by wr_lock. Modified independently to the
@@ -303,6 +304,7 @@ struct iscsi_conn {
struct work_struct nop_in_delayed_work;
#endif
unsigned int nop_in_interval; /* in jiffies */
unsigned int nop_in_timeout; /* in jiffies */
struct list_head nop_req_list;
spinlock_t nop_req_list_lock;
u32 nop_in_ttt;
@@ -750,6 +752,17 @@ static inline void cmd_del_from_rx_ddigest_list(struct iscsi_cmnd *cmnd)
#endif
}
static inline unsigned long iscsi_get_timeout(struct iscsi_cmnd *req)
{
return (cmnd_opcode(req) == ISCSI_OP_NOP_OUT) ?
req->conn->nop_in_timeout : req->conn->data_rsp_timeout;
}
static inline unsigned long iscsi_get_timeout_time(struct iscsi_cmnd *req)
{
return req->write_start + iscsi_get_timeout(req);
}
static inline int test_write_ready(struct iscsi_conn *conn)
{
/*

View File

@@ -1217,8 +1217,32 @@ void req_add_to_write_timeout_list(struct iscsi_cmnd *req)
req->on_write_timeout_list = 1;
req->write_start = jiffies;
list_add_tail(&req->write_timeout_list_entry,
&conn->write_timeout_list);
if (unlikely(cmnd_opcode(req) == ISCSI_OP_NOP_OUT)) {
unsigned long req_tt = iscsi_get_timeout_time(req);
struct iscsi_cmnd *r;
bool inserted = false;
list_for_each_entry(r, &conn->write_timeout_list,
write_timeout_list_entry) {
unsigned long tt = iscsi_get_timeout_time(r);
if (time_after(tt, req_tt)) {
TRACE_DBG("Add NOP IN req %p (tt %ld) before "
"req %p (tt %ld)", req, req_tt, r, tt);
list_add_tail(&req->write_timeout_list_entry,
&r->write_timeout_list_entry);
inserted = true;
break;
} else
TRACE_DBG("Skipping op %x req %p (tt %ld)",
cmnd_opcode(r), r, tt);
}
if (!inserted) {
TRACE_DBG("Add NOP IN req %p in the tail", req);
list_add_tail(&req->write_timeout_list_entry,
&conn->write_timeout_list);
}
} else
list_add_tail(&req->write_timeout_list_entry,
&conn->write_timeout_list);
if (!timer_pending(&conn->rsp_timer)) {
unsigned long timeout_time;
@@ -1227,11 +1251,11 @@ void req_add_to_write_timeout_list(struct iscsi_cmnd *req)
&req->prelim_compl_flags))) {
set_conn_tm_active = true;
timeout_time = req->write_start +
ISCSI_TM_DATA_WAIT_TIMEOUT +
ISCSI_ADD_SCHED_TIME;
ISCSI_TM_DATA_WAIT_TIMEOUT;
} else
timeout_time = req->write_start +
conn->rsp_timeout + ISCSI_ADD_SCHED_TIME;
timeout_time = iscsi_get_timeout_time(req);
timeout_time += ISCSI_ADD_SCHED_TIME;
TRACE_DBG("Starting timer on %ld (con %p, write_start %ld)",
timeout_time, conn, req->write_start);

View File

@@ -204,6 +204,8 @@ static void tgt_params_check(struct iscsi_session *session,
MAX_RSP_TIMEOUT);
CHECK_PARAM(info, iparams, nop_in_interval, MIN_NOP_IN_INTERVAL,
MAX_NOP_IN_INTERVAL);
CHECK_PARAM(info, iparams, nop_in_timeout, MIN_NOP_IN_TIMEOUT,
MAX_NOP_IN_TIMEOUT);
return;
}
@@ -222,16 +224,19 @@ static int iscsi_tgt_params_set(struct iscsi_session *session,
SET_PARAM(params, info, iparams, queued_cmnds);
SET_PARAM(params, info, iparams, rsp_timeout);
SET_PARAM(params, info, iparams, nop_in_interval);
SET_PARAM(params, info, iparams, nop_in_timeout);
PRINT_INFO("Target parameters set for session %llx: "
"QueuedCommands %d, Response timeout %d, Nop-In "
"interval %d", session->sid, params->queued_cmnds,
params->rsp_timeout, params->nop_in_interval);
"interval %d, Nop-In timeout %d", session->sid,
params->queued_cmnds, params->rsp_timeout,
params->nop_in_interval, params->nop_in_timeout);
list_for_each_entry(conn, &session->conn_list,
conn_list_entry) {
conn->rsp_timeout = session->tgt_params.rsp_timeout * HZ;
conn->data_rsp_timeout = session->tgt_params.rsp_timeout * HZ;
conn->nop_in_interval = session->tgt_params.nop_in_interval * HZ;
conn->nop_in_timeout = session->tgt_params.nop_in_timeout * HZ;
spin_lock_bh(&conn->conn_thr_pool->rd_lock);
if (!conn->closing && (conn->nop_in_interval > 0)) {
TRACE_DBG("Schedule Nop-In work for conn %p", conn);
@@ -244,6 +249,7 @@ static int iscsi_tgt_params_set(struct iscsi_session *session,
GET_PARAM(params, info, iparams, queued_cmnds);
GET_PARAM(params, info, iparams, rsp_timeout);
GET_PARAM(params, info, iparams, nop_in_interval);
GET_PARAM(params, info, iparams, nop_in_timeout);
}
return 0;

View File

@@ -350,6 +350,7 @@ struct iscsi_key target_keys[] = {
{"QueuedCommands", SET_KEY_VALUES(NR_QUEUED_CMNDS), 1, &minimum_ops},
{"RspTimeout", SET_KEY_VALUES(RSP_TIMEOUT), 1, &minimum_ops},
{"NopInInterval", SET_KEY_VALUES(NOP_IN_INTERVAL), 1, &minimum_ops},
{"NopInTimeout", SET_KEY_VALUES(NOP_IN_TIMEOUT), 1, &minimum_ops},
{"MaxSessions", 0, 0, 0, 65535, 1, &minimum_ops},
{NULL,},
};