aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/virtio_blk.c
diff options
context:
space:
mode:
authorAsias He <asias@redhat.com>2012-05-25 04:03:27 -0400
committerRusty Russell <rusty@rustcorp.com.au>2012-07-30 00:00:51 -0400
commit2c95a3290919541b846bee3e0fbaa75860929f53 (patch)
tree749fca56cbcce3770871c6202567cfcc0903c67a /drivers/block/virtio_blk.c
parent483001c765af6892b3fc3726576cb42f17d1d6b5 (diff)
virtio-blk: Use block layer provided spinlock
Block layer will allocate a spinlock for the queue if the driver does not provide one in blk_init_queue(). The reason to use the internal spinlock is that blk_cleanup_queue() will switch to use the internal spinlock in the cleanup code path. if (q->queue_lock != &q->__queue_lock) q->queue_lock = &q->__queue_lock; However, processes which are in D state might have taken the driver provided spinlock, when the processes wake up, they would release the block provided spinlock. ===================================== [ BUG: bad unlock balance detected! ] 3.4.0-rc7+ #238 Not tainted ------------------------------------- fio/3587 is trying to release lock (&(&q->__queue_lock)->rlock) at: [<ffffffff813274d2>] blk_queue_bio+0x2a2/0x380 but there are no more locks to release! other info that might help us debug this: 1 lock held by fio/3587: #0: (&(&vblk->lock)->rlock){......}, at: [<ffffffff8132661a>] get_request_wait+0x19a/0x250 Other drivers use block layer provided spinlock as well, e.g. SCSI. Switching to the block layer provided spinlock saves a bit of memory and does not increase lock contention. Performance test shows no real difference is observed before and after this patch. Changes in v2: Improve commit log as Michael suggested. Cc: virtualization@lists.linux-foundation.org Cc: kvm@vger.kernel.org Cc: stable@kernel.org Signed-off-by: Asias He <asias@redhat.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/block/virtio_blk.c')
-rw-r--r--drivers/block/virtio_blk.c9
1 files changed, 3 insertions, 6 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index b4fa2d71496e..774c31dce7c0 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -21,8 +21,6 @@ struct workqueue_struct *virtblk_wq;
21 21
22struct virtio_blk 22struct virtio_blk
23{ 23{
24 spinlock_t lock;
25
26 struct virtio_device *vdev; 24 struct virtio_device *vdev;
27 struct virtqueue *vq; 25 struct virtqueue *vq;
28 26
@@ -65,7 +63,7 @@ static void blk_done(struct virtqueue *vq)
65 unsigned int len; 63 unsigned int len;
66 unsigned long flags; 64 unsigned long flags;
67 65
68 spin_lock_irqsave(&vblk->lock, flags); 66 spin_lock_irqsave(vblk->disk->queue->queue_lock, flags);
69 while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) { 67 while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) {
70 int error; 68 int error;
71 69
@@ -99,7 +97,7 @@ static void blk_done(struct virtqueue *vq)
99 } 97 }
100 /* In case queue is stopped waiting for more buffers. */ 98 /* In case queue is stopped waiting for more buffers. */
101 blk_start_queue(vblk->disk->queue); 99 blk_start_queue(vblk->disk->queue);
102 spin_unlock_irqrestore(&vblk->lock, flags); 100 spin_unlock_irqrestore(vblk->disk->queue->queue_lock, flags);
103} 101}
104 102
105static bool do_req(struct request_queue *q, struct virtio_blk *vblk, 103static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
@@ -431,7 +429,6 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
431 goto out_free_index; 429 goto out_free_index;
432 } 430 }
433 431
434 spin_lock_init(&vblk->lock);
435 vblk->vdev = vdev; 432 vblk->vdev = vdev;
436 vblk->sg_elems = sg_elems; 433 vblk->sg_elems = sg_elems;
437 sg_init_table(vblk->sg, vblk->sg_elems); 434 sg_init_table(vblk->sg, vblk->sg_elems);
@@ -456,7 +453,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
456 goto out_mempool; 453 goto out_mempool;
457 } 454 }
458 455
459 q = vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock); 456 q = vblk->disk->queue = blk_init_queue(do_virtblk_request, NULL);
460 if (!q) { 457 if (!q) {
461 err = -ENOMEM; 458 err = -ENOMEM;
462 goto out_put_disk; 459 goto out_put_disk;