aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author <axboe@suse.de>2005-04-12 17:22:06 -0400
committerJames Bottomley <jejb@titanic>2005-04-16 21:10:09 -0400
commit152587deb8903c0edf483a5b889f975bc6bea7e0 (patch)
tree62fc13bff0a28134adbb523ed1a2c0efdd9a85cb
parent56fece20086ebe32bce2c0d74ceadd516b56baae (diff)
[PATCH] fix NMI lockup with CFQ scheduler
The current problem seen is that the queue lock is actually in the SCSI device structure, so when that structure is freed on device release, we go boom if the queue tries to access the lock again. The fix here is to move the lock from the scsi_device to the queue. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/block/ll_rw_blk.c9
-rw-r--r--drivers/scsi/scsi_lib.c6
-rw-r--r--drivers/scsi/scsi_scan.c1
-rw-r--r--include/linux/blkdev.h5
-rw-r--r--include/scsi/scsi_device.h1
5 files changed, 16 insertions, 6 deletions
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 46e54b441663..11ef9d9ea139 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -1715,6 +1715,15 @@ request_queue_t *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock)
1715 if (blk_init_free_list(q)) 1715 if (blk_init_free_list(q))
1716 goto out_init; 1716 goto out_init;
1717 1717
1718 /*
1719 * if caller didn't supply a lock, they get per-queue locking with
1720 * our embedded lock
1721 */
1722 if (!lock) {
1723 spin_lock_init(&q->__queue_lock);
1724 lock = &q->__queue_lock;
1725 }
1726
1718 q->request_fn = rfn; 1727 q->request_fn = rfn;
1719 q->back_merge_fn = ll_back_merge_fn; 1728 q->back_merge_fn = ll_back_merge_fn;
1720 q->front_merge_fn = ll_front_merge_fn; 1729 q->front_merge_fn = ll_front_merge_fn;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 7cbc4127fb5a..d230c699c728 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -360,9 +360,9 @@ void scsi_device_unbusy(struct scsi_device *sdev)
360 shost->host_failed)) 360 shost->host_failed))
361 scsi_eh_wakeup(shost); 361 scsi_eh_wakeup(shost);
362 spin_unlock(shost->host_lock); 362 spin_unlock(shost->host_lock);
363 spin_lock(&sdev->sdev_lock); 363 spin_lock(sdev->request_queue->queue_lock);
364 sdev->device_busy--; 364 sdev->device_busy--;
365 spin_unlock_irqrestore(&sdev->sdev_lock, flags); 365 spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
366} 366}
367 367
368/* 368/*
@@ -1425,7 +1425,7 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
1425 struct Scsi_Host *shost = sdev->host; 1425 struct Scsi_Host *shost = sdev->host;
1426 struct request_queue *q; 1426 struct request_queue *q;
1427 1427
1428 q = blk_init_queue(scsi_request_fn, &sdev->sdev_lock); 1428 q = blk_init_queue(scsi_request_fn, NULL);
1429 if (!q) 1429 if (!q)
1430 return NULL; 1430 return NULL;
1431 1431
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index a8a37a338c02..287d197a7c17 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -249,7 +249,6 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
249 */ 249 */
250 sdev->borken = 1; 250 sdev->borken = 1;
251 251
252 spin_lock_init(&sdev->sdev_lock);
253 sdev->request_queue = scsi_alloc_queue(sdev); 252 sdev->request_queue = scsi_alloc_queue(sdev);
254 if (!sdev->request_queue) { 253 if (!sdev->request_queue) {
255 /* release fn is set up in scsi_sysfs_device_initialise, so 254 /* release fn is set up in scsi_sysfs_device_initialise, so
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 70ac2860a605..ef1afc178c0a 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -355,8 +355,11 @@ struct request_queue
355 unsigned long queue_flags; 355 unsigned long queue_flags;
356 356
357 /* 357 /*
358 * protects queue structures from reentrancy 358 * protects queue structures from reentrancy. ->__queue_lock should
359 * _never_ be used directly, it is queue private. always use
360 * ->queue_lock.
359 */ 361 */
362 spinlock_t __queue_lock;
360 spinlock_t *queue_lock; 363 spinlock_t *queue_lock;
361 364
362 /* 365 /*
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 07d974051b0c..f6d051318299 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -44,7 +44,6 @@ struct scsi_device {
44 struct list_head same_target_siblings; /* just the devices sharing same target id */ 44 struct list_head same_target_siblings; /* just the devices sharing same target id */
45 45
46 volatile unsigned short device_busy; /* commands actually active on low-level */ 46 volatile unsigned short device_busy; /* commands actually active on low-level */
47 spinlock_t sdev_lock; /* also the request queue_lock */
48 spinlock_t list_lock; 47 spinlock_t list_lock;
49 struct list_head cmd_list; /* queue of in use SCSI Command structures */ 48 struct list_head cmd_list; /* queue of in use SCSI Command structures */
50 struct list_head starved_entry; 49 struct list_head starved_entry;