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

Minoru Usui usui at mxm.nes.nec.co.jp
Tue Mar 8 11:06:51 UTC 2011


This patch changes zerobuf variable from array to VIR_ALLOC_N().

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

diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index 2eede74..3a22da4 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 bytes = 1024 * 1024;
-    char zerobuf[512];
+    size_t rbytes = READ_BLOCK_SIZE_DEFAULT;
+    size_t wbytes = WRITE_BLOCK_SIZE_DEFAULT;
+    int interval;
+    char *zerobuf;
     char *buf = NULL;
 
     if ((inputfd = open(inputvol->target.path, O_RDONLY)) < 0) {
@@ -131,9 +140,19 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol,
         goto cleanup;
     }
 
-    bzero(&zerobuf, sizeof(zerobuf));
+#ifdef __linux__
+    if (ioctl(fd, BLKBSZGET, &wbytes) < 0) {
+        wbytes = WRITE_BLOCK_SIZE_DEFAULT;
+    }
+#endif
+
+    if (VIR_ALLOC_N(zerobuf, wbytes) < 0) {
+        ret = -errno;
+        virReportOOMError();
+        goto cleanup;
+    }
 
-    if (VIR_ALLOC_N(buf, bytes) < 0) {
+    if (VIR_ALLOC_N(buf, rbytes) < 0) {
         ret = -errno;
         virReportOOMError();
         goto cleanup;
@@ -144,10 +163,10 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol,
     while (amtread != 0) {
         int amtleft;
 
-        if (remain < bytes)
-            bytes = remain;
+        if (remain < rbytes)
+            rbytes = remain;
 
-        if ((amtread = saferead(inputfd, buf, bytes)) < 0) {
+        if ((amtread = saferead(inputfd, buf, rbytes)) < 0) {
             ret = -errno;
             virReportSystemError(errno,
                                  _("failed reading from file '%s'"),
@@ -160,7 +179,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 +198,7 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol,
                 goto cleanup;
 
             }
-        } while ((amtleft -= 512) > 0);
+        } while ((amtleft -= interval) > 0);
     }
 
     if (VIR_CLOSE(inputfd) < 0) {
@@ -196,6 +215,7 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol,
 cleanup:
     VIR_FORCE_CLOSE(inputfd);
 
+    VIR_FREE(zerobuf);
     VIR_FREE(buf);
 
     return ret;

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




More information about the libvir-list mailing list