Hi, This is an untested patch to make disk allocations faster and non-fragmented. I'm using posix_fallocate() now but relying on glibc really calling fallocate() if it exists for the file system to be the fastest. - This fails build because libutil needs to be added as a dependency? ../src/.libs/libvirt_driver_storage.a(storage_backend_fs.o): In function `virStorageBackendFileSystemVolCreate': /home/amit/src/libvirt/src/storage_backend_fs.c:1023: undefined reference to `safezero' - What's vol->capacity? Why is ftruncate() needed after the call to (current) safewrite()? My assumption is that the user can specify some max. capacity and wish to allocate only a chunk off it at create-time. Is that correct? The best case to get a non-fragmented VM image is to have it allocated completely at create-time with fallocate(). Currently xfs and ext4 support the fallocate() syscall (btrfs will, too, when it's ready). Comments? Amit >From dfe4780f5990571f026e02e6187cb64505c982c1 Mon Sep 17 00:00:00 2001 From: Amit Shah <amit.shah@xxxxxxxxxx> Date: Tue, 24 Feb 2009 16:55:58 +0530 Subject: [PATCH] Use posix_fallocate() to allocate disk space Using posix_fallocate() to allocate disk space and fill it with zeros is faster than writing the zeros block-by-block. Also, for backing file systems that support the fallocate() syscall, this operation will give us a big speed boost. The biggest advantage of using this is the file will not be fragmented for the allocated chunks. Signed-off-by: Amit Shah <amit.shah@xxxxxxxxxx> --- src/storage_backend_fs.c | 23 ++++++++--------------- src/util.c | 5 +++++ src/util.h | 1 + 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/storage_backend_fs.c b/src/storage_backend_fs.c index 240de96..74b0fda 100644 --- a/src/storage_backend_fs.c +++ b/src/storage_backend_fs.c @@ -1019,21 +1019,14 @@ virStorageBackendFileSystemVolCreate(virConnectPtr conn, /* XXX slooooooooooooooooow. * Need to add in progress bars & bg thread somehow */ if (vol->allocation) { - unsigned long long remain = vol->allocation; - static char const zeros[4096]; - while (remain) { - int bytes = sizeof(zeros); - if (bytes > remain) - bytes = remain; - if ((bytes = safewrite(fd, zeros, bytes)) < 0) { - virReportSystemError(conn, errno, - _("cannot fill file '%s'"), - vol->target.path); - unlink(vol->target.path); - close(fd); - return -1; - } - remain -= bytes; + int r; + if ((r = safezero(fd, 0, 0, vol->allocation)) < 0) { + virReportSystemError(conn, r, + _("cannot fill file '%s'"), + vol->target.path); + unlink(vol->target.path); + close(fd); + return -1; } } diff --git a/src/util.c b/src/util.c index 990433a..1bee7f0 100644 --- a/src/util.c +++ b/src/util.c @@ -117,6 +117,11 @@ ssize_t safewrite(int fd, const void *buf, size_t count) return nwritten; } +int safezero(int fd, int flags, off_t offset, off_t len) +{ + return posix_fallocate(fd, offset, len); +} + #ifndef PROXY int virFileStripSuffix(char *str, diff --git a/src/util.h b/src/util.h index a79cfa7..acaabb1 100644 --- a/src/util.h +++ b/src/util.h @@ -31,6 +31,7 @@ int saferead(int fd, void *buf, size_t count); ssize_t safewrite(int fd, const void *buf, size_t count); +int safezero(int fd, int flags, off_t offset, off_t len); enum { VIR_EXEC_NONE = 0, -- 1.6.0.6 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list