qemu-img: wait for convert coroutines to complete

On error path (like i/o error in one of the coroutines), it's required to
  - wait for coroutines completion before cleaning the common structures
  - reenter dependent coroutines so they ever finish

Introduced in 2d9187bc65.

Cc: qemu-stable@nongnu.org
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
Reviewed-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
master
Anton Nefedov 2017-04-26 11:33:15 +03:00 committed by Kevin Wolf
parent 22d5cd82e9
commit b91127edd0
1 changed files with 11 additions and 15 deletions

View File

@ -1761,13 +1761,13 @@ static void coroutine_fn convert_co_do_copy(void *opaque)
qemu_co_mutex_lock(&s->lock); qemu_co_mutex_lock(&s->lock);
if (s->ret != -EINPROGRESS || s->sector_num >= s->total_sectors) { if (s->ret != -EINPROGRESS || s->sector_num >= s->total_sectors) {
qemu_co_mutex_unlock(&s->lock); qemu_co_mutex_unlock(&s->lock);
goto out; break;
} }
n = convert_iteration_sectors(s, s->sector_num); n = convert_iteration_sectors(s, s->sector_num);
if (n < 0) { if (n < 0) {
qemu_co_mutex_unlock(&s->lock); qemu_co_mutex_unlock(&s->lock);
s->ret = n; s->ret = n;
goto out; break;
} }
/* save current sector and allocation status to local variables */ /* save current sector and allocation status to local variables */
sector_num = s->sector_num; sector_num = s->sector_num;
@ -1792,7 +1792,6 @@ static void coroutine_fn convert_co_do_copy(void *opaque)
error_report("error while reading sector %" PRId64 error_report("error while reading sector %" PRId64
": %s", sector_num, strerror(-ret)); ": %s", sector_num, strerror(-ret));
s->ret = ret; s->ret = ret;
goto out;
} }
} else if (!s->min_sparse && status == BLK_ZERO) { } else if (!s->min_sparse && status == BLK_ZERO) {
status = BLK_DATA; status = BLK_DATA;
@ -1801,22 +1800,20 @@ static void coroutine_fn convert_co_do_copy(void *opaque)
if (s->wr_in_order) { if (s->wr_in_order) {
/* keep writes in order */ /* keep writes in order */
while (s->wr_offs != sector_num) { while (s->wr_offs != sector_num && s->ret == -EINPROGRESS) {
if (s->ret != -EINPROGRESS) {
goto out;
}
s->wait_sector_num[index] = sector_num; s->wait_sector_num[index] = sector_num;
qemu_coroutine_yield(); qemu_coroutine_yield();
} }
s->wait_sector_num[index] = -1; s->wait_sector_num[index] = -1;
} }
ret = convert_co_write(s, sector_num, n, buf, status); if (s->ret == -EINPROGRESS) {
if (ret < 0) { ret = convert_co_write(s, sector_num, n, buf, status);
error_report("error while writing sector %" PRId64 if (ret < 0) {
": %s", sector_num, strerror(-ret)); error_report("error while writing sector %" PRId64
s->ret = ret; ": %s", sector_num, strerror(-ret));
goto out; s->ret = ret;
}
} }
if (s->wr_in_order) { if (s->wr_in_order) {
@ -1837,7 +1834,6 @@ static void coroutine_fn convert_co_do_copy(void *opaque)
} }
} }
out:
qemu_vfree(buf); qemu_vfree(buf);
s->co[index] = NULL; s->co[index] = NULL;
s->running_coroutines--; s->running_coroutines--;
@ -1899,7 +1895,7 @@ static int convert_do_copy(ImgConvertState *s)
qemu_coroutine_enter(s->co[i]); qemu_coroutine_enter(s->co[i]);
} }
while (s->ret == -EINPROGRESS) { while (s->running_coroutines) {
main_loop_wait(false); main_loop_wait(false);
} }