bluetooth-add-support-for-atheros-a.patch
bluetooth-add-a-new-pid-vid-0cf3-e005-for-ar3012.patch
bluetooth-add-support-for-bcm20702a0-b.patch
+virtio_blk-drop-unused-request-tracking-list.patch
+virtio-blk-fix-hot-unplug-race-in-remove-method.patch
+virtio-blk-call-del_gendisk-before-disable-guest-kick.patch
+virtio-blk-reset-device-after-blk_cleanup_queue.patch
--- /dev/null
+From 88963fd6c66bf065c6e9c36f1f5de4dff30624a1 Mon Sep 17 00:00:00 2001
+From: Asias He <asias@redhat.com>
+Date: Fri, 25 May 2012 10:34:47 +0800
+Subject: virtio-blk: Call del_gendisk() before disable guest kick
+
+From: Asias He <asias@redhat.com>
+
+commit 02e2b124943648fba0a2ccee5c3656a5653e0151 upstream.
+
+del_gendisk() might not return due to failing to remove the
+/sys/block/vda/serial sysfs entry when another thread (udev) is
+trying to read it.
+
+virtblk_remove()
+ vdev->config->reset() : guest will not kick us through interrupt
+ del_gendisk()
+ device_del()
+ kobject_del(): got stuck, sysfs entry ref count non zero
+
+sysfs_open_file(): user space process read /sys/block/vda/serial
+ sysfs_get_active() : got sysfs entry ref count
+ dev_attr_show()
+ virtblk_serial_show()
+ blk_execute_rq() : got stuck, interrupt is disabled
+ request cannot be finished
+
+This patch fixes it by calling del_gendisk() before we disable guest's
+interrupt so that the request sent in virtblk_serial_show() will be
+finished and del_gendisk() will success.
+
+This fixes another race in hot-unplug process.
+
+It is save to call del_gendisk(vblk->disk) before
+flush_work(&vblk->config_work) which might access vblk->disk, because
+vblk->disk is not freed until put_disk(vblk->disk).
+
+Cc: virtualization@lists.linux-foundation.org
+Cc: kvm@vger.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>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Yijing Wang <wangyijing@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/virtio_blk.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/block/virtio_blk.c
++++ b/drivers/block/virtio_blk.c
+@@ -581,13 +581,13 @@ static void __devexit virtblk_remove(str
+ vblk->config_enable = false;
+ mutex_unlock(&vblk->config_lock);
+
++ del_gendisk(vblk->disk);
++
+ /* Stop all the virtqueues. */
+ vdev->config->reset(vdev);
+
+ flush_work(&vblk->config_work);
+
+- del_gendisk(vblk->disk);
+-
+ /* Abort requests dispatched to driver. */
+ spin_lock_irqsave(&vblk->lock, flags);
+ while ((vbr = virtqueue_detach_unused_buf(vblk->vq))) {
--- /dev/null
+From e5000b33460e5008a3a189dc2107d274d8096eff Mon Sep 17 00:00:00 2001
+From: Asias He <asias@redhat.com>
+Date: Fri, 4 May 2012 20:22:04 +0800
+Subject: virtio-blk: Fix hot-unplug race in remove method
+
+From: Asias He <asias@redhat.com>
+
+commit b79d866c8b7014a51f611a64c40546109beaf24a upstream.
+
+If we reset the virtio-blk device before the requests already dispatched
+to the virtio-blk driver from the block layer are finised, we will stuck
+in blk_cleanup_queue() and the remove will fail.
+
+blk_cleanup_queue() calls blk_drain_queue() to drain all requests queued
+before DEAD marking. However it will never success if the device is
+already stopped. We'll have q->in_flight[] > 0, so the drain will not
+finish.
+
+How to reproduce the race:
+1. hot-plug a virtio-blk device
+2. keep reading/writing the device in guest
+3. hot-unplug while the device is busy serving I/O
+
+Test:
+~1000 rounds of hot-plug/hot-unplug test passed with this patch.
+
+Changes in v3:
+- Drop blk_abort_queue and blk_abort_request
+- Use __blk_end_request_all to complete request dispatched to driver
+
+Changes in v2:
+- Drop req_in_flight
+- Use virtqueue_detach_unused_buf to get request dispatched to driver
+
+Signed-off-by: Asias He <asias@redhat.com>
+Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Yijing Wang <wangyijing@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/virtio_blk.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/drivers/block/virtio_blk.c
++++ b/drivers/block/virtio_blk.c
+@@ -573,6 +573,8 @@ static void __devexit virtblk_remove(str
+ {
+ struct virtio_blk *vblk = vdev->priv;
+ int index = vblk->index;
++ struct virtblk_req *vbr;
++ unsigned long flags;
+
+ /* Prevent config work handler from accessing the device. */
+ mutex_lock(&vblk->config_lock);
+@@ -585,6 +587,15 @@ static void __devexit virtblk_remove(str
+ flush_work(&vblk->config_work);
+
+ del_gendisk(vblk->disk);
++
++ /* Abort requests dispatched to driver. */
++ spin_lock_irqsave(&vblk->lock, flags);
++ while ((vbr = virtqueue_detach_unused_buf(vblk->vq))) {
++ __blk_end_request_all(vbr->req, -EIO);
++ mempool_free(vbr, vblk->pool);
++ }
++ spin_unlock_irqrestore(&vblk->lock, flags);
++
+ blk_cleanup_queue(vblk->disk->queue);
+ put_disk(vblk->disk);
+ mempool_destroy(vblk->pool);
--- /dev/null
+From 95964784565aeac65d1c03fc7b2443f8f7102340 Mon Sep 17 00:00:00 2001
+From: Asias He <asias@redhat.com>
+Date: Fri, 25 May 2012 10:34:48 +0800
+Subject: virtio-blk: Reset device after blk_cleanup_queue()
+
+From: Asias He <asias@redhat.com>
+
+commit 483001c765af6892b3fc3726576cb42f17d1d6b5 upstream.
+
+blk_cleanup_queue() will call blk_drian_queue() to drain all the
+requests before queue DEAD marking. If we reset the device before
+blk_cleanup_queue() the drain would fail.
+
+1) if the queue is stopped in do_virtblk_request() because device is
+full, the q->request_fn() will not be called.
+
+blk_drain_queue() {
+ while(true) {
+ ...
+ if (!list_empty(&q->queue_head))
+ __blk_run_queue(q) {
+ if (queue is not stoped)
+ q->request_fn()
+ }
+ ...
+ }
+}
+
+Do no reset the device before blk_cleanup_queue() gives the chance to
+start the queue in interrupt handler blk_done().
+
+2) In commit b79d866c8b7014a51f611a64c40546109beaf24a, We abort requests
+dispatched to driver before blk_cleanup_queue(). There is a race if
+requests are dispatched to driver after the abort and before the queue
+DEAD mark. To fix this, instead of aborting the requests explicitly, we
+can just reset the device after after blk_cleanup_queue so that the
+device can complete all the requests before queue DEAD marking in the
+drain process.
+
+Cc: Rusty Russell <rusty@rustcorp.com.au>
+Cc: virtualization@lists.linux-foundation.org
+Cc: kvm@vger.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>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Yijing Wang <wangyijing@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/virtio_blk.c | 12 +-----------
+ 1 file changed, 1 insertion(+), 11 deletions(-)
+
+--- a/drivers/block/virtio_blk.c
++++ b/drivers/block/virtio_blk.c
+@@ -573,8 +573,6 @@ static void __devexit virtblk_remove(str
+ {
+ struct virtio_blk *vblk = vdev->priv;
+ int index = vblk->index;
+- struct virtblk_req *vbr;
+- unsigned long flags;
+
+ /* Prevent config work handler from accessing the device. */
+ mutex_lock(&vblk->config_lock);
+@@ -582,21 +580,13 @@ static void __devexit virtblk_remove(str
+ mutex_unlock(&vblk->config_lock);
+
+ del_gendisk(vblk->disk);
++ blk_cleanup_queue(vblk->disk->queue);
+
+ /* Stop all the virtqueues. */
+ vdev->config->reset(vdev);
+
+ flush_work(&vblk->config_work);
+
+- /* Abort requests dispatched to driver. */
+- spin_lock_irqsave(&vblk->lock, flags);
+- while ((vbr = virtqueue_detach_unused_buf(vblk->vq))) {
+- __blk_end_request_all(vbr->req, -EIO);
+- mempool_free(vbr, vblk->pool);
+- }
+- spin_unlock_irqrestore(&vblk->lock, flags);
+-
+- blk_cleanup_queue(vblk->disk->queue);
+ put_disk(vblk->disk);
+ mempool_destroy(vblk->pool);
+ vdev->config->del_vqs(vdev);
--- /dev/null
+From 788c8de383e3c59df49126f95343eed0cf1733ea Mon Sep 17 00:00:00 2001
+From: Asias He <asias@redhat.com>
+Date: Fri, 30 Mar 2012 11:24:10 +0800
+Subject: virtio_blk: Drop unused request tracking list
+
+From: Asias He <asias@redhat.com>
+
+commit f65ca1dc6a8c81c6bd72297d4399ec5f4c1f3a01 upstream.
+
+Benchmark shows small performance improvement on fusion io device.
+
+Before:
+ seq-read : io=1,024MB, bw=19,982KB/s, iops=39,964, runt= 52475msec
+ seq-write: io=1,024MB, bw=20,321KB/s, iops=40,641, runt= 51601msec
+ rnd-read : io=1,024MB, bw=15,404KB/s, iops=30,808, runt= 68070msec
+ rnd-write: io=1,024MB, bw=14,776KB/s, iops=29,552, runt= 70963msec
+
+After:
+ seq-read : io=1,024MB, bw=20,343KB/s, iops=40,685, runt= 51546msec
+ seq-write: io=1,024MB, bw=20,803KB/s, iops=41,606, runt= 50404msec
+ rnd-read : io=1,024MB, bw=16,221KB/s, iops=32,442, runt= 64642msec
+ rnd-write: io=1,024MB, bw=15,199KB/s, iops=30,397, runt= 68991msec
+
+Signed-off-by: Asias He <asias@redhat.com>
+Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Yijing Wang <wangyijing@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/virtio_blk.c | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+--- a/drivers/block/virtio_blk.c
++++ b/drivers/block/virtio_blk.c
+@@ -27,9 +27,6 @@ struct virtio_blk
+ /* The disk structure for the kernel. */
+ struct gendisk *disk;
+
+- /* Request tracking. */
+- struct list_head reqs;
+-
+ mempool_t *pool;
+
+ /* Process context for config space updates */
+@@ -53,7 +50,6 @@ struct virtio_blk
+
+ struct virtblk_req
+ {
+- struct list_head list;
+ struct request *req;
+ struct virtio_blk_outhdr out_hdr;
+ struct virtio_scsi_inhdr in_hdr;
+@@ -97,7 +93,6 @@ static void blk_done(struct virtqueue *v
+ }
+
+ __blk_end_request_all(vbr->req, error);
+- list_del(&vbr->list);
+ mempool_free(vbr, vblk->pool);
+ }
+ /* In case queue is stopped waiting for more buffers. */
+@@ -182,7 +177,6 @@ static bool do_req(struct request_queue
+ return false;
+ }
+
+- list_add_tail(&vbr->list, &vblk->reqs);
+ return true;
+ }
+
+@@ -435,7 +429,6 @@ static int __devinit virtblk_probe(struc
+ goto out_free_index;
+ }
+
+- INIT_LIST_HEAD(&vblk->reqs);
+ vblk->vdev = vdev;
+ vblk->sg_elems = sg_elems;
+ sg_init_table(vblk->sg, vblk->sg_elems);
+@@ -586,9 +579,6 @@ static void __devexit virtblk_remove(str
+ vblk->config_enable = false;
+ mutex_unlock(&vblk->config_lock);
+
+- /* Nothing should be pending. */
+- BUG_ON(!list_empty(&vblk->reqs));
+-
+ /* Stop all the virtqueues. */
+ vdev->config->reset(vdev);
+