]> git.proxmox.com Git - pve-qemu-kvm.git/blobdiff - debian/patches/0004-introduce-new-vma-archive-format.patch
update to latest backup patches
[pve-qemu-kvm.git] / debian / patches / 0004-introduce-new-vma-archive-format.patch
index 5be20d37c97f68c769c0618b7ebb4660cde3b969..905c58761088469754ebde009456f03363192eeb 100644 (file)
@@ -1,7 +1,7 @@
-From 69a3f26bdbe445ce01f096b9d5e1aaf45ad98b81 Mon Sep 17 00:00:00 2001
+From 5476ae43806488e74cd293bbaa17f130aa53d402 Mon Sep 17 00:00:00 2001
 From: Dietmar Maurer <dietmar@proxmox.com>
 Date: Tue, 13 Nov 2012 11:11:38 +0100
-Subject: [PATCH v3 4/7] introduce new vma archive format
+Subject: [PATCH v4 4/6] introduce new vma archive format
 
 This is a very simple archive format, see docs/specs/vma_spec.txt
 
@@ -9,13 +9,14 @@ Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
 ---
  Makefile                |    3 +-
  Makefile.objs           |    2 +-
+ backup.h                |    1 +
  blockdev.c              |    6 +-
  docs/specs/vma_spec.txt |   24 ++
- vma-reader.c            |  801 ++++++++++++++++++++++++++++++++++++++++
- vma-writer.c            |  931 +++++++++++++++++++++++++++++++++++++++++++++++
- vma.c                   |  561 ++++++++++++++++++++++++++++
- vma.h                   |  146 ++++++++
8 files changed, 2470 insertions(+), 4 deletions(-)
+ vma-reader.c            |  799 ++++++++++++++++++++++++++++++++++++++++
+ vma-writer.c            |  932 +++++++++++++++++++++++++++++++++++++++++++++++
+ vma.c                   |  559 ++++++++++++++++++++++++++++
+ vma.h                   |  145 ++++++++
9 files changed, 2467 insertions(+), 4 deletions(-)
  create mode 100644 docs/specs/vma_spec.txt
  create mode 100644 vma-reader.c
  create mode 100644 vma-writer.c
@@ -23,52 +24,64 @@ Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
  create mode 100644 vma.h
 
 diff --git a/Makefile b/Makefile
-index 9ecbcbb..30a9268 100644
+index 0d9099a..16f1c25 100644
 --- a/Makefile
 +++ b/Makefile
-@@ -100,7 +100,7 @@ defconfig:
- -include config-all-devices.mak
+@@ -115,7 +115,7 @@ ifeq ($(CONFIG_SMARTCARD_NSS),y)
+ include $(SRC_PATH)/libcacard/Makefile
+ endif
  
 -all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all
 +all: $(DOCS) $(TOOLS) vma$(EXESUF) $(HELPERS-y) recurse-all
  
  config-host.h: config-host.h-timestamp
  config-host.h-timestamp: config-host.mak
-@@ -194,6 +194,7 @@ tools-obj-$(CONFIG_POSIX) += compatfd.o
- qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y) libqemustub.a
- qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y) libqemustub.a
- qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y) libqemustub.a
-+vma$(EXESUF): vma.o vma-writer.o vma-reader.o $(tools-obj-y) $(block-obj-y) libqemustub.a
+@@ -167,6 +167,7 @@ qemu-img.o: qemu-img-cmds.h
+ qemu-img$(EXESUF): qemu-img.o $(block-obj-y) libqemuutil.a libqemustub.a
+ qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) libqemuutil.a libqemustub.a
+ qemu-io$(EXESUF): qemu-io.o cmd.o $(block-obj-y) libqemuutil.a libqemustub.a
++vma$(EXESUF): vma.o vma-writer.o vma-reader.o $(block-obj-y)  libqemuutil.a libqemustub.a
  
  qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
  
 diff --git a/Makefile.objs b/Makefile.objs
-index cb46be5..b5732e2 100644
+index df64f70..91f133b 100644
 --- a/Makefile.objs
 +++ b/Makefile.objs
-@@ -48,7 +48,7 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o
- block-obj-y = iov.o cache-utils.o qemu-option.o module.o async.o
- block-obj-y += nbd.o block.o blockjob.o aes.o qemu-config.o
- block-obj-y += thread-pool.o qemu-progress.o qemu-sockets.o uri.o notify.o
+@@ -13,7 +13,7 @@ block-obj-$(CONFIG_POSIX) += aio-posix.o
+ block-obj-$(CONFIG_WIN32) += aio-win32.o
+ block-obj-y += block/
+ block-obj-y += qapi-types.o qapi-visit.o
 -block-obj-y += backup.o
 +block-obj-y += vma-writer.o backup.o
- block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y)
- block-obj-$(CONFIG_POSIX) += event_notifier-posix.o aio-posix.o
- block-obj-$(CONFIG_WIN32) += event_notifier-win32.o aio-win32.o
+ block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
+ block-obj-y += qemu-coroutine-sleep.o
+diff --git a/backup.h b/backup.h
+index c8ba153..406f011 100644
+--- a/backup.h
++++ b/backup.h
+@@ -15,6 +15,7 @@
+ #define QEMU_BACKUP_H
+ #include <uuid/uuid.h>
++#include "block/block.h"
+ #define BACKUP_CLUSTER_BITS 16
+ #define BACKUP_CLUSTER_SIZE (1<<BACKUP_CLUSTER_BITS)
 diff --git a/blockdev.c b/blockdev.c
-index 37edb75..0632c57 100644
+index c340fde..1cfc780 100644
 --- a/blockdev.c
 +++ b/blockdev.c
 @@ -21,6 +21,7 @@
  #include "trace.h"
- #include "arch_init.h"
+ #include "sysemu/arch_init.h"
  #include "backup.h"
 +#include "vma.h"
  
  static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
  
-@@ -1507,10 +1508,11 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
+@@ -1530,10 +1531,11 @@ char *qmp_backup(const char *backup_file, bool has_format, BackupFormat format,
      /* Todo: try to auto-detect format based on file name */
      format = has_format ? format : BACKUP_FORMAT_VMA;
  
@@ -114,10 +127,10 @@ index 0000000..052c629
 +
 diff --git a/vma-reader.c b/vma-reader.c
 new file mode 100644
-index 0000000..2217a94
+index 0000000..7e81847
 --- /dev/null
 +++ b/vma-reader.c
-@@ -0,0 +1,801 @@
+@@ -0,0 +1,799 @@
 +/*
 + * VMA: Virtual Machine Archive
 + *
@@ -143,12 +156,10 @@ index 0000000..2217a94
 +#include <uuid/uuid.h>
 +
 +#include "qemu-common.h"
-+#include "qemu_socket.h"
-+#include "qemu-coroutine.h"
-+#include "qemu-aio.h"
++#include "qemu/timer.h"
 +#include "qemu/ratelimit.h"
 +#include "vma.h"
-+#include "block.h"
++#include "block/block.h"
 +
 +#define BITS_PER_LONG  (sizeof(unsigned long) * 8)
 +
@@ -921,10 +932,10 @@ index 0000000..2217a94
 +
 diff --git a/vma-writer.c b/vma-writer.c
 new file mode 100644
-index 0000000..688af4b
+index 0000000..761d7ca
 --- /dev/null
 +++ b/vma-writer.c
-@@ -0,0 +1,931 @@
+@@ -0,0 +1,932 @@
 +/*
 + * VMA: Virtual Machine Archive
 + *
@@ -950,13 +961,9 @@ index 0000000..688af4b
 +#include <uuid/uuid.h>
 +
 +#include "qemu-common.h"
-+#include "qemu_socket.h"
-+#include "qemu-coroutine.h"
-+#include "qemu-aio.h"
-+#include "qemu/ratelimit.h"
 +#include "vma.h"
-+#include "block.h"
-+#include "monitor.h"
++#include "block/block.h"
++#include "monitor/monitor.h"
 +
 +#define DEBUG_VMA 0
 +
@@ -967,8 +974,8 @@ index 0000000..688af4b
 +
 +typedef struct VmaAIOCB VmaAIOCB;
 +struct VmaAIOCB {
-+    VmaWriter *vmaw;
 +    unsigned char buffer[VMA_MAX_EXTENT_SIZE];
++    VmaWriter *vmaw;
 +    size_t bytes;
 +    Coroutine *co;
 +};
@@ -988,14 +995,13 @@ index 0000000..688af4b
 +    int outbuf_count; /* in VMA_BLOCKS */
 +    uint64_t outbuf_block_info[VMA_BLOCKS_PER_EXTENT];
 +
-+    VmaAIOCB aiocbs[WRITE_BUFFERS];
++    VmaAIOCB *aiocbs[WRITE_BUFFERS];
 +    CoQueue wqueue;
 +
 +    GChecksum *md5csum;
 +    CoMutex writer_lock;
 +    CoMutex flush_lock;
 +    Coroutine *co_writer;
-+    RateLimit limit;
 +
 +    /* drive informations */
 +    VmaStreamInfo stream_info[256];
@@ -1146,12 +1152,17 @@ index 0000000..688af4b
 +{
 +    VmaWriter *vmaw = opaque;
 +
-+    qemu_aio_set_fd_handler(vmaw->fd, NULL, NULL, NULL, NULL);
-+
 +    DPRINTF("vma_co_continue_write\n");
 +    qemu_coroutine_enter(vmaw->co_writer, NULL);
 +}
 +
++static int vma_co_write_finished(void *opaque)
++{
++    VmaWriter *vmaw = opaque;
++
++    return (vmaw->co_writer != 0);
++}
++
 +static ssize_t coroutine_fn
 +vma_co_write(VmaWriter *vmaw, const void *buf, size_t bytes)
 +{
@@ -1163,6 +1174,17 @@ index 0000000..688af4b
 +
 +    DPRINTF("vma_co_write enter %zd\n", bytes);
 +
++    assert(vmaw->co_writer == NULL);
++
++    vmaw->co_writer = qemu_coroutine_self();
++
++    qemu_aio_set_fd_handler(vmaw->fd, NULL, vma_co_continue_write,
++                            vma_co_write_finished, vmaw);
++
++    DPRINTF("vma_co_write wait until writable\n");
++    qemu_coroutine_yield();
++    DPRINTF("vma_co_write starting %zd\n", bytes);
++
 +    while (done < bytes) {
 +        ret = write(vmaw->fd, buf + done, bytes - done);
 +        if (ret > 0) {
@@ -1171,11 +1193,6 @@ index 0000000..688af4b
 +        } else if (ret < 0) {
 +            if (errno == EAGAIN || errno == EWOULDBLOCK) {
 +                DPRINTF("vma_co_write yield %zd\n", done);
-+
-+                vmaw->co_writer = qemu_coroutine_self();
-+                qemu_aio_set_fd_handler(vmaw->fd, NULL, vma_co_continue_write,
-+                                        NULL, vmaw);
-+
 +                qemu_coroutine_yield();
 +                DPRINTF("vma_co_write restart %zd\n", done);
 +            } else {
@@ -1189,6 +1206,10 @@ index 0000000..688af4b
 +        }
 +    }
 +
++    qemu_aio_set_fd_handler(vmaw->fd, NULL, NULL, NULL, NULL);
++
++    vmaw->co_writer = NULL;
++
 +    qemu_co_mutex_unlock(&vmaw->writer_lock);
 +
 +    DPRINTF("vma_co_write leave %zd\n", done);
@@ -1227,10 +1248,10 @@ index 0000000..688af4b
 +        int i;
 +        VmaAIOCB *cb = NULL;
 +        for (i = 0; i < WRITE_BUFFERS; i++) {
-+            if (vmaw->aiocbs[i].bytes) {
-+                cb = &vmaw->aiocbs[i];
++            if (vmaw->aiocbs[i]->bytes) {
++                cb = vmaw->aiocbs[i];
 +                DPRINTF("FOUND USED AIO BUFFER %d %zd\n", i,
-+                        vmaw->aiocbs[i].bytes);
++                        vmaw->aiocbs[i]->bytes);
 +                break;
 +            }
 +        }
@@ -1260,8 +1281,8 @@ index 0000000..688af4b
 +    while (!cb) {
 +        int i;
 +        for (i = 0; i < WRITE_BUFFERS; i++) {
-+            if (!vmaw->aiocbs[i].bytes) {
-+                cb = &vmaw->aiocbs[i];
++            if (!vmaw->aiocbs[i]->bytes) {
++                cb = vmaw->aiocbs[i];
 +                break;
 +            }
 +        }
@@ -1283,8 +1304,7 @@ index 0000000..688af4b
 +    return bytes;
 +}
 +
-+VmaWriter *vma_writer_create(const char *filename, uuid_t uuid, int64_t speed,
-+                             Error **errp)
++VmaWriter *vma_writer_create(const char *filename, uuid_t uuid, Error **errp)
 +{
 +    const char *p;
 +
@@ -1308,7 +1328,10 @@ index 0000000..688af4b
 +            goto err;
 +        }
 +        vmaw->fd = fileno(vmaw->cmd);
-+        socket_set_nonblock(vmaw->fd);
++
++        /* try to use O_NONBLOCK and O_DIRECT */
++        fcntl(vmaw->fd, F_SETFL, fcntl(vmaw->fd, F_GETFL)|O_NONBLOCK);
++        fcntl(vmaw->fd, F_SETFL, fcntl(vmaw->fd, F_GETFL)|O_DIRECT);
 +
 +    } else {
 +        struct stat st;
@@ -1316,18 +1339,21 @@ index 0000000..688af4b
 +        const char *tmp_id_str;
 +
 +        if ((stat(filename, &st) == 0) && S_ISFIFO(st.st_mode)) {
-+            oflags = O_NONBLOCK|O_WRONLY;
++            oflags = O_NONBLOCK|O_DIRECT|O_WRONLY;
 +            vmaw->fd = qemu_open(filename, oflags, 0644);
 +        } else if (strstart(filename, "/dev/fdset/", &tmp_id_str)) {
-+            oflags = O_NONBLOCK|O_WRONLY;
++            oflags = O_NONBLOCK|O_DIRECT|O_WRONLY;
 +            vmaw->fd = qemu_open(filename, oflags, 0644);
 +        } else if (strstart(filename, "/dev/fdname/", &tmp_id_str)) {
 +            vmaw->fd = monitor_get_fd(cur_mon, tmp_id_str, errp);
 +            if (vmaw->fd < 0) {
 +                goto err;
 +            }
++            /* try to use O_NONBLOCK and O_DIRECT */
++            fcntl(vmaw->fd, F_SETFL, fcntl(vmaw->fd, F_GETFL)|O_NONBLOCK);
++            fcntl(vmaw->fd, F_SETFL, fcntl(vmaw->fd, F_GETFL)|O_DIRECT);
 +        } else  {
-+            oflags = O_NONBLOCK|O_WRONLY|O_CREAT|O_EXCL;
++            oflags = O_NONBLOCK|O_DIRECT|O_WRONLY|O_CREAT|O_EXCL;
 +            vmaw->fd = qemu_open(filename, oflags, 0644);
 +        }
 +
@@ -1338,6 +1364,13 @@ index 0000000..688af4b
 +        }
 +    }
 +
++    /* we use O_DIRECT, so we need to align IO buffers */
++    int i;
++    for (i = 0; i < WRITE_BUFFERS; i++) {
++        vmaw->aiocbs[i] = qemu_memalign(512, sizeof(VmaAIOCB));
++        memset(vmaw->aiocbs[i], 0, sizeof(VmaAIOCB));
++    }
++
 +    vmaw->outbuf_count = 0;
 +    vmaw->outbuf_pos = VMA_EXTENT_HEADER_SIZE;
 +
@@ -1349,12 +1382,6 @@ index 0000000..688af4b
 +
 +    uuid_copy(vmaw->uuid, uuid);
 +
-+    if (speed <= 0) {
-+        speed = 10*1024*1024*1024LLU; /* default 10GB/s */
-+    }
-+
-+    ratelimit_set_speed(&vmaw->limit, speed, 100000000ULL /* 0.1 sec */);
-+
 +    return vmaw;
 +
 +err:
@@ -1578,19 +1605,12 @@ index 0000000..688af4b
 +    return vmaw->status;
 +}
 +
-+static int vma_writer_get_buffer(VmaWriter *vmaw, size_t bytes)
++static int vma_writer_get_buffer(VmaWriter *vmaw)
 +{
 +    int ret = 0;
 +
 +    qemu_co_mutex_lock(&vmaw->flush_lock);
 +
-+    /* rate limit */
-+    uint64_t delay_ns = ratelimit_calculate_delay(&vmaw->limit, bytes);
-+    if (delay_ns) {
-+        DPRINTF("DELAY %zd\n", delay_ns);
-+        co_sleep_ns(rt_clock, delay_ns);
-+    }
-+
 +    /* wait until buffer is available */
 +    while (vmaw->outbuf_count >= (VMA_BLOCKS_PER_EXTENT - 1)) {
 +        ret = vma_writer_flush(vmaw);
@@ -1649,22 +1669,8 @@ index 0000000..688af4b
 +        return -1;
 +    }
 +
-+    /* detect block containing zeroes */
-+    int i;
-+    int bit = 1;
-+    uint16_t mask = 0;
-+    size_t real_size = 0;
-+    for (i = 0; i < 16; i++) {
-+        unsigned char *vmablock = buf + (i*VMA_BLOCK_SIZE);
-+        if (!buffer_is_zero(vmablock, VMA_BLOCK_SIZE)) {
-+            mask |= bit;
-+            real_size += VMA_BLOCK_SIZE;
-+        }
-+        bit = bit << 1;
-+    }
-+
 +    /* wait until buffer is available */
-+    if (vma_writer_get_buffer(vmaw, real_size) < 0) {
++    if (vma_writer_get_buffer(vmaw) < 0) {
 +        vma_writer_set_error(vmaw, "vma_writer_write: "
 +                             "vma_writer_get_buffer failed");
 +        return -1;
@@ -1672,10 +1678,13 @@ index 0000000..688af4b
 +
 +    DPRINTF("VMA WRITE %d %zd\n", dev_id, cluster_num);
 +
-+    bit = 1;
++    int i;
++    int bit = 1;
++    uint16_t mask = 0;
 +    for (i = 0; i < 16; i++) {
 +        unsigned char *vmablock = buf + (i*VMA_BLOCK_SIZE);
-+        if (mask & bit) {
++        if (!buffer_is_zero(vmablock, VMA_BLOCK_SIZE)) {
++            mask |= bit;
 +            memcpy(vmaw->outbuf + vmaw->outbuf_pos, vmablock, VMA_BLOCK_SIZE);
 +            vmaw->outbuf_pos += VMA_BLOCK_SIZE;
 +        } else {
@@ -1790,6 +1799,10 @@ index 0000000..688af4b
 +        g_checksum_free(vmaw->md5csum);
 +    }
 +
++    for (i = 0; i < WRITE_BUFFERS; i++) {
++        free(vmaw->aiocbs[i]);
++    }
++
 +    g_free(vmaw);
 +}
 +
@@ -1840,10 +1853,9 @@ index 0000000..688af4b
 +    return vma_writer_add_config(vmaw, name, data, data_len);
 +}
 +
-+static void *vma_open_cb(const char *filename, uuid_t uuid, int64_t speed,
-+                         Error **errp)
++static void *vma_open_cb(const char *filename, uuid_t uuid, Error **errp)
 +{
-+    return vma_writer_create(filename, uuid, speed, errp);
++    return vma_writer_create(filename, uuid, errp);
 +}
 +
 +const BackupDriver backup_vma_driver = {
@@ -1858,10 +1870,10 @@ index 0000000..688af4b
 +
 diff --git a/vma.c b/vma.c
 new file mode 100644
-index 0000000..9b47b92
+index 0000000..b2e276c
 --- /dev/null
 +++ b/vma.c
-@@ -0,0 +1,561 @@
+@@ -0,0 +1,559 @@
 +/*
 + * VMA: Virtual Machine Archive
 + *
@@ -1886,13 +1898,9 @@ index 0000000..9b47b92
 +#include <glib.h>
 +
 +#include "qemu-common.h"
-+#include "qemu-option.h"
-+#include "qemu-error.h"
-+#include "osdep.h"
-+#include "sysemu.h"
-+#include "block_int.h"
-+#include <stdio.h>
++#include "qemu/error-report.h"
 +#include "vma.h"
++#include "block/block.h"
 +
 +static void help(void)
 +{
@@ -2151,9 +2159,11 @@ index 0000000..9b47b92
 +                                        dirname, di->devname);
 +                printf("DEVINFO %s %zd\n", devfn, di->size);
 +
-+                if (bdrv_img_create(devfn, "raw", NULL, NULL, NULL,
-+                                    di->size, flags)) {
-+                    g_error("can't create file %s", devfn);
++                bdrv_img_create(devfn, "raw", NULL, NULL, NULL, di->size,
++                                flags, &errp);
++                if (error_is_set(&errp)) {
++                    g_error("can't create file %s: %s", devfn,
++                            error_get_pretty(errp));
 +                }
 +
 +                /* Note: we created an empty file above, so there is no
@@ -2277,7 +2287,7 @@ index 0000000..9b47b92
 +    uuid_generate(uuid);
 +
 +    Error *local_err = NULL;
-+    VmaWriter *vmaw = vma_writer_create(archivename, uuid, 0, &local_err);
++    VmaWriter *vmaw = vma_writer_create(archivename, uuid, &local_err);
 +
 +    if (vmaw == NULL) {
 +        g_error("%s", error_get_pretty(local_err));
@@ -2327,12 +2337,12 @@ index 0000000..9b47b92
 +        bcb->vmaw = vmaw;
 +        bcb->dev_id = dev_id;
 +
-+        if (backup_job_create(bs, backup_dump_cb, backup_complete_cb, 
-+                            bcb) < 0) {
++        if (backup_job_create(bs, backup_dump_cb, backup_complete_cb,
++                              bcb, 0) < 0) {
 +            unlink(archivename);
 +            g_error("backup_job_start failed");
 +        } else {
-+            backup_job_start(bs);
++            backup_job_start(bs, false);
 +        }
 +    }
 +
@@ -2425,10 +2435,10 @@ index 0000000..9b47b92
 +}
 diff --git a/vma.h b/vma.h
 new file mode 100644
-index 0000000..689e639
+index 0000000..76d0dc8
 --- /dev/null
 +++ b/vma.h
-@@ -0,0 +1,146 @@
+@@ -0,0 +1,145 @@
 +/*
 + * VMA: Virtual Machine Archive
 + *
@@ -2544,8 +2554,7 @@ index 0000000..689e639
 +
 +extern const BackupDriver backup_vma_driver;
 +
-+VmaWriter *vma_writer_create(const char *filename, uuid_t uuid, int64_t speed,
-+                             Error **errp);
++VmaWriter *vma_writer_create(const char *filename, uuid_t uuid, Error **errp);
 +int vma_writer_close(VmaWriter *vmaw, Error **errp);
 +void vma_writer_destroy(VmaWriter *vmaw);
 +int vma_writer_add_config(VmaWriter *vmaw, const char *name, gpointer data,