From 927f11e1316c1cf96ab70d271f8b29d65dc75f7c Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 16 Jan 2018 16:04:21 +0100 Subject: 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 Reviewed-by: Max Reitz Reviewed-by: Eric Blake --- block/file-posix.c | 79 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 23 deletions(-) (limited to 'block') diff --git a/block/file-posix.c b/block/file-posix.c index 7f2cc63..fbc21a9 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -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, -- cgit v1.1