[libvirt] [PATCH] Fix performance problem of virStorageVolCreateXMLFrom()

Minoru Usui usui at mxm.nes.nec.co.jp
Tue Mar 8 04:01:34 UTC 2011


virStorageVolCreateXMLFrom() is slow if destination Pool is LVM.
Because write block size is not appropriate.

On linux environment, block size of LVM Pool which is made by virStoragePoolCreateXML()
is 4096 bytes.
On the other hand, write block size of virStorageVolCreateXMLFrom() is 512 bytes.
This value are hard corded in virStorageBackendCopyToFD().

This patch fix this block size problem on linux.

[lvm block size]
  # virsh vol-dumpxml vol.img --pool lvm-pool |grep '<path>'
      <path>/dev/lvm-pool/vol.img</path>
  # blockdev --getbsz /dev/lvm-pool/vol.img
  4096

[before patch]
  # echo 1 > /proc/sys/vm/drop_caches
  # time virsh  vol-create-from lvm-pool vol.xml --inputpool dir-pool vol.img
  real    1m17.736s
  user    0m0.007s
  sys     0m0.021s

[after patch]
  # echo 1 > /proc/sys/vm/drop_caches
  # time virsh  vol-create-from lvm-pool vol.xml --inputpool dir-pool vol.img
  real    0m36.883s
  user    0m0.011s
  sys     0m0.031s

Signed-off-by: Minoru Usui <usui at mxm.nes.nec.co.jp>
---
 src/storage/storage_backend.c |   23 +++++++++++++++++++----
 1 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index 174155d..a1a930c 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -36,6 +36,10 @@
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <dirent.h>
+#ifdef __linux__
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#endif
 
 #if HAVE_SELINUX
 # include <selinux/selinux.h>
@@ -108,6 +112,9 @@ enum {
     TOOL_QCOW_CREATE,
 };
 
+#define READ_BLOCK_SIZE_DEFAULT  (1024 * 1024)
+#define WRITE_BLOCK_SIZE_DEFAULT (512)
+
 static int ATTRIBUTE_NONNULL (2)
 virStorageBackendCopyToFD(virStorageVolDefPtr vol,
                           virStorageVolDefPtr inputvol,
@@ -119,8 +126,10 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol,
     int amtread = -1;
     int ret = 0;
     unsigned long long remain;
-    size_t rbytes = 1024 * 1024; /* For Read */
-    char zerobuf[512];
+    size_t rbytes = READ_BLOCK_SIZE_DEFAULT;
+    size_t wbytes = WRITE_BLOCK_SIZE_DEFAULT;
+    int interval;
+    char zerobuf[WRITE_BLOCK_SIZE_DEFAULT];
     char *buf = NULL;
 
     if ((inputfd = open(inputvol->target.path, O_RDONLY)) < 0) {
@@ -131,6 +140,12 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol,
         goto cleanup;
     }
 
+#ifdef __linux__
+    if (ioctl(fd, BLKBSZGET, &wbytes) < 0) {
+        wbytes = WRITE_BLOCK_SIZE_DEFAULT;
+    }
+#endif
+
     bzero(&zerobuf, sizeof(zerobuf));
 
     if (VIR_ALLOC_N(buf, rbytes) < 0) {
@@ -160,7 +175,7 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol,
          * blocks */
         amtleft = amtread;
         do {
-            int interval = ((512 > amtleft) ? amtleft : 512);
+            interval = ((wbytes > amtleft) ? amtleft : wbytes);
             int offset = amtread - amtleft;
 
             if (is_dest_file && memcmp(buf+offset, zerobuf, interval) == 0) {
@@ -179,7 +194,7 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol,
                 goto cleanup;
 
             }
-        } while ((amtleft -= 512) > 0);
+        } while ((amtleft -= interval) > 0);
     }
 
     if (VIR_CLOSE(inputfd) < 0) {


-- 
Minoru Usui <usui at mxm.nes.nec.co.jp>




More information about the libvir-list mailing list