]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 9 Jun 2014 23:07:16 +0000 (16:07 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 9 Jun 2014 23:07:16 +0000 (16:07 -0700)
added patches:
virtio-blk-call-del_gendisk-before-disable-guest-kick.patch
virtio-blk-fix-hot-unplug-race-in-remove-method.patch
virtio-blk-reset-device-after-blk_cleanup_queue.patch
virtio_blk-drop-unused-request-tracking-list.patch

queue-3.4/series
queue-3.4/virtio-blk-call-del_gendisk-before-disable-guest-kick.patch [new file with mode: 0644]
queue-3.4/virtio-blk-fix-hot-unplug-race-in-remove-method.patch [new file with mode: 0644]
queue-3.4/virtio-blk-reset-device-after-blk_cleanup_queue.patch [new file with mode: 0644]
queue-3.4/virtio_blk-drop-unused-request-tracking-list.patch [new file with mode: 0644]

index 423367b5acb7cc676b2baae245c5009564007c77..f69bd5c55d3719f4a0a4b42e7cd0f9613e341577 100644 (file)
@@ -40,3 +40,7 @@ bluetooth-add-support-for-atheros.patch
 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
diff --git a/queue-3.4/virtio-blk-call-del_gendisk-before-disable-guest-kick.patch b/queue-3.4/virtio-blk-call-del_gendisk-before-disable-guest-kick.patch
new file mode 100644 (file)
index 0000000..922351f
--- /dev/null
@@ -0,0 +1,67 @@
+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))) {
diff --git a/queue-3.4/virtio-blk-fix-hot-unplug-race-in-remove-method.patch b/queue-3.4/virtio-blk-fix-hot-unplug-race-in-remove-method.patch
new file mode 100644 (file)
index 0000000..27b8441
--- /dev/null
@@ -0,0 +1,71 @@
+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);
diff --git a/queue-3.4/virtio-blk-reset-device-after-blk_cleanup_queue.patch b/queue-3.4/virtio-blk-reset-device-after-blk_cleanup_queue.patch
new file mode 100644 (file)
index 0000000..dd61528
--- /dev/null
@@ -0,0 +1,87 @@
+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);
diff --git a/queue-3.4/virtio_blk-drop-unused-request-tracking-list.patch b/queue-3.4/virtio_blk-drop-unused-request-tracking-list.patch
new file mode 100644 (file)
index 0000000..a559cfd
--- /dev/null
@@ -0,0 +1,88 @@
+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);