Commit e7d2d832 authored by James Bottomley's avatar James Bottomley

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

 commands

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.
parent 7570df54
...@@ -210,7 +210,7 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j) ...@@ -210,7 +210,7 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j)
retval->eh_notify = NULL; /* Who we notify when we exit. */ retval->eh_notify = NULL; /* Who we notify when we exit. */
retval->host_blocked = FALSE; retval->host_blocked = 0;
retval->host_self_blocked = FALSE; retval->host_self_blocked = FALSE;
#ifdef DEBUG #ifdef DEBUG
......
...@@ -394,11 +394,6 @@ struct Scsi_Host ...@@ -394,11 +394,6 @@ struct Scsi_Host
unsigned highmem_io:1; unsigned highmem_io:1;
unsigned use_blk_tcq:1; 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 * Host has requested that no further requests come through for the
* time being. * time being.
...@@ -417,6 +412,19 @@ struct Scsi_Host ...@@ -417,6 +412,19 @@ struct Scsi_Host
*/ */
unsigned some_device_starved:1; 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 *); void (*select_queue_depths)(struct Scsi_Host *, Scsi_Device *);
/* /*
......
...@@ -627,7 +627,7 @@ static int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason) ...@@ -627,7 +627,7 @@ static int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason)
return 0; return 0;
} }
} }
host->host_blocked = TRUE; host->host_blocked = SCSI_START_HOST_BLOCKED;
} else { } else {
if (cmd->device->device_busy == 0) { if (cmd->device->device_busy == 0) {
if (scsi_retry_command(cmd) == 0) { if (scsi_retry_command(cmd) == 0) {
...@@ -1396,7 +1396,7 @@ void scsi_finish_command(Scsi_Cmnd * SCpnt) ...@@ -1396,7 +1396,7 @@ void scsi_finish_command(Scsi_Cmnd * SCpnt)
* for both the queue full condition on a device, and for a * for both the queue full condition on a device, and for a
* host full condition on the host. * host full condition on the host.
*/ */
host->host_blocked = FALSE; host->host_blocked = 0;
device->device_blocked = FALSE; device->device_blocked = FALSE;
/* /*
......
...@@ -754,6 +754,16 @@ void scsi_request_fn(request_queue_t * q) ...@@ -754,6 +754,16 @@ void scsi_request_fn(request_queue_t * q)
if (SHpnt->in_recovery || blk_queue_plugged(q)) if (SHpnt->in_recovery || blk_queue_plugged(q))
return; return;
if(SHpnt->host_busy == 0 && SHpnt->host_blocked) {
/* unblock after host_blocked iterates to zero */
if(--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. * If the device cannot accept another request, then quit.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment