]> git.proxmox.com Git - pve-qemu-kvm.git/blobdiff - debian/patches/pve/0041-savevm-async-updates.patch
update to 2.7
[pve-qemu-kvm.git] / debian / patches / pve / 0041-savevm-async-updates.patch
diff --git a/debian/patches/pve/0041-savevm-async-updates.patch b/debian/patches/pve/0041-savevm-async-updates.patch
new file mode 100644 (file)
index 0000000..942073c
--- /dev/null
@@ -0,0 +1,236 @@
+From 8ba1bc13200b72a287554224b5aeb8cbf1bba156 Mon Sep 17 00:00:00 2001
+From: Wolfgang Bumiller <w.bumiller@proxmox.com>
+Date: Fri, 9 Sep 2016 15:21:19 +0200
+Subject: [PATCH 41/41] savevm-async updates
+
+---
+ savevm-async.c | 99 +++++++++++++++++++++++++++++++++++++---------------------
+ 1 file changed, 63 insertions(+), 36 deletions(-)
+
+diff --git a/savevm-async.c b/savevm-async.c
+index 76cd8fa..fddb18c 100644
+--- a/savevm-async.c
++++ b/savevm-async.c
+@@ -20,6 +20,8 @@
+ /* #define DEBUG_SAVEVM_STATE */
++#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
++
+ #ifdef DEBUG_SAVEVM_STATE
+ #define DPRINTF(fmt, ...) \
+     do { printf("savevm-async: " fmt, ## __VA_ARGS__); } while (0)
+@@ -38,7 +40,7 @@ enum {
+ static struct SnapshotState {
+-    BlockDriverState *bs;
++    BlockBackend *target;
+     size_t bs_pos;
+     int state;
+     Error *error;
+@@ -99,17 +101,17 @@ static int save_snapshot_cleanup(void)
+         ret = qemu_fclose(snap_state.file);
+     }
+-    if (snap_state.bs) {
++    if (snap_state.target) {
+         /* try to truncate, but ignore errors (will fail on block devices).
+          * note: bdrv_read() need whole blocks, so we round up
+          */
+         size_t size = (snap_state.bs_pos + BDRV_SECTOR_SIZE) & BDRV_SECTOR_MASK;
+-        bdrv_truncate(snap_state.bs, size);
+-        bdrv_op_unblock_all(snap_state.bs, snap_state.blocker);
++        blk_truncate(snap_state.target, size);
++        blk_op_unblock_all(snap_state.target, snap_state.blocker);
+         error_free(snap_state.blocker);
+         snap_state.blocker = NULL;
+-        bdrv_unref(snap_state.bs);
+-        snap_state.bs = NULL;
++        blk_unref(snap_state.target);
++        snap_state.target = NULL;
+     }
+     return ret;
+@@ -151,21 +153,49 @@ static void save_snapshot_completed(void)
+ static int block_state_close(void *opaque)
+ {
+     snap_state.file = NULL;
+-    return bdrv_flush(snap_state.bs);
++    return blk_flush(snap_state.target);
+ }
+-static ssize_t block_state_put_buffer(void *opaque, const uint8_t *buf,
+-                                      int64_t pos, size_t size)
++typedef struct BlkRwCo {
++    int64_t offset;
++    QEMUIOVector *qiov;
++    int ret;
++} BlkRwCo;
++
++static void block_state_write_entry(void *opaque) {
++    BlkRwCo *rwco = opaque;
++    rwco->ret = blk_co_pwritev(snap_state.target, rwco->offset, rwco->qiov->size,
++                               rwco->qiov, 0);
++}
++
++static ssize_t block_state_writev_buffer(void *opaque, struct iovec *iov,
++                                         int iovcnt, int64_t pos)
+ {
+-    ssize_t ret;
++    AioContext *aio_context;
++    QEMUIOVector qiov;
++    Coroutine *co;
++    BlkRwCo rwco;
++
++    qemu_iovec_init_external(&qiov, iov, iovcnt);
++
++    rwco = (BlkRwCo) {
++        .offset = pos,
++        .qiov   = &qiov,
++        .ret    = NOT_DONE,
++    };
+-    assert(pos == snap_state.bs_pos);
++    co = qemu_coroutine_create(&block_state_write_entry, &rwco);
++    qemu_coroutine_enter(co);
+-    if ((ret = bdrv_pwrite(snap_state.bs, snap_state.bs_pos, buf, size)) > 0) {
+-        snap_state.bs_pos += ret;
++    aio_context = blk_get_aio_context(snap_state.target);
++    while (rwco.ret == NOT_DONE) {
++        aio_poll(aio_context, true);
+     }
+-    return ret;
++    if (rwco.ret < 0) {
++        return rwco.ret;
++    }
++    return qiov.size;
+ }
+ static int store_and_stop(void) {
+@@ -227,7 +257,7 @@ static void process_savevm_co(void *opaque)
+         /* stop the VM if we get to the end of available space,
+          * or if pending_size is just a few MB
+          */
+-        maxlen = bdrv_getlength(snap_state.bs) - 30*1024*1024;
++        maxlen = blk_getlength(snap_state.target) - 30*1024*1024;
+         if ((pending_size < 100000) ||
+             ((snap_state.bs_pos + pending_size) >= maxlen)) {
+             if (store_and_stop())
+@@ -244,7 +274,7 @@ static void process_savevm_co(void *opaque)
+ }
+ static const QEMUFileOps block_file_ops = {
+-    .put_buffer =     block_state_put_buffer,
++    .writev_buffer =  block_state_writev_buffer,
+     .close =          block_state_close,
+ };
+@@ -254,7 +284,6 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
+     Error *local_err = NULL;
+     int bdrv_oflags = BDRV_O_RDWR | BDRV_O_NO_FLUSH;
+-    int ret;
+     if (snap_state.state != SAVE_STATE_DONE) {
+         error_set(errp, ERROR_CLASS_GENERIC_ERROR,
+@@ -284,13 +313,11 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
+     }
+     /* Open the image */
+-    snap_state.bs = bdrv_new();
+- 
+     QDict *options = NULL;
+     options = qdict_new();
+     qdict_put(options, "driver", qstring_from_str("raw"));
+-    ret = bdrv_open(&snap_state.bs, statefile, NULL, options, bdrv_oflags, &local_err);
+-    if (ret < 0) {
++    snap_state.target = blk_new_open(statefile, NULL, options, bdrv_oflags, &local_err);
++    if (!snap_state.target) {
+         error_set(errp, ERROR_CLASS_GENERIC_ERROR, "failed to open '%s'", statefile);
+         goto restart;
+     }
+@@ -304,9 +331,9 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
+     error_setg(&snap_state.blocker, "block device is in use by savevm");
+-    bdrv_op_block_all(snap_state.bs, snap_state.blocker);
++    blk_op_block_all(snap_state.target, snap_state.blocker);
+-    Coroutine *co = qemu_coroutine_create(process_savevm_co);
++    Coroutine *co = qemu_coroutine_create(process_savevm_co, NULL);
+     qemu_coroutine_enter(co);
+     return;
+@@ -457,8 +484,8 @@ void qmp_delete_drive_snapshot(const char *device, const char *name,
+ static ssize_t loadstate_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
+                                     size_t size)
+ {
+-    BlockDriverState *bs = (BlockDriverState *)opaque;
+-    int64_t maxlen = bdrv_getlength(bs);
++    BlockBackend *be = opaque;
++    int64_t maxlen = blk_getlength(be);
+     if (pos > maxlen) {
+         return -EIO;
+     }
+@@ -468,7 +495,7 @@ static ssize_t loadstate_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
+     if (size == 0) {
+         return 0;
+     }
+-    return bdrv_pread(bs, pos, buf, size);
++    return blk_pread(be, pos, buf, size);
+ }
+ static const QEMUFileOps loadstate_file_ops = {
+@@ -477,25 +504,25 @@ static const QEMUFileOps loadstate_file_ops = {
+ int load_state_from_blockdev(const char *filename)
+ {
+-    BlockDriverState *bs = NULL;
++    BlockBackend *be;
+     Error *local_err = NULL;
+     Error *blocker = NULL;
+     QEMUFile *f;
+     int ret;
+-    bs = bdrv_new();
+-    ret = bdrv_open(&bs, filename, NULL, NULL, 0, &local_err);
+-    error_setg(&blocker, "block device is in use by load state");
+-    bdrv_op_block_all(bs, blocker);
++    be = blk_new_open(filename, NULL, NULL, 0, &local_err);
+-    if (ret < 0) {
++    if (!be) {
+         error_report("Could not open VM state file");
+         goto the_end;
+     }
++    error_setg(&blocker, "block device is in use by load state");
++    blk_op_block_all(be, blocker);
++
+     /* restore the VM state */
+-    f = qemu_fopen_ops(bs, &loadstate_file_ops);
++    f = qemu_fopen_ops(be, &loadstate_file_ops);
+     if (!f) {
+         error_report("Could not open VM state file");
+         ret = -EINVAL;
+@@ -516,10 +543,10 @@ int load_state_from_blockdev(const char *filename)
+     ret = 0;
+  the_end:
+-    if (bs) {
+-        bdrv_op_unblock_all(bs, blocker);
++    if (be) {
++        blk_op_unblock_all(be, blocker);
+         error_free(blocker);
+-        bdrv_unref(bs);
++        blk_unref(be);
+     }
+     return ret;
+ }
+-- 
+2.1.4
+