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(a)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