Currently the safezero() function uses build conditionals to choose either
the posix_fallocate() or mmap() with a fallback to safewrite() in order to
preallocate a file.
This patch will modify the logic in order to allow fallbacks in the
event that posix_fallocate() or the ftruncate()and mmap() doesn't work
properly. The fallback will be to use the slow safewrite of zero filled
buffers to the file.
This patch also introduces virFileFdPosixFallocate() so that it can be
used by the resize code rather than having two separate functions
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virfile.c | 37 +++++++++++++++++++++++++++----------
src/util/virfile.h | 2 ++
3 files changed, 30 insertions(+), 10 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 08111d4..5556d31 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1278,6 +1278,7 @@ virFileDirectFdFlag;
virFileExists;
virFileFclose;
virFileFdopen;
+virFileFdPosixFallocate;
virFileFindHugeTLBFS;
virFileFindMountPoint;
virFileFindResource;
diff --git a/src/util/virfile.c b/src/util/virfile.c
index f9efc65..7f03cbf 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -1034,26 +1034,26 @@ safewrite(int fd, const void *buf, size_t count)
return nwritten;
}
-#ifdef HAVE_POSIX_FALLOCATE
int
-safezero(int fd, off_t offset, off_t len)
+virFileFdPosixFallocate(int fd, off_t offset, off_t len)
{
+#ifdef HAVE_POSIX_FALLOCATE
int ret = posix_fallocate(fd, offset, len);
if (ret == 0)
return 0;
+ VIR_WARN("Failed to pre-allocate '%lu' bytes with return value
'%d'",
+ len, ret);
errno = ret;
+#endif /* HAVE_POSIX_FALLOCATE */
return -1;
}
-#else
-
-int
-safezero(int fd, off_t offset, off_t len)
+static int
+safezero_mmap(int fd, off_t offset, off_t len)
{
+#ifdef HAVE_MMAP
int r;
char *buf;
- unsigned long long remain, bytes;
-# ifdef HAVE_MMAP
static long pagemask = 0;
off_t map_skip;
@@ -1080,7 +1080,16 @@ safezero(int fd, off_t offset, off_t len)
/* fall back to writing zeroes using safewrite if mmap fails (for
* example because of virtual memory limits) */
-# endif /* HAVE_MMAP */
+#endif /* HAVE_MMAP */
+ return -1;
+}
+
+static int
+safezero_slow(int fd, off_t offset, off_t len)
+{
+ int r;
+ char *buf;
+ unsigned long long remain, bytes;
if (lseek(fd, offset, SEEK_SET) < 0)
return -1;
@@ -1111,8 +1120,16 @@ safezero(int fd, off_t offset, off_t len)
VIR_FREE(buf);
return 0;
}
-#endif /* HAVE_POSIX_FALLOCATE */
+int
+safezero(int fd, off_t offset, off_t len)
+{
+ if (virFileFdPosixFallocate(fd, offset, len) == 0)
+ return 0;
+ if (safezero_mmap(fd, offset, len) == 0)
+ return 0;
+ return safezero_slow(fd, offset, len);
+}
#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
/* search /proc/mounts for mount point of *type; return pointer to
diff --git a/src/util/virfile.h b/src/util/virfile.h
index 403d0ba..29a1776 100644
--- a/src/util/virfile.h
+++ b/src/util/virfile.h
@@ -41,6 +41,8 @@ typedef enum {
ssize_t saferead(int fd, void *buf, size_t count) ATTRIBUTE_RETURN_CHECK;
ssize_t safewrite(int fd, const void *buf, size_t count)
ATTRIBUTE_RETURN_CHECK;
+int virFileFdPosixFallocate(int fd, off_t offset, off_t len)
+ ATTRIBUTE_RETURN_CHECK;
int safezero(int fd, off_t offset, off_t len)
ATTRIBUTE_RETURN_CHECK;
--
1.9.3