use posix_fallocate() to allocate diskspace faster

* src/libvirt_private.syms src/storage_backend_fs.c src/util.c
  src/util.h: use posix_fallocate() on supported systems to
  allocate diskspace faster, patches by Amit Shah
Daniel
This commit is contained in:
Daniel Veillard 2009-03-20 12:17:56 +00:00
parent 92d313ebe6
commit c29d092905
7 changed files with 111 additions and 12 deletions

View File

@ -65,6 +65,7 @@ Patches have also been contributed by:
Maximilian Wilhelm <max@rfc2324.org> Maximilian Wilhelm <max@rfc2324.org>
Ryota Ozaki <ozaki.ryota@gmail.com> Ryota Ozaki <ozaki.ryota@gmail.com>
Pritesh Kothari <Pritesh.Kothari@Sun.COM> Pritesh Kothari <Pritesh.Kothari@Sun.COM>
Amit Shah <amit.shah@redhat.com>
[....send patches to get your name here....] [....send patches to get your name here....]

View File

@ -1,3 +1,9 @@
Fri Mar 20 13:16:01 CET 2009 Daniel Veillard <veillard@redhat.com>
* src/libvirt_private.syms src/storage_backend_fs.c src/util.c
src/util.h: use posix_fallocate() on supported systems to
allocate diskspace faster, patches by Amit Shah
Fri Mar 20 11:41:40 GMT 2009 Daniel P. Berrange <berrange@redhat.com> Fri Mar 20 11:41:40 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
Fix test breakage on x86_64 from previous change Fix test breakage on x86_64 from previous change

View File

@ -72,7 +72,7 @@ dnl Use --disable-largefile if you don't want this.
AC_SYS_LARGEFILE AC_SYS_LARGEFILE
dnl Availability of various common functions (non-fatal if missing). dnl Availability of various common functions (non-fatal if missing).
AC_CHECK_FUNCS([cfmakeraw regexec uname sched_getaffinity getuid getgid]) AC_CHECK_FUNCS([cfmakeraw regexec uname sched_getaffinity getuid getgid posix_fallocate mmap])
dnl Availability of various not common threadsafe functions dnl Availability of various not common threadsafe functions
AC_CHECK_FUNCS([strerror_r strtok_r getmntent_r getgrnam_r getpwuid_r]) AC_CHECK_FUNCS([strerror_r strtok_r getmntent_r getgrnam_r getpwuid_r])

View File

@ -308,6 +308,7 @@ virStrToLong_ui;
virFileLinkPointsTo; virFileLinkPointsTo;
saferead; saferead;
safewrite; safewrite;
safezero;
virMacAddrCompare; virMacAddrCompare;
virEnumFromString; virEnumFromString;
virEnumToString; virEnumToString;

View File

@ -62,6 +62,8 @@ static int qcowXGetBackingStore(virConnectPtr, char **,
static int vmdk4GetBackingStore(virConnectPtr, char **, static int vmdk4GetBackingStore(virConnectPtr, char **,
const unsigned char *, size_t); const unsigned char *, size_t);
static int track_allocation_progress = 0;
/* Either 'magic' or 'extension' *must* be provided */ /* Either 'magic' or 'extension' *must* be provided */
struct FileTypeInfo { struct FileTypeInfo {
int type; /* One of the constants above */ int type; /* One of the constants above */
@ -1016,24 +1018,44 @@ virStorageBackendFileSystemVolCreate(virConnectPtr conn,
} }
/* Pre-allocate any data if requested */ /* Pre-allocate any data if requested */
/* XXX slooooooooooooooooow. /* XXX slooooooooooooooooow on non-extents-based file systems */
* Need to add in progress bars & bg thread somehow */ /* FIXME: Add in progress bars & bg thread if progress bar requested */
if (vol->allocation) { if (vol->allocation) {
unsigned long long remain = vol->allocation; if (track_allocation_progress) {
static char const zeros[4096]; unsigned long long remain = vol->allocation;
while (remain) {
int bytes = sizeof(zeros); while (remain) {
if (bytes > remain) /* Allocate in chunks of 512MiB: big-enough chunk
bytes = remain; * size and takes approx. 9s on ext3. A progress
if ((bytes = safewrite(fd, zeros, bytes)) < 0) { * update every 9s is a fair-enough trade-off
virReportSystemError(conn, errno, */
unsigned long long bytes = 512 * 1024 * 1024;
int r;
if (bytes > remain)
bytes = remain;
if ((r = safezero(fd, 0, vol->allocation - remain,
bytes)) != 0) {
virReportSystemError(conn, r,
_("cannot fill file '%s'"),
vol->target.path);
unlink(vol->target.path);
close(fd);
return -1;
}
remain -= bytes;
}
} else { /* No progress bars to be shown */
int r;
if ((r = safezero(fd, 0, 0, vol->allocation)) != 0) {
virReportSystemError(conn, r,
_("cannot fill file '%s'"), _("cannot fill file '%s'"),
vol->target.path); vol->target.path);
unlink(vol->target.path); unlink(vol->target.path);
close(fd); close(fd);
return -1; return -1;
} }
remain -= bytes;
} }
} }

View File

@ -39,6 +39,9 @@
#if HAVE_SYS_WAIT_H #if HAVE_SYS_WAIT_H
#include <sys/wait.h> #include <sys/wait.h>
#endif #endif
#if HAVE_MMAP
#include <sys/mman.h>
#endif
#include <string.h> #include <string.h>
#include <signal.h> #include <signal.h>
#if HAVE_TERMIOS_H #if HAVE_TERMIOS_H
@ -117,6 +120,71 @@ ssize_t safewrite(int fd, const void *buf, size_t count)
return nwritten; return nwritten;
} }
#ifdef HAVE_POSIX_FALLOCATE
int safezero(int fd, int flags, off_t offset, off_t len)
{
return posix_fallocate(fd, offset, len);
}
#else
#ifdef HAVE_MMAP
int safezero(int fd, int flags, off_t offset, off_t len)
{
int r;
char *buf;
/* memset wants the mmap'ed file to be present on disk so create a
* sparse file
*/
r = ftruncate(fd, len);
if (r < 0)
return -errno;
buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
if (buf == MAP_FAILED)
return -errno;
memset(buf, 0, len);
munmap(buf, len);
return 0;
}
#else /* HAVE_MMAP */
int safezero(int fd, int flags, off_t offset, off_t len)
{
int r;
char *buf;
unsigned long long remain, bytes;
/* Split up the write in small chunks so as not to allocate lots of RAM */
remain = len;
bytes = 1024 * 1024;
r = VIR_ALLOC_N(buf, bytes);
if (r < 0)
return -ENOMEM;
while (remain) {
if (bytes > remain)
bytes = remain;
r = safewrite(fd, buf, len);
if (r < 0) {
VIR_FREE(buf);
return r;
}
/* safewrite() guarantees all data will be written */
remain -= bytes;
}
VIR_FREE(buf);
return 0;
}
#endif /* HAVE_MMAP */
#endif /* HAVE_POSIX_FALLOCATE */
#ifndef PROXY #ifndef PROXY
int virFileStripSuffix(char *str, int virFileStripSuffix(char *str,

View File

@ -31,6 +31,7 @@
int saferead(int fd, void *buf, size_t count); int saferead(int fd, void *buf, size_t count);
ssize_t safewrite(int fd, const 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 { enum {
VIR_EXEC_NONE = 0, VIR_EXEC_NONE = 0,