From 61a3061760caaaaa4f025f5712dcd8f84f2f5d70 Mon Sep 17 00:00:00 2001
From: Max Reitz <mreitz@redhat.com>
Date: Mon, 10 Nov 2014 09:14:06 +0100
Subject: [PATCH 29/41] raw-posix: Add falloc and full preallocation option
Message-id: <1415610847-15383-4-git-send-email-mreitz@redhat.com>
Patchwork-id: 62239
O-Subject: [RHEL-7.1 qemu-kvm PATCH v2 3/4] raw-posix: Add falloc and full preallocation option
Bugzilla: 1087724
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
RH-Acked-by: Fam Zheng <famz@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
From: Hu Tao <hutao@cn.fujitsu.com>
This patch adds a new option preallocation for raw format, and implements
falloc and full preallocation.
Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 06247428be8037b3739280f82cb29efe8397695f)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
Conflicts:
block/raw-posix.c
QEMUOptionParameter has not been replaced with QemuOpts downstream
(upstream 6f482f742dd841b45297fb0e5f3d2c81779253be) and no "nocow"
downstream.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block/raw-posix.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++------
qemu-doc.texi | 9 ++++++++
qemu-img.texi | 9 ++++++++
3 files changed, 78 insertions(+), 7 deletions(-)
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 9ee5b8e..cfe7452 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -30,6 +30,7 @@
#include "block/thread-pool.h"
#include "qemu/iov.h"
#include "raw-aio.h"
+#include "qapi/util.h"
#if defined(__APPLE__) && (__MACH__)
#include <paths.h>
@@ -1230,11 +1231,23 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
int fd;
int result = 0;
int64_t total_size = 0;
+ PreallocMode prealloc = PREALLOC_MODE_OFF;
+ char *buf = NULL;
+ Error *local_err = NULL;
/* Read out options */
while (options && options->name) {
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
total_size = options->value.n / BDRV_SECTOR_SIZE;
+ } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
+ prealloc = qapi_enum_parse(PreallocMode_lookup, options->value.s,
+ PREALLOC_MODE_MAX, PREALLOC_MODE_OFF,
+ &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ result = -EINVAL;
+ goto out;
+ }
}
options++;
}
@@ -1244,16 +1257,51 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
if (fd < 0) {
result = -errno;
error_setg_errno(errp, -result, "Could not create file");
- } else {
- if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
- result = -errno;
- error_setg_errno(errp, -result, "Could not resize file");
+ goto out;
+ }
+
+ if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
+ result = -errno;
+ error_setg_errno(errp, -result, "Could not resize file");
+ goto out_close;
+ }
+
+ if (prealloc == PREALLOC_MODE_FALLOC) {
+ /* posix_fallocate() doesn't set errno. */
+ result = -posix_fallocate(fd, 0, total_size * BDRV_SECTOR_SIZE);
+ if (result != 0) {
+ error_setg_errno(errp, -result,
+ "Could not preallocate data for the new file");
}
- if (qemu_close(fd) != 0) {
- result = -errno;
- error_setg_errno(errp, -result, "Could not close the new file");
+ } else if (prealloc == PREALLOC_MODE_FULL) {
+ buf = g_malloc0(65536);
+ int64_t num = 0, left = total_size * BDRV_SECTOR_SIZE;
+
+ while (left > 0) {
+ num = MIN(left, 65536);
+ result = write(fd, buf, num);
+ if (result < 0) {
+ result = -errno;
+ error_setg_errno(errp, -result,
+ "Could not write to the new file");
+ break;
+ }
+ left -= num;
}
+ fsync(fd);
+ g_free(buf);
+ } else if (prealloc != PREALLOC_MODE_OFF) {
+ result = -EINVAL;
+ error_setg(errp, "Unsupported preallocation mode: %s",
+ PreallocMode_lookup[prealloc]);
+ }
+
+out_close:
+ if (qemu_close(fd) != 0 && result == 0) {
+ result = -errno;
+ error_setg_errno(errp, -result, "Could not close the new file");
}
+out:
return result;
}
@@ -1404,6 +1452,11 @@ static QEMUOptionParameter raw_create_options[] = {
.type = OPT_SIZE,
.help = "Virtual disk size"
},
+ {
+ .name = BLOCK_OPT_PREALLOC,
+ .type = OPT_STRING,
+ .help = "Preallocation mode (allowed values: off, falloc, full)"
+ },
{ NULL }
};
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 54ab3c5..dc5b49e 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -527,6 +527,15 @@ Linux or NTFS on Windows), then only the written sectors will reserve
space. Use @code{qemu-img info} to know the real size used by the
image or @code{ls -ls} on Unix/Linux.
+Supported options:
+@table @code
+@item preallocation
+Preallocation mode (allowed values: @code{off}, @code{falloc}, @code{full}).
+@code{falloc} mode preallocates space for image by calling posix_fallocate().
+@code{full} mode preallocates space for image by writing zeros to underlying
+storage.
+@end table
+
@item qcow2
QEMU image format, the most versatile format. Use it to have smaller
images (useful if your filesystem does not supports holes, for example
diff --git a/qemu-img.texi b/qemu-img.texi
index 5f99ebb..80d3261 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -392,6 +392,15 @@ Linux or NTFS on Windows), then only the written sectors will reserve
space. Use @code{qemu-img info} to know the real size used by the
image or @code{ls -ls} on Unix/Linux.
+Supported options:
+@table @code
+@item preallocation
+Preallocation mode (allowed values: @code{off}, @code{falloc}, @code{full}).
+@code{falloc} mode preallocates space for image by calling posix_fallocate().
+@code{full} mode preallocates space for image by writing zeros to underlying
+storage.
+@end table
+
@item qcow2
QEMU image format, the most versatile format. Use it to have smaller
images (useful if your filesystem does not supports holes, for example
--
1.8.3.1