-From 7bab4498b955ced91ad838fb711e013d9b7ed81f Mon Sep 17 00:00:00 2001
+From 7d2906f7da677d2f2533d1455453dc328cb65590 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/7] add backup related monitor commands
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
---
backup.h | 13 ++
- blockdev.c | 396 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
- hmp-commands.hx | 31 +++++
+ blockdev.c | 410 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ hmp-commands.hx | 31 ++++
hmp.c | 63 +++++++++
hmp.h | 3 +
monitor.c | 7 +
- qapi-schema.json | 91 +++++++++++++
+ qapi-schema.json | 91 ++++++++++++
qmp-commands.hx | 27 ++++
- 8 files changed, 631 insertions(+), 0 deletions(-)
+ 8 files changed, 645 insertions(+), 0 deletions(-)
diff --git a/backup.h b/backup.h
index 87b9942..c6e5d3c 100644
+
#endif /* QEMU_BACKUP_H */
diff --git a/blockdev.c b/blockdev.c
-index e73fd6e..68a8c55 100644
+index e73fd6e..37edb75 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -20,6 +20,7 @@
static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
-@@ -1321,6 +1322,401 @@ void qmp_drive_mirror(const char *device, const char *target,
+@@ -1321,6 +1322,415 @@ void qmp_drive_mirror(const char *device, const char *target,
drive_get_ref(drive_get_by_blockdev(bs));
}
+typedef struct BackupCB {
+ BlockDriverState *bs;
+ uint8_t dev_id;
++ bool started;
++ bool completed;
+ size_t size;
+ size_t transferred;
+ size_t zero_bytes;
+ backup_state.driver->close_cb(backup_state.writer, &local_err);
+ error_propagate(&backup_state.error, local_err);
+ backup_state.writer = NULL;
-+
+ }
+
-+ GList *l = backup_state.bcb_list;
-+ while (l) {
-+ BackupCB *bcb = l->data;
-+ drive_put_ref_bh_schedule(drive_get_by_blockdev(bcb->bs));
-+ g_free(l->data);
-+ l = g_list_next(l);
++ if (backup_state.bcb_list) {
++ GList *l = backup_state.bcb_list;
++ while (l) {
++ BackupCB *bcb = l->data;
++ l = g_list_next(l);
++ drive_put_ref_bh_schedule(drive_get_by_blockdev(bcb->bs));
++ g_free(bcb);
++ }
++ g_list_free(backup_state.bcb_list);
++ backup_state.bcb_list = NULL;
+ }
-+ g_list_free(backup_state.bcb_list);
-+ backup_state.bcb_list = NULL;
+}
+
+static void backup_complete_cb(void *opaque, int ret)
+ assert(backup_state.driver->complete_cb);
+ assert(backup_state.driver->close_cb);
+
-+ drive_put_ref_bh_schedule(drive_get_by_blockdev(bcb->bs));
-+
-+ backup_state.bcb_list = g_list_remove(backup_state.bcb_list, bcb);
++ bcb->completed = true;
+
+ backup_state.driver->complete_cb(backup_state.writer, bcb->dev_id, ret);
+
-+ if (g_list_length(backup_state.bcb_list) == 0) {
-+ backup_cleanup();
-+ } else {
-+ backup_run_next_job();
-+ }
-+
-+ g_free(bcb);
++ backup_run_next_job();
+}
+
+static void backup_cancel(void)
+{
-+ GList *l = backup_state.bcb_list;
-+ int job_count = 0;
++ if (!backup_state.error) {
++ error_setg(&backup_state.error, "backup cancelled");
++ }
++
++ /* we only need to cancel the running job - backup_run_next_job() cancels
++ * the other jobs */
+
++ GList *l = backup_state.bcb_list;
+ while (l) {
+ BackupCB *bcb = l->data;
+ l = g_list_next(l);
-+ if (bcb->bs->job) {
-+ block_job_cancel(bcb->bs->job);
-+ job_count++;
-+ }
++ 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);
++ }
++ break;
++ }
+ }
+
-+ if (!job_count) {
++ if (!l) { /* all jobs completed */
+ backup_cleanup();
+ }
+}
+
+void qmp_backup_cancel(Error **errp)
+{
-+ if (!backup_state.error) {
-+ error_setg(&backup_state.error, "backup cancelled");
-+ }
-+
+ backup_cancel();
+}
+
+static void backup_run_next_job(void)
+{
+ GList *l = backup_state.bcb_list;
-+ if (l) {
++ while(l) {
+ BackupCB *bcb = l->data;
-+ backup_job_start(bcb->bs);
++ l = g_list_next(l);
++
++ if (bcb->bs && bcb->bs->job && !bcb->completed) {
++ if (!bcb->started) {
++ bcb->started = true;
++ if (!backup_state.error) {
++ backup_job_start(bcb->bs);
++ } else {
++ block_job_completed(bcb->bs->job, -1);
++ }
++ }
++ return;
++ }
+ }
++
++ backup_cleanup();
+}
+
+static void backup_start_jobs(void)
+{
-+ /* start all jobs (one for each device) */
++ /* create all jobs (one for each device), start first one */
+ GList *l = backup_state.bcb_list;
+ while (l) {
+ BackupCB *bcb = l->data;
+
+ if (backup_job_create(bcb->bs, backup_dump_cb, backup_complete_cb,
+ bcb) != 0) {
++ error_setg(&backup_state.error, "backup_job_create failed");
+ backup_cancel();
-+ break;
++ return;
+ }
+ }
+
-+ if (!l) { /* no errors */
-+ backup_run_next_job();
-+ }
++ backup_run_next_job();
+}
+
+char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
-From 77a6564c9985c37990c3e90f558f2ef48d6d5f15 Mon Sep 17 00:00:00 2001
+From 69a3f26bdbe445ce01f096b9d5e1aaf45ad98b81 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
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 68a8c55..80cb04d 100644
+index 37edb75..0632c57 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -21,6 +21,7 @@
static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
-@@ -1493,10 +1494,11 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
+@@ -1507,10 +1508,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;
-From 9c8e193692a2f96116793ddbe3fa89650985f272 Mon Sep 17 00:00:00 2001
+From 4f629e5e088e63ea8e73d69e4e4beabc251d31a1 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/7] add vm state to backups
3 files changed, 200 insertions(+), 5 deletions(-)
diff --git a/blockdev.c b/blockdev.c
-index 80cb04d..96d7a3b 100644
+index 0632c57..f19eb02 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -22,6 +22,8 @@
} backup_state;
typedef struct BackupCB {
-@@ -1479,10 +1485,170 @@ static void backup_start_jobs(void)
- }
+@@ -1493,10 +1499,170 @@ static void backup_start_jobs(void)
+ backup_run_next_job();
}
+static int backup_state_close(void *opaque)
{
BlockDriverState *bs;
Error *local_err = NULL;
-@@ -1491,6 +1657,8 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
+@@ -1505,6 +1671,8 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
gchar **devs = NULL;
GList *bcblist = NULL;
/* Todo: try to auto-detect format based on file name */
format = has_format ? format : BACKUP_FORMAT_VMA;
-@@ -1572,6 +1740,22 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
+@@ -1586,6 +1754,22 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
size_t total = 0;
/* register all devices for vma writer */
l = bcblist;
while (l) {
BackupCB *bcb = l->data;
-@@ -1635,6 +1819,9 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
+@@ -1649,6 +1833,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;
/* Grab a reference so hotplug does not delete the
* BlockDriverState from underneath us.
-@@ -1646,7 +1833,12 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
+@@ -1660,7 +1847,12 @@ char *qmp_backup(const char *backupfile, bool has_format, BackupFormat format,
drive_get_ref(drive_get_by_blockdev(bcb->bs));
}