257 lines
8.6 KiB
Diff
257 lines
8.6 KiB
Diff
From 84631ae35b99f60a08a4a02f1596f5c9d17ebff0 Mon Sep 17 00:00:00 2001
|
|
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
|
Date: Wed, 9 Dec 2015 16:31:51 +0100
|
|
Subject: [PATCH 23/49] backup: vma: allow empty backups
|
|
|
|
---
|
|
vma-reader.c | 29 ++++++++++++-------------
|
|
vma-writer.c | 30 ++++++++++++++++----------
|
|
vma.c | 70 ++++++++++++++++++++++++++++++++++++------------------------
|
|
vma.h | 1 +
|
|
4 files changed, 76 insertions(+), 54 deletions(-)
|
|
|
|
diff --git a/vma-reader.c b/vma-reader.c
|
|
index 2aafb26b2a..78f1de9499 100644
|
|
--- a/vma-reader.c
|
|
+++ b/vma-reader.c
|
|
@@ -326,11 +326,6 @@ static int vma_reader_read_head(VmaReader *vmar, Error **errp)
|
|
}
|
|
}
|
|
|
|
- if (!count) {
|
|
- error_setg(errp, "vma does not contain data");
|
|
- return -1;
|
|
- }
|
|
-
|
|
for (i = 0; i < VMA_MAX_CONFIGS; i++) {
|
|
uint32_t name_ptr = GUINT32_FROM_BE(h->config_names[i]);
|
|
uint32_t data_ptr = GUINT32_FROM_BE(h->config_data[i]);
|
|
@@ -822,16 +817,20 @@ static int vma_reader_restore_full(VmaReader *vmar, int vmstate_fd,
|
|
}
|
|
|
|
if (verbose) {
|
|
- printf("total bytes read %zd, sparse bytes %zd (%.3g%%)\n",
|
|
- vmar->clusters_read*VMA_CLUSTER_SIZE,
|
|
- vmar->zero_cluster_data,
|
|
- (double)(100.0*vmar->zero_cluster_data)/
|
|
- (vmar->clusters_read*VMA_CLUSTER_SIZE));
|
|
-
|
|
- int64_t datasize = vmar->clusters_read*VMA_CLUSTER_SIZE-vmar->zero_cluster_data;
|
|
- if (datasize) { // this does not make sense for empty files
|
|
- printf("space reduction due to 4K zero blocks %.3g%%\n",
|
|
- (double)(100.0*vmar->partial_zero_cluster_data) / datasize);
|
|
+ if (vmar->clusters_read) {
|
|
+ printf("total bytes read %zd, sparse bytes %zd (%.3g%%)\n",
|
|
+ vmar->clusters_read*VMA_CLUSTER_SIZE,
|
|
+ vmar->zero_cluster_data,
|
|
+ (double)(100.0*vmar->zero_cluster_data)/
|
|
+ (vmar->clusters_read*VMA_CLUSTER_SIZE));
|
|
+
|
|
+ int64_t datasize = vmar->clusters_read*VMA_CLUSTER_SIZE-vmar->zero_cluster_data;
|
|
+ if (datasize) { // this does not make sense for empty files
|
|
+ printf("space reduction due to 4K zero blocks %.3g%%\n",
|
|
+ (double)(100.0*vmar->partial_zero_cluster_data) / datasize);
|
|
+ }
|
|
+ } else {
|
|
+ printf("vma archive contains no image data\n");
|
|
}
|
|
}
|
|
return ret;
|
|
diff --git a/vma-writer.c b/vma-writer.c
|
|
index 216577a4f7..0dd668b257 100644
|
|
--- a/vma-writer.c
|
|
+++ b/vma-writer.c
|
|
@@ -252,7 +252,7 @@ vma_queue_write(VmaWriter *vmaw, const void *buf, size_t bytes)
|
|
}
|
|
|
|
vmaw->co_writer = NULL;
|
|
-
|
|
+
|
|
return (done == bytes) ? bytes : -1;
|
|
}
|
|
|
|
@@ -376,10 +376,6 @@ static int coroutine_fn vma_write_header(VmaWriter *vmaw)
|
|
time_t ctime = time(NULL);
|
|
head->ctime = GUINT64_TO_BE(ctime);
|
|
|
|
- if (!vmaw->stream_count) {
|
|
- return -1;
|
|
- }
|
|
-
|
|
for (i = 0; i < VMA_MAX_CONFIGS; i++) {
|
|
head->config_names[i] = GUINT32_TO_BE(vmaw->config_names[i]);
|
|
head->config_data[i] = GUINT32_TO_BE(vmaw->config_data[i]);
|
|
@@ -496,6 +492,23 @@ static int vma_count_open_streams(VmaWriter *vmaw)
|
|
return open_drives;
|
|
}
|
|
|
|
+
|
|
+/**
|
|
+ * You need to call this if the vma archive does not contain
|
|
+ * any data stream.
|
|
+ */
|
|
+int coroutine_fn
|
|
+vma_writer_flush_output(VmaWriter *vmaw)
|
|
+{
|
|
+ qemu_co_mutex_lock(&vmaw->flush_lock);
|
|
+ int ret = vma_writer_flush(vmaw);
|
|
+ qemu_co_mutex_unlock(&vmaw->flush_lock);
|
|
+ if (ret < 0) {
|
|
+ vma_writer_set_error(vmaw, "vma_writer_flush_header failed");
|
|
+ }
|
|
+ return ret;
|
|
+}
|
|
+
|
|
/**
|
|
* all jobs should call this when there is no more data
|
|
* Returns: number of remaining stream (0 ==> finished)
|
|
@@ -523,12 +536,7 @@ vma_writer_close_stream(VmaWriter *vmaw, uint8_t dev_id)
|
|
|
|
if (open_drives <= 0) {
|
|
DPRINTF("vma_writer_set_status all drives completed\n");
|
|
- qemu_co_mutex_lock(&vmaw->flush_lock);
|
|
- int ret = vma_writer_flush(vmaw);
|
|
- qemu_co_mutex_unlock(&vmaw->flush_lock);
|
|
- if (ret < 0) {
|
|
- vma_writer_set_error(vmaw, "vma_writer_close_stream: flush failed");
|
|
- }
|
|
+ vma_writer_flush_output(vmaw);
|
|
}
|
|
|
|
return open_drives;
|
|
diff --git a/vma.c b/vma.c
|
|
index 1ffaced897..c7c05385f6 100644
|
|
--- a/vma.c
|
|
+++ b/vma.c
|
|
@@ -28,7 +28,7 @@ static void help(void)
|
|
"\n"
|
|
"vma list <filename>\n"
|
|
"vma config <filename> [-c config]\n"
|
|
- "vma create <filename> [-c config] <archive> pathname ...\n"
|
|
+ "vma create <filename> [-c config] pathname ...\n"
|
|
"vma extract <filename> [-r <fifo>] <targetdir>\n"
|
|
"vma verify <filename> [-v]\n"
|
|
;
|
|
@@ -396,6 +396,18 @@ typedef struct BackupJob {
|
|
|
|
#define BACKUP_SECTORS_PER_CLUSTER (VMA_CLUSTER_SIZE / BDRV_SECTOR_SIZE)
|
|
|
|
+static void coroutine_fn backup_run_empty(void *opaque)
|
|
+{
|
|
+ VmaWriter *vmaw = (VmaWriter *)opaque;
|
|
+
|
|
+ vma_writer_flush_output(vmaw);
|
|
+
|
|
+ Error *err = NULL;
|
|
+ if (vma_writer_close(vmaw, &err) != 0) {
|
|
+ g_warning("vma_writer_close failed %s", error_get_pretty(err));
|
|
+ }
|
|
+}
|
|
+
|
|
static void coroutine_fn backup_run(void *opaque)
|
|
{
|
|
BackupJob *job = (BackupJob *)opaque;
|
|
@@ -469,8 +481,8 @@ static int create_archive(int argc, char **argv)
|
|
}
|
|
|
|
|
|
- /* make sure we have archive name and at least one path */
|
|
- if ((optind + 2) > argc) {
|
|
+ /* make sure we an archive name */
|
|
+ if ((optind + 1) > argc) {
|
|
help();
|
|
}
|
|
|
|
@@ -505,11 +517,11 @@ static int create_archive(int argc, char **argv)
|
|
l = g_list_next(l);
|
|
}
|
|
|
|
- int ind = 0;
|
|
+ int devcount = 0;
|
|
while (optind < argc) {
|
|
const char *path = argv[optind++];
|
|
char *devname = NULL;
|
|
- path = extract_devname(path, &devname, ind++);
|
|
+ path = extract_devname(path, &devname, devcount++);
|
|
|
|
Error *errp = NULL;
|
|
BlockDriverState *bs;
|
|
@@ -540,37 +552,39 @@ static int create_archive(int argc, char **argv)
|
|
int percent = 0;
|
|
int last_percent = -1;
|
|
|
|
- while (1) {
|
|
- main_loop_wait(false);
|
|
- vma_writer_get_status(vmaw, &vmastat);
|
|
+ if (devcount) {
|
|
+ while (1) {
|
|
+ main_loop_wait(false);
|
|
+ vma_writer_get_status(vmaw, &vmastat);
|
|
+
|
|
+ if (verbose) {
|
|
|
|
- if (verbose) {
|
|
+ uint64_t total = 0;
|
|
+ uint64_t transferred = 0;
|
|
+ uint64_t zero_bytes = 0;
|
|
|
|
- uint64_t total = 0;
|
|
- uint64_t transferred = 0;
|
|
- uint64_t zero_bytes = 0;
|
|
+ int i;
|
|
+ for (i = 0; i < 256; i++) {
|
|
+ if (vmastat.stream_info[i].size) {
|
|
+ total += vmastat.stream_info[i].size;
|
|
+ transferred += vmastat.stream_info[i].transferred;
|
|
+ zero_bytes += vmastat.stream_info[i].zero_bytes;
|
|
+ }
|
|
+ }
|
|
+ percent = (transferred*100)/total;
|
|
+ if (percent != last_percent) {
|
|
+ fprintf(stderr, "progress %d%% %zd/%zd %zd\n", percent,
|
|
+ transferred, total, zero_bytes);
|
|
+ fflush(stderr);
|
|
|
|
- int i;
|
|
- for (i = 0; i < 256; i++) {
|
|
- if (vmastat.stream_info[i].size) {
|
|
- total += vmastat.stream_info[i].size;
|
|
- transferred += vmastat.stream_info[i].transferred;
|
|
- zero_bytes += vmastat.stream_info[i].zero_bytes;
|
|
+ last_percent = percent;
|
|
}
|
|
}
|
|
- percent = (transferred*100)/total;
|
|
- if (percent != last_percent) {
|
|
- fprintf(stderr, "progress %d%% %zd/%zd %zd\n", percent,
|
|
- transferred, total, zero_bytes);
|
|
- fflush(stderr);
|
|
|
|
- last_percent = percent;
|
|
+ if (vmastat.closed) {
|
|
+ break;
|
|
}
|
|
}
|
|
-
|
|
- if (vmastat.closed) {
|
|
- break;
|
|
- }
|
|
} else {
|
|
Coroutine *co = qemu_coroutine_create(backup_run_empty, vmaw);
|
|
qemu_coroutine_enter(co);
|
|
diff --git a/vma.h b/vma.h
|
|
index 98377e473e..365ceb2bcb 100644
|
|
--- a/vma.h
|
|
+++ b/vma.h
|
|
@@ -128,6 +128,7 @@ int64_t coroutine_fn vma_writer_write(VmaWriter *vmaw, uint8_t dev_id,
|
|
size_t *zero_bytes);
|
|
|
|
int coroutine_fn vma_writer_close_stream(VmaWriter *vmaw, uint8_t dev_id);
|
|
+int coroutine_fn vma_writer_flush_output(VmaWriter *vmaw);
|
|
|
|
int vma_writer_get_status(VmaWriter *vmaw, VmaStatus *status);
|
|
void vma_writer_set_error(VmaWriter *vmaw, const char *fmt, ...);
|
|
--
|
|
2.11.0
|
|
|