From 197f34f785baf4214f222faba7dc67f0d26135bf Mon Sep 17 00:00:00 2001 Message-Id: <197f34f785baf4214f222faba7dc67f0d26135bf.1422637807.git.jen@redhat.com> In-Reply-To: References: From: Max Reitz Date: Mon, 19 Jan 2015 14:52:06 -0500 Subject: [CHANGE 05/10] raw-posix: Add falloc and full preallocation option To: rhvirt-patches@redhat.com, jen@redhat.com RH-Author: Max Reitz Message-id: <1421679130-22714-6-git-send-email-mreitz@redhat.com> Patchwork-id: 63365 O-Subject: [RHEL-6.7 qemu-kvm PATCH 5/9] raw-posix: Add falloc and full preallocation option Bugzilla: 1040220 RH-Acked-by: Fam Zheng RH-Acked-by: Laszlo Ersek RH-Acked-by: Stefan Hajnoczi From: Hu Tao BZ: 1040220 This patch adds a new option preallocation for raw format, and implements falloc and full preallocation. Signed-off-by: Hu Tao Reviewed-by: Max Reitz Signed-off-by: Kevin Wolf (cherry picked from commit 06247428be8037b3739280f82cb29efe8397695f) Signed-off-by: Jeff E. Nelson Conflicts: qemu-doc.texi block/raw-posix.c The modified section of qemu-doc.texi does not exist downstream (and it is not absolutely necessary, because the modifications made upstream are exactly the same as those in qemu-img.texi, and those are part of this patch). For block/raw-posix.c, first the option handling is different downstream; second, nocow does not exist; third, error message passing is different, so some messages are kept and printed (those directly related to preallocation) and others are omitted (those where operations failed that did exist before (open, truncate, close) but where no message was printed); and fourth, total_size in raw_create() is given in sectors instead of bytes. Signed-off-by: Max Reitz --- block/raw-posix.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++----- qemu-img.texi | 9 ++++++++ 2 files changed, 68 insertions(+), 5 deletions(-) Signed-off-by: Jeff E. Nelson --- block/raw-posix.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++----- qemu-img.texi | 9 ++++++++ 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index bd19cad..f54211a 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -30,6 +30,8 @@ #include "compatfd.h" #include #include "block/raw-posix-aio.h" +#include "qapi/util.h" +#include "qapi-visit.h" #ifdef CONFIG_COCOA #include @@ -621,11 +623,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) { + qerror_report_err(local_err); + error_free(local_err); + return -EINVAL; + } } options++; } @@ -634,14 +648,49 @@ static int raw_create(const char *filename, QEMUOptionParameter *options) 0644); if (fd < 0) { result = -errno; - } else { - if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) { - result = -errno; + goto out; + } + + if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) { + result = -errno; + 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_report("Could not preallocate data for the new file: %s", + strerror(-result)); } - if (close(fd) != 0) { - result = -errno; + } 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_report("Could not write to the new file: %s", + strerror(-result)); + break; + } + left -= num; } + fsync(fd); + g_free(buf); + } else if (prealloc != PREALLOC_MODE_OFF) { + result = -EINVAL; + error_report("Unsupported preallocation mode: %s", + PreallocMode_lookup[prealloc]); + } + +out_close: + if (qemu_close(fd) != 0 && result == 0) { + result = -errno; } +out: return result; } @@ -684,6 +733,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-img.texi b/qemu-img.texi index cc50e13..1511c98 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -332,6 +332,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 -- 2.1.0