iscsi: fix iscsi task refcount for out of order write completions

For large writes that require multiple SCSI tasks (one for immediate
data, then one or more for R2T-solicited data), we bump the refcount
for the task associated with the initial immediate data PDU, to
ensure it does not get freed until all of the child tasks are
completed.  But in some cases this initial immediate data PDU could
complete after all of the R2T-soliciated data PDUs.  The
completion code was not handling this case correctly which would
result in the iSCSI connection thinking it still had outstanding
SCSI tasks when the connection closed.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Change-Id: I9f9c5322755462d1918fde0075c87c84295cb10c
This commit is contained in:
Jim Harris 2016-10-13 20:34:12 -07:00
parent eef39e8d35
commit 9459848ce5

View File

@ -920,7 +920,15 @@ void process_task_completion(spdk_event_t event)
if (primary->scsi.bytes_completed == primary->scsi.transfer_len) {
spdk_del_transfer_task(conn, primary->scsi.id);
spdk_iscsi_task_response(conn, primary);
if (task != primary) {
/*
* Check if this is the last task completed for an iSCSI write
* that required child subtasks. If task != primary, we know
* for sure that it was part of an iSCSI write with child subtasks.
* The trickier case is when the last task completed was the initial
* task - in this case the task will have a smaller length than
* the overall transfer length.
*/
if (task != primary || task->scsi.length != task->scsi.transfer_len) {
TAILQ_REMOVE(&conn->active_r2t_tasks, primary, link);
spdk_iscsi_task_put(primary);
}