[libvirt] [PATCH 1/2] virfile: Refactor safezero

John Ferlan jferlan at redhat.com
Mon Dec 15 21:13:21 UTC 2014


Currently build conditionals decide which of two safezero() functions
should be built - either the posix_fallocate() or mmap() with a fallback
to a slower safewrite() algorithm in order to preallocate space in a raw file.

This patch will refactor safezero to utilize static functions for either
posix_fallocate or mmap/safewrite. The build conditional still exist, but
are only for shorter sections of code.

The posix_fallocate path will make use of the ret/errno setting to contain
the logic for safezero to decide whether it needs to fallback to other
algorithms. A return of -1 with errno not changed will indicate the conditional
is not present; otherwise, a return of -1 with errno change indicates the
call was made and it failed (no functional difference to current algorithm).

The mmap/safewrite option changes only slightly to handle the ftruncate
failure for mmap. That is, previously if the ftruncate failed, there was
no fallback to the slow safewrite option.

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 src/util/virfile.c | 47 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/src/util/virfile.c b/src/util/virfile.c
index b4d762f..5e8c306 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -1034,26 +1034,24 @@ 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)
+static int
+safezero_posix_fallocate(int fd, off_t offset, off_t len)
 {
+#ifdef HAVE_POSIX_FALLOCATE
     int ret = posix_fallocate(fd, offset, len);
     if (ret == 0)
         return 0;
     errno = ret;
+#endif
     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;
     off_t map_skip;
 
@@ -1080,7 +1078,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 +1118,26 @@ 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)
+{
+    int ret;
+
+    /* posix_fallocate returns 0 on success or error number on failure,
+     * but errno is not set so use that to our advantage since we set
+     * errno to the returned value if we make the call. If we don't make
+     * the call because it doesn't exist, then errno won't change and
+     * we can try other methods.
+     */
+    errno = 0;
+    ret = safezero_posix_fallocate(fd, offset, len);
+    if (ret == 0 || errno != 0)
+        return ret;
+
+    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
-- 
1.9.3




More information about the libvir-list mailing list