pve-qemu/debian/patches/pve/0012-vma-add-verify-command...

322 lines
10 KiB
Diff

From 144e613eeca6a3383b981f9ca8b82c4a354b36c2 Mon Sep 17 00:00:00 2001
From: Dietmar Maurer <dietmar@proxmox.com>
Date: Mon, 11 Mar 2013 07:07:46 +0100
Subject: [PATCH 12/47] vma: add verify command
Users wants to verify the archive after backup.
Examples:
# vma verify -v test.vma
# lzop -d -c test.vma.lzo |vma verify -
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
---
vma-reader.c | 121 ++++++++++++++++++++++++++++++++++++++++++++---------------
vma.c | 55 +++++++++++++++++++++++++++
vma.h | 1 +
3 files changed, 147 insertions(+), 30 deletions(-)
diff --git a/vma-reader.c b/vma-reader.c
index 51dd8fe..2aafb26 100644
--- a/vma-reader.c
+++ b/vma-reader.c
@@ -45,6 +45,8 @@ struct VmaReader {
time_t start_time;
int64_t cluster_count;
int64_t clusters_read;
+ int64_t zero_cluster_data;
+ int64_t partial_zero_cluster_data;
int clusters_read_per;
};
@@ -425,6 +427,27 @@ VmaDeviceInfo *vma_reader_get_device_info(VmaReader *vmar, guint8 dev_id)
return NULL;
}
+static void allocate_rstate(VmaReader *vmar, guint8 dev_id,
+ BlockDriverState *bs, bool write_zeroes)
+{
+ assert(vmar);
+ assert(dev_id);
+
+ vmar->rstate[dev_id].bs = bs;
+ vmar->rstate[dev_id].write_zeroes = write_zeroes;
+
+ int64_t size = vmar->devinfo[dev_id].size;
+
+ int64_t bitmap_size = (size/BDRV_SECTOR_SIZE) +
+ (VMA_CLUSTER_SIZE/BDRV_SECTOR_SIZE) * BITS_PER_LONG - 1;
+ bitmap_size /= (VMA_CLUSTER_SIZE/BDRV_SECTOR_SIZE) * BITS_PER_LONG;
+
+ vmar->rstate[dev_id].bitmap_size = bitmap_size;
+ vmar->rstate[dev_id].bitmap = g_new0(unsigned long, bitmap_size);
+
+ vmar->cluster_count += size/VMA_CLUSTER_SIZE;
+}
+
int vma_reader_register_bs(VmaReader *vmar, guint8 dev_id, BlockDriverState *bs,
bool write_zeroes, Error **errp)
{
@@ -447,17 +470,7 @@ int vma_reader_register_bs(VmaReader *vmar, guint8 dev_id, BlockDriverState *bs,
return -1;
}
- vmar->rstate[dev_id].bs = bs;
- vmar->rstate[dev_id].write_zeroes = write_zeroes;
-
- int64_t bitmap_size = (size/BDRV_SECTOR_SIZE) +
- (VMA_CLUSTER_SIZE/BDRV_SECTOR_SIZE) * BITS_PER_LONG - 1;
- bitmap_size /= (VMA_CLUSTER_SIZE/BDRV_SECTOR_SIZE) * BITS_PER_LONG;
-
- vmar->rstate[dev_id].bitmap_size = bitmap_size;
- vmar->rstate[dev_id].bitmap = g_new0(unsigned long, bitmap_size);
-
- vmar->cluster_count += size/VMA_CLUSTER_SIZE;
+ allocate_rstate(vmar, dev_id, bs, write_zeroes);
return 0;
}
@@ -524,9 +537,10 @@ static int restore_write_data(VmaReader *vmar, guint8 dev_id,
}
return 0;
}
+
static int restore_extent(VmaReader *vmar, unsigned char *buf,
int extent_size, int vmstate_fd,
- bool verbose, Error **errp)
+ bool verbose, bool verify, Error **errp)
{
assert(vmar);
assert(buf);
@@ -551,7 +565,7 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf,
if (dev_id != vmar->vmstate_stream) {
bs = rstate->bs;
- if (!bs) {
+ if (!verify && !bs) {
error_setg(errp, "got wrong dev id %d", dev_id);
return -1;
}
@@ -607,10 +621,13 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf,
return -1;
}
- int nb_sectors = end_sector - sector_num;
- if (restore_write_data(vmar, dev_id, bs, vmstate_fd, buf + start,
- sector_num, nb_sectors, errp) < 0) {
- return -1;
+ if (!verify) {
+ int nb_sectors = end_sector - sector_num;
+ if (restore_write_data(vmar, dev_id, bs, vmstate_fd,
+ buf + start, sector_num, nb_sectors,
+ errp) < 0) {
+ return -1;
+ }
}
start += VMA_CLUSTER_SIZE;
@@ -640,26 +657,37 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf,
return -1;
}
- int nb_sectors = end_sector - sector_num;
- if (restore_write_data(vmar, dev_id, bs, vmstate_fd,
- buf + start, sector_num,
- nb_sectors, errp) < 0) {
- return -1;
+ if (!verify) {
+ int nb_sectors = end_sector - sector_num;
+ if (restore_write_data(vmar, dev_id, bs, vmstate_fd,
+ buf + start, sector_num,
+ nb_sectors, errp) < 0) {
+ return -1;
+ }
}
start += VMA_BLOCK_SIZE;
} else {
- if (rstate->write_zeroes && (end_sector > sector_num)) {
+
+ if (end_sector > sector_num) {
/* Todo: use bdrv_co_write_zeroes (but that need to
* be run inside coroutine?)
*/
int nb_sectors = end_sector - sector_num;
- if (restore_write_data(vmar, dev_id, bs, vmstate_fd,
- zero_vma_block, sector_num,
- nb_sectors, errp) < 0) {
- return -1;
+ int zero_size = BDRV_SECTOR_SIZE*nb_sectors;
+ vmar->zero_cluster_data += zero_size;
+ if (mask != 0) {
+ vmar->partial_zero_cluster_data += zero_size;
+ }
+
+ if (rstate->write_zeroes && !verify) {
+ if (restore_write_data(vmar, dev_id, bs, vmstate_fd,
+ zero_vma_block, sector_num,
+ nb_sectors, errp) < 0) {
+ return -1;
+ }
}
}
}
@@ -677,8 +705,9 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf,
return 0;
}
-int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose,
- Error **errp)
+static int vma_reader_restore_full(VmaReader *vmar, int vmstate_fd,
+ bool verbose, bool verify,
+ Error **errp)
{
assert(vmar);
assert(vmar->head_data);
@@ -745,7 +774,7 @@ int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose,
}
if (restore_extent(vmar, buf, extent_size, vmstate_fd, verbose,
- errp) < 0) {
+ verify, errp) < 0) {
return -1;
}
@@ -792,6 +821,38 @@ int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose,
}
}
+ 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);
+ }
+ }
return ret;
}
+int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose,
+ Error **errp)
+{
+ return vma_reader_restore_full(vmar, vmstate_fd, verbose, false, errp);
+}
+
+int vma_reader_verify(VmaReader *vmar, bool verbose, Error **errp)
+{
+ guint8 dev_id;
+
+ for (dev_id = 1; dev_id < 255; dev_id++) {
+ if (vma_reader_get_device_info(vmar, dev_id)) {
+ allocate_rstate(vmar, dev_id, NULL, false);
+ }
+ }
+
+ return vma_reader_restore_full(vmar, -1, verbose, true, errp);
+}
+
diff --git a/vma.c b/vma.c
index 8014090..d55874a 100644
--- a/vma.c
+++ b/vma.c
@@ -28,6 +28,7 @@ static void help(void)
"vma list <filename>\n"
"vma create <filename> [-c config] <archive> pathname ...\n"
"vma extract <filename> [-r <fifo>] <targetdir>\n"
+ "vma verify <filename> [-v]\n"
;
printf("%s", help_msg);
@@ -332,6 +333,58 @@ static int extract_content(int argc, char **argv)
return ret;
}
+static int verify_content(int argc, char **argv)
+{
+ int c, ret = 0;
+ int verbose = 0;
+ const char *filename;
+
+ for (;;) {
+ c = getopt(argc, argv, "hv");
+ if (c == -1) {
+ break;
+ }
+ switch (c) {
+ case '?':
+ case 'h':
+ help();
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ help();
+ }
+ }
+
+ /* Get the filename */
+ if ((optind + 1) != argc) {
+ help();
+ }
+ filename = argv[optind++];
+
+ Error *errp = NULL;
+ VmaReader *vmar = vma_reader_create(filename, &errp);
+
+ if (!vmar) {
+ g_error("%s", error_get_pretty(errp));
+ }
+
+ if (verbose) {
+ print_content(vmar);
+ }
+
+ if (vma_reader_verify(vmar, verbose, &errp) < 0) {
+ g_error("verify failed - %s", error_get_pretty(errp));
+ }
+
+ vma_reader_destroy(vmar);
+
+ bdrv_close_all();
+
+ return ret;
+}
+
typedef struct BackupJob {
BlockDriverState *bs;
int64_t len;
@@ -578,6 +631,8 @@ int main(int argc, char **argv)
return create_archive(argc, argv);
} else if (!strcmp(cmdname, "extract")) {
return extract_content(argc, argv);
+ } else if (!strcmp(cmdname, "verify")) {
+ return verify_content(argc, argv);
}
help();
diff --git a/vma.h b/vma.h
index 6625eb9..9bb6ea4 100644
--- a/vma.h
+++ b/vma.h
@@ -142,5 +142,6 @@ int vma_reader_register_bs(VmaReader *vmar, guint8 dev_id,
Error **errp);
int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose,
Error **errp);
+int vma_reader_verify(VmaReader *vmar, bool verbose, Error **errp);
#endif /* BACKUP_VMA_H */
--
2.1.4