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