From 144e613eeca6a3383b981f9ca8b82c4a354b36c2 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer 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 --- 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 \n" "vma create [-c config] pathname ...\n" "vma extract [-r ] \n" + "vma verify [-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