322 lines
10 KiB
Diff
322 lines
10 KiB
Diff
From d4c9597f3064b68853cefca90dd335cd5e5320d0 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/49] 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 51dd8fee0e..2aafb26b2a 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 8732bfa85e..ab7b766014 100644
|
|
--- a/vma.c
|
|
+++ b/vma.c
|
|
@@ -29,6 +29,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);
|
|
@@ -333,6 +334,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;
|
|
@@ -579,6 +632,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 6625eb95c6..9bb6ea4f69 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.11.0
|
|
|