[libvirt] [PATCH 1/2] Introduce posix_fallocate() to allocate disk space

Amit Shah amit.shah at redhat.com
Thu Mar 19 14:47:53 UTC 2009


Using posix_fallocate() to allocate disk space and fill it with zeros is faster
than writing the zeros block-by-block.

Also, for backing file systems that support extents and the fallocate() syscall,
this operation will give us a big speed boost.

This also brings us the advantage of very less fragmentation for the chunk being
allocated.

For systems that don't support posix_fallocate(), fall back to safewrite().

Signed-off-by: Amit Shah <amit.shah at redhat.com>
---
 configure.in             |    2 +-
 src/libvirt_private.syms |    1 +
 src/util.c               |   38 ++++++++++++++++++++++++++++++++++++++
 src/util.h               |    1 +
 4 files changed, 41 insertions(+), 1 deletions(-)

diff --git a/configure.in b/configure.in
index 413d27c..edce040 100644
--- a/configure.in
+++ b/configure.in
@@ -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])
 
 dnl Availability of various not common threadsafe functions
 AC_CHECK_FUNCS([strerror_r strtok_r getmntent_r getgrnam_r getpwuid_r])
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index f0d8afa..a5f9f92 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -308,6 +308,7 @@ virStrToLong_ui;
 virFileLinkPointsTo;
 saferead;
 safewrite;
+safezero;
 virMacAddrCompare;
 virEnumFromString;
 virEnumToString;
diff --git a/src/util.c b/src/util.c
index 66ad9a4..955c4e5 100644
--- a/src/util.c
+++ b/src/util.c
@@ -117,6 +117,44 @@ 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
+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
+
 #ifndef PROXY
 
 int virFileStripSuffix(char *str,
diff --git a/src/util.h b/src/util.h
index 87cbf67..3fd5d25 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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,
-- 
1.6.0.6




More information about the libvir-list mailing list