Commit 7dbe32be authored by Jens Axboe's avatar Jens Axboe Committed by Linus Torvalds

[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.
parent 76e4b1f8
...@@ -963,21 +963,22 @@ void scsi_request_fn(request_queue_t * q) ...@@ -963,21 +963,22 @@ void scsi_request_fn(request_queue_t * q)
/* /*
* This sets up the scatter-gather table (allocating if * This sets up the scatter-gather table (allocating if
* required). Hosts that need bounce buffers will also * required).
* get those allocated here.
*/ */
if (!scsi_init_io(SCpnt)) { 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); spin_lock_irq(q->queue_lock);
SHpnt->host_busy--; SHpnt->host_busy--;
SDpnt->device_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. * Initialize the actual SCSI command for this request.
*/ */
......
...@@ -78,8 +78,12 @@ int scsi_init_io(Scsi_Cmnd *SCpnt) ...@@ -78,8 +78,12 @@ int scsi_init_io(Scsi_Cmnd *SCpnt)
if (in_interrupt()) if (in_interrupt())
gfp_mask &= ~__GFP_WAIT; gfp_mask &= ~__GFP_WAIT;
/*
* if sg table allocation fails, requeue request later.
*/
sgpnt = scsi_alloc_sgtable(SCpnt, gfp_mask); sgpnt = scsi_alloc_sgtable(SCpnt, gfp_mask);
BUG_ON(!sgpnt); if (!sgpnt)
return 0;
SCpnt->request_buffer = (char *) sgpnt; SCpnt->request_buffer = (char *) sgpnt;
SCpnt->request_bufflen = req->nr_sectors << 9; SCpnt->request_bufflen = req->nr_sectors << 9;
...@@ -102,8 +106,13 @@ int scsi_init_io(Scsi_Cmnd *SCpnt) ...@@ -102,8 +106,13 @@ int scsi_init_io(Scsi_Cmnd *SCpnt)
printk("Incorrect number of segments after building list\n"); printk("Incorrect number of segments after building list\n");
printk("counted %d, received %d\n", count, SCpnt->use_sg); 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); 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;
} }
/* /*
......
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