aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Bogdanov <[email protected]>2022-06-07 16:19:53 +0300
committerMartin K. Petersen <[email protected]>2022-06-16 21:53:39 -0400
commit65080c51fde468465e3547d72e4a593b1361c0f4 (patch)
tree946787be2ef14d129373f1a54029c4c26a764f6f
parentc0d93b12f31c31748ca5d3349777c70f1e2a8228 (diff)
scsi: iscsi: Prefer xmit of DataOut over new commands
iscsi_data_xmit() (TX worker) is iterating over the queue of new SCSI commands concurrently with the queue being replenished. Only after the queue is emptied will we start sending pending DataOut PDUs. That leads to DataOut timeout on the target side and to connection reinstatement. Give priority to pending DataOut commands over new commands. Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Konstantin Shelekhin <[email protected]> Reviewed-by: Mike Christie <[email protected]> Signed-off-by: Dmitry Bogdanov <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
-rw-r--r--drivers/scsi/libiscsi.c44
1 files changed, 24 insertions, 20 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 797abf4f5399..8d78559ae94a 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1567,6 +1567,28 @@ check_mgmt:
goto done;
}
+check_requeue:
+ while (!list_empty(&conn->requeue)) {
+ /*
+ * we always do fastlogout - conn stop code will clean up.
+ */
+ if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
+ break;
+
+ task = list_entry(conn->requeue.next, struct iscsi_task,
+ running);
+
+ if (iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_DATA_OUT))
+ break;
+
+ list_del_init(&task->running);
+ rc = iscsi_xmit_task(conn, task, true);
+ if (rc)
+ goto done;
+ if (!list_empty(&conn->mgmtqueue))
+ goto check_mgmt;
+ }
+
/* process pending command queue */
while (!list_empty(&conn->cmdqueue)) {
task = list_entry(conn->cmdqueue.next, struct iscsi_task,
@@ -1594,28 +1616,10 @@ check_mgmt:
*/
if (!list_empty(&conn->mgmtqueue))
goto check_mgmt;
+ if (!list_empty(&conn->requeue))
+ goto check_requeue;
}
- while (!list_empty(&conn->requeue)) {
- /*
- * we always do fastlogout - conn stop code will clean up.
- */
- if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
- break;
-
- task = list_entry(conn->requeue.next, struct iscsi_task,
- running);
-
- if (iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_DATA_OUT))
- break;
-
- list_del_init(&task->running);
- rc = iscsi_xmit_task(conn, task, true);
- if (rc)
- goto done;
- if (!list_empty(&conn->mgmtqueue))
- goto check_mgmt;
- }
spin_unlock_bh(&conn->session->frwd_lock);
return -ENODATA;