patch-2.3.34 linux/drivers/scsi/scsi_lib.c
Next file: linux/drivers/scsi/scsi_merge.c
Previous file: linux/drivers/scsi/scsi_ioctl.c
Back to the patch index
Back to the overall index
- Lines: 267
- Date:
Sat Dec 18 15:36:40 1999
- Orig file:
v2.3.33/linux/drivers/scsi/scsi_lib.c
- Orig date:
Wed Dec 15 10:43:16 1999
diff -u --recursive --new-file v2.3.33/linux/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c
@@ -87,8 +87,10 @@
SCpnt->request.special = (void *) SCpnt;
/*
- * For the moment, we insert at the head of the queue. This may turn
- * out to be a bad idea, but we will see about that when we get there.
+ * We have the option of inserting the head or the tail of the queue.
+ * Typically we use the tail for new ioctls and so forth. We use the
+ * head of the queue for things like a QUEUE_FULL message from a
+ * device, or a host that is unable to accept a particular command.
*/
spin_lock_irqsave(&io_request_lock, flags);
@@ -97,8 +99,12 @@
q->current_request = &SCpnt->request;
} else {
/*
- * FIXME(eric) - we always insert at the tail of the list. Otherwise
- * ioctl commands would always take precedence over normal I/O.
+ * FIXME(eric) - we always insert at the tail of the
+ * list. Otherwise ioctl commands would always take
+ * precedence over normal I/O. An ioctl on a busy
+ * disk might be delayed indefinitely because the
+ * request might not float high enough in the queue
+ * to be scheduled.
*/
SCpnt->request.next = NULL;
if (q->current_request == NULL) {
@@ -116,9 +122,9 @@
}
/*
- * Now hit the requeue function for the queue. If the host is already
- * busy, so be it - we have nothing special to do. If the host can queue
- * it, then send it off.
+ * Now hit the requeue function for the queue. If the host is
+ * already busy, so be it - we have nothing special to do. If
+ * the host can queue it, then send it off.
*/
q->request_fn(q);
spin_unlock_irqrestore(&io_request_lock, flags);
@@ -219,13 +225,41 @@
q->current_request = &SCpnt->request;
SCpnt->request.special = (void *) SCpnt;
}
+
/*
* Just hit the requeue function for the queue.
- * FIXME - if this queue is empty, check to see if we might need to
- * start requests for other devices attached to the same host.
*/
q->request_fn(q);
+ SDpnt = (Scsi_Device *) q->queuedata;
+ SHpnt = SDpnt->host;
+
+ /*
+ * If this is a single-lun device, and we are currently finished
+ * with this device, then see if we need to get another device
+ * started. FIXME(eric) - if this function gets too cluttered
+ * with special case code, then spin off separate versions and
+ * use function pointers to pick the right one.
+ */
+ if (SDpnt->single_lun
+ && q->current_request == NULL
+ && SDpnt->device_busy == 0) {
+ request_queue_t *q;
+
+ for (SDpnt = SHpnt->host_queue;
+ SDpnt;
+ SDpnt = SDpnt->next) {
+ if (((SHpnt->can_queue > 0)
+ && (SHpnt->host_busy >= SHpnt->can_queue))
+ || (SHpnt->host_blocked)
+ || (SDpnt->device_blocked)) {
+ break;
+ }
+ q = &SDpnt->request_queue;
+ q->request_fn(q);
+ }
+ }
+
/*
* Now see whether there are other devices on the bus which
* might be starved. If so, hit the request function. If we
@@ -234,8 +268,6 @@
* flag as the queue function releases the lock and thus some
* other device might have become starved along the way.
*/
- SDpnt = (Scsi_Device *) q->queuedata;
- SHpnt = SDpnt->host;
all_clear = 1;
if (SHpnt->some_device_starved) {
for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
@@ -274,6 +306,9 @@
*
* Notes: This is called for block device requests in order to
* mark some number of sectors as complete.
+ *
+ * We are guaranteeing that the request queue will be goosed
+ * at some point during this call.
*/
Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors)
{
@@ -311,7 +346,16 @@
* to queue the remainder of them.
*/
if (req->bh) {
+ request_queue_t *q;
+
+ q = &SCpnt->device->request_queue;
+
req->buffer = bh->b_data;
+ /*
+ * Bleah. Leftovers again. Stick the leftovers in
+ * the front of the queue, and goose the queue again.
+ */
+ scsi_queue_next_request(q, SCpnt);
return SCpnt;
}
/*
@@ -323,6 +367,11 @@
up(req->sem);
}
add_blkdev_randomness(MAJOR(req->rq_dev));
+
+ /*
+ * This will goose the queue request function at the end, so we don't
+ * need to worry about launching another command.
+ */
scsi_release_command(SCpnt);
return NULL;
}
@@ -351,6 +400,19 @@
int this_count = SCpnt->bufflen >> 9;
request_queue_t *q = &SCpnt->device->request_queue;
+ /*
+ * We must do one of several things here:
+ *
+ * Call scsi_end_request. This will finish off the specified
+ * number of sectors. If we are done, the command block will
+ * be released, and the queue function will be goosed. If we
+ * are not done, then scsi_end_request will directly goose
+ * the the queue.
+ *
+ * We can just use scsi_queue_next_request() here. This
+ * would be used if we just wanted to retry, for example.
+ *
+ */
ASSERT_LOCK(&io_request_lock, 0);
/*
@@ -417,7 +479,6 @@
* rest of the command, or start a new one.
*/
if (result == 0) {
- scsi_queue_next_request(q, SCpnt);
return;
}
}
@@ -446,13 +507,13 @@
*/
SCpnt->device->changed = 1;
SCpnt = scsi_end_request(SCpnt, 0, this_count);
- scsi_queue_next_request(q, SCpnt);
return;
} else {
/*
- * Must have been a power glitch, or a bus reset.
- * Could not have been a media change, so we just retry
- * the request and see what happens.
+ * Must have been a power glitch, or a
+ * bus reset. Could not have been a
+ * media change, so we just retry the
+ * request and see what happens.
*/
scsi_queue_next_request(q, SCpnt);
return;
@@ -469,11 +530,14 @@
case ILLEGAL_REQUEST:
if (SCpnt->device->ten) {
SCpnt->device->ten = 0;
+ /*
+ * This will cause a retry with a 6-byte
+ * command.
+ */
scsi_queue_next_request(q, SCpnt);
result = 0;
} else {
SCpnt = scsi_end_request(SCpnt, 0, this_count);
- scsi_queue_next_request(q, SCpnt);
return;
}
break;
@@ -481,7 +545,6 @@
printk(KERN_INFO "Device %x not ready.\n",
SCpnt->request.rq_dev);
SCpnt = scsi_end_request(SCpnt, 0, this_count);
- scsi_queue_next_request(q, SCpnt);
return;
break;
case MEDIUM_ERROR:
@@ -492,7 +555,6 @@
print_command(SCpnt->cmnd);
print_sense("sd", SCpnt);
SCpnt = scsi_end_request(SCpnt, 0, block_sectors);
- scsi_queue_next_request(q, SCpnt);
return;
default:
break;
@@ -508,7 +570,6 @@
if (driver_byte(result) & DRIVER_SENSE)
print_sense("sd", SCpnt);
SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.current_nr_sectors);
- scsi_queue_next_request(q, SCpnt);
return;
}
}
@@ -603,7 +664,7 @@
*/
while (1 == 1) {
/*
- * If the host cannot accept another request, then quit.
+ * If the device cannot accept another request, then quit.
*/
if (SDpnt->device_blocked) {
break;
@@ -671,7 +732,7 @@
*/
recount_segments(SCpnt);
} else {
- SCpnt = scsi_allocate_device(SDpnt, FALSE);
+ SCpnt = scsi_allocate_device(SDpnt, FALSE, FALSE);
}
/*
* If so, we are ready to do something. Bump the count
@@ -785,29 +846,5 @@
* the request queue and try to find another command.
*/
spin_lock_irq(&io_request_lock);
- }
-
- /*
- * If this is a single-lun device, and we are currently finished
- * with this device, then see if we need to get another device
- * started.
- */
- if (SDpnt->single_lun
- && q->current_request == NULL
- && SDpnt->device_busy == 0) {
- request_queue_t *q;
-
- for (SDpnt = SHpnt->host_queue;
- SDpnt;
- SDpnt = SDpnt->next) {
- if (((SHpnt->can_queue > 0)
- && (SHpnt->host_busy >= SHpnt->can_queue))
- || (SHpnt->host_blocked)
- || (SDpnt->device_blocked)) {
- break;
- }
- q = &SDpnt->request_queue;
- q->request_fn(q);
- }
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)