[libvirt] [PATCH] Use posix_fallocate() to allocate disk space

Amit Shah amit.shah at redhat.com
Tue Feb 24 11:39:31 UTC 2009


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 at 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 at 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




More information about the libvir-list mailing list