raw-posix: Add falloc and full preallocation option

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>
This commit is contained in:
Hu Tao 2014-09-10 17:05:48 +08:00 committed by Kevin Wolf
parent ffeaac9b4e
commit 06247428be
3 changed files with 96 additions and 24 deletions

View File

@ -30,6 +30,7 @@
#include "block/thread-pool.h" #include "block/thread-pool.h"
#include "qemu/iov.h" #include "qemu/iov.h"
#include "raw-aio.h" #include "raw-aio.h"
#include "qapi/util.h"
#if defined(__APPLE__) && (__MACH__) #if defined(__APPLE__) && (__MACH__)
#include <paths.h> #include <paths.h>
@ -1365,6 +1366,9 @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
int result = 0; int result = 0;
int64_t total_size = 0; int64_t total_size = 0;
bool nocow = false; bool nocow = false;
PreallocMode prealloc;
char *buf = NULL;
Error *local_err = NULL;
strstart(filename, "file:", &filename); strstart(filename, "file:", &filename);
@ -1372,13 +1376,25 @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
BDRV_SECTOR_SIZE); BDRV_SECTOR_SIZE);
nocow = qemu_opt_get_bool(opts, BLOCK_OPT_NOCOW, false); nocow = qemu_opt_get_bool(opts, BLOCK_OPT_NOCOW, false);
buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
prealloc = qapi_enum_parse(PreallocMode_lookup, buf,
PREALLOC_MODE_MAX, PREALLOC_MODE_OFF,
&local_err);
g_free(buf);
if (local_err) {
error_propagate(errp, local_err);
result = -EINVAL;
goto out;
}
fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644); 0644);
if (fd < 0) { if (fd < 0) {
result = -errno; result = -errno;
error_setg_errno(errp, -result, "Could not create file"); error_setg_errno(errp, -result, "Could not create file");
} else { goto out;
}
if (nocow) { if (nocow) {
#ifdef __linux__ #ifdef __linux__
/* Set NOCOW flag to solve performance issue on fs like btrfs. /* Set NOCOW flag to solve performance issue on fs like btrfs.
@ -1397,12 +1413,45 @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
if (ftruncate(fd, total_size) != 0) { if (ftruncate(fd, total_size) != 0) {
result = -errno; result = -errno;
error_setg_errno(errp, -result, "Could not resize file"); error_setg_errno(errp, -result, "Could not resize file");
goto out_close;
} }
if (qemu_close(fd) != 0) {
if (prealloc == PREALLOC_MODE_FALLOC) {
/* posix_fallocate() doesn't set errno. */
result = -posix_fallocate(fd, 0, total_size);
if (result != 0) {
error_setg_errno(errp, -result,
"Could not preallocate data for the new file");
}
} else if (prealloc == PREALLOC_MODE_FULL) {
buf = g_malloc0(65536);
int64_t num = 0, left = total_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; result = -errno;
error_setg_errno(errp, -result, "Could not close the new file"); error_setg_errno(errp, -result, "Could not close the new file");
} }
} out:
return result; return result;
} }
@ -1585,6 +1634,11 @@ static QemuOptsList raw_create_opts = {
.type = QEMU_OPT_BOOL, .type = QEMU_OPT_BOOL,
.help = "Turn off copy-on-write (valid only on btrfs)" .help = "Turn off copy-on-write (valid only on btrfs)"
}, },
{
.name = BLOCK_OPT_PREALLOC,
.type = QEMU_OPT_STRING,
.help = "Preallocation mode (allowed values: off, falloc, full)"
},
{ /* end of list */ } { /* end of list */ }
} }
}; };

View File

@ -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 space. Use @code{qemu-img info} to know the real size used by the
image or @code{ls -ls} on Unix/Linux. 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 @item qcow2
QEMU image format, the most versatile format. Use it to have smaller QEMU image format, the most versatile format. Use it to have smaller
images (useful if your filesystem does not supports holes, for example images (useful if your filesystem does not supports holes, for example

View File

@ -419,6 +419,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 space. Use @code{qemu-img info} to know the real size used by the
image or @code{ls -ls} on Unix/Linux. 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 @item qcow2
QEMU image format, the most versatile format. Use it to have smaller QEMU image format, the most versatile format. Use it to have smaller
images (useful if your filesystem does not supports holes, for example images (useful if your filesystem does not supports holes, for example