diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-08-14 16:52:34 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-08-14 16:52:34 +0100 |
commit | 074a9925e1cfd659d5376dcaccd1436d3840e611 (patch) | |
tree | 55eaba21dfd87054a46069e79de852d5d440e06e /block | |
parent | 8e0adf64140ab93aba79be2f0227a47eda78e464 (diff) | |
parent | e424aff5f307227b1c2512bbb8ece891bb895cef (diff) | |
download | qemu-074a9925e1cfd659d5376dcaccd1436d3840e611.tar.gz |
Merge remote-tracking branch 'remotes/cody/tags/block-pull-request' into staging
# gpg: Signature made Fri 14 Aug 2015 14:54:27 BST using RSA key ID C0DE3057
# gpg: Good signature from "Jeffrey Cody <jcody@redhat.com>"
# gpg: aka "Jeffrey Cody <jeff@codyprime.org>"
# gpg: aka "Jeffrey Cody <codyprime@gmail.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg: It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 9957 4B4D 3474 90E7 9D98 D624 BDBE 7B27 C0DE 3057
* remotes/cody/tags/block-pull-request:
mirror: Fix coroutine reentrance
block/mirror: limit qiov to IOV_MAX elements
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'block')
-rw-r--r-- | block/mirror.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/block/mirror.c b/block/mirror.c index fc4d8f561e..94744432eb 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -60,6 +60,7 @@ typedef struct MirrorBlockJob { int sectors_in_flight; int ret; bool unmap; + bool waiting_for_io; } MirrorBlockJob; typedef struct MirrorOp { @@ -114,11 +115,7 @@ static void mirror_iteration_done(MirrorOp *op, int ret) qemu_iovec_destroy(&op->qiov); g_slice_free(MirrorOp, op); - /* Enter coroutine when it is not sleeping. The coroutine sleeps to - * rate-limit itself. The coroutine will eventually resume since there is - * a sleep timeout so don't wake it early. - */ - if (s->common.busy) { + if (s->waiting_for_io) { qemu_coroutine_enter(s->common.co, NULL); } } @@ -203,7 +200,9 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) /* Wait for I/O to this cluster (from a previous iteration) to be done. */ while (test_bit(next_chunk, s->in_flight_bitmap)) { trace_mirror_yield_in_flight(s, sector_num, s->in_flight); + s->waiting_for_io = true; qemu_coroutine_yield(); + s->waiting_for_io = false; } do { @@ -239,12 +238,18 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) */ while (nb_chunks == 0 && s->buf_free_count < added_chunks) { trace_mirror_yield_buf_busy(s, nb_chunks, s->in_flight); + s->waiting_for_io = true; qemu_coroutine_yield(); + s->waiting_for_io = false; } if (s->buf_free_count < nb_chunks + added_chunks) { trace_mirror_break_buf_busy(s, nb_chunks, s->in_flight); break; } + if (IOV_MAX < nb_chunks + added_chunks) { + trace_mirror_break_iov_max(s, nb_chunks, added_chunks); + break; + } /* We have enough free space to copy these sectors. */ bitmap_set(s->in_flight_bitmap, next_chunk, added_chunks); @@ -333,7 +338,9 @@ static void mirror_free_init(MirrorBlockJob *s) static void mirror_drain(MirrorBlockJob *s) { while (s->in_flight > 0) { + s->waiting_for_io = true; qemu_coroutine_yield(); + s->waiting_for_io = false; } } @@ -506,7 +513,9 @@ static void coroutine_fn mirror_run(void *opaque) if (s->in_flight == MAX_IN_FLIGHT || s->buf_free_count == 0 || (cnt == 0 && s->in_flight > 0)) { trace_mirror_yield(s, s->in_flight, s->buf_free_count, cnt); + s->waiting_for_io = true; qemu_coroutine_yield(); + s->waiting_for_io = false; continue; } else if (cnt != 0) { delay_ns = mirror_iteration(s); |