]> git.hungrycats.org Git - linux/commitdiff
fix scsi queue plugging behaviour
authorJames Bottomley <jejb@raven.il.steeleye.com>
Mon, 14 Apr 2003 04:18:41 +0000 (23:18 -0500)
committerJames Bottomley <jejb@raven.il.steeleye.com>
Mon, 14 Apr 2003 04:18:41 +0000 (23:18 -0500)
Following recent changes removing blk_queue_empty(), we were
incorrectly plugging the queue some times (most often as part of
the SCSI scan process).  This was causing a non-deterministic panic
in the scan code because a destroyed queue was sometimes being
unplugged and run.

drivers/scsi/scsi_lib.c

index 9e9253041e0608cf95e174a88ef8d9c1dbf387a6..b2b0ce3b30a16aaeded4fae7caefbe4d045e92c4 100644 (file)
@@ -984,7 +984,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
                if (sreq->sr_magic == SCSI_REQ_MAGIC) {
                        cmd = scsi_get_command(sreq->sr_device, GFP_ATOMIC);
                        if (unlikely(!cmd))
-                               return BLKPREP_DEFER;
+                               goto defer;
                        scsi_init_cmd_from_req(cmd, sreq);
                } else
                        cmd = req->special;
@@ -995,7 +995,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
                if (!req->special) {
                        cmd = scsi_get_command(sdev, GFP_ATOMIC);
                        if (unlikely(!cmd))
-                               return BLKPREP_DEFER;
+                               goto defer;
                } else
                        cmd = req->special;
                
@@ -1060,6 +1060,14 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
         */
        req->flags |= REQ_DONTPREP;
        return BLKPREP_OK;
+
+ defer:
+       /* If we defer, the elv_next_request() returns NULL, but the
+        * queue must be restarted, so we plug here if no returning
+        * command will automatically do that. */
+       if (sdev->device_busy == 0)
+               blk_plug_device(q);
+       return BLKPREP_DEFER;
 }
 
 /*
@@ -1164,16 +1172,8 @@ static void scsi_request_fn(request_queue_t *q)
                 */
                req = elv_next_request(q);
 
-               if (!req) {
-                       /*
-                        * If the device is busy, a returning I/O will
-                        * restart the queue. Otherwise, we have to plug
-                        * the queue
-                        */
-                       if (sdev->device_busy == 0)
-                               blk_plug_device(q);
+               if (!req)
                        goto completed;
-               }
 
                if (!scsi_dev_queue_ready(q, sdev))
                        goto completed;