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(a)redhat.com>
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(a)redhat.com>
---
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