From: Dietmar Maurer Date: Mon, 11 Mar 2013 10:12:09 +0000 (+0100) Subject: add vma verify command X-Git-Url: https://git.proxmox.com/?p=pve-qemu-kvm.git;a=commitdiff_plain;h=0340a1bbe116855f1865633a38b47844043d8fd5 add vma verify command --- diff --git a/Makefile b/Makefile index 4f15e79..d34589d 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ RELEASE=2.3 # also update debian/changelog KVMVER=1.4 -KVMPKGREL=7 +KVMPKGREL=8 KVMPACKAGE=pve-qemu-kvm KVMDIR=qemu-kvm diff --git a/debian/changelog b/debian/changelog index eeaa8e9..dda159c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +pve-qemu-kvm (1.4-8) unstable; urgency=low + + * vma: add 'vma verify' command to verify vma archives + + -- Proxmox Support Team Mon, 11 Mar 2013 11:10:34 +0100 + pve-qemu-kvm (1.4-7) unstable; urgency=low * update seabios to 1.7.2.1 (fix freebsd boot) diff --git a/debian/patches/0007-vma-add-verify-command.patch b/debian/patches/0007-vma-add-verify-command.patch new file mode 100644 index 0000000..2feba4f --- /dev/null +++ b/debian/patches/0007-vma-add-verify-command.patch @@ -0,0 +1,320 @@ +From acdcd483ac6977e096ef7cde746d22bbf82e04d3 Mon Sep 17 00:00:00 2001 +From: Dietmar Maurer +Date: Mon, 11 Mar 2013 07:07:46 +0100 +Subject: [PATCH v5 7/7] 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 +--- + vma-reader.c | 118 +++++++++++++++++++++++++++++++++++++++++++--------------- + vma.c | 57 +++++++++++++++++++++++++++- + vma.h | 1 + + 3 files changed, 145 insertions(+), 31 deletions(-) + +diff --git a/vma-reader.c b/vma-reader.c +index bc36cba..a740f04 100644 +--- a/vma-reader.c ++++ b/vma-reader.c +@@ -53,6 +53,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; + }; + +@@ -433,6 +435,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) + { +@@ -449,17 +472,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; + } +@@ -526,9 +539,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); +@@ -553,7 +567,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; + } +@@ -609,10 +623,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; +@@ -642,26 +659,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; ++ } + } + } + } +@@ -679,8 +707,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); +@@ -747,7 +776,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; + } + +@@ -794,6 +823,35 @@ 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)); ++ printf("space reduction due to 4K zero bocks %.3g%%\n", ++ (double)(100.0*vmar->partial_zero_cluster_data) / ++ (vmar->clusters_read*VMA_CLUSTER_SIZE-vmar->zero_cluster_data)); ++ } + 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 6633aa5..bcde379 100644 +--- a/vma.c ++++ b/vma.c +@@ -33,7 +33,8 @@ static void help(void) + "\n" + "vma list \n" + "vma create [-c config] pathname ...\n" +- "vma extract [-r] \n" ++ "vma extract [-v] [-r] \n" ++ "vma verify [-v]\n" + ; + + printf("%s", help_msg); +@@ -337,6 +338,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 BackupCB { + VmaWriter *vmaw; + uint8_t dev_id; +@@ -554,6 +607,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 76d0dc8..ebd96c1 100644 +--- a/vma.h ++++ b/vma.h +@@ -141,5 +141,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 */ +-- +1.7.2.5 + diff --git a/debian/patches/series b/debian/patches/series index 50721ad..01a5aff 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -16,6 +16,7 @@ enable-kvm-by-default.patch 0004-introduce-new-vma-archive-format.patch 0005-add-regression-tests-for-backup.patch 0006-add-vm-state-to-backups.patch +0007-vma-add-verify-command.patch # always-update-expected-downtime.patch virtio-balloon-fix-query.patch set-cpu-model-to-kvm64.patch