diff options
author | Asias He <asias@redhat.com> | 2012-05-25 04:03:27 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2012-07-30 00:00:51 -0400 |
commit | 2c95a3290919541b846bee3e0fbaa75860929f53 (patch) | |
tree | 749fca56cbcce3770871c6202567cfcc0903c67a /drivers/block/virtio_blk.c | |
parent | 483001c765af6892b3fc3726576cb42f17d1d6b5 (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.c | 9 |
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 | ||
22 | struct virtio_blk | 22 | struct 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 | ||
105 | static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | 103 | static 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; |