mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 11:22:23 +00:00
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:
parent
92d313ebe6
commit
c29d092905
1
AUTHORS
1
AUTHORS
@ -65,6 +65,7 @@ Patches have also been contributed by:
|
||||
Maximilian Wilhelm <max@rfc2324.org>
|
||||
Ryota Ozaki <ozaki.ryota@gmail.com>
|
||||
Pritesh Kothari <Pritesh.Kothari@Sun.COM>
|
||||
Amit Shah <amit.shah@redhat.com>
|
||||
|
||||
[....send patches to get your name here....]
|
||||
|
||||
|
@ -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>
|
||||
|
||||
Fix test breakage on x86_64 from previous change
|
||||
|
@ -72,7 +72,7 @@ dnl Use --disable-largefile if you don't want this.
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
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
|
||||
AC_CHECK_FUNCS([strerror_r strtok_r getmntent_r getgrnam_r getpwuid_r])
|
||||
|
@ -308,6 +308,7 @@ virStrToLong_ui;
|
||||
virFileLinkPointsTo;
|
||||
saferead;
|
||||
safewrite;
|
||||
safezero;
|
||||
virMacAddrCompare;
|
||||
virEnumFromString;
|
||||
virEnumToString;
|
||||
|
@ -62,6 +62,8 @@ static int qcowXGetBackingStore(virConnectPtr, char **,
|
||||
static int vmdk4GetBackingStore(virConnectPtr, char **,
|
||||
const unsigned char *, size_t);
|
||||
|
||||
static int track_allocation_progress = 0;
|
||||
|
||||
/* Either 'magic' or 'extension' *must* be provided */
|
||||
struct FileTypeInfo {
|
||||
int type; /* One of the constants above */
|
||||
@ -1016,24 +1018,44 @@ virStorageBackendFileSystemVolCreate(virConnectPtr conn,
|
||||
}
|
||||
|
||||
/* Pre-allocate any data if requested */
|
||||
/* XXX slooooooooooooooooow.
|
||||
* Need to add in progress bars & bg thread somehow */
|
||||
/* XXX slooooooooooooooooow on non-extents-based file systems */
|
||||
/* FIXME: Add in progress bars & bg thread if progress bar requested */
|
||||
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,
|
||||
if (track_allocation_progress) {
|
||||
unsigned long long remain = vol->allocation;
|
||||
|
||||
while (remain) {
|
||||
/* Allocate in chunks of 512MiB: big-enough chunk
|
||||
* size and takes approx. 9s on ext3. A progress
|
||||
* update every 9s is a fair-enough trade-off
|
||||
*/
|
||||
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'"),
|
||||
vol->target.path);
|
||||
unlink(vol->target.path);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
remain -= bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
68
src/util.c
68
src/util.c
@ -39,6 +39,9 @@
|
||||
#if HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
#if HAVE_MMAP
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#if HAVE_TERMIOS_H
|
||||
@ -117,6 +120,71 @@ ssize_t safewrite(int fd, const void *buf, size_t count)
|
||||
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
|
||||
|
||||
int virFileStripSuffix(char *str,
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user