Home Home > GIT Browse > stable
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Axboe <axboe@suse.de>2002-05-17 10:02:37 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-05-17 10:02:37 -0700
commit7dbe32bed2b9103e744ced54d3f3076e5f01028e (patch)
treebfad577254c871234591443ba45358ee3e08d5e4
parent76e4b1f8c0f00247cab2014471a8c21429355fcc (diff)
[PATCH] fix scsi oops on failed sg table allocation
This patch fixes the deliberate BUG_ON() on failed sgtable allocations. I left that in because I was too lazy to fix it at the time... Basically make scsi_init_io() return 0 on failure (like before) but this time allow us to recover. scsi_init_io() will end_request on a fatal condition. So now just mark the device/host as starved if needed, and leave the request at the front of the queue for next service.
-rw-r--r--drivers/scsi/scsi_lib.c19
-rw-r--r--drivers/scsi/scsi_merge.c15
2 files changed, 22 insertions, 12 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 66f21a37291e..5aed6474d1ab 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -963,21 +963,22 @@ void scsi_request_fn(request_queue_t * q)
/*
* This sets up the scatter-gather table (allocating if
- * required). Hosts that need bounce buffers will also
- * get those allocated here.
+ * required).
*/
if (!scsi_init_io(SCpnt)) {
- SCpnt = __scsi_end_request(SCpnt, 0,
- SCpnt->request.nr_sectors, 0, 0);
- if( SCpnt != NULL )
- {
- panic("Should not have leftover blocks\n");
- }
spin_lock_irq(q->queue_lock);
SHpnt->host_busy--;
SDpnt->device_busy--;
- continue;
+ if (SDpnt->device_busy == 0) {
+ SDpnt->starved = 1;
+ SHpnt->some_device_starved = 1;
+ }
+ SCpnt->request.special = SCpnt;
+ SCpnt->request.flags |= REQ_SPECIAL;
+ _elv_add_request(q, &SCpnt->request, 0, 0);
+ break;
}
+
/*
* Initialize the actual SCSI command for this request.
*/
diff --git a/drivers/scsi/scsi_merge.c b/drivers/scsi/scsi_merge.c
index d462dd1c0db5..cec944e1cd64 100644
--- a/drivers/scsi/scsi_merge.c
+++ b/drivers/scsi/scsi_merge.c
@@ -78,8 +78,12 @@ int scsi_init_io(Scsi_Cmnd *SCpnt)
if (in_interrupt())
gfp_mask &= ~__GFP_WAIT;
+ /*
+ * if sg table allocation fails, requeue request later.
+ */
sgpnt = scsi_alloc_sgtable(SCpnt, gfp_mask);
- BUG_ON(!sgpnt);
+ if (!sgpnt)
+ return 0;
SCpnt->request_buffer = (char *) sgpnt;
SCpnt->request_bufflen = req->nr_sectors << 9;
@@ -102,8 +106,13 @@ int scsi_init_io(Scsi_Cmnd *SCpnt)
printk("Incorrect number of segments after building list\n");
printk("counted %d, received %d\n", count, SCpnt->use_sg);
printk("req nr_sec %lu, cur_nr_sec %u\n", req->nr_sectors, req->current_nr_sectors);
- BUG();
- return 0; /* ahem */
+
+ /*
+ * kill it. there should be no leftover blocks in this request
+ */
+ SCpnt = scsi_end_request(SCpnt, 0, req->nr_sectors);
+ BUG_ON(SCpnt);
+ return 0;
}
/*