From d0f717e219607a27280f811ad9d2844dec1a08fe Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mar 18 2005 11:18:19 +0000 Subject: - patches.fixes/scsi-dead-device: Fix SCSI reference counting problem with a dead device. - series.conf: --- diff --git a/kernel-source.changes b/kernel-source.changes index adde679..fed8c17 100644 --- a/kernel-source.changes +++ b/kernel-source.changes @@ -1,4 +1,11 @@ ------------------------------------------------------------------- +Fri Mar 18 12:18:13 CET 2005 - axboe@suse.de + +- patches.fixes/scsi-dead-device: Fix SCSI reference counting + problem with a dead device. +- series.conf: + +------------------------------------------------------------------- Fri Mar 18 10:45:24 CET 2005 - vojtech@suse.cz - patches.drivers/input-bk-rightwin.diff diff --git a/patches.fixes/scsi-dead-device b/patches.fixes/scsi-dead-device new file mode 100644 index 0000000..9016854 --- /dev/null +++ b/patches.fixes/scsi-dead-device @@ -0,0 +1,82 @@ +From: Jens Axboe +Subject: Fix SCSI reference counting problem with a dead device +Patch-mainline: +References: + +We have a circular reference counting problem in SCSI - the device needs to +hold on to the queue, but the queue also needs to hold on to the device. +Currently the device can be deleted, but it only puts a reference to the +queue which can cause the queue to still exist and try to grab the device +after it has been freed. + +Fix this by clearing the device pointer in the queue and just killing +pending requests if the device is gone. + +Acked-by: +Signed-off-by: + +--- linux-2.6.11/drivers/scsi/scsi_lib.c~ 2005-03-18 12:11:48.000000000 +0100 ++++ linux-2.6.11/drivers/scsi/scsi_lib.c 2005-03-18 12:14:36.000000000 +0100 +@@ -1230,6 +1230,22 @@ + } + + /* ++ * Kill requests for a dead device ++ */ ++static void scsi_kill_requests(request_queue_t *q) ++{ ++ struct request *req; ++ ++ while ((req = elv_next_request(q)) != NULL) { ++ blkdev_dequeue_request(req); ++ req->flags |= REQ_QUIET; ++ while (end_that_request_first(req, 0, req->nr_sectors)) ++ ; ++ end_that_request_last(req); ++ } ++} ++ ++/* + * Function: scsi_request_fn() + * + * Purpose: Main strategy routine for SCSI. +@@ -1243,10 +1259,16 @@ + static void scsi_request_fn(struct request_queue *q) + { + struct scsi_device *sdev = q->queuedata; +- struct Scsi_Host *shost = sdev->host; ++ struct Scsi_Host *shost; + struct scsi_cmnd *cmd; + struct request *req; + ++ if (!sdev) { ++ printk("scsi: killing requests for dead queue\n"); ++ scsi_kill_requests(q); ++ return; ++ } ++ + if(!get_device(&sdev->sdev_gendev)) + /* We must be tearing the block queue down already */ + return; +@@ -1255,6 +1277,7 @@ + * To start with, we keep looping until the queue is empty, or until + * the host is no longer able to accept any more requests. + */ ++ shost = sdev->host; + while (!blk_queue_plugged(q)) { + int rtn; + /* +--- linux-2.6.11/drivers/scsi/scsi_sysfs.c~ 2005-03-18 12:11:26.000000000 +0100 ++++ linux-2.6.11/drivers/scsi/scsi_sysfs.c 2005-03-18 12:15:06.000000000 +0100 +@@ -178,8 +178,10 @@ + + put_device(parent); + } +- if (sdev->request_queue) ++ if (sdev->request_queue) { ++ sdev->request_queue->queuedata = NULL; + scsi_free_queue(sdev->request_queue); ++ } + + kfree(sdev->inquiry); + kfree(sdev); diff --git a/series.conf b/series.conf index ec7ce2d..4bcce3b 100644 --- a/series.conf +++ b/series.conf @@ -949,6 +949,7 @@ patches.drivers/drm-ioctl32 patches.fixes/rwv_einval + patches.fixes/scsi-dead-device # bug 59325 +Unused: patches.suse/Trig-eventhooks-v1.9-2.6.2.patch