Re: [Qemu-devel] [PATCH v10 3/4] This patch adds new qemu-img subcommand that compares content of two disk images.

2013-02-12 Thread Kevin Wolf
Am 12.02.2013 08:00, schrieb Miroslav Rezanina:
 Signed-off-by: Miroslav Rezanina mreza...@redhat.com

What happened to the commit message here? Previous versions had
qemu-img: Add compare subcommand as their subject and what is now the
subject was the body. Made much more sense.

Stefan, if you apply the series, can you fix this up?

Kevin



Re: [Qemu-devel] [PATCH v10 3/4] This patch adds new qemu-img subcommand that compares content of two disk images.

2013-02-12 Thread Miroslav Rezanina
- Original Message -
 From: Kevin Wolf kw...@redhat.com
 To: Miroslav Rezanina mreza...@redhat.com
 Cc: qemu-devel@nongnu.org, pbonz...@redhat.com, stefa...@redhat.com, 
 ebl...@redhat.com
 Sent: Tuesday, February 12, 2013 10:36:07 AM
 Subject: Re: [PATCH v10 3/4] This patch adds new qemu-img subcommand that 
 compares content of two disk images.
 
 Am 12.02.2013 08:00, schrieb Miroslav Rezanina:
  Signed-off-by: Miroslav Rezanina mreza...@redhat.com
 
 What happened to the commit message here? Previous versions had
 qemu-img: Add compare subcommand as their subject and what is now
 the
 subject was the body. Made much more sense.
 
 Stefan, if you apply the series, can you fix this up?
 
 Kevin
 

Ups...I had to accidentally delete the line when handling the cherry-pick (from 
v9 to v10). Subject and commit message from v9 are valid and should be used. 
Sorry for the mistake.


-- 
Miroslav Rezanina
Software Engineer - Virtualization Team




[Qemu-devel] [PATCH v10 3/4] This patch adds new qemu-img subcommand that compares content of two disk images.

2013-02-11 Thread Miroslav Rezanina
Signed-off-by: Miroslav Rezanina mreza...@redhat.com
---
 qemu-img-cmds.hx |6 +
 qemu-img.c   |  290 +-
 qemu-img.texi|   53 ++
 3 files changed, 348 insertions(+), 1 deletions(-)

diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index 9283776..4ca7e95 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -27,6 +27,12 @@ STEXI
 @item commit [-q] [-f @var{fmt}] [-t @var{cache}] @var{filename}
 ETEXI
 
+DEF(compare, img_compare,
+compare [-f fmt] [-F fmt] [-p] [-q] [-s] filename1 filename2)
+STEXI
+@item compare [-f @var{fmt}] [-F @var{fmt}] [-p] [-q] [-s] @var{filename1} 
@var{filename2}
+ETEXI
+
 DEF(convert, img_convert,
 convert [-c] [-p] [-q] [-f fmt] [-t cache] [-O output_fmt] [-o options] 
[-s snapshot_name] [-S sparse_size] filename [filename2 [...]] output_filename)
 STEXI
diff --git a/qemu-img.c b/qemu-img.c
index a2a2044..5f0c0c1 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -113,7 +113,12 @@ static void help(void)
  '-a' applies a snapshot (revert disk to saved state)\n
  '-c' creates a snapshot\n
  '-d' deletes a snapshot\n
- '-l' lists all snapshots in the given image\n;
+ '-l' lists all snapshots in the given image\n
+   \n
+   Parameters to compare subcommand:\n
+ '-f' first image format\n
+ '-F' second image format\n
+ '-s' run in Strict mode - fail on different image size or sector 
allocation\n;
 
 printf(%s\nSupported formats:, help_msg);
 bdrv_iterate_format(format_print, NULL);
@@ -817,6 +822,289 @@ static int compare_sectors(const uint8_t *buf1, const 
uint8_t *buf2, int n,
 
 #define IO_BUF_SIZE (2 * 1024 * 1024)
 
+static int64_t sectors_to_bytes(int64_t sectors)
+{
+return sectors  BDRV_SECTOR_BITS;
+}
+
+static int64_t sectors_to_process(int64_t total, int64_t from)
+{
+return MIN(total - from, IO_BUF_SIZE  BDRV_SECTOR_BITS);
+}
+
+/*
+ * Check if passed sectors are empty (not allocated or contain only 0 bytes)
+ *
+ * Returns 0 in case sectors are filled with 0, 1 if sectors contain non-zero
+ * data and negative value on error.
+ *
+ * @param bs:  Driver used for accessing file
+ * @param sect_num: Number of first sector to check
+ * @param sect_count: Number of sectors to check
+ * @param filename: Name of disk file we are checking (logging purpose)
+ * @param buffer: Allocated buffer for storing read data
+ * @param quiet: Flag for quiet mode
+ */
+static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num,
+   int sect_count, const char *filename,
+   uint8_t *buffer, bool quiet)
+{
+int pnum, ret = 0;
+ret = bdrv_read(bs, sect_num, buffer, sect_count);
+if (ret  0) {
+error_report(Error while reading offset % PRId64  of %s: %s,
+ sectors_to_bytes(sect_num), filename, strerror(-ret));
+return ret;
+}
+ret = is_allocated_sectors(buffer, sect_count, pnum);
+if (ret || pnum != sect_count) {
+qprintf(quiet, Content mismatch at offset % PRId64 !\n,
+sectors_to_bytes(ret ? sect_num : sect_num + pnum));
+return 1;
+}
+
+return 0;
+}
+
+/*
+ * Compares two images. Exit codes:
+ *
+ * 0 - Images are identical
+ * 1 - Images differ
+ * 1 - Error occurred
+ */
+static int img_compare(int argc, char **argv)
+{
+const char *fmt1 = NULL, *fmt2 = NULL, *filename1, *filename2;
+BlockDriverState *bs1, *bs2;
+int64_t total_sectors1, total_sectors2;
+uint8_t *buf1 = NULL, *buf2 = NULL;
+int pnum1, pnum2;
+int allocated1, allocated2;
+int ret = 0; /* return value - 0 Ident, 1 Different, 1 Error */
+bool progress = false, quiet = false, strict = false;
+int64_t total_sectors;
+int64_t sector_num = 0;
+int64_t nb_sectors;
+int c, pnum;
+uint64_t bs_sectors;
+uint64_t progress_base;
+
+for (;;) {
+c = getopt(argc, argv, hpf:F:sq);
+if (c == -1) {
+break;
+}
+switch (c) {
+case '?':
+case 'h':
+help();
+break;
+case 'f':
+fmt1 = optarg;
+break;
+case 'F':
+fmt2 = optarg;
+break;
+case 'p':
+progress = true;
+break;
+case 'q':
+quiet = true;
+break;
+case 's':
+strict = true;
+break;
+}
+}
+
+/* Progress is not shown in Quiet mode */
+if (quiet) {
+progress = false;
+}
+
+
+if (optind  argc - 2) {
+help();
+}
+filename1 = argv[optind++];
+filename2 = argv[optind++];
+
+/* Initialize before goto out */
+qemu_progress_init(progress, 2.0);
+
+bs1 = bdrv_new_open(filename1, fmt1, BDRV_O_FLAGS, true, quiet);
+if (!bs1) {
+error_report(Can't open file %s,