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@xxxxxxxxxx> --- 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 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list