mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-14 01:01:27 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user