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....]
+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
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])
virFileLinkPointsTo;
saferead;
safewrite;
+safezero;
virMacAddrCompare;
virEnumFromString;
virEnumToString;
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 */
}
/* 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;
}
}
#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
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,
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,