]> git.proxmox.com Git - pve-qemu-kvm.git/commitdiff
update backup patches
authorDietmar Maurer <dietmar@proxmox.com>
Thu, 24 Jan 2013 09:46:06 +0000 (10:46 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Thu, 24 Jan 2013 09:46:06 +0000 (10:46 +0100)
bump version 1.3-16

Makefile
debian/changelog
debian/patches/0001-RFC-Efficient-VM-backup-for-qemu.patch
debian/patches/0002-add-basic-backup-support-to-block-driver.patch
debian/patches/0003-add-backup-related-monitor-commands.patch
debian/patches/0004-introduce-new-vma-archive-format.patch
debian/patches/0005-add-regression-tests-for-backup.patch
debian/patches/0006-add-vm-state-to-backups.patch
debian/patches/0007-use-extra-thread-for-vma-writer.patch

index 4285d9c79ab8a5ee95d6b417db4c714a4686f63c..19659b61a88c815e6184b3b7fc2b5f584b6e9c0f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ RELEASE=2.3
 
 # also update debian/changelog
 KVMVER=1.3
-KVMPKGREL=15
+KVMPKGREL=16
 
 KVMPACKAGE=pve-qemu-kvm
 KVMDIR=qemu-kvm
index f616ed2310d6354deb77ddb6ed0de8afac3d1fec..ee604b519b7579f2828cd5d10914e1b309b1f133 100644 (file)
@@ -1,4 +1,4 @@
-pve-qemu-kvm (1.3-15) unstable; urgency=low
+pve-qemu-kvm (1.3-16) unstable; urgency=low
 
   * update backup patches - removed threaded code - we use qemu-aio
     instead to avoid problems in bdrv_drain_all().
index 3b4acdc9dc98d91911c3e6cc0cf40ee64b7aeb96..6a7717e4b392154e70ef1bae0562cc472a244fe0 100644 (file)
@@ -1,4 +1,4 @@
-From f4a34368cdc254ea7602c5913c50506f61e7652e Mon Sep 17 00:00:00 2001
+From 5a37c10eb0991e86cba666b82ac756dc2ff1cd8c Mon Sep 17 00:00:00 2001
 From: Dietmar Maurer <dietmar@proxmox.com>
 Date: Tue, 13 Nov 2012 09:24:50 +0100
 Subject: [PATCH v3 1/6] RFC: Efficient VM backup for qemu
@@ -26,8 +26,8 @@ Changes since v2:
 * BackupDriver: remove cancel_cb
 * use enum for BackupFormat
 * vma: use bdrv_open instead of bdrv_file_open
-* vma: use extra writer thread
-* backup on drive after another (try to avoid high load)
+* vma: fix aio, use O_DIRECT
+* backup one drive after another (try to avoid high load)
 
 Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
 ---
index 053f60a55fab3635b7285cdff245d3769ecc9aa7..90667b35604bb147b704bb8655a8bcd0d731c22a 100644 (file)
@@ -1,4 +1,4 @@
-From 4374768a3a4d92f0ac0a77688cb7f65ff108ef83 Mon Sep 17 00:00:00 2001
+From 26891c19f68a14927e8c52417112d80668be1b3a Mon Sep 17 00:00:00 2001
 From: Dietmar Maurer <dietmar@proxmox.com>
 Date: Tue, 13 Nov 2012 10:03:52 +0100
 Subject: [PATCH v3 2/6] add basic backup support to block driver
@@ -16,12 +16,12 @@ Currently backup cluster size is hardcoded to 65536 bytes.
 Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
 ---
  Makefile.objs |    1 +
- backup.c      |  334 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ backup.c      |  335 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  backup.h      |   32 ++++++
  block.c       |   71 +++++++++++-
  block.h       |    2 +
  blockjob.h    |   10 ++
- 6 files changed, 444 insertions(+), 6 deletions(-)
+ 6 files changed, 445 insertions(+), 6 deletions(-)
  create mode 100644 backup.c
  create mode 100644 backup.h
 
@@ -39,10 +39,10 @@ index 3c7abca..cb46be5 100644
  block-obj-$(CONFIG_WIN32) += event_notifier-win32.o aio-win32.o
 diff --git a/backup.c b/backup.c
 new file mode 100644
-index 0000000..af511c7
+index 0000000..3ccb74c
 --- /dev/null
 +++ b/backup.c
-@@ -0,0 +1,334 @@
+@@ -0,0 +1,335 @@
 +/*
 + * QEMU backup
 + *
@@ -299,7 +299,8 @@ index 0000000..af511c7
 +    while (backup_in_progress_count > 0) {
 +        DPRINTF("backup_run backup_in_progress_count != 0 (%d)",
 +                backup_in_progress_count);
-+        co_sleep_ns(rt_clock, 10000);
++        block_job_sleep_ns(&job->common, rt_clock, 10000);
++
 +    }
 +
 +    DPRINTF("backup_run complete %d\n", ret);
index bc6999ffc4062f17310fe8b7a82c874797e7bb07..41f39187e29bfb83ab7827195989f26de8261c11 100644 (file)
@@ -1,4 +1,4 @@
-From b9c06929cb9e9583b002fa6de76ad3c318c89f35 Mon Sep 17 00:00:00 2001
+From cd593564217e6ae808cc8555845b14eabac95bd0 Mon Sep 17 00:00:00 2001
 From: Dietmar Maurer <dietmar@proxmox.com>
 Date: Tue, 13 Nov 2012 11:27:56 +0100
 Subject: [PATCH v3 3/6] add backup related monitor commands
@@ -13,14 +13,14 @@ could move the whole archive format related code out of qemu.
 Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
 ---
  backup.h         |   12 ++
- blockdev.c       |  412 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ blockdev.c       |  419 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
  hmp-commands.hx  |   31 ++++
  hmp.c            |   63 ++++++++
  hmp.h            |    3 +
  monitor.c        |    7 +
  qapi-schema.json |   91 ++++++++++++
  qmp-commands.hx  |   27 ++++
- 8 files changed, 646 insertions(+), 0 deletions(-)
+ 8 files changed, 653 insertions(+), 0 deletions(-)
 
 diff --git a/backup.h b/backup.h
 index a5f85e6..c9c20c9 100644
@@ -44,7 +44,7 @@ index a5f85e6..c9c20c9 100644
 +
  #endif /* QEMU_BACKUP_H */
 diff --git a/blockdev.c b/blockdev.c
-index e73fd6e..bd2198e 100644
+index e73fd6e..ba28654 100644
 --- a/blockdev.c
 +++ b/blockdev.c
 @@ -20,6 +20,7 @@
@@ -55,7 +55,7 @@ index e73fd6e..bd2198e 100644
  
  static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
  
-@@ -1321,6 +1322,417 @@ void qmp_drive_mirror(const char *device, const char *target,
+@@ -1321,6 +1322,424 @@ void qmp_drive_mirror(const char *device, const char *target,
      drive_get_ref(drive_get_by_blockdev(bs));
  }
  
@@ -160,25 +160,32 @@ index e73fd6e..bd2198e 100644
 +        error_setg(&backup_state.error, "backup cancelled");
 +    }
 +
++    /* drain all i/o (awake jobs waiting for aio) */
++    bdrv_drain_all();
++
 +    /* we only need to cancel the running job - backup_run_next_job() cancels
 +     * the other jobs */
 +
++    int job_count = 0;
 +    GList *l = backup_state.bcb_list;
 +    while (l) {
 +        BackupCB *bcb = l->data;
 +        l = g_list_next(l);
 +      BlockJob *job = bcb->bs->job;
-+        if (!bcb->completed && job) {
-+            block_job_cancel(job);
-+            /* make sure we call the complete callback */
-+            if (!job->co) {
-+                block_job_completed(job, -1);
++      if (job) {
++            job_count++;
++            if (!bcb->completed) {
++                block_job_cancel(job);
++                /* make sure we call the complete callback */
++                if (!job->co) {
++                    block_job_completed(job, -1);
++                }
++                break;
 +            }
-+            break;
-+       }
++        }
 +    }
 +
-+    if (!l) { /* all jobs completed */
++    if (job_count == 0) { /* can happen when backup_start_jobs() fails */
 +        backup_cleanup();
 +    }
 +}
index 0f07c018f4b8988bdf00eee8331c31ba1ee6cb52..3210080486b57f7bdd612e8a18e1b9a1d85fe781 100644 (file)
@@ -1,4 +1,4 @@
-From bb18514bdcb93d9b2906bfb2a8aa9fd6c2265710 Mon Sep 17 00:00:00 2001
+From 2b6ca0c6087ed51bc8318731713bb3aa83f606db 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/6] introduce new vma archive format
@@ -11,11 +11,11 @@ Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
  Makefile.objs           |    2 +-
  blockdev.c              |    6 +-
  docs/specs/vma_spec.txt |   24 ++
- vma-reader.c            |  801 +++++++++++++++++++++++++++++++++++++++++
- vma-writer.c            |  914 +++++++++++++++++++++++++++++++++++++++++++++++
- vma.c                   |  561 +++++++++++++++++++++++++++++
+ vma-reader.c            |  801 ++++++++++++++++++++++++++++++++++++++++
+ vma-writer.c            |  933 +++++++++++++++++++++++++++++++++++++++++++++++
+ vma.c                   |  561 ++++++++++++++++++++++++++++
  vma.h                   |  145 ++++++++
- 8 files changed, 2452 insertions(+), 4 deletions(-)
+ 8 files changed, 2471 insertions(+), 4 deletions(-)
  create mode 100644 docs/specs/vma_spec.txt
  create mode 100644 vma-reader.c
  create mode 100644 vma-writer.c
@@ -57,7 +57,7 @@ index cb46be5..b5732e2 100644
  block-obj-$(CONFIG_POSIX) += event_notifier-posix.o aio-posix.o
  block-obj-$(CONFIG_WIN32) += event_notifier-win32.o aio-win32.o
 diff --git a/blockdev.c b/blockdev.c
-index bd2198e..99f3e02 100644
+index ba28654..a030a13 100644
 --- a/blockdev.c
 +++ b/blockdev.c
 @@ -21,6 +21,7 @@
@@ -68,7 +68,7 @@ index bd2198e..99f3e02 100644
  
  static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
  
-@@ -1508,10 +1509,11 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
+@@ -1515,10 +1516,11 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
      /* Todo: try to auto-detect format based on file name */
      format = has_format ? format : BACKUP_FORMAT_VMA;
  
@@ -921,10 +921,10 @@ index 0000000..2217a94
 +
 diff --git a/vma-writer.c b/vma-writer.c
 new file mode 100644
-index 0000000..3f5bbd5
+index 0000000..08c4ee3
 --- /dev/null
 +++ b/vma-writer.c
-@@ -0,0 +1,914 @@
+@@ -0,0 +1,933 @@
 +/*
 + * VMA: Virtual Machine Archive
 + *
@@ -966,8 +966,8 @@ index 0000000..3f5bbd5
 +
 +typedef struct VmaAIOCB VmaAIOCB;
 +struct VmaAIOCB {
-+    VmaWriter *vmaw;
 +    unsigned char buffer[VMA_MAX_EXTENT_SIZE];
++    VmaWriter *vmaw;
 +    size_t bytes;
 +    Coroutine *co;
 +};
@@ -987,7 +987,7 @@ index 0000000..3f5bbd5
 +    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;
@@ -1150,6 +1150,13 @@ index 0000000..3f5bbd5
 +    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)
 +{
@@ -1161,8 +1168,12 @@ index 0000000..3f5bbd5
 +
 +    DPRINTF("vma_co_write enter %zd\n", bytes);
 +
++    assert(vmaw->co_writer == NULL);
++
 +    while (done < bytes) {
-+        ret = write(vmaw->fd, buf + done, bytes - done);
++        /* Note: we limit maximal write size - else VM gets slow */ 
++        ret = write(vmaw->fd, buf + done, 
++                    (bytes - done) > 4096 ? 4096 : bytes - done);
 +        if (ret > 0) {
 +            done += ret;
 +            DPRINTF("vma_co_write written %zd %zd\n", done, ret);
@@ -1172,7 +1183,7 @@ index 0000000..3f5bbd5
 +
 +                vmaw->co_writer = qemu_coroutine_self();
 +                qemu_aio_set_fd_handler(vmaw->fd, NULL, vma_co_continue_write,
-+                                        NULL, vmaw);
++                                        vma_co_write_finished, vmaw);
 +
 +                qemu_coroutine_yield();
 +                DPRINTF("vma_co_write restart %zd\n", done);
@@ -1187,6 +1198,8 @@ index 0000000..3f5bbd5
 +        }
 +    }
 +
++    vmaw->co_writer = NULL;
++
 +    qemu_co_mutex_unlock(&vmaw->writer_lock);
 +
 +    DPRINTF("vma_co_write leave %zd\n", done);
@@ -1225,10 +1238,10 @@ index 0000000..3f5bbd5
 +        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;
 +            }
 +        }
@@ -1258,8 +1271,8 @@ index 0000000..3f5bbd5
 +    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;
 +            }
 +        }
@@ -1305,7 +1318,10 @@ index 0000000..3f5bbd5
 +            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;
@@ -1313,18 +1329,21 @@ index 0000000..3f5bbd5
 +        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);
 +        }
 +
@@ -1335,6 +1354,13 @@ index 0000000..3f5bbd5
 +        }
 +    }
 +
++    /* 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;
 +
@@ -1569,7 +1595,7 @@ index 0000000..3f5bbd5
 +    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;
 +
@@ -1633,22 +1659,8 @@ index 0000000..3f5bbd5
 +        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;
@@ -1656,10 +1668,13 @@ index 0000000..3f5bbd5
 +
 +    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 {
@@ -1774,6 +1789,10 @@ index 0000000..3f5bbd5
 +        g_checksum_free(vmaw->md5csum);
 +    }
 +
++    for (i = 0; i < WRITE_BUFFERS; i++) {
++        free(vmaw->aiocbs[i]);
++    }
++
 +    g_free(vmaw);
 +}
 +
index 7fa849a50e2bfa0f0543a3bf0aea3c760f975f53..e4c9de1ae42c3ea7b329062b5688ab7e792904f7 100644 (file)
@@ -1,4 +1,4 @@
-From 59bc6b7cd95ff518bb415ae49bc3078c145003f3 Mon Sep 17 00:00:00 2001
+From 43cf41bbbb32384d4a51e37868be363a11eda35b Mon Sep 17 00:00:00 2001
 From: Dietmar Maurer <dietmar@proxmox.com>
 Date: Wed, 14 Nov 2012 09:57:04 +0100
 Subject: [PATCH v3 5/6] add regression tests for backup
index 8b5ab81b70306c207ffa9ebb16a518d4a12541d8..7bdc9f68bb23eff0bc3fc43a06ce565b67d70569 100644 (file)
@@ -1,4 +1,4 @@
-From 9901e8c82fb25ce5ce82c9e18276d8190bb4aca7 Mon Sep 17 00:00:00 2001
+From 6f87d124089c383af873d9774d3b47597dc7d5e9 Mon Sep 17 00:00:00 2001
 From: Dietmar Maurer <dietmar@proxmox.com>
 Date: Thu, 29 Nov 2012 10:46:49 +0100
 Subject: [PATCH v3 6/6] add vm state to backups
@@ -12,7 +12,7 @@ Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
  3 files changed, 200 insertions(+), 5 deletions(-)
 
 diff --git a/blockdev.c b/blockdev.c
-index 99f3e02..cb9293b 100644
+index a030a13..d5878c5 100644
 --- a/blockdev.c
 +++ b/blockdev.c
 @@ -22,6 +22,8 @@
@@ -35,7 +35,7 @@ index 99f3e02..cb9293b 100644
  } backup_state;
  
  typedef struct BackupCB {
-@@ -1494,10 +1500,170 @@ static void backup_start_jobs(void)
+@@ -1501,10 +1507,170 @@ static void backup_start_jobs(void)
      backup_run_next_job();
  }
  
@@ -207,7 +207,7 @@ index 99f3e02..cb9293b 100644
  {
      BlockDriverState *bs;
      Error *local_err = NULL;
-@@ -1506,6 +1672,8 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
+@@ -1513,6 +1679,8 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
      gchar **devs = NULL;
      GList *bcblist = NULL;
  
@@ -216,7 +216,7 @@ index 99f3e02..cb9293b 100644
      /* Todo: try to auto-detect format based on file name */
      format = has_format ? format : BACKUP_FORMAT_VMA;
  
-@@ -1586,6 +1754,22 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
+@@ -1593,6 +1761,22 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
      size_t total = 0;
  
      /* register all devices for vma writer */
@@ -239,7 +239,7 @@ index 99f3e02..cb9293b 100644
      l = bcblist;
      while (l) {
          BackupCB *bcb = l->data;
-@@ -1651,6 +1835,9 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
+@@ -1658,6 +1842,9 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
      backup_state.total = total;
      backup_state.transferred = 0;
      backup_state.zero_bytes = 0;
@@ -249,7 +249,7 @@ index 99f3e02..cb9293b 100644
  
      /* Grab a reference so hotplug does not delete the
       * BlockDriverState from underneath us.
-@@ -1662,7 +1849,12 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
+@@ -1669,7 +1856,12 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
          drive_get_ref(drive_get_by_blockdev(bcb->bs));
      }
  
index 10dba436fca31e2d0adebb4fc61abcf548f229ff..d6d1f5fac2dac67f89e9b7324afdbb101fa1871b 100644 (file)
@@ -14,11 +14,11 @@ Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
  vma-writer.c |  296 +++++++++++++++++++++++++++++++++++-----------------------
  1 files changed, 180 insertions(+), 116 deletions(-)
 
-diff --git a/vma-writer.c b/vma-writer.c
-index 688af4b..e18591e 100644
---- a/vma-writer.c
-+++ b/vma-writer.c
-@@ -38,13 +38,20 @@
+Index: new/vma-writer.c
+===================================================================
+--- new.orig/vma-writer.c      2013-01-23 07:35:12.000000000 +0100
++++ new/vma-writer.c   2013-01-23 09:24:19.000000000 +0100
+@@ -37,13 +37,21 @@
  
  #define WRITE_BUFFERS 5
  
@@ -40,11 +40,12 @@ index 688af4b..e18591e 100644
 +    GMutex *mutex;
 +    GCond *change_cond;
 +    WriteBuffer wbuf[WRITE_BUFFERS];
++    CoQueue wqueue;
 +} WriterThread;
  
  struct VmaWriter {
      int fd;
-@@ -61,8 +68,7 @@ struct VmaWriter {
+@@ -60,8 +68,7 @@
      int outbuf_count; /* in VMA_BLOCKS */
      uint64_t outbuf_block_info[VMA_BLOCKS_PER_EXTENT];
  
@@ -54,7 +55,7 @@ index 688af4b..e18591e 100644
  
      GChecksum *md5csum;
      CoMutex writer_lock;
-@@ -88,6 +94,80 @@ struct VmaWriter {
+@@ -86,6 +93,107 @@
      uint32_t config_count;
  };
  
@@ -65,7 +66,7 @@ index 688af4b..e18591e 100644
 +    while (1) {
 +        WriteBuffer *b = NULL;
 +
-+        g_mutex_lock(wt->mutex);
++      qemu_mutex_lock_iothread();
 +        int i;
 +        for (i = 0; i < WRITE_BUFFERS; i++) {
 +            if (wt->wbuf[i].bytes) {
@@ -73,7 +74,7 @@ index 688af4b..e18591e 100644
 +                break;
 +            }
 +        }
-+        g_mutex_unlock(wt->mutex);
++      qemu_mutex_unlock_iothread();
 +
 +        if (b) {
 +            size_t done = 0;
@@ -83,18 +84,28 @@ index 688af4b..e18591e 100644
 +                    done += ret;
 +                } else if (ret < 0) {
 +                    if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
-+                        g_mutex_lock(wt->mutex);
++                        qemu_mutex_lock_iothread();
 +                        wt->error = errno;
-+                        g_mutex_unlock(wt->mutex);
++                        qemu_mutex_unlock_iothread();
 +                        break;
 +                    }
 +                } else if (ret == 0) {
 +                    /* should not happen - simply try again */
 +                }
 +            }
-+            g_mutex_lock(wt->mutex);
++            qemu_mutex_lock_iothread();
 +            b->bytes = 0;
-+            g_mutex_unlock(wt->mutex);
++            DPRINTF("AWAKE JOB %d\n", wt->error);
++            if (wt->error) {
++                for (i = 0; i < WRITE_BUFFERS; i++) {
++                    wt->wbuf[i].bytes = 0;
++                }
++                qemu_co_queue_restart_all(&wt->wqueue);
++            } else {
++                qemu_co_queue_next(&wt->wqueue);
++            }
++            qemu_mutex_unlock_iothread();
++            DPRINTF("AWAKE JOB END\n");
 +        }
 +
 +        if (wt->error) {
@@ -105,11 +116,19 @@ index 688af4b..e18591e 100644
 +        g_mutex_lock(wt->mutex);
 +        bool cancel = wt->cancel;
 +        if (!b && !cancel) {
++            DPRINTF("WRITER THREAD WAIT FOR DATA\n");         
 +            g_cond_wait(wt->change_cond, wt->mutex);
++            cancel = wt->cancel;
 +        }
 +        g_mutex_unlock(wt->mutex);
 +
 +        if (cancel) {
++            qemu_mutex_lock_iothread();
++            for (i = 0; i < WRITE_BUFFERS; i++) {
++                wt->wbuf[i].bytes = 0;
++            }
++            qemu_co_queue_restart_all(&wt->wqueue);
++            qemu_mutex_unlock_iothread();
 +            DPRINTF("END WRITER THREAD\n");
 +            g_thread_exit(NULL);
 +        }
@@ -122,20 +141,29 @@ index 688af4b..e18591e 100644
 +{
 +    assert(vmaw);
 +
++    DPRINTF("vma_stop_writer_thread start\n");
++
 +    if (vmaw->wt.thread) {
++        DPRINTF("vma_stop_writer_thread 1\n");
 +        g_mutex_lock(vmaw->wt.mutex);
++        DPRINTF("vma_stop_writer_thread 2\n");
 +        vmaw->wt.cancel = true;
 +        g_cond_signal(vmaw->wt.change_cond);
 +        g_mutex_unlock(vmaw->wt.mutex);
++        DPRINTF("vma_stop_writer_thread 3\n");
++        qemu_mutex_unlock_iothread();
 +        g_thread_join(vmaw->wt.thread);
++        qemu_mutex_lock_iothread();
++        DPRINTF("vma_stop_writer_thread 4\n");
 +        vmaw->wt.thread = NULL;
 +    }
++    DPRINTF("vma_stop_writer_thread end\n");
 +}
 +
  void vma_writer_set_error(VmaWriter *vmaw, const char *fmt, ...)
  {
      va_list ap;
-@@ -215,111 +295,47 @@ int vma_writer_register_stream(VmaWriter *vmaw, const char *devname,
+@@ -213,111 +321,45 @@
      return n;
  }
  
@@ -226,8 +254,7 @@ index 688af4b..e18591e 100644
          int i;
 -        VmaAIOCB *cb = NULL;
 +        WriteBuffer *b = NULL;
-+        g_mutex_lock(vmaw->wt.mutex);
-+
++ 
 +        error = vmaw->wt.error;
 +
          for (i = 0; i < WRITE_BUFFERS; i++) {
@@ -243,15 +270,14 @@ index 688af4b..e18591e 100644
              }
          }
 -        if (!cb) {
-+        g_mutex_unlock(vmaw->wt.mutex);
 +
 +        if (!b || error) {
              break;
          }
 -        qemu_co_queue_wait(&vmaw->wqueue);
-+        uint64_t delay_ns = 10000;
-+        DPRINTF("WAIT FOR BUFFER FLUSH %zd\n", delay_ns);
-+        co_sleep_ns(rt_clock, delay_ns);
++        DPRINTF("WAIT FOR BUFFER FLUSH\n");
++        qemu_co_queue_wait(&vmaw->wt.wqueue);
++        DPRINTF("WAIT FOR BUFFER FLUSH END\n");
 +    }
 +
 +    if (error) {
@@ -269,7 +295,7 @@ index 688af4b..e18591e 100644
  static ssize_t coroutine_fn
  vma_queue_write(VmaWriter *vmaw, const void *buf, size_t bytes)
  {
-@@ -329,29 +345,46 @@ vma_queue_write(VmaWriter *vmaw, const void *buf, size_t bytes)
+@@ -327,29 +369,42 @@
      assert(buf);
      assert(bytes <= VMA_MAX_EXTENT_SIZE);
  
@@ -278,13 +304,11 @@ index 688af4b..e18591e 100644
 +    int error = 0;
 +
 +    /* wait for a free output buffer */
-+    g_mutex_lock(vmaw->wt.mutex);
 +    WriteBuffer *b = NULL;
 +    while (!b) {
 +        error = vmaw->wt.error;
 +        if (error) {
-+            g_mutex_unlock(vmaw->wt.mutex);
-+            vma_writer_set_error(vmaw, "vma_queue_write error - %s",
++             vma_writer_set_error(vmaw, "vma_queue_write error - %s",
 +                                 strerror(error));
 +            return -1;
 +        }
@@ -301,11 +325,9 @@ index 688af4b..e18591e 100644
 -        if (!cb) {
 -            qemu_co_queue_wait(&vmaw->wqueue);
 +        if (!b) {
-+            uint64_t delay_ns = 10000;
-+            DPRINTF("WAIT FOR BUFFER %zd\n", delay_ns);
-+            g_mutex_unlock(vmaw->wt.mutex);
-+            co_sleep_ns(rt_clock, delay_ns);
-+            g_mutex_lock(vmaw->wt.mutex);
++            DPRINTF("WAIT FOR BUFFER\n");
++            qemu_co_queue_wait(&vmaw->wt.wqueue);
++            DPRINTF("WAIT FOR BUFFER DONE\n");
          }
      }
  
@@ -315,13 +337,13 @@ index 688af4b..e18591e 100644
 +    /* copy data to output buffer */
 +    memcpy(b->buffer, buf, bytes);
 +    b->bytes = bytes;
-+
-+    /* signal writer thread that we have new data */
-+    g_cond_signal(vmaw->wt.change_cond);
  
 -    DPRINTF("vma_queue_write start %zd\n", bytes);
 -    cb->co = qemu_coroutine_create(vma_co_writer_task);
 -    qemu_coroutine_enter(cb->co, cb);
++    g_mutex_lock(vmaw->wt.mutex);
++    /* signal writer thread that we have new data */
++    g_cond_signal(vmaw->wt.change_cond);
 +    g_mutex_unlock(vmaw->wt.mutex);
  
 -    DPRINTF("vma_queue_write leave\n");
@@ -329,7 +351,7 @@ index 688af4b..e18591e 100644
  
      return bytes;
  }
-@@ -389,10 +422,10 @@ VmaWriter *vma_writer_create(const char *filename, uuid_t uuid, int64_t speed,
+@@ -386,10 +441,10 @@
          const char *tmp_id_str;
  
          if ((stat(filename, &st) == 0) && S_ISFIFO(st.st_mode)) {
@@ -342,7 +364,7 @@ index 688af4b..e18591e 100644
              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);
-@@ -400,7 +433,7 @@ VmaWriter *vma_writer_create(const char *filename, uuid_t uuid, int64_t speed,
+@@ -397,7 +452,7 @@
                  goto err;
              }
          } else  {
@@ -351,18 +373,15 @@ index 688af4b..e18591e 100644
              vmaw->fd = qemu_open(filename, oflags, 0644);
          }
  
-@@ -418,7 +451,6 @@ VmaWriter *vma_writer_create(const char *filename, uuid_t uuid, int64_t speed,
+@@ -415,10 +470,19 @@
  
      qemu_co_mutex_init(&vmaw->writer_lock);
      qemu_co_mutex_init(&vmaw->flush_lock);
 -    qemu_co_queue_init(&vmaw->wqueue);
++    qemu_co_queue_init(&vmaw->wt.wqueue);
  
      uuid_copy(vmaw->uuid, uuid);
  
-@@ -428,6 +460,15 @@ VmaWriter *vma_writer_create(const char *filename, uuid_t uuid, int64_t speed,
-     ratelimit_set_speed(&vmaw->limit, speed, 100000000ULL /* 0.1 sec */);
 +    vmaw->wt.mutex = g_mutex_new();
 +    vmaw->wt.change_cond = g_cond_new();
 +    vmaw->wt.fd = vmaw->fd;
@@ -375,7 +394,7 @@ index 688af4b..e18591e 100644
      return vmaw;
  
  err:
-@@ -442,6 +483,14 @@ err:
+@@ -433,6 +497,14 @@
              g_checksum_free(vmaw->md5csum);
          }
  
@@ -390,13 +409,11 @@ index 688af4b..e18591e 100644
          g_free(vmaw);
      }
  
-@@ -688,6 +737,16 @@ vma_writer_write(VmaWriter *vmaw, uint8_t dev_id, int64_t cluster_num,
+@@ -672,6 +744,14 @@
  
      *zero_bytes = 0;
  
-+    g_mutex_lock(vmaw->wt.mutex);
 +    int error = vmaw->wt.error;
-+    g_mutex_unlock(vmaw->wt.mutex);
 +
 +    if (error) {
 +        vma_writer_set_error(vmaw, "vma_writer_get_buffer write error - %s",
@@ -407,20 +424,26 @@ index 688af4b..e18591e 100644
      if (vmaw->status < 0) {
          return vmaw->status;
      }
-@@ -801,11 +860,7 @@ int vma_writer_close(VmaWriter *vmaw, Error **errp)
+@@ -783,14 +863,17 @@
+     int i;
  
++    DPRINTF("vma_writer_close start\n");
      vma_queue_flush(vmaw);
  
--    /* this should not happen - just to be sure */
+     /* this should not happen - just to be sure */
 -    while (!qemu_co_queue_empty(&vmaw->wqueue)) {
--        DPRINTF("vma_writer_close wait\n");
--        co_sleep_ns(rt_clock, 1000000);
--    }
-+    vma_stop_writer_thread(vmaw);
++    while (!qemu_co_queue_empty(&vmaw->wt.wqueue)) {
+         DPRINTF("vma_writer_close wait\n");
+         co_sleep_ns(rt_clock, 1000000);
+     }
  
++    vma_stop_writer_thread(vmaw);
++
      if (vmaw->cmd) {
          if (pclose(vmaw->cmd) < 0) {
-@@ -851,8 +906,9 @@ void vma_writer_destroy(VmaWriter *vmaw)
+             vma_writer_set_error(vmaw, "vma_writer_close: "
+@@ -835,8 +918,9 @@
  {
      assert(vmaw);
  
@@ -431,7 +454,7 @@ index 688af4b..e18591e 100644
      for (i = 0; i <= 255; i++) {
          if (vmaw->stream_info[i].devname) {
              g_free(vmaw->stream_info[i].devname);
-@@ -863,6 +919,14 @@ void vma_writer_destroy(VmaWriter *vmaw)
+@@ -847,6 +931,14 @@
          g_checksum_free(vmaw->md5csum);
      }
  
@@ -446,6 +469,3 @@ index 688af4b..e18591e 100644
      g_free(vmaw);
  }
  
--- 
-1.7.2.5
-