qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [Patch 3/4] [RFC] Zero Cluster Dedup, Offline dedup, qemu-


From: Shahar Frank
Subject: [Qemu-devel] [Patch 3/4] [RFC] Zero Cluster Dedup, Offline dedup, qemu-img extentions
Date: Mon, 6 Oct 2008 10:31:39 -0700

MDSUM Extension for the map verb

Signed-off-by: Shahar Frank <address@hidden>

diff --git a/Makefile b/Makefile
index 35061a4..21e43d5 100644
--- a/Makefile
+++ b/Makefile
@@ -187,7 +187,7 @@ libqemu_user.a: $(USER_OBJS)
 ######################################################################
 
 qemu-img$(EXESUF): qemu-img.o qemu-tool.o osdep.o $(BLOCK_OBJS)
-       $(CC) $(LDFLAGS) -o $@ $^ -lz $(LIBS)
+       $(CC) $(LDFLAGS) -o $@ $^ -lz $(LIBS) $(MD5SUMLIBS) 
 
 %.o: %.c
        $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
diff --git a/configure b/configure
index a224e6a..6420066 100755
--- a/configure
+++ b/configure
@@ -114,6 +114,7 @@ mixemu="no"
 bluez="yes"
 signalfd="no"
 eventfd="no"
+md5sum="yes"
 
 # OS specific
 targetos=`uname -s`
@@ -346,6 +347,8 @@ for opt do
   ;;
   --disable-aio) aio="no"
   ;;
+  --disable-md5sum) md5sum="no"
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
@@ -448,6 +451,7 @@ echo "  --enable-uname-release=R Return R for uname
-r in usermode emulation"
 echo "  --sparc_cpu=V            Build qemu for Sparc architecture v7,
v8, v8plus, v8plusa, v9"
 echo "  --disable-vde            disable support for vde network"
 echo "  --disable-aio            disable AIO support"
+echo "  --disable-md5sum         disable MD5SUM support"
 echo ""
 echo "NOTE: The object files are built at the place where configure is
launched"
 exit 1
@@ -489,6 +493,7 @@ if test "$mingw32" = "yes" ; then
     linux_user="no"
 fi
 
+MD5SUMLIBS=
 if [ "$darwin" = "yes" -o "$mingw32" = "yes" ] ; then
     AIOLIBS=
 elif [ "$bsd" = "yes" ]; then
@@ -496,6 +501,7 @@ elif [ "$bsd" = "yes" ]; then
 else
     # Some Linux architectures (e.g. s390) don't imply -lpthread
automatically.
     AIOLIBS="-lrt -lpthread"
+    MD5SUMLIBS="-lssl"
 fi
 
 # Check for gcc4, error if pre-gcc4
@@ -920,6 +926,20 @@ EOF
 fi
 
 ##########################################
+# md5sum probe
+if test "$md5sum" = "yes" ; then
+  md5sum=no
+  cat > $TMPC << EOF
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+int main(void) { return (int)BIO_new(BIO_s_mem()); }
+EOF
+  if $cc $ARCH_CFLAGS -o $TMPE $MD5SUMLIBS $TMPC 2> /dev/null ; then
+    md5sum=yes
+  fi
+fi
+
+##########################################
 # signalfd probe
 cat > $TMPC << EOF
 #define _GNU_SOURCE
@@ -1018,6 +1038,7 @@ echo "uname -r          $uname_release"
 echo "NPTL support      $nptl"
 echo "vde support       $vde"
 echo "AIO support       $aio"
+echo "md5sum support    $md5sum"
 
 if test $sdl_too_old = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL
support"
@@ -1064,6 +1085,7 @@ echo "CFLAGS=$CFLAGS" >> $config_mak
 echo "LDFLAGS=$LDFLAGS" >> $config_mak
 echo "EXESUF=$EXESUF" >> $config_mak
 echo "AIOLIBS=$AIOLIBS" >> $config_mak
+echo "MD5SUMLIBS=$MD5SUMLIBS" >> $config_mak
 case "$cpu" in
   i386)
     echo "ARCH=i386" >> $config_mak
@@ -1280,6 +1302,10 @@ if test "$aio" = "yes" ; then
   echo "#define CONFIG_AIO 1" >> $config_h
   echo "CONFIG_AIO=yes" >> $config_mak
 fi
+if test "$md5sum" = "yes" ; then
+  echo "#define CONFIG_MD5SUM 1" >> $config_h
+  echo "CONFIG_MD5SUM=yes" >> $config_mak
+fi
 if test "$signalfd" = "yes" ; then
   echo "#define CONFIG_signalfd 1" >> $config_h
 fi
diff --git a/qemu-img.c b/qemu-img.c
index c6fe43d..8cda447 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -77,6 +77,7 @@ static void help(void)
            "  '-e' indicates that the target image must be encrypted
(qcow format only)\n"
            "  '-6' indicates that the target image must use
compatibility level 6 (vmdk format only)\n"
            "  '-r' indicated that the base images are recursed in (for
info and map)\n"
+           "  '-s' indicated that the md5sum of the clusters is to be
printed (for map)\n"
           );
     printf("\nSupported format:");
     bdrv_iterate_format(format_print, NULL);
@@ -172,6 +173,79 @@ static int read_password(char *buf, int buf_size)
 }
 #endif
 
+
+#ifdef CONFIG_MD5SUM
+/* md5sum functiuons */
+
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+
+#define MD5HASHSZ              16
+
+/* openssl buffering */
+BIO *bio;
+BIO *bio_md;
+
+static inline int update_hash_block(void *block, int len)
+{
+    return BIO_write(bio, block, len);
+}
+
+static inline int reset_hashing(void)
+{
+    return BIO_reset(bio);
+}
+
+static inline int get_hash(char *buf, int len)
+{
+    return BIO_gets(bio_md, buf, len);
+}
+
+static int compute_block_hash(void *buf, int bufsz, void *mdbuf, int
mdlen)
+{
+    int hashlen;
+    
+    reset_hashing();
+    update_hash_block(buf, bufsz);
+    if ((hashlen = get_hash(mdbuf, mdlen)) < 0)
+        return -1;
+    return hashlen;
+}
+
+static int sprint_hash(char *buf, int bufsz, uint8_t * hash, int
hashsz)
+{
+    int i;
+    
+    if (bufsz < hashsz * 2)
+        hashsz = bufsz / 2;
+    for (i = 0; i < hashsz; i++)
+        sprintf(buf + i * 2, "%02x", hash[i]);
+    if (i * 2 < bufsz)
+        buf[i * 2 + 1] = 0;
+    return i*2;
+}
+
+static int initialize_hashing(void)
+{
+    bio = BIO_new(BIO_s_mem());
+    if (!bio)
+        error("can't allocate bio struct");
+    bio_md = BIO_new(BIO_f_md());
+    if (!bio_md)
+        error("can't allocate bio_md struct");
+    if (BIO_set_md(bio_md, EVP_md5()) != 1)
+        error("can't set bio md");
+    bio = BIO_push(bio_md, bio);
+    if (!bio)
+        error("can't push hashing md to hashing bio");
+    reset_hashing();
+    return 0;
+}
+
+#else
+static int initialize_hashing(void) {};
+#endif
+
 static BlockDriverState *bdrv_new_open(const char *filename,
                                        const char *fmt)
 {
@@ -348,6 +422,33 @@ static int img_commit(int argc, char **argv)
 
 #define IO_BUF_SIZE 65536
 
+#ifdef CONFIG_MD5SUM
+static void
+sectors_sum_str(BlockDriverState *bs, uint64_t offset, int sectors,
char *str, int len)
+{
+    char buf[IO_BUF_SIZE];
+    char mdbuf[MD5HASHSZ];
+    
+    if (sectors <= 0 || sectors > (IO_BUF_SIZE >> 9))
+        error("sectors_sum_str: bad sectors param %d", sectors);
+    if (bdrv_read(bs, offset >> 9, buf, sectors) < 0)
+        error("sectors_sum_str: error while reading offset 0x%"PRIx64,
offset);
+    
+    if (compute_block_hash(buf, sectors << 9, mdbuf, sizeof mdbuf) < 0)
+        error("sectors_sum_str: can't compute hash");
+    
+    sprint_hash(str, len, mdbuf, sizeof mdbuf);
+}
+#else
+static void
+sectors_sum_str(BlockDriverState *bs, uint64_t offset,  int sectors,
char *str, int len)
+{
+    if (len > 0)
+        str[0] = 0;
+    return;
+}
+#endif
+
 static int img_map(int argc, char **argv)
 {
     int c, ret = 0, cluster_size, cluster_sectors;
@@ -357,11 +458,12 @@ static int img_map(int argc, char **argv)
     int64_t offset, poffset, e;
     uint64_t bs_sectors;
     BlockDriverInfo bdi;
-    int local = 1;
+    int local = 1, sum = 0;
+    char sumstr[64];
     
     fmt = NULL;
     for(;;) {
-        c = getopt(argc, argv, "f:hr");
+        c = getopt(argc, argv, "f:hrs");
         if (c == -1)
             break;
         switch(c) {
@@ -374,6 +476,15 @@ static int img_map(int argc, char **argv)
         case 'r':
             local = 0;
             break;
+        case 's':
+#ifdef CONFIG_MD5SUM
+            sum = 1;
+            sumstr[0] = ' ';
+            sumstr[1] = 0;
+#else
+            fprintf(stderr, "warning: md5sum is not supported\n");
+#endif
+            break;
         }
     }
     if (optind >= argc)
@@ -408,12 +519,14 @@ static int img_map(int argc, char **argv)
     for (offset = 0; offset < e; offset += cluster_size) {
         poffset = bs->drv->bdrv_map(bs, offset, local, &store);
         if (poffset > 0 || poffset == -ENOTSUP) {
+            if (sum)
+                sectors_sum_str(bs, offset, cluster_sectors, sumstr+1,
sizeof sumstr - 1);
             if (poffset == -ENOTSUP)
                 poffset = 0;
-            printf("%s 0x%016"PRIx64" 0x%016"PRIx64"\n",
-                   store->filename, offset, poffset);
+            printf("%s 0x%016"PRIx64" 0x%016"PRIx64"%s\n",
+                   store->filename, offset, poffset, sumstr);
         }
-       if (poffset < 0) {
+        if (poffset < 0) {
             ret = poffset;
             break;
         }
@@ -897,6 +1010,7 @@ int main(int argc, char **argv)
     const char *cmd;
     int ret = 0;
 
+    initialize_hashing();
     bdrv_init();
     if (argc < 2)
         help();

Attachment: 3-md5sum.patch
Description: 3-md5sum.patch


reply via email to

[Prev in Thread] Current Thread [Next in Thread]