Re: 2.6.14-mm1

From: James Bottomley
Date: Tue Nov 08 2005 - 09:21:25 EST


On Mon, 2005-11-07 at 10:52 -0800, Andrew Morton wrote:
> sd_issue_flush() has been altered to run scsi_disk_get_from_dev(), which
> takes a semaphore. It does this from within spinlock and, as we see here,
> from within softirq.
>
> Methinks the people who developed and tested that patch forgot to enable
> CONFIG_PREEMPT, CONFIG_DEBUG_KERNEL, CONFIG_DEBUG_SLAB,
> CONFIG_DEBUG_SPINLOCK and CONFIG_DEBUG_SPINLOCK_SLEEP.

Actually, I do too (as far as I can on non-x86). I assume you also need
a filesystem that excites this, though.

Try the attached: We can probably rely on the block device having opened
the sd device, so there should already be a reference held on the
scsi_disk ... well that's my theory and I'm sticking to it.

James

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -769,20 +769,16 @@ static void sd_end_flush(request_queue_t
static int sd_prepare_flush(request_queue_t *q, struct request *rq)
{
struct scsi_device *sdev = q->queuedata;
- struct scsi_disk *sdkp = scsi_disk_get_from_dev(&sdev->sdev_gendev);
- int ret = 0;
+ struct scsi_disk *sdkp = dev_get_drvdata(&sdev->sdev_gendev);

- if (sdkp) {
- if (sdkp->WCE) {
- memset(rq->cmd, 0, sizeof(rq->cmd));
- rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
- rq->timeout = SD_TIMEOUT;
- rq->cmd[0] = SYNCHRONIZE_CACHE;
- ret = 1;
- }
- scsi_disk_put(sdkp);
- }
- return ret;
+ if (!sdkp || !sdkp->WCE)
+ return 0;
+
+ memset(rq->cmd, 0, sizeof(rq->cmd));
+ rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
+ rq->timeout = SD_TIMEOUT;
+ rq->cmd[0] = SYNCHRONIZE_CACHE;
+ return 1;
}

static void sd_rescan(struct device *dev)



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/