Hi Mike,

I got fed up with the large number of rejects I've seen from queuecommand
due to the CmdSN window closing on us.
So I put together a patch for dynamically adjusting shost->can_queue
depending on the number of rejects.

Purely as a proof-on-concept, but works out quite nicely.
I did on purpose _not_ calling the change_queue_depth callback
as this would induce quite some overhead here with very
little gain, as shost->can_queue seems to be more appropriate
here as we're deducing the number of commands for the host/target,
not the LUN.

Interesting though, both NetApp and MSA level out at around
64 commands. Maybe we should consider changing the default ...

Feedback welcome.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                   zSeries & Storage
[email protected]                          +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Markus Rex, HRB 16746 (AG Nürnberg)

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at http://groups.google.com/group/open-iscsi
-~----------~----~----~----~------~----~------~--~---

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 0356e3d..a4d6eda 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1592,7 +1743,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void 
(*done)(struct scsi_cmnd *))
        struct iscsi_cls_session *cls_session;
        struct Scsi_Host *host;
        struct iscsi_host *ihost;
-       int reason = 0;
+       int reason = 0, adjust_qdepth = 0;
        struct iscsi_session *session;
        struct iscsi_conn *conn;
        struct iscsi_task *task = NULL;
@@ -1684,27 +1835,53 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void 
(*done)(struct scsi_cmnd *))
        }
 
        session->queued_cmdsn++;
+       if (session->reject_count < 20) {
+               adjust_qdepth = 1;
+               session->reject_count = 100;
+       } else {
+               session->reject_count--;
+       }
        spin_unlock(&session->lock);
        spin_lock(host->host_lock);
+       if (adjust_qdepth == 1) {
+               host->can_queue++;
+               iscsi_session_printk(KERN_INFO, session,
+                                    "adjusted queue depth to %u\n",
+                                    host->can_queue);
+       }
        return 0;
 
 prepd_reject:
        sc->scsi_done = NULL;
        iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
 reject:
-       spin_unlock(&session->lock);
        ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
                          sc->cmnd[0], reason);
+
+       if (session->reject_count > 200) {
+               adjust_qdepth = -1;
+               session->reject_count = 100;
+       } else {
+               session->reject_count++;
+       }
+       spin_unlock(&session->lock);
        spin_lock(host->host_lock);
+       if (adjust_qdepth == -1) {
+               host->can_queue--;
+               iscsi_session_printk(KERN_INFO, session,
+                                    "adjusted queue depth to %u\n",
+                                    host->can_queue);
+       }
        return SCSI_MLQUEUE_TARGET_BUSY;
 
 prepd_fault:
        sc->scsi_done = NULL;
        iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
 fault:
-       spin_unlock(&session->lock);
+       session->fault_count++;
        ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
                          sc->cmnd[0], reason);
+       spin_unlock(&session->lock);
        if (!scsi_bidi_cmnd(sc))
                scsi_set_resid(sc, scsi_bufflen(sc));
        else {
@@ -2793,6 +2982,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
 
        conn->last_recv = jiffies;
        conn->last_ping = jiffies;
+       session->reject_count = 100;
        if (conn->recv_timeout && conn->ping_timeout)
                mod_timer(&conn->transport_timer,
                          jiffies + (conn->recv_timeout * HZ));
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 61afeb5..b006a32 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -298,6 +303,7 @@ struct iscsi_session {
                                                 * - r2tpool               */
        int                     state;          /* session state           */
        int                     age;            /* counts session re-opens */
+       unsigned long           reject_count;   /* counts cmd rejects */
 
        int                     scsi_cmds_max;  /* max scsi commands */
        int                     cmds_max;       /* size of cmds array */

Reply via email to