LWN.net Logo

Advertisement

Advanced thin client solution for Linux, based on Open Source. Mix Windows and Linux applications on the same desktop.

Advertise here

[PATCH] first cut at fixing unable to requeue with no outstanding commands

From:  James Bottomley <James.Bottomley@steeleye.com>
To:  linux-scsi@vger.kernel.org
Subject:  [PATCH] first cut at fixing unable to requeue with no outstanding commands
Date:  Mon, 30 Sep 2002 17:06:36 -0400

The attached represents an attempt to break the scsi mid-layer of the 
assumption that any device can queue at least one command.

What essentially happens if the host rejects a command with no other 
outstanding commands, it does a very crude countdown (basically counts the 
number of cycles through the scsi request function) until the device gets 
enabled again when the count reaches zero.  I think the iteration in the 
request function is better than a fixed timer because it makes the system more 
responsive to I/O pressure (and also, it's easier to code).

I've tested this by making a SCSI driver artificially reject commands with 
none outstanding (and run it on my root device).  A value of seven seems to 
cause a delay of between half and five seconds before the host starts up again 
(depending on the I/O load).

If this approach looks acceptable, I plan the following enhancements

1. Make device_busy count down in the same fashion
2. give ->queuecommand() a two value return (one for blocking the entire host 
and another for just blocking the device).
3. Make the countdown tuneable from the host template.

James



===== hosts.c 1.9 vs edited =====
--- 1.9/drivers/scsi/hosts.c	Tue Jun 11 15:43:08 2002
+++ edited/hosts.c	Mon Sep 30 15:29:56 2002
@@ -210,7 +210,7 @@
     retval->eh_notify   = NULL;    /* Who we notify when we exit. */
 
 
-    retval->host_blocked = FALSE;
+    retval->host_blocked = 0;
     retval->host_self_blocked = FALSE;
 
 #ifdef DEBUG
===== hosts.h 1.12 vs edited =====
--- 1.12/drivers/scsi/hosts.h	Sun Jul 21 03:55:49 2002
+++ edited/hosts.h	Mon Sep 30 15:25:53 2002
@@ -395,11 +395,6 @@
     unsigned use_blk_tcq:1;
 
     /*
-     * Host has rejected a command because it was busy.
-     */
-    unsigned host_blocked:1;
-
-    /*
      * Host has requested that no further requests come through for the
      * time being.
      */
@@ -417,6 +412,19 @@
      */
     unsigned some_device_starved:1;
    
+    /*
+     * Host has rejected a command because it was busy.
+     */
+    unsigned int host_blocked;
+
+    /*
+     * Initial value for the blocking.  If the queue is empty, host_blocked
+     * counts down in the request_fn until it restarts host operations as
+     * zero is reached.  
+     *
+     * FIXME: This should probably be a value in the template */
+    #define SCSI_START_HOST_BLOCKED	7
+
     void (*select_queue_depths)(struct Scsi_Host *, Scsi_Device *);
 
     /*
===== scsi.c 1.36 vs edited =====
--- 1.36/drivers/scsi/scsi.c	Fri Sep 20 00:40:42 2002
+++ edited/scsi.c	Mon Sep 30 15:26:41 2002
@@ -643,7 +643,7 @@
 				return 0;
 			}
 		}
-		host->host_blocked = TRUE;
+		host->host_blocked = SCSI_START_HOST_BLOCKED;
 	} else {
 		if (cmd->device->device_busy == 0) {
 			if (scsi_retry_command(cmd) == 0) {
@@ -1443,7 +1443,7 @@
          * for both the queue full condition on a device, and for a
          * host full condition on the host.
          */
-        host->host_blocked = FALSE;
+        host->host_blocked = 0;
         device->device_blocked = FALSE;
 
 	/*
===== scsi_lib.c 1.30 vs edited =====
--- 1.30/drivers/scsi/scsi_lib.c	Wed Sep 18 11:36:10 2002
+++ edited/scsi_lib.c	Mon Sep 30 15:33:00 2002
@@ -754,6 +754,16 @@
 		if (SHpnt->in_recovery || blk_queue_plugged(q))
 			return;
 
+		if(SHpnt->host_busy == 0 && SHpnt->host_blocked) {
+			/* unblock after host_blocked iterates to zero */
+			if(--SHpnt->host_blocked == 0) {
+				printk("scsi%d unblocking host at zero depth\n", SHpnt->host_no);
+			} else {
+				blk_plug_device(q);
+				break;
+			}
+		}
+				
 		/*
 		 * If the device cannot accept another request, then quit.
 		 */


Copyright © 2002, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds