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