From: Greg Kroah-Hartman Date: Mon, 9 Jun 2014 23:07:16 +0000 (-0700) Subject: 3.4-stable patches X-Git-Tag: v3.14.7~10 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5bb71cb5fe39f739ae114af3ad4366956347006e;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches 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 --- diff --git a/queue-3.4/series b/queue-3.4/series index 423367b5acb..f69bd5c55d3 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -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 index 00000000000..922351f3927 --- /dev/null +++ b/queue-3.4/virtio-blk-call-del_gendisk-before-disable-guest-kick.patch @@ -0,0 +1,67 @@ +From 88963fd6c66bf065c6e9c36f1f5de4dff30624a1 Mon Sep 17 00:00:00 2001 +From: Asias He +Date: Fri, 25 May 2012 10:34:47 +0800 +Subject: virtio-blk: Call del_gendisk() before disable guest kick + +From: Asias He + +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 +Acked-by: Michael S. Tsirkin +Signed-off-by: Rusty Russell +Signed-off-by: Ben Hutchings +Cc: Yijing Wang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..27b8441a817 --- /dev/null +++ b/queue-3.4/virtio-blk-fix-hot-unplug-race-in-remove-method.patch @@ -0,0 +1,71 @@ +From e5000b33460e5008a3a189dc2107d274d8096eff Mon Sep 17 00:00:00 2001 +From: Asias He +Date: Fri, 4 May 2012 20:22:04 +0800 +Subject: virtio-blk: Fix hot-unplug race in remove method + +From: Asias He + +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 +Signed-off-by: Rusty Russell +Signed-off-by: Ben Hutchings +Cc: Yijing Wang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..dd6152872ec --- /dev/null +++ b/queue-3.4/virtio-blk-reset-device-after-blk_cleanup_queue.patch @@ -0,0 +1,87 @@ +From 95964784565aeac65d1c03fc7b2443f8f7102340 Mon Sep 17 00:00:00 2001 +From: Asias He +Date: Fri, 25 May 2012 10:34:48 +0800 +Subject: virtio-blk: Reset device after blk_cleanup_queue() + +From: Asias He + +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 +Cc: virtualization@lists.linux-foundation.org +Cc: kvm@vger.kernel.org +Signed-off-by: Asias He +Acked-by: Michael S. Tsirkin +Signed-off-by: Rusty Russell +Signed-off-by: Ben Hutchings +Cc: Yijing Wang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..a559cfd1a0d --- /dev/null +++ b/queue-3.4/virtio_blk-drop-unused-request-tracking-list.patch @@ -0,0 +1,88 @@ +From 788c8de383e3c59df49126f95343eed0cf1733ea Mon Sep 17 00:00:00 2001 +From: Asias He +Date: Fri, 30 Mar 2012 11:24:10 +0800 +Subject: virtio_blk: Drop unused request tracking list + +From: Asias He + +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 +Signed-off-by: Rusty Russell +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +Cc: Yijing Wang +Signed-off-by: Greg Kroah-Hartman + +--- + 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); +