TM handling fixes, part2, hopefully, final.

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@3450 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2011-05-12 01:31:01 +00:00
parent 02aced3f19
commit 5e7544e5a4
3 changed files with 29 additions and 7 deletions
+5
View File
@@ -653,6 +653,11 @@ again:
goto cont;
}
}
if (cmnd->data_out_in_data_receiving) {
TRACE_MGMT_DBG("Aborted cmnd %p is waiting for "
"DATA OUT data, keep waiting", cmnd);
goto cont;
}
if (((cmnd == conn->read_cmnd) || (cmnd->r2t_len_to_receive != 0)) &&
(time_after_eq(j, cmnd->write_start + ISCSI_TM_DATA_WAIT_TIMEOUT) ||
force)) {
+17 -7
View File
@@ -417,6 +417,7 @@ void cmnd_done(struct iscsi_cmnd *cmnd)
EXTRACHECKS_BUG_ON(cmnd->on_rx_digest_list);
EXTRACHECKS_BUG_ON(cmnd->hashed);
EXTRACHECKS_BUG_ON(cmnd->cmd_req);
EXTRACHECKS_BUG_ON(cmnd->data_out_in_data_receiving);
req_del_from_write_timeout_list(cmnd);
@@ -625,11 +626,14 @@ static void req_cmnd_pre_release(struct iscsi_cmnd *req)
if (unlikely(req->hashed)) {
/* It sometimes can happen during errors recovery */
TRACE_MGMT_DBG("Removing req %p from hash", req);
cmnd_remove_data_wait_hash(req);
}
if (unlikely(req->cmd_req)) {
/* It sometimes can happen during errors recovery */
TRACE_MGMT_DBG("Putting cmd_req %p (req %p)", req->cmd_req, req);
req->cmd_req->data_out_in_data_receiving = 0;
cmnd_put(req->cmd_req);
req->cmd_req = NULL;
}
@@ -1271,8 +1275,6 @@ static struct iscsi_cmnd *cmnd_find_data_wait_hash(struct iscsi_conn *conn,
spin_lock(&session->cmnd_data_wait_hash_lock);
res = __cmnd_find_data_wait_hash(conn, itt);
if (cmnd_get_check(res) != 0)
res = NULL;
spin_unlock(&session->cmnd_data_wait_hash_lock);
return res;
@@ -2048,8 +2050,9 @@ static int data_out_start(struct iscsi_cmnd *cmnd)
TRACE_ENTRY();
/*
* There is no race with send_r2t() and conn_abort(), since
* all functions called from single read thread
* There is no race with send_r2t(), conn_abort() and
* iscsi_check_tm_data_wait_timeouts(), since
* all the functions called from single read thread
*/
iscsi_extracheck_is_rd_thread(cmnd->conn);
@@ -2069,6 +2072,8 @@ static int data_out_start(struct iscsi_cmnd *cmnd)
goto out;
}
cmnd_get(orig_req);
if (unlikely(orig_req->r2t_len_to_receive < cmnd->pdu.datasize)) {
if (orig_req->prelim_compl_flags != 0) {
/* We can have fake r2t_len_to_receive */
@@ -2102,6 +2107,9 @@ go:
goto out;
}
EXTRACHECKS_BUG_ON(orig_req->data_out_in_data_receiving);
orig_req->data_out_in_data_receiving = 1;
TRACE_WRITE("cmnd %p, orig_req %p, offset %u, datasize %u", cmnd,
orig_req, offset, cmnd->pdu.datasize);
@@ -2129,6 +2137,8 @@ static void data_out_end(struct iscsi_cmnd *cmnd)
iscsi_extracheck_is_rd_thread(cmnd->conn);
req->data_out_in_data_receiving = 0;
if (!(cmnd->conn->ddigest_type & DIGEST_NONE) &&
!cmnd->ddigest_checked) {
cmd_add_on_rx_ddigest_list(req, cmnd);
@@ -2968,9 +2978,9 @@ static void iscsi_push_cmnd(struct iscsi_cmnd *cmnd)
if (unlikely(before(cmd_sn, session->exp_cmd_sn))) {
TRACE_MGMT_DBG("Ignoring out of expected range cmd_sn "
"(sn %u, exp_sn %u, op %x, CDB op %x)", cmd_sn,
session->exp_cmd_sn, cmnd_opcode(cmnd),
cmnd_scsicode(cmnd));
"(sn %u, exp_sn %u, cmd %p, op %x, CDB op %x)",
cmd_sn, session->exp_cmd_sn, cmnd,
cmnd_opcode(cmnd), cmnd_scsicode(cmnd));
drop = 1;
}
+7
View File
@@ -393,6 +393,13 @@ struct iscsi_cmnd {
unsigned int force_cleanup_done:1;
unsigned int dec_active_cmds:1;
unsigned int ddigest_checked:1;
/*
* Used to prevent release of original req while its related DATA OUT
* cmd is receiving data, i.e. stays between data_out_start() and
* data_out_end(). Ref counting can't be used for that, because
* req_cmnd_release() supposed to be called only once.
*/
unsigned int data_out_in_data_receiving:1;
#ifdef CONFIG_SCST_EXTRACHECKS
unsigned int on_rx_digest_list:1;
unsigned int release_called:1;