]> xenbits.xensource.com Git - libvirt.git/commitdiff
use posix_fallocate() to allocate diskspace faster
authorDaniel Veillard <veillard@redhat.com>
Fri, 20 Mar 2009 12:17:56 +0000 (12:17 +0000)
committerDaniel Veillard <veillard@redhat.com>
Fri, 20 Mar 2009 12:17:56 +0000 (12:17 +0000)
* src/libvirt_private.syms src/storage_backend_fs.c src/util.c
  src/util.h: use posix_fallocate() on supported systems to
  allocate diskspace faster, patches by Amit Shah
Daniel

AUTHORS
ChangeLog
configure.in
src/libvirt_private.syms
src/storage_backend_fs.c
src/util.c
src/util.h

diff --git a/AUTHORS b/AUTHORS
index 906fff61d98b3a1c892cee56a16ed3cfb288936d..1c4f3b86683323bd00be51e45ec5bb2f2ab5b3a2 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -65,6 +65,7 @@ Patches have also been contributed by:
   Maximilian Wilhelm   <max@rfc2324.org>
   Ryota Ozaki          <ozaki.ryota@gmail.com>
   Pritesh Kothari      <Pritesh.Kothari@Sun.COM>
+  Amit Shah            <amit.shah@redhat.com>
 
   [....send patches to get your name here....]
 
index ff79c06e555a4440437b56256b975bfd57695ee0..4e55fad4c6e343f98f6ff0f8528d49ed47de7915 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Fri Mar 20 13:16:01 CET 2009 Daniel Veillard <veillard@redhat.com>
+
+       * src/libvirt_private.syms src/storage_backend_fs.c src/util.c
+         src/util.h: use posix_fallocate() on supported systems to
+         allocate diskspace faster, patches by Amit Shah
+
 Fri Mar 20 11:41:40 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
 
        Fix test breakage on x86_64 from previous change
index 413d27cc6aad3968b6655d9156b5b76d6f748d8e..6b2bb5e0d2faf0ffd46ae26715014c2965b3b538 100644 (file)
@@ -72,7 +72,7 @@ dnl Use --disable-largefile if you don't want this.
 AC_SYS_LARGEFILE
 
 dnl Availability of various common functions (non-fatal if missing).
-AC_CHECK_FUNCS([cfmakeraw regexec uname sched_getaffinity getuid getgid])
+AC_CHECK_FUNCS([cfmakeraw regexec uname sched_getaffinity getuid getgid posix_fallocate mmap])
 
 dnl Availability of various not common threadsafe functions
 AC_CHECK_FUNCS([strerror_r strtok_r getmntent_r getgrnam_r getpwuid_r])
index f0d8afac15ed0409bcaf712e18349412b283044d..a5f9f925a6295927e052783abc1a745a24f0679b 100644 (file)
@@ -308,6 +308,7 @@ virStrToLong_ui;
 virFileLinkPointsTo;
 saferead;
 safewrite;
+safezero;
 virMacAddrCompare;
 virEnumFromString;
 virEnumToString;
index c0b130e1f37b63e11984a86fa28bc004153843b0..5000f4366fd20b12a562ac50c6c07421c61bf3e2 100644 (file)
@@ -62,6 +62,8 @@ static int qcowXGetBackingStore(virConnectPtr, char **,
 static int vmdk4GetBackingStore(virConnectPtr, char **,
                                 const unsigned char *, size_t);
 
+static int track_allocation_progress = 0;
+
 /* Either 'magic' or 'extension' *must* be provided */
 struct FileTypeInfo {
     int type;           /* One of the constants above */
@@ -1016,24 +1018,44 @@ virStorageBackendFileSystemVolCreate(virConnectPtr conn,
         }
 
         /* Pre-allocate any data if requested */
-        /* XXX slooooooooooooooooow.
-         * Need to add in progress bars & bg thread somehow */
+        /* XXX slooooooooooooooooow on non-extents-based file systems */
+        /* FIXME: Add in progress bars & bg thread if progress bar requested */
         if (vol->allocation) {
-            unsigned long long remain = vol->allocation;
-            static char const zeros[4096];
-            while (remain) {
-                int bytes = sizeof(zeros);
-                if (bytes > remain)
-                    bytes = remain;
-                if ((bytes = safewrite(fd, zeros, bytes)) < 0) {
-                    virReportSystemError(conn, errno,
+            if (track_allocation_progress) {
+                unsigned long long remain = vol->allocation;
+
+                while (remain) {
+                    /* Allocate in chunks of 512MiB: big-enough chunk
+                     * size and takes approx. 9s on ext3. A progress
+                     * update every 9s is a fair-enough trade-off
+                     */
+                    unsigned long long bytes = 512 * 1024 * 1024;
+                    int r;
+
+                    if (bytes > remain)
+                        bytes = remain;
+                    if ((r = safezero(fd, 0, vol->allocation - remain,
+                                      bytes)) != 0) {
+                        virReportSystemError(conn, r,
+                                             _("cannot fill file '%s'"),
+                                             vol->target.path);
+                        unlink(vol->target.path);
+                        close(fd);
+                        return -1;
+                    }
+                    remain -= bytes;
+                }
+            } else { /* No progress bars to be shown */
+                int r;
+
+                if ((r = safezero(fd, 0, 0, vol->allocation)) != 0) {
+                    virReportSystemError(conn, r,
                                          _("cannot fill file '%s'"),
                                          vol->target.path);
                     unlink(vol->target.path);
                     close(fd);
                     return -1;
                 }
-                remain -= bytes;
             }
         }
 
index 66ad9a4a3769942e98ff43b0218e10eeeed837b5..93d2937d2b020cdb8293c72c38083d8ef7ae3097 100644 (file)
@@ -39,6 +39,9 @@
 #if HAVE_SYS_WAIT_H
 #include <sys/wait.h>
 #endif
+#if HAVE_MMAP
+#include <sys/mman.h>
+#endif
 #include <string.h>
 #include <signal.h>
 #if HAVE_TERMIOS_H
@@ -117,6 +120,71 @@ ssize_t safewrite(int fd, const void *buf, size_t count)
         return nwritten;
 }
 
+#ifdef HAVE_POSIX_FALLOCATE
+int safezero(int fd, int flags, off_t offset, off_t len)
+{
+    return posix_fallocate(fd, offset, len);
+}
+#else
+
+#ifdef HAVE_MMAP
+int safezero(int fd, int flags, off_t offset, off_t len)
+{
+    int r;
+    char *buf;
+
+    /* memset wants the mmap'ed file to be present on disk so create a
+     * sparse file
+     */
+    r = ftruncate(fd, len);
+    if (r < 0)
+        return -errno;
+
+    buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
+    if (buf == MAP_FAILED)
+        return -errno;
+
+    memset(buf, 0, len);
+    munmap(buf, len);
+
+    return 0;
+}
+
+#else /* HAVE_MMAP */
+
+int safezero(int fd, int flags, off_t offset, off_t len)
+{
+    int r;
+    char *buf;
+    unsigned long long remain, bytes;
+
+    /* Split up the write in small chunks so as not to allocate lots of RAM */
+    remain = len;
+    bytes = 1024 * 1024;
+
+    r = VIR_ALLOC_N(buf, bytes);
+    if (r < 0)
+        return -ENOMEM;
+
+    while (remain) {
+        if (bytes > remain)
+            bytes = remain;
+
+        r = safewrite(fd, buf, len);
+        if (r < 0) {
+            VIR_FREE(buf);
+            return r;
+        }
+
+        /* safewrite() guarantees all data will be written */
+        remain -= bytes;
+    }
+    VIR_FREE(buf);
+    return 0;
+}
+#endif /* HAVE_MMAP */
+#endif /* HAVE_POSIX_FALLOCATE */
+
 #ifndef PROXY
 
 int virFileStripSuffix(char *str,
index 87cbf67477b09ad6c37323331989b904ee2ba49b..3fd5d2511c304582e76b5c308577c29147fd440e 100644 (file)
@@ -31,6 +31,7 @@
 
 int saferead(int fd, void *buf, size_t count);
 ssize_t safewrite(int fd, const void *buf, size_t count);
+int safezero(int fd, int flags, off_t offset, off_t len);
 
 enum {
     VIR_EXEC_NONE   = 0,