mmap can fail on 32-bit systems if we're trying to zero out a lot of data.
Fall back to using block-by-block writing in that case.  While we could map
smaller blocks it's unlikely that this code is used a lot and its easier to
just fall back to one of the existing methods.

Also modified the block-by-block zeroing to not allocate a megabyte of
zeroes if we're writing less than that.

Signed-off-by: Oskari Saarenmaa <o...@ohmu.fi>
---
 src/util/virfile.c | 34 ++++++++++++++--------------------
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/src/util/virfile.c b/src/util/virfile.c
index 16f8101..f662127 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -1032,16 +1032,18 @@ safezero(int fd, off_t offset, off_t len)
     errno = ret;
     return -1;
 }
+
 #else
 
-# ifdef HAVE_MMAP
 int
 safezero(int fd, off_t offset, off_t len)
 {
-    static long pagemask = 0;
-    off_t map_skip;
     int r;
     char *buf;
+    unsigned long long remain, bytes;
+# ifdef HAVE_MMAP
+    static long pagemask = 0;
+    off_t map_skip;
 
     /* align offset and length, rounding offset down and length up */
     if (pagemask == 0)
@@ -1057,30 +1059,23 @@ safezero(int fd, off_t offset, off_t len)
 
     buf = mmap(NULL, len + map_skip, PROT_READ | PROT_WRITE, MAP_SHARED,
                fd, offset - map_skip);
-    if (buf == MAP_FAILED)
-        return -1;
+    if (buf != MAP_FAILED) {
+        memset(buf + map_skip, 0, len);
+        munmap(buf, len + map_skip);
 
-    memset(buf + map_skip, 0, len);
-    munmap(buf, len + map_skip);
-
-    return 0;
-}
-
-# else /* HAVE_MMAP */
+        return 0;
+    }
 
-int
-safezero(int fd, off_t offset, off_t len)
-{
-    int r;
-    char *buf;
-    unsigned long long remain, bytes;
+    /* fall back to writing zeroes using safewrite if mmap fails (for
+     * example because of virtual memory limits) */
+# endif /* HAVE_MMAP */
 
     if (lseek(fd, offset, SEEK_SET) < 0)
         return -1;
 
     /* Split up the write in small chunks so as not to allocate lots of RAM */
     remain = len;
-    bytes = 1024 * 1024;
+    bytes = MAX(1024 * 1024, len);
 
     r = VIR_ALLOC_N(buf, bytes);
     if (r < 0) {
@@ -1104,7 +1099,6 @@ safezero(int fd, off_t offset, off_t len)
     VIR_FREE(buf);
     return 0;
 }
-# endif /* HAVE_MMAP */
 #endif /* HAVE_POSIX_FALLOCATE */
 
 
-- 
1.8.3.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to