file-posix: Support .bdrv_co_create

This adds the .bdrv_co_create driver callback to file, which enables
image creation over QMP.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Kevin Wolf 2018-01-16 16:04:21 +01:00
parent b0292b851b
commit 927f11e131
2 changed files with 75 additions and 24 deletions

View File

@ -1982,34 +1982,25 @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
return (int64_t)st.st_blocks * 512; return (int64_t)st.st_blocks * 512;
} }
static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts, static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
Error **errp)
{ {
BlockdevCreateOptionsFile *file_opts;
int fd; int fd;
int result = 0; int result = 0;
int64_t total_size = 0;
bool nocow = false;
PreallocMode prealloc;
char *buf = NULL;
Error *local_err = NULL;
strstart(filename, "file:", &filename); /* Validate options and set default values */
assert(options->driver == BLOCKDEV_DRIVER_FILE);
file_opts = &options->u.file;
/* Read out options */ if (!file_opts->has_nocow) {
total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), file_opts->nocow = false;
BDRV_SECTOR_SIZE); }
nocow = qemu_opt_get_bool(opts, BLOCK_OPT_NOCOW, false); if (!file_opts->has_preallocation) {
buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC); file_opts->preallocation = PREALLOC_MODE_OFF;
prealloc = qapi_enum_parse(&PreallocMode_lookup, buf,
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_RDWR | O_CREAT | O_TRUNC | O_BINARY, /* Create file */
fd = qemu_open(file_opts->filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
0644); 0644);
if (fd < 0) { if (fd < 0) {
result = -errno; result = -errno;
@ -2017,7 +2008,7 @@ static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
goto out; goto out;
} }
if (nocow) { if (file_opts->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.
* This is an optimisation. The FS_IOC_SETFLAGS ioctl return value * This is an optimisation. The FS_IOC_SETFLAGS ioctl return value
@ -2032,7 +2023,8 @@ static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
#endif #endif
} }
result = raw_regular_truncate(fd, total_size, prealloc, errp); result = raw_regular_truncate(fd, file_opts->size, file_opts->preallocation,
errp);
if (result < 0) { if (result < 0) {
goto out_close; goto out_close;
} }
@ -2046,6 +2038,46 @@ out:
return result; return result;
} }
static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
Error **errp)
{
BlockdevCreateOptions options;
int64_t total_size = 0;
bool nocow = false;
PreallocMode prealloc;
char *buf = NULL;
Error *local_err = NULL;
/* Skip file: protocol prefix */
strstart(filename, "file:", &filename);
/* Read out options */
total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
BDRV_SECTOR_SIZE);
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_OFF, &local_err);
g_free(buf);
if (local_err) {
error_propagate(errp, local_err);
return -EINVAL;
}
options = (BlockdevCreateOptions) {
.driver = BLOCKDEV_DRIVER_FILE,
.u.file = {
.filename = (char *) filename,
.size = total_size,
.has_preallocation = true,
.preallocation = prealloc,
.has_nocow = true,
.nocow = nocow,
},
};
return raw_co_create(&options, errp);
}
/* /*
* Find allocation range in @bs around offset @start. * Find allocation range in @bs around offset @start.
* May change underlying file descriptor's file offset. * May change underlying file descriptor's file offset.
@ -2277,6 +2309,7 @@ BlockDriver bdrv_file = {
.bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_commit = raw_reopen_commit,
.bdrv_reopen_abort = raw_reopen_abort, .bdrv_reopen_abort = raw_reopen_abort,
.bdrv_close = raw_close, .bdrv_close = raw_close,
.bdrv_co_create = raw_co_create,
.bdrv_co_create_opts = raw_co_create_opts, .bdrv_co_create_opts = raw_co_create_opts,
.bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_co_block_status = raw_co_block_status, .bdrv_co_block_status = raw_co_block_status,

View File

@ -3358,6 +3358,24 @@
## ##
{ 'command': 'blockdev-del', 'data': { 'node-name': 'str' } } { 'command': 'blockdev-del', 'data': { 'node-name': 'str' } }
##
# @BlockdevCreateOptionsFile:
#
# Driver specific image creation options for file.
#
# @filename Filename for the new image file
# @size Size of the virtual disk in bytes
# @preallocation Preallocation mode for the new image (default: off)
# @nocow Turn off copy-on-write (valid only on btrfs; default: off)
#
# Since: 2.12
##
{ 'struct': 'BlockdevCreateOptionsFile',
'data': { 'filename': 'str',
'size': 'size',
'*preallocation': 'PreallocMode',
'*nocow': 'bool' } }
## ##
# @BlockdevQcow2Version: # @BlockdevQcow2Version:
# #
@ -3429,7 +3447,7 @@
'bochs': 'BlockdevCreateNotSupported', 'bochs': 'BlockdevCreateNotSupported',
'cloop': 'BlockdevCreateNotSupported', 'cloop': 'BlockdevCreateNotSupported',
'dmg': 'BlockdevCreateNotSupported', 'dmg': 'BlockdevCreateNotSupported',
'file': 'BlockdevCreateNotSupported', 'file': 'BlockdevCreateOptionsFile',
'ftp': 'BlockdevCreateNotSupported', 'ftp': 'BlockdevCreateNotSupported',
'ftps': 'BlockdevCreateNotSupported', 'ftps': 'BlockdevCreateNotSupported',
'gluster': 'BlockdevCreateNotSupported', 'gluster': 'BlockdevCreateNotSupported',