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:
parent
b0292b851b
commit
927f11e131
@ -1982,34 +1982,25 @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
|
||||
return (int64_t)st.st_blocks * 512;
|
||||
}
|
||||
|
||||
static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
|
||||
Error **errp)
|
||||
static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
|
||||
{
|
||||
BlockdevCreateOptionsFile *file_opts;
|
||||
int fd;
|
||||
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 */
|
||||
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);
|
||||
result = -EINVAL;
|
||||
goto out;
|
||||
if (!file_opts->has_nocow) {
|
||||
file_opts->nocow = false;
|
||||
}
|
||||
if (!file_opts->has_preallocation) {
|
||||
file_opts->preallocation = PREALLOC_MODE_OFF;
|
||||
}
|
||||
|
||||
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);
|
||||
if (fd < 0) {
|
||||
result = -errno;
|
||||
@ -2017,7 +2008,7 @@ static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nocow) {
|
||||
if (file_opts->nocow) {
|
||||
#ifdef __linux__
|
||||
/* Set NOCOW flag to solve performance issue on fs like btrfs.
|
||||
* 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
|
||||
}
|
||||
|
||||
result = raw_regular_truncate(fd, total_size, prealloc, errp);
|
||||
result = raw_regular_truncate(fd, file_opts->size, file_opts->preallocation,
|
||||
errp);
|
||||
if (result < 0) {
|
||||
goto out_close;
|
||||
}
|
||||
@ -2046,6 +2038,46 @@ out:
|
||||
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.
|
||||
* May change underlying file descriptor's file offset.
|
||||
@ -2277,6 +2309,7 @@ BlockDriver bdrv_file = {
|
||||
.bdrv_reopen_commit = raw_reopen_commit,
|
||||
.bdrv_reopen_abort = raw_reopen_abort,
|
||||
.bdrv_close = raw_close,
|
||||
.bdrv_co_create = raw_co_create,
|
||||
.bdrv_co_create_opts = raw_co_create_opts,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
.bdrv_co_block_status = raw_co_block_status,
|
||||
|
@ -3358,6 +3358,24 @@
|
||||
##
|
||||
{ '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:
|
||||
#
|
||||
@ -3429,7 +3447,7 @@
|
||||
'bochs': 'BlockdevCreateNotSupported',
|
||||
'cloop': 'BlockdevCreateNotSupported',
|
||||
'dmg': 'BlockdevCreateNotSupported',
|
||||
'file': 'BlockdevCreateNotSupported',
|
||||
'file': 'BlockdevCreateOptionsFile',
|
||||
'ftp': 'BlockdevCreateNotSupported',
|
||||
'ftps': 'BlockdevCreateNotSupported',
|
||||
'gluster': 'BlockdevCreateNotSupported',
|
||||
|
Loading…
Reference in New Issue
Block a user