From patchwork Tue Jun 18 09:31:57 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Wang X-Patchwork-Id: 252201 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 41C4C2C009F for ; Tue, 18 Jun 2013 19:37:07 +1000 (EST) Received: from localhost ([::1]:33830 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UosLZ-0002l0-3O for incoming@patchwork.ozlabs.org; Tue, 18 Jun 2013 05:37:05 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51551) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UosIP-0007TT-CF for qemu-devel@nongnu.org; Tue, 18 Jun 2013 05:33:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UosIJ-0002Br-2o for qemu-devel@nongnu.org; Tue, 18 Jun 2013 05:33:49 -0400 Received: from mail-ie0-x22c.google.com ([2607:f8b0:4001:c03::22c]:64459) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UosII-0002Bm-KM for qemu-devel@nongnu.org; Tue, 18 Jun 2013 05:33:43 -0400 Received: by mail-ie0-f172.google.com with SMTP id 16so9582069iea.3 for ; Tue, 18 Jun 2013 02:33:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=AzTGxPEXsJn4QGcC4PzfWKKUvSXDDp5IjpxauLg1A44=; b=ZUO+5QTXH0SJHQx4eJeIY0dcmiWPGk23DJ2Oie08fvQuWTfbYncLGClrpEiUzk+/vQ /WQTH3tXHNhhuHjohXVshRrLuR1JgXrMDDZZj/GF+PImpKq2w5ICVYqYCC3WeuMdp335 GqM8swgTzeROVTTRkuFEtSGexoF6EHmwJVsJDSoISOHwiFpY7XAVZ8X8GyEs3oStiADB F0G4/u3y9zFNBsTlAK/4Z0+Bgjzxv0Z5Nciflp6SZ6lTImvC3JAPLyLzgWZuXGi6aK6B ezM+RKs/TaziCOtsOvOpztDtX3ZtyNNfr7nOzwpu0pyi63P0my3pJktRyWyPiv62nko/ /9IA== X-Received: by 10.50.101.73 with SMTP id fe9mr7442074igb.73.1371548022086; Tue, 18 Jun 2013 02:33:42 -0700 (PDT) Received: from 11.wdongxu.kvm58 ([202.108.130.153]) by mx.google.com with ESMTPSA id bc6sm373016igb.1.2013.06.18.02.33.37 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 18 Jun 2013 02:33:41 -0700 (PDT) From: Dong Xu Wang To: qemu-devel@nongnu.org Date: Tue, 18 Jun 2013 17:31:57 +0800 Message-Id: <1371547919-15654-6-git-send-email-wdongxu@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.11.7 In-Reply-To: <1371547919-15654-1-git-send-email-wdongxu@linux.vnet.ibm.com> References: <1371547919-15654-1-git-send-email-wdongxu@linux.vnet.ibm.com> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:4001:c03::22c Cc: kwolf@redhat.com, Dong Xu Wang , wdongxu@cn.ibm.com, armbru@redhat.com, stefanha@redhat.com Subject: [Qemu-devel] [PATCH V16 5/7] Use QemuOpts support in block layer X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch uses QemuOpts related functions in block layer, add a member bdrv_create_opts to BlockDriver struct, it returns a QemuOptsList pointer, which includes the image format's create options. And create options's primary consumer is block creating related functions, so modify them together. Signed-off-by: Dong Xu Wang --- v13->v14: 1) add block/ssh.c support. 2) fix memory leak after using qemu_opt_get_del. v12->v13: 1) split into 2 patches. one for block, one for QemuOpts funcitons. 2) fix leaking cco->opts. 3) other small fix. v11->v12: 1) create functions, such as qemu_opt_get_del and qemu_opt_replace_set. These functions works like origin code. 2) use QEMU_OPT_SIZE, not QEMU_OPT_NUMBER. 3) in bdrv_create, if opts is NULL, will create an empty one, so can discard if(opts) code safely. v10->v11: 1) qed.h move QED_DEFAULT_CLUSTER_SIZE from enum to macro, or qemu_opts_print produce un-expanded cluster_size. 2) In qcow2.c and qcow.c, bdrv_create_file(filename, NULL), NULL -> opts, or while using protocol, there will be an error. v8->v9: 1) add qemu_ prefix to gluster_create_opts. 2) fix bug: bdrv_gluster_unix and bdrv_gluster_rdma should also be converted. v7->v8: 1) rebase to upstream source tree. 2) add gluster.c, raw-win32.c, and rbd.c. v6->v7: 1) use osdep.h:stringify(), not redefining new macro. 2) preserve TODO comment. 3) fix typo. BLOCK_OPT_ENCRYPT->BLOCK_OPT_STATIC. 4) initialize disk_type even when opts is NULL. v5->v6: 1) judge if opts == NULL in block layer create functions. 2) use bdrv_create_file(filename, NULL) in qcow_create and cow_create funtion. 3) made more readable while using qemu_opt_get_number. block.c | 100 +++++++++++------------ block/cow.c | 52 ++++++------ block/gluster.c | 37 +++++---- block/iscsi.c | 31 ++++---- block/qcow.c | 67 ++++++++-------- block/qcow2.c | 199 +++++++++++++++++++++++++--------------------- block/qed.c | 108 +++++++++++++------------ block/qed.h | 2 +- block/raw-posix.c | 59 ++++++-------- block/raw-win32.c | 31 ++++---- block/raw.c | 30 ++++--- block/rbd.c | 62 +++++++-------- block/sheepdog.c | 81 +++++++++---------- block/ssh.c | 29 ++++--- block/vdi.c | 70 ++++++++-------- block/vmdk.c | 129 ++++++++++++++++-------------- block/vpc.c | 65 ++++++++------- block/vvfat.c | 11 +-- include/block/block.h | 5 +- include/block/block_int.h | 6 +- qemu-img.c | 65 ++++++++------- 21 files changed, 629 insertions(+), 610 deletions(-) diff --git a/block.c b/block.c index b88ad2f..0460366 100644 --- a/block.c +++ b/block.c @@ -364,7 +364,7 @@ BlockDriver *bdrv_find_whitelisted_format(const char *format_name, typedef struct CreateCo { BlockDriver *drv; char *filename; - QEMUOptionParameter *options; + QemuOpts *opts; int ret; } CreateCo; @@ -373,11 +373,10 @@ static void coroutine_fn bdrv_create_co_entry(void *opaque) CreateCo *cco = opaque; assert(cco->drv); - cco->ret = cco->drv->bdrv_create(cco->filename, cco->options); + cco->ret = cco->drv->bdrv_create(cco->filename, cco->opts); } -int bdrv_create(BlockDriver *drv, const char* filename, - QEMUOptionParameter *options) +int bdrv_create(BlockDriver *drv, const char* filename, QemuOpts *opts) { int ret; @@ -385,7 +384,7 @@ int bdrv_create(BlockDriver *drv, const char* filename, CreateCo cco = { .drv = drv, .filename = g_strdup(filename), - .options = options, + .opts = opts ?: qemu_opts_create_nofail(drv->bdrv_create_opts), .ret = NOT_DONE, }; @@ -408,11 +407,14 @@ int bdrv_create(BlockDriver *drv, const char* filename, ret = cco.ret; out: + if (!opts) { + qemu_opts_del(cco.opts); + } g_free(cco.filename); return ret; } -int bdrv_create_file(const char* filename, QEMUOptionParameter *options) +int bdrv_create_file(const char *filename, QemuOpts *opts) { BlockDriver *drv; @@ -421,7 +423,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options) return -ENOENT; } - return bdrv_create(drv, filename, options); + return bdrv_create(drv, filename, opts); } /* @@ -976,7 +978,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, BlockDriverState *bs1; int64_t total_size; BlockDriver *bdrv_qcow2; - QEMUOptionParameter *create_options; + QemuOpts *opts; char backing_filename[PATH_MAX]; if (qdict_size(options) != 0) { @@ -1015,19 +1017,16 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, } bdrv_qcow2 = bdrv_find_format("qcow2"); - create_options = parse_option_parameters("", bdrv_qcow2->create_options, - NULL); + opts = qemu_opts_create_nofail(bdrv_qcow2->bdrv_create_opts); - set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size); - set_option_parameter(create_options, BLOCK_OPT_BACKING_FILE, - backing_filename); + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_size); + qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, backing_filename); if (drv) { - set_option_parameter(create_options, BLOCK_OPT_BACKING_FMT, - drv->format_name); + qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, drv->format_name); } - ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options); - free_option_parameters(create_options); + ret = bdrv_create(bdrv_qcow2, tmp_filename, opts); + qemu_opts_del(opts); if (ret < 0) { goto fail; } @@ -4436,8 +4435,10 @@ void bdrv_img_create(const char *filename, const char *fmt, char *options, uint64_t img_size, int flags, Error **errp, bool quiet) { - QEMUOptionParameter *param = NULL, *create_options = NULL; - QEMUOptionParameter *backing_fmt, *backing_file, *size; + QemuOpts *opts = NULL; + QemuOptsList *create_opts = NULL; + const char *backing_fmt, *backing_file; + int64_t size; BlockDriverState *bs = NULL; BlockDriver *drv, *proto_drv; BlockDriver *backing_drv = NULL; @@ -4455,28 +4456,23 @@ void bdrv_img_create(const char *filename, const char *fmt, error_setg(errp, "Unknown protocol '%s'", filename); return; } - - create_options = append_option_parameters(create_options, - drv->create_options); - create_options = append_option_parameters(create_options, - proto_drv->create_options); - + create_opts = qemu_opts_append(drv->bdrv_create_opts, + proto_drv->bdrv_create_opts); /* Create parameter list with default values */ - param = parse_option_parameters("", create_options, param); + opts = qemu_opts_create_nofail(create_opts); - set_option_parameter_int(param, BLOCK_OPT_SIZE, img_size); + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size); /* Parse -o options */ if (options) { - param = parse_option_parameters(options, create_options, param); - if (param == NULL) { + if (qemu_opts_do_parse_replace(opts, options, NULL) != 0) { error_setg(errp, "Invalid options for file format '%s'.", fmt); goto out; } } if (base_filename) { - if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE, + if (qemu_opt_replace_set(opts, BLOCK_OPT_BACKING_FILE, base_filename)) { error_setg(errp, "Backing file not supported for file format '%s'", fmt); @@ -4485,39 +4481,37 @@ void bdrv_img_create(const char *filename, const char *fmt, } if (base_fmt) { - if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) { + if (qemu_opt_replace_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt)) { error_setg(errp, "Backing file format not supported for file " "format '%s'", fmt); goto out; } } - backing_file = get_option_parameter(param, BLOCK_OPT_BACKING_FILE); - if (backing_file && backing_file->value.s) { - if (!strcmp(filename, backing_file->value.s)) { + backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE); + if (backing_file) { + if (!strcmp(filename, backing_file)) { error_setg(errp, "Error: Trying to create an image with the " "same filename as the backing file"); goto out; } } - backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT); - if (backing_fmt && backing_fmt->value.s) { - backing_drv = bdrv_find_format(backing_fmt->value.s); + backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT); + if (backing_fmt) { + backing_drv = bdrv_find_format(backing_fmt); if (!backing_drv) { - error_setg(errp, "Unknown backing file format '%s'", - backing_fmt->value.s); + error_setg(errp, "Unknown backing file format '%s'", backing_fmt); goto out; } } // The size for the image must always be specified, with one exception: // If we are using a backing file, we can obtain the size from there - size = get_option_parameter(param, BLOCK_OPT_SIZE); - if (size && size->value.n == -1) { - if (backing_file && backing_file->value.s) { + size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0); + if (size == -1) { + if (backing_file) { uint64_t size; - char buf[32]; int back_flags; /* backing files always opened read-only */ @@ -4526,18 +4520,16 @@ void bdrv_img_create(const char *filename, const char *fmt, bs = bdrv_new(""); - ret = bdrv_open(bs, backing_file->value.s, NULL, back_flags, - backing_drv); + ret = bdrv_open(bs, backing_file, NULL, back_flags, backing_drv); if (ret < 0) { error_setg_errno(errp, -ret, "Could not open '%s'", - backing_file->value.s); + backing_file); goto out; } bdrv_get_geometry(bs, &size); size *= 512; - snprintf(buf, sizeof(buf), "%" PRId64, size); - set_option_parameter(param, BLOCK_OPT_SIZE, buf); + qemu_opt_replace_set_number(opts, BLOCK_OPT_SIZE, size); } else { error_setg(errp, "Image creation needs a size parameter"); goto out; @@ -4546,17 +4538,17 @@ void bdrv_img_create(const char *filename, const char *fmt, if (!quiet) { printf("Formatting '%s', fmt=%s ", filename, fmt); - print_option_parameters(param); + qemu_opts_print(opts); puts(""); } - ret = bdrv_create(drv, filename, param); + ret = bdrv_create(drv, filename, opts); if (ret < 0) { if (ret == -ENOTSUP) { error_setg(errp,"Formatting or formatting option not supported for " "file format '%s'", fmt); } else if (ret == -EFBIG) { const char *cluster_size_hint = ""; - if (get_option_parameter(create_options, BLOCK_OPT_CLUSTER_SIZE)) { + if (qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE, 0)) { cluster_size_hint = " (try using a larger cluster size)"; } error_setg(errp, "The image size is too large for file format '%s'%s", @@ -4568,8 +4560,10 @@ void bdrv_img_create(const char *filename, const char *fmt, } out: - free_option_parameters(create_options); - free_option_parameters(param); + if (opts) { + qemu_opts_del(opts); + } + qemu_opts_free(create_opts); if (bs) { bdrv_delete(bs); diff --git a/block/cow.c b/block/cow.c index 9f94599..d1fe5fe 100644 --- a/block/cow.c +++ b/block/cow.c @@ -255,7 +255,7 @@ static void cow_close(BlockDriverState *bs) { } -static int cow_create(const char *filename, QEMUOptionParameter *options) +static int cow_create(const char *filename, QemuOpts *opts) { struct cow_header_v2 cow_header; struct stat st; @@ -264,24 +264,18 @@ static int cow_create(const char *filename, QEMUOptionParameter *options) int ret; BlockDriverState *cow_bs; - /* Read out options */ - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - image_sectors = options->value.n / 512; - } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { - image_filename = options->value.s; - } - options++; - } + /* Read out opts */ + image_sectors = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512; + image_filename = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE); - ret = bdrv_create_file(filename, options); + ret = bdrv_create_file(filename, opts); if (ret < 0) { - return ret; + goto finish; } ret = bdrv_file_open(&cow_bs, filename, NULL, BDRV_O_RDWR); if (ret < 0) { - return ret; + goto finish; } memset(&cow_header, 0, sizeof(cow_header)); @@ -315,21 +309,27 @@ static int cow_create(const char *filename, QEMUOptionParameter *options) exit: bdrv_delete(cow_bs); +finish: + g_free((/* !const */ char*)image_filename); return ret; } -static QEMUOptionParameter cow_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { - .name = BLOCK_OPT_BACKING_FILE, - .type = OPT_STRING, - .help = "File name of a base image" - }, - { NULL } +static QemuOptsList cow_create_opts = { + .name = "cow-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(cow_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { + .name = BLOCK_OPT_BACKING_FILE, + .type = QEMU_OPT_STRING, + .help = "File name of a base image" + }, + { /* end of list */ } + } }; static BlockDriver bdrv_cow = { @@ -345,7 +345,7 @@ static BlockDriver bdrv_cow = { .bdrv_write = cow_co_write, .bdrv_co_is_allocated = cow_co_is_allocated, - .create_options = cow_create_options, + .bdrv_create_opts = &cow_create_opts, }; static void bdrv_cow_init(void) diff --git a/block/gluster.c b/block/gluster.c index 91acde2..4a48eab 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -365,8 +365,7 @@ out: return ret; } -static int qemu_gluster_create(const char *filename, - QEMUOptionParameter *options) +static int qemu_gluster_create(const char *filename, QemuOpts *opts) { struct glfs *glfs; struct glfs_fd *fd; @@ -380,12 +379,8 @@ static int qemu_gluster_create(const char *filename, goto out; } - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - total_size = options->value.n / BDRV_SECTOR_SIZE; - } - options++; - } + total_size = + qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE; fd = glfs_creat(glfs, gconf->image, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR); @@ -574,13 +569,17 @@ static void qemu_gluster_close(BlockDriverState *bs) glfs_fini(s->glfs); } -static QEMUOptionParameter qemu_gluster_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { NULL } +static QemuOptsList qemu_gluster_create_opts = { + .name = "qemu-gluster-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(qemu_gluster_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { /* end of list */ } + } }; static BlockDriver bdrv_gluster = { @@ -595,7 +594,7 @@ static BlockDriver bdrv_gluster = { .bdrv_aio_readv = qemu_gluster_aio_readv, .bdrv_aio_writev = qemu_gluster_aio_writev, .bdrv_aio_flush = qemu_gluster_aio_flush, - .create_options = qemu_gluster_create_options, + .bdrv_create_opts = &qemu_gluster_create_opts, }; static BlockDriver bdrv_gluster_tcp = { @@ -610,7 +609,7 @@ static BlockDriver bdrv_gluster_tcp = { .bdrv_aio_readv = qemu_gluster_aio_readv, .bdrv_aio_writev = qemu_gluster_aio_writev, .bdrv_aio_flush = qemu_gluster_aio_flush, - .create_options = qemu_gluster_create_options, + .bdrv_create_opts = &qemu_gluster_create_opts, }; static BlockDriver bdrv_gluster_unix = { @@ -625,7 +624,7 @@ static BlockDriver bdrv_gluster_unix = { .bdrv_aio_readv = qemu_gluster_aio_readv, .bdrv_aio_writev = qemu_gluster_aio_writev, .bdrv_aio_flush = qemu_gluster_aio_flush, - .create_options = qemu_gluster_create_options, + .bdrv_create_opts = &qemu_gluster_create_opts, }; static BlockDriver bdrv_gluster_rdma = { @@ -640,7 +639,7 @@ static BlockDriver bdrv_gluster_rdma = { .bdrv_aio_readv = qemu_gluster_aio_readv, .bdrv_aio_writev = qemu_gluster_aio_writev, .bdrv_aio_flush = qemu_gluster_aio_flush, - .create_options = qemu_gluster_create_options, + .bdrv_create_opts = &qemu_gluster_create_opts, }; static void bdrv_gluster_init(void) diff --git a/block/iscsi.c b/block/iscsi.c index f7199c1..ddb8f60 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1213,7 +1213,7 @@ static int iscsi_has_zero_init(BlockDriverState *bs) return 0; } -static int iscsi_create(const char *filename, QEMUOptionParameter *options) +static int iscsi_create(const char *filename, QemuOpts *opts) { int ret = 0; int64_t total_size = 0; @@ -1224,13 +1224,8 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options) memset(&bs, 0, sizeof(BlockDriverState)); /* Read out options */ - while (options && options->name) { - if (!strcmp(options->name, "size")) { - total_size = options->value.n / BDRV_SECTOR_SIZE; - } - options++; - } - + total_size = + qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE; bs.opaque = g_malloc0(sizeof(struct IscsiLun)); iscsilun = bs.opaque; @@ -1263,13 +1258,17 @@ out: return ret; } -static QEMUOptionParameter iscsi_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { NULL } +static QemuOptsList iscsi_create_opts = { + .name = "iscsi-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(iscsi_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { /* end of list */ } + } }; static BlockDriver bdrv_iscsi = { @@ -1280,7 +1279,7 @@ static BlockDriver bdrv_iscsi = { .bdrv_file_open = iscsi_open, .bdrv_close = iscsi_close, .bdrv_create = iscsi_create, - .create_options = iscsi_create_options, + .bdrv_create_opts = &iscsi_create_opts, .bdrv_getlength = iscsi_getlength, .bdrv_truncate = iscsi_truncate, diff --git a/block/qcow.c b/block/qcow.c index e2a64c7..e469436 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -651,7 +651,7 @@ static void qcow_close(BlockDriverState *bs) error_free(s->migration_blocker); } -static int qcow_create(const char *filename, QEMUOptionParameter *options) +static int qcow_create(const char *filename, QemuOpts *opts) { int header_size, backing_filename_len, l1_size, shift, i; QCowHeader header; @@ -662,26 +662,21 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options) int ret; BlockDriverState *qcow_bs; - /* Read out options */ - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - total_size = options->value.n / 512; - } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { - backing_file = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) { - flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0; - } - options++; + /* Read out opts */ + total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512; + backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE); + if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, 0)) { + flags |= BLOCK_FLAG_ENCRYPT; } - ret = bdrv_create_file(filename, options); + ret = bdrv_create_file(filename, opts); if (ret < 0) { - return ret; + goto finish; } ret = bdrv_file_open(&qcow_bs, filename, NULL, BDRV_O_RDWR); if (ret < 0) { - return ret; + goto finish; } ret = bdrv_truncate(qcow_bs, 0); @@ -752,6 +747,8 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options) ret = 0; exit: bdrv_delete(qcow_bs); +finish: + g_free((/* !const */ char*)backing_file); return ret; } @@ -864,24 +861,28 @@ static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) return 0; } - -static QEMUOptionParameter qcow_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { - .name = BLOCK_OPT_BACKING_FILE, - .type = OPT_STRING, - .help = "File name of a base image" - }, - { - .name = BLOCK_OPT_ENCRYPT, - .type = OPT_FLAG, - .help = "Encrypt the image" - }, - { NULL } +static QemuOptsList qcow_create_opts = { + .name = "qcow-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(qcow_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { + .name = BLOCK_OPT_BACKING_FILE, + .type = QEMU_OPT_STRING, + .help = "File name of a base image" + }, + { + .name = BLOCK_OPT_ENCRYPT, + .type = QEMU_OPT_BOOL, + .help = "Encrypt the image", + .def_value_str = "off" + }, + { /* end of list */ } + } }; static BlockDriver bdrv_qcow = { @@ -902,7 +903,7 @@ static BlockDriver bdrv_qcow = { .bdrv_write_compressed = qcow_write_compressed, .bdrv_get_info = qcow_get_info, - .create_options = qcow_create_options, + .bdrv_create_opts = &qcow_create_opts, }; static void bdrv_qcow_init(void) diff --git a/block/qcow2.c b/block/qcow2.c index 0fa5cb2..dcd63d1 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1232,10 +1232,11 @@ static int preallocate(BlockDriverState *bs) static int qcow2_create2(const char *filename, int64_t total_size, const char *backing_file, const char *backing_format, int flags, size_t cluster_size, int prealloc, - QEMUOptionParameter *options, int version) + QemuOpts *opts, int version) { /* Calculate cluster_bits */ int cluster_bits; + int ret = 0; cluster_bits = ffs(cluster_size) - 1; if (cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS || (1 << cluster_bits) != cluster_size) @@ -1243,7 +1244,8 @@ static int qcow2_create2(const char *filename, int64_t total_size, error_report( "Cluster size must be a power of two between %d and %dk", 1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - 10)); - return -EINVAL; + ret = -EINVAL; + goto finish; } /* @@ -1261,16 +1263,15 @@ static int qcow2_create2(const char *filename, int64_t total_size, BlockDriverState* bs; QCowHeader header; uint8_t* refcount_table; - int ret; - ret = bdrv_create_file(filename, options); + ret = bdrv_create_file(filename, opts); if (ret < 0) { - return ret; + goto finish; } ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR); if (ret < 0) { - return ret; + goto finish; } /* Write the header */ @@ -1363,10 +1364,13 @@ static int qcow2_create2(const char *filename, int64_t total_size, ret = 0; out: bdrv_delete(bs); +finish: + g_free((/* !const */ char*)backing_file); + g_free((/* !const */ char*)backing_format); return ret; } -static int qcow2_create(const char *filename, QEMUOptionParameter *options) +static int qcow2_create(const char *filename, QemuOpts *opts) { const char *backing_file = NULL; const char *backing_fmt = NULL; @@ -1375,61 +1379,67 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options) size_t cluster_size = DEFAULT_CLUSTER_SIZE; int prealloc = 0; int version = 2; + const char *buf; + int ret = 0; /* Read out options */ - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - sectors = options->value.n / 512; - } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { - backing_file = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) { - backing_fmt = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) { - flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0; - } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) { - if (options->value.n) { - cluster_size = options->value.n; - } - } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) { - if (!options->value.s || !strcmp(options->value.s, "off")) { - prealloc = 0; - } else if (!strcmp(options->value.s, "metadata")) { - prealloc = 1; - } else { - fprintf(stderr, "Invalid preallocation mode: '%s'\n", - options->value.s); - return -EINVAL; - } - } else if (!strcmp(options->name, BLOCK_OPT_COMPAT_LEVEL)) { - if (!options->value.s || !strcmp(options->value.s, "0.10")) { - version = 2; - } else if (!strcmp(options->value.s, "1.1")) { - version = 3; - } else { - fprintf(stderr, "Invalid compatibility level: '%s'\n", - options->value.s); - return -EINVAL; - } - } else if (!strcmp(options->name, BLOCK_OPT_LAZY_REFCOUNTS)) { - flags |= options->value.n ? BLOCK_FLAG_LAZY_REFCOUNTS : 0; - } - options++; + sectors = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512; + backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE); + backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT); + if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, 0)) { + flags |= BLOCK_FLAG_ENCRYPT; + } + cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, + DEFAULT_CLUSTER_SIZE); + buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC); + if (!buf || !strcmp(buf, "off")) { + prealloc = 0; + } else if (!strcmp(buf, "metadata")) { + prealloc = 1; + } else { + fprintf(stderr, "Invalid preallocation mode: '%s'\n", + buf); + ret = -EINVAL; + goto finish; + } + g_free((/* !const */ char*)buf); + buf = qemu_opt_get_del(opts, BLOCK_OPT_COMPAT_LEVEL); + if (!buf || !strcmp(buf, "0.10")) { + version = 2; + } else if (!strcmp(buf, "1.1")) { + version = 3; + } else { + fprintf(stderr, "Invalid compatibility level: '%s'\n", + buf); + ret = -EINVAL; + goto finish; + } + + if (qemu_opt_get_bool_del(opts, BLOCK_OPT_LAZY_REFCOUNTS, 0)) { + flags |= BLOCK_FLAG_LAZY_REFCOUNTS; } if (backing_file && prealloc) { fprintf(stderr, "Backing file and preallocation cannot be used at " "the same time\n"); - return -EINVAL; + ret = -EINVAL; + goto finish; } if (version < 3 && (flags & BLOCK_FLAG_LAZY_REFCOUNTS)) { fprintf(stderr, "Lazy refcounts only supported with compatibility " "level 1.1 and above (use compat=1.1 or greater)\n"); - return -EINVAL; + ret = -EINVAL; + goto finish; } return qcow2_create2(filename, sectors, backing_file, backing_fmt, flags, - cluster_size, prealloc, options, version); + cluster_size, prealloc, opts, version); +finish: + g_free((/* !const */ char*)backing_file); + g_free((/* !const */ char*)backing_fmt); + g_free((/* !const */ char*)buf); + return ret; } static int qcow2_make_empty(BlockDriverState *bs) @@ -1704,49 +1714,55 @@ static int qcow2_load_vmstate(BlockDriverState *bs, uint8_t *buf, return ret; } -static QEMUOptionParameter qcow2_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { - .name = BLOCK_OPT_COMPAT_LEVEL, - .type = OPT_STRING, - .help = "Compatibility level (0.10 or 1.1)" - }, - { - .name = BLOCK_OPT_BACKING_FILE, - .type = OPT_STRING, - .help = "File name of a base image" - }, - { - .name = BLOCK_OPT_BACKING_FMT, - .type = OPT_STRING, - .help = "Image format of the base image" - }, - { - .name = BLOCK_OPT_ENCRYPT, - .type = OPT_FLAG, - .help = "Encrypt the image" - }, - { - .name = BLOCK_OPT_CLUSTER_SIZE, - .type = OPT_SIZE, - .help = "qcow2 cluster size", - .value = { .n = DEFAULT_CLUSTER_SIZE }, - }, - { - .name = BLOCK_OPT_PREALLOC, - .type = OPT_STRING, - .help = "Preallocation mode (allowed values: off, metadata)" - }, - { - .name = BLOCK_OPT_LAZY_REFCOUNTS, - .type = OPT_FLAG, - .help = "Postpone refcount updates", - }, - { NULL } +static QemuOptsList qcow2_create_opts = { + .name = "qcow2-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(qcow2_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { + .name = BLOCK_OPT_COMPAT_LEVEL, + .type = QEMU_OPT_STRING, + .help = "Compatibility level (0.10 or 1.1)" + }, + { + .name = BLOCK_OPT_BACKING_FILE, + .type = QEMU_OPT_STRING, + .help = "File name of a base image" + }, + { + .name = BLOCK_OPT_BACKING_FMT, + .type = QEMU_OPT_STRING, + .help = "Image format of the base image" + }, + { + .name = BLOCK_OPT_ENCRYPT, + .type = QEMU_OPT_BOOL, + .help = "Encrypt the image", + .def_value_str = "off" + }, + { + .name = BLOCK_OPT_CLUSTER_SIZE, + .type = QEMU_OPT_SIZE, + .help = "qcow2 cluster size", + .def_value_str = stringify(DEFAULT_CLUSTER_SIZE) + }, + { + .name = BLOCK_OPT_PREALLOC, + .type = QEMU_OPT_STRING, + .help = "Preallocation mode (allowed values: off, metadata)" + }, + { + .name = BLOCK_OPT_LAZY_REFCOUNTS, + .type = QEMU_OPT_BOOL, + .help = "Postpone refcount updates", + .def_value_str = "off" + }, + { /* end of list */ } + } }; static BlockDriver bdrv_qcow2 = { @@ -1784,8 +1800,9 @@ static BlockDriver bdrv_qcow2 = { .bdrv_invalidate_cache = qcow2_invalidate_cache, - .create_options = qcow2_create_options, .bdrv_check = qcow2_check, + + .bdrv_create_opts = &qcow2_create_opts, }; static void bdrv_qcow2_init(void) diff --git a/block/qed.c b/block/qed.c index 4651403..88daf22 100644 --- a/block/qed.c +++ b/block/qed.c @@ -555,12 +555,12 @@ static int qed_create(const char *filename, uint32_t cluster_size, ret = bdrv_create_file(filename, NULL); if (ret < 0) { - return ret; + goto finish; } ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR | BDRV_O_CACHE_WB); if (ret < 0) { - return ret; + goto finish; } /* File must start empty and grow, check truncate is supported */ @@ -600,55 +600,57 @@ static int qed_create(const char *filename, uint32_t cluster_size, out: g_free(l1_table); bdrv_delete(bs); +finish: + g_free((/* !const */ char*)backing_file); + g_free((/* !const */ char*)backing_fmt); return ret; } -static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options) +static int bdrv_qed_create(const char *filename, QemuOpts *opts) { uint64_t image_size = 0; uint32_t cluster_size = QED_DEFAULT_CLUSTER_SIZE; uint32_t table_size = QED_DEFAULT_TABLE_SIZE; const char *backing_file = NULL; const char *backing_fmt = NULL; + int ret = 0; - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - image_size = options->value.n; - } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { - backing_file = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) { - backing_fmt = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) { - if (options->value.n) { - cluster_size = options->value.n; - } - } else if (!strcmp(options->name, BLOCK_OPT_TABLE_SIZE)) { - if (options->value.n) { - table_size = options->value.n; - } - } - options++; - } + image_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0); + backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE); + backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT); + cluster_size = qemu_opt_get_size_del(opts, + BLOCK_OPT_CLUSTER_SIZE, + QED_DEFAULT_CLUSTER_SIZE); + table_size = qemu_opt_get_size_del(opts, BLOCK_OPT_TABLE_SIZE, + QED_DEFAULT_TABLE_SIZE); if (!qed_is_cluster_size_valid(cluster_size)) { fprintf(stderr, "QED cluster size must be within range [%u, %u] and power of 2\n", QED_MIN_CLUSTER_SIZE, QED_MAX_CLUSTER_SIZE); - return -EINVAL; + ret = -EINVAL; + goto finish; } if (!qed_is_table_size_valid(table_size)) { fprintf(stderr, "QED table size must be within range [%u, %u] and power of 2\n", QED_MIN_TABLE_SIZE, QED_MAX_TABLE_SIZE); - return -EINVAL; + ret = -EINVAL; + goto finish; } if (!qed_is_image_size_valid(image_size, cluster_size, table_size)) { fprintf(stderr, "QED image size must be a non-zero multiple of " "cluster size and less than %" PRIu64 " bytes\n", qed_max_image_size(cluster_size, table_size)); - return -EINVAL; + ret = -EINVAL; + goto finish; } return qed_create(filename, cluster_size, image_size, table_size, backing_file, backing_fmt); + +finish: + g_free((/* !const */ char*)backing_file); + g_free((/* !const */ char*)backing_fmt); + return ret; } typedef struct { @@ -1537,36 +1539,44 @@ static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result, return qed_check(s, result, !!fix); } -static QEMUOptionParameter qed_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size (in bytes)" - }, { - .name = BLOCK_OPT_BACKING_FILE, - .type = OPT_STRING, - .help = "File name of a base image" - }, { - .name = BLOCK_OPT_BACKING_FMT, - .type = OPT_STRING, - .help = "Image format of the base image" - }, { - .name = BLOCK_OPT_CLUSTER_SIZE, - .type = OPT_SIZE, - .help = "Cluster size (in bytes)", - .value = { .n = QED_DEFAULT_CLUSTER_SIZE }, - }, { - .name = BLOCK_OPT_TABLE_SIZE, - .type = OPT_SIZE, - .help = "L1/L2 table size (in clusters)" - }, - { /* end of list */ } +static QemuOptsList qed_create_opts = { + .name = "qed-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(qed_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { + .name = BLOCK_OPT_BACKING_FILE, + .type = QEMU_OPT_STRING, + .help = "File name of a base image" + }, + { + .name = BLOCK_OPT_BACKING_FMT, + .type = QEMU_OPT_STRING, + .help = "Image format of the base image" + }, + { + .name = BLOCK_OPT_CLUSTER_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Cluster size (in bytes)", + .def_value_str = stringify(QED_DEFAULT_CLUSTER_SIZE), + }, + { + .name = BLOCK_OPT_TABLE_SIZE, + .type = QEMU_OPT_SIZE, + .help = "L1/L2 table size (in clusters)" + }, + { /* end of list */ } + } }; static BlockDriver bdrv_qed = { .format_name = "qed", .instance_size = sizeof(BDRVQEDState), - .create_options = qed_create_options, + .bdrv_create_opts = &qed_create_opts, .bdrv_probe = bdrv_qed_probe, .bdrv_rebind = bdrv_qed_rebind, diff --git a/block/qed.h b/block/qed.h index 2b4dded..99a7726 100644 --- a/block/qed.h +++ b/block/qed.h @@ -43,6 +43,7 @@ * * All fields are little-endian on disk. */ +#define QED_DEFAULT_CLUSTER_SIZE 65536 enum { QED_MAGIC = 'Q' | 'E' << 8 | 'D' << 16 | '\0' << 24, @@ -69,7 +70,6 @@ enum { */ QED_MIN_CLUSTER_SIZE = 4 * 1024, /* in bytes */ QED_MAX_CLUSTER_SIZE = 64 * 1024 * 1024, - QED_DEFAULT_CLUSTER_SIZE = 64 * 1024, /* Allocated clusters are tracked using a 2-level pagetable. Table size is * a multiple of clusters so large maximum image sizes can be supported diff --git a/block/raw-posix.c b/block/raw-posix.c index c0ccf27..66e58c1 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -123,6 +123,19 @@ #define MAX_BLOCKSIZE 4096 +static QemuOptsList file_proto_create_opts = { + .name = "file-proto-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(file_proto_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { /* end of list */ } + } +}; + typedef struct BDRVRawState { int fd; int type; @@ -1040,19 +1053,14 @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs) return (int64_t)st.st_blocks * 512; } -static int raw_create(const char *filename, QEMUOptionParameter *options) +static int raw_create(const char *filename, QemuOpts *opts) { int fd; int result = 0; int64_t total_size = 0; - /* Read out options */ - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - total_size = options->value.n / BDRV_SECTOR_SIZE; - } - options++; - } + total_size = + qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE; fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); @@ -1179,15 +1187,6 @@ static coroutine_fn BlockDriverAIOCB *raw_aio_discard(BlockDriverState *bs, cb, opaque, QEMU_AIO_DISCARD); } -static QEMUOptionParameter raw_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { NULL } -}; - static BlockDriver bdrv_file = { .format_name = "file", .protocol_name = "file", @@ -1210,8 +1209,7 @@ static BlockDriver bdrv_file = { .bdrv_getlength = raw_getlength, .bdrv_get_allocated_file_size = raw_get_allocated_file_size, - - .create_options = raw_create_options, + .bdrv_create_opts = &file_proto_create_opts, }; /***********************************************/ @@ -1496,20 +1494,15 @@ static coroutine_fn BlockDriverAIOCB *hdev_aio_discard(BlockDriverState *bs, cb, opaque, QEMU_AIO_DISCARD|QEMU_AIO_BLKDEV); } -static int hdev_create(const char *filename, QEMUOptionParameter *options) +static int hdev_create(const char *filename, QemuOpts *opts) { int fd; int ret = 0; struct stat stat_buf; int64_t total_size = 0; - /* Read out options */ - while (options && options->name) { - if (!strcmp(options->name, "size")) { - total_size = options->value.n / BDRV_SECTOR_SIZE; - } - options++; - } + total_size = + qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE; fd = qemu_open(filename, O_WRONLY | O_BINARY); if (fd < 0) @@ -1533,7 +1526,7 @@ static int hdev_has_zero_init(BlockDriverState *bs) static BlockDriver bdrv_host_device = { .format_name = "host_device", - .protocol_name = "host_device", + .protocol_name = "host_device", .instance_size = sizeof(BDRVRawState), .bdrv_probe_device = hdev_probe_device, .bdrv_file_open = hdev_open, @@ -1542,7 +1535,6 @@ static BlockDriver bdrv_host_device = { .bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_abort = raw_reopen_abort, .bdrv_create = hdev_create, - .create_options = raw_create_options, .bdrv_has_zero_init = hdev_has_zero_init, .bdrv_aio_readv = raw_aio_readv, @@ -1551,9 +1543,10 @@ static BlockDriver bdrv_host_device = { .bdrv_aio_discard = hdev_aio_discard, .bdrv_truncate = raw_truncate, - .bdrv_getlength = raw_getlength, + .bdrv_getlength = raw_getlength, .bdrv_get_allocated_file_size = raw_get_allocated_file_size, + .bdrv_create_opts = &file_proto_create_opts, /* generic scsi device */ #ifdef __linux__ @@ -1667,7 +1660,6 @@ static BlockDriver bdrv_host_floppy = { .bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_abort = raw_reopen_abort, .bdrv_create = hdev_create, - .create_options = raw_create_options, .bdrv_has_zero_init = hdev_has_zero_init, .bdrv_aio_readv = raw_aio_readv, @@ -1683,6 +1675,7 @@ static BlockDriver bdrv_host_floppy = { .bdrv_is_inserted = floppy_is_inserted, .bdrv_media_changed = floppy_media_changed, .bdrv_eject = floppy_eject, + .bdrv_create_opts = &file_proto_create_opts, }; static int cdrom_open(BlockDriverState *bs, QDict *options, int flags) @@ -1769,7 +1762,6 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_abort = raw_reopen_abort, .bdrv_create = hdev_create, - .create_options = raw_create_options, .bdrv_has_zero_init = hdev_has_zero_init, .bdrv_aio_readv = raw_aio_readv, @@ -1789,6 +1781,8 @@ static BlockDriver bdrv_host_cdrom = { /* generic scsi device */ .bdrv_ioctl = hdev_ioctl, .bdrv_aio_ioctl = hdev_aio_ioctl, + + .bdrv_create_opts = &file_proto_create_opts, }; #endif /* __linux__ */ @@ -1891,7 +1885,6 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_abort = raw_reopen_abort, .bdrv_create = hdev_create, - .create_options = raw_create_options, .bdrv_has_zero_init = hdev_has_zero_init, .bdrv_aio_readv = raw_aio_readv, diff --git a/block/raw-win32.c b/block/raw-win32.c index 7c03b6d..db00105 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -420,18 +420,15 @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs) return st.st_size; } -static int raw_create(const char *filename, QEMUOptionParameter *options) +static int raw_create(const char *filename, QemuOpts *opts) { int fd; int64_t total_size = 0; /* Read out options */ - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - total_size = options->value.n / 512; - } - options++; - } + + total_size = + qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512; fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); @@ -443,13 +440,17 @@ static int raw_create(const char *filename, QEMUOptionParameter *options) return 0; } -static QEMUOptionParameter raw_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { NULL } +static QemuOptsList raw_create_opts = { + .name = "raw-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { /* end of list */ } + } }; static BlockDriver bdrv_file = { @@ -469,7 +470,7 @@ static BlockDriver bdrv_file = { .bdrv_get_allocated_file_size = raw_get_allocated_file_size, - .create_options = raw_create_options, + .bdrv_create_opts = &raw_create_opts, }; /***********************************************/ diff --git a/block/raw.c b/block/raw.c index ce10422..f526ab8 100644 --- a/block/raw.c +++ b/block/raw.c @@ -95,18 +95,22 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs, return bdrv_aio_ioctl(bs->file, req, buf, cb, opaque); } -static int raw_create(const char *filename, QEMUOptionParameter *options) -{ - return bdrv_create_file(filename, options); -} - -static QEMUOptionParameter raw_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { NULL } +static int raw_create(const char *filename, QemuOpts *opts) +{ + return bdrv_create_file(filename, opts); +} + +static QemuOptsList raw_create_opts = { + .name = "raw-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { /* end of list */ } + } }; static int raw_has_zero_init(BlockDriverState *bs) @@ -143,8 +147,8 @@ static BlockDriver bdrv_raw = { .bdrv_aio_ioctl = raw_aio_ioctl, .bdrv_create = raw_create, - .create_options = raw_create_options, .bdrv_has_zero_init = raw_has_zero_init, + .bdrv_create_opts = &raw_create_opts, }; static void bdrv_raw_init(void) diff --git a/block/rbd.c b/block/rbd.c index 0f2608b..9cc8684 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -288,7 +288,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf) return ret; } -static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options) +static int qemu_rbd_create(const char *filename, QemuOpts *opts) { int64_t bytes = 0; int64_t objsize; @@ -311,24 +311,18 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options) } /* Read out options */ - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - bytes = options->value.n; - } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) { - if (options->value.n) { - objsize = options->value.n; - if ((objsize - 1) & objsize) { /* not a power of 2? */ - error_report("obj size needs to be power of 2"); - return -EINVAL; - } - if (objsize < 4096) { - error_report("obj size too small"); - return -EINVAL; - } - obj_order = ffs(objsize) - 1; - } + bytes = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0); + objsize = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, 0); + if (objsize) { + if ((objsize - 1) & objsize) { /* not a power of 2? */ + error_report("obj size needs to be power of 2"); + return -EINVAL; + } + if (objsize < 4096) { + error_report("obj size too small"); + return -EINVAL; } - options++; + obj_order = ffs(objsize) - 1; } clientname = qemu_rbd_parse_clientname(conf, clientname_buf); @@ -976,20 +970,24 @@ static BlockDriverAIOCB* qemu_rbd_aio_discard(BlockDriverState *bs, } #endif -static QEMUOptionParameter qemu_rbd_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { - .name = BLOCK_OPT_CLUSTER_SIZE, - .type = OPT_SIZE, - .help = "RBD object size" - }, - {NULL} +static QemuOptsList rbd_create_opts = { + .name = "rbd-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(rbd_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { + .name = BLOCK_OPT_CLUSTER_SIZE, + .type = QEMU_OPT_SIZE, + .help = "RBD object size", + .def_value_str = stringify(0), + }, + { /* end of list */ } + } }; - static BlockDriver bdrv_rbd = { .format_name = "rbd", .instance_size = sizeof(BDRVRBDState), @@ -997,7 +995,7 @@ static BlockDriver bdrv_rbd = { .bdrv_close = qemu_rbd_close, .bdrv_create = qemu_rbd_create, .bdrv_get_info = qemu_rbd_getinfo, - .create_options = qemu_rbd_create_options, + .bdrv_create_opts = &rbd_create_opts, .bdrv_getlength = qemu_rbd_getlength, .bdrv_truncate = qemu_rbd_truncate, .protocol_name = "rbd", diff --git a/block/sheepdog.c b/block/sheepdog.c index 1b7c3f1..1976c15 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1454,12 +1454,12 @@ out: return ret; } -static int sd_create(const char *filename, QEMUOptionParameter *options) +static int sd_create(const char *filename, QemuOpts *opts) { int ret = 0; uint32_t vid = 0, base_vid = 0; int64_t vdi_size = 0; - char *backing_file = NULL; + const char *backing_file = NULL, *buf = NULL; BDRVSheepdogState *s; char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN]; uint32_t snapid; @@ -1478,26 +1478,18 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) goto out; } - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - vdi_size = options->value.n; - } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { - backing_file = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) { - if (!options->value.s || !strcmp(options->value.s, "off")) { - prealloc = false; - } else if (!strcmp(options->value.s, "full")) { - prealloc = true; - } else { - error_report("Invalid preallocation mode: '%s'", - options->value.s); - ret = -EINVAL; - goto out; - } - } - options++; + vdi_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0); + backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE); + buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC); + if (!buf || !strcmp(buf, "off")) { + prealloc = false; + } else if (!strcmp(buf, "full")) { + prealloc = true; + } else { + error_report("Invalid preallocation mode: '%s'", buf); + ret = -EINVAL; + goto out; } - if (vdi_size > SD_MAX_VDI_SIZE) { error_report("too big image size"); ret = -EINVAL; @@ -1542,6 +1534,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) ret = sd_prealloc(filename); out: + g_free((/* !const */ char*)backing_file); + g_free((/* !const */ char*)buf); g_free(s); return ret; } @@ -2259,7 +2253,6 @@ static int sd_load_vmstate(BlockDriverState *bs, uint8_t *data, return do_load_save_vmstate(s, data, pos, size, 1); } - static coroutine_fn int sd_co_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors) { @@ -2321,23 +2314,27 @@ sd_co_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, return ret; } -static QEMUOptionParameter sd_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { - .name = BLOCK_OPT_BACKING_FILE, - .type = OPT_STRING, - .help = "File name of a base image" - }, - { - .name = BLOCK_OPT_PREALLOC, - .type = OPT_STRING, - .help = "Preallocation mode (allowed values: off, full)" - }, - { NULL } +static QemuOptsList sd_create_opts = { + .name = "sheepdog-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(sd_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { + .name = BLOCK_OPT_BACKING_FILE, + .type = QEMU_OPT_STRING, + .help = "File name of a base image" + }, + { + .name = BLOCK_OPT_PREALLOC, + .type = QEMU_OPT_STRING, + .help = "Preallocation mode (allowed values: off, full)" + }, + { /* end of list */ } + } }; static BlockDriver bdrv_sheepdog = { @@ -2364,7 +2361,7 @@ static BlockDriver bdrv_sheepdog = { .bdrv_save_vmstate = sd_save_vmstate, .bdrv_load_vmstate = sd_load_vmstate, - .create_options = sd_create_options, + .bdrv_create_opts = &sd_create_opts, }; static BlockDriver bdrv_sheepdog_tcp = { @@ -2391,7 +2388,7 @@ static BlockDriver bdrv_sheepdog_tcp = { .bdrv_save_vmstate = sd_save_vmstate, .bdrv_load_vmstate = sd_load_vmstate, - .create_options = sd_create_options, + .bdrv_create_opts = &sd_create_opts, }; static BlockDriver bdrv_sheepdog_unix = { @@ -2418,7 +2415,7 @@ static BlockDriver bdrv_sheepdog_unix = { .bdrv_save_vmstate = sd_save_vmstate, .bdrv_load_vmstate = sd_load_vmstate, - .create_options = sd_create_options, + .bdrv_create_opts = &sd_create_opts, }; static void bdrv_sheepdog_init(void) diff --git a/block/ssh.c b/block/ssh.c index 246a70d..13d33d3 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -641,16 +641,20 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags) return ret; } -static QEMUOptionParameter ssh_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { NULL } +static QemuOptsList ssh_create_opts = { + .name = "ssh-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(ssh_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { /* end of list */ } + } }; -static int ssh_create(const char *filename, QEMUOptionParameter *options) +static int ssh_create(const char *filename, QemuOpts *opts) { int r, ret; Error *local_err = NULL; @@ -663,12 +667,7 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options) ssh_state_init(&s); /* Get desired file size. */ - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - total_size = options->value.n; - } - options++; - } + total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0); DPRINTF("total_size=%" PRIi64, total_size); uri_options = qdict_new(); @@ -1041,7 +1040,7 @@ static BlockDriver bdrv_ssh = { .bdrv_co_writev = ssh_co_writev, .bdrv_getlength = ssh_getlength, .bdrv_co_flush_to_disk = ssh_co_flush, - .create_options = ssh_create_options, + .bdrv_create_opts = &ssh_create_opts, }; static void bdrv_ssh_init(void) diff --git a/block/vdi.c b/block/vdi.c index 2662d89..0e9d1f8 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -633,7 +633,7 @@ static int vdi_co_write(BlockDriverState *bs, return ret; } -static int vdi_create(const char *filename, QEMUOptionParameter *options) +static int vdi_create(const char *filename, QemuOpts *opts) { int fd; int result = 0; @@ -648,25 +648,18 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options) logout("\n"); /* Read out options. */ - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - bytes = options->value.n; + bytes = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0); #if defined(CONFIG_VDI_BLOCK_SIZE) - } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) { - if (options->value.n) { - /* TODO: Additional checks (SECTOR_SIZE * 2^n, ...). */ - block_size = options->value.n; - } + /* TODO: Additional checks (SECTOR_SIZE * 2^n, ...). */ + block_size = qemu_opt_get_size_del(opts, + BLOCK_OPT_CLUSTER_SIZE, + DEFAULT_CLUSTER_SIZE); #endif #if defined(CONFIG_VDI_STATIC_IMAGE) - } else if (!strcmp(options->name, BLOCK_OPT_STATIC)) { - if (options->value.n) { - image_type = VDI_TYPE_STATIC; - } -#endif - } - options++; + if (qemu_opt_get_bool_del(opts, BLOCK_OPT_STATIC, 0)) { + image_type = VDI_TYPE_STATIC; } +#endif fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, @@ -746,29 +739,34 @@ static void vdi_close(BlockDriverState *bs) error_free(s->migration_blocker); } -static QEMUOptionParameter vdi_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, +static QemuOptsList vdi_create_opts = { + .name = "vdi-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(vdi_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, #if defined(CONFIG_VDI_BLOCK_SIZE) - { - .name = BLOCK_OPT_CLUSTER_SIZE, - .type = OPT_SIZE, - .help = "VDI cluster (block) size", - .value = { .n = DEFAULT_CLUSTER_SIZE }, - }, + { + .name = BLOCK_OPT_CLUSTER_SIZE, + .type = QEMU_OPT_SIZE, + .help = "VDI cluster (block) size", + .def_value_str = stringify(DEFAULT_CLUSTER_SIZE) + }, #endif #if defined(CONFIG_VDI_STATIC_IMAGE) - { - .name = BLOCK_OPT_STATIC, - .type = OPT_FLAG, - .help = "VDI static (pre-allocated) image" - }, + { + .name = BLOCK_OPT_STATIC, + .type = QEMU_OPT_BOOL, + .help = "VDI static (pre-allocated) image", + .def_value_str = "off" + }, #endif - /* TODO: An additional option to set UUID values might be useful. */ - { NULL } + /* TODO: An additional option to set UUID values might be useful. */ + { /* end of list */ } + } }; static BlockDriver bdrv_vdi = { @@ -789,7 +787,7 @@ static BlockDriver bdrv_vdi = { .bdrv_get_info = vdi_get_info, - .create_options = vdi_create_options, + .bdrv_create_opts = &vdi_create_opts, .bdrv_check = vdi_check, }; diff --git a/block/vmdk.c b/block/vmdk.c index 65ae011..dfaba11 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1517,7 +1517,7 @@ static int relative_path(char *dest, int dest_size, return VMDK_OK; } -static int vmdk_create(const char *filename, QEMUOptionParameter *options) +static int vmdk_create(const char *filename, QemuOpts *opts) { int fd, idx = 0; char desc[BUF_SIZE]; @@ -1557,24 +1557,19 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) "ddb.adapterType = \"%s\"\n"; if (filename_decompose(filename, path, prefix, postfix, PATH_MAX)) { - return -EINVAL; + ret = -EINVAL; + goto finish; } - /* Read out options */ - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - total_size = options->value.n; - } else if (!strcmp(options->name, BLOCK_OPT_ADAPTER_TYPE)) { - adapter_type = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { - backing_file = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) { - flags |= options->value.n ? BLOCK_FLAG_COMPAT6 : 0; - } else if (!strcmp(options->name, BLOCK_OPT_SUBFMT)) { - fmt = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_ZEROED_GRAIN)) { - zeroed_grain |= options->value.n; - } - options++; + /* Read out opts */ + total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0); + adapter_type = qemu_opt_get_del(opts, BLOCK_OPT_ADAPTER_TYPE); + backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE); + if (qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, 0)) { + flags |= BLOCK_FLAG_COMPAT6; + } + fmt = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT); + if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ZEROED_GRAIN, 0)) { + zeroed_grain = true; } if (!adapter_type) { adapter_type = "ide"; @@ -1583,7 +1578,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) strcmp(adapter_type, "lsilogic") && strcmp(adapter_type, "legacyESX")) { fprintf(stderr, "VMDK: Unknown adapter type: '%s'.\n", adapter_type); - return -EINVAL; + ret = -EINVAL; + goto finish; } if (strcmp(adapter_type, "ide") != 0) { /* that's the number of heads with which vmware operates when @@ -1599,7 +1595,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) strcmp(fmt, "twoGbMaxExtentFlat") && strcmp(fmt, "streamOptimized")) { fprintf(stderr, "VMDK: Unknown subformat: %s\n", fmt); - return -EINVAL; + ret = -EINVAL; + goto finish; } split = !(strcmp(fmt, "twoGbMaxExtentFlat") && strcmp(fmt, "twoGbMaxExtentSparse")); @@ -1613,7 +1610,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) } if (flat && backing_file) { /* not supporting backing file for flat image */ - return -ENOTSUP; + ret = -ENOTSUP; + goto finish; } if (backing_file) { char parent_filename[PATH_MAX]; @@ -1621,11 +1619,12 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) ret = bdrv_open(bs, backing_file, NULL, 0, NULL); if (ret != 0) { bdrv_delete(bs); - return ret; + goto finish; } if (strcmp(bs->drv->format_name, "vmdk")) { bdrv_delete(bs); - return -EINVAL; + ret = -EINVAL; + goto finish; } parent_cid = vmdk_read_cid(bs, 0); bdrv_delete(bs); @@ -1690,7 +1689,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) 0644); } if (fd < 0) { - return -errno; + ret = -errno; + goto finish; } /* the descriptor offset = 0x200 */ if (!split && !flat && 0x200 != lseek(fd, 0x200, SEEK_SET)) { @@ -1705,6 +1705,9 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) ret = 0; exit: qemu_close(fd); +finish: + g_free((/* !const */ char*)adapter_type); + g_free((/* !const */ char*)backing_file); return ret; } @@ -1757,41 +1760,47 @@ static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs) return ret; } -static QEMUOptionParameter vmdk_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { - .name = BLOCK_OPT_ADAPTER_TYPE, - .type = OPT_STRING, - .help = "Virtual adapter type, can be one of " - "ide (default), lsilogic, buslogic or legacyESX" - }, - { - .name = BLOCK_OPT_BACKING_FILE, - .type = OPT_STRING, - .help = "File name of a base image" - }, - { - .name = BLOCK_OPT_COMPAT6, - .type = OPT_FLAG, - .help = "VMDK version 6 image" - }, - { - .name = BLOCK_OPT_SUBFMT, - .type = OPT_STRING, - .help = - "VMDK flat extent format, can be one of " - "{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse | twoGbMaxExtentFlat | streamOptimized} " - }, - { - .name = BLOCK_OPT_ZEROED_GRAIN, - .type = OPT_FLAG, - .help = "Enable efficient zero writes using the zeroed-grain GTE feature" - }, - { NULL } +static QemuOptsList vmdk_create_opts = { + .name = "vmdk-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(vmdk_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { + .name = BLOCK_OPT_ADAPTER_TYPE, + .type = QEMU_OPT_STRING, + .help = "Virtual adapter type, can be one of " + "ide (default), lsilogic, buslogic or legacyESX" + }, + { + .name = BLOCK_OPT_BACKING_FILE, + .type = QEMU_OPT_STRING, + .help = "File name of a base image" + }, + { + .name = BLOCK_OPT_COMPAT6, + .type = QEMU_OPT_BOOL, + .help = "VMDK version 6 image", + .def_value_str = "off" + }, + { + .name = BLOCK_OPT_SUBFMT, + .type = QEMU_OPT_STRING, + .help = + "VMDK flat extent format, can be one of " + "{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse | twoGbMaxExtentFlat | streamOptimized} " + }, + { + .name = BLOCK_OPT_ZEROED_GRAIN, + .type = QEMU_OPT_BOOL, + .help = "Enable efficient zero writes " + "using the zeroed-grain GTE feature" + }, + { /* end of list */ } + } }; static BlockDriver bdrv_vmdk = { @@ -1809,7 +1818,7 @@ static BlockDriver bdrv_vmdk = { .bdrv_co_is_allocated = vmdk_co_is_allocated, .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size, - .create_options = vmdk_create_options, + .bdrv_create_opts = &vmdk_create_opts, }; static void bdrv_vmdk_init(void) diff --git a/block/vpc.c b/block/vpc.c index 3cad52e..78b01dc 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -683,40 +683,39 @@ static int create_fixed_disk(int fd, uint8_t *buf, int64_t total_size) return ret; } -static int vpc_create(const char *filename, QEMUOptionParameter *options) +static int vpc_create(const char *filename, QemuOpts *opts) { uint8_t buf[1024]; struct vhd_footer *footer = (struct vhd_footer *) buf; - QEMUOptionParameter *disk_type_param; + const char *disk_type_param = NULL; int fd, i; uint16_t cyls = 0; uint8_t heads = 0; uint8_t secs_per_cyl = 0; int64_t total_sectors; - int64_t total_size; - int disk_type; + int64_t total_size = 0; + int disk_type = VHD_DYNAMIC; int ret = -EIO; - /* Read out options */ - total_size = get_option_parameter(options, BLOCK_OPT_SIZE)->value.n; - - disk_type_param = get_option_parameter(options, BLOCK_OPT_SUBFMT); - if (disk_type_param && disk_type_param->value.s) { - if (!strcmp(disk_type_param->value.s, "dynamic")) { + /* Read out opts */ + total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0); + disk_type_param = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT); + if (disk_type_param) { + if (!strcmp(disk_type_param, "dynamic")) { disk_type = VHD_DYNAMIC; - } else if (!strcmp(disk_type_param->value.s, "fixed")) { + } else if (!strcmp(disk_type_param, "fixed")) { disk_type = VHD_FIXED; } else { - return -EINVAL; + ret = -EINVAL; + goto finish; } - } else { - disk_type = VHD_DYNAMIC; } /* Create the file */ fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); if (fd < 0) { - return -EIO; + ret = -EIO; + goto finish; } /* @@ -783,6 +782,8 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options) fail: qemu_close(fd); +finish: + g_free((/* !const */ char*)disk_type_param); return ret; } @@ -798,20 +799,24 @@ static void vpc_close(BlockDriverState *bs) error_free(s->migration_blocker); } -static QEMUOptionParameter vpc_create_options[] = { - { - .name = BLOCK_OPT_SIZE, - .type = OPT_SIZE, - .help = "Virtual disk size" - }, - { - .name = BLOCK_OPT_SUBFMT, - .type = OPT_STRING, - .help = - "Type of virtual hard disk format. Supported formats are " - "{dynamic (default) | fixed} " - }, - { NULL } +static QemuOptsList vpc_create_opts = { + .name = "vpc-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(vpc_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { + .name = BLOCK_OPT_SUBFMT, + .type = QEMU_OPT_STRING, + .help = + "Type of virtual hard disk format. Supported formats are " + "{dynamic (default) | fixed} " + }, + { /* end of list */ } + } }; static BlockDriver bdrv_vpc = { @@ -827,7 +832,7 @@ static BlockDriver bdrv_vpc = { .bdrv_read = vpc_co_read, .bdrv_write = vpc_co_write, - .create_options = vpc_create_options, + .bdrv_create_opts = &vpc_create_opts, }; static void bdrv_vpc_init(void) diff --git a/block/vvfat.c b/block/vvfat.c index 87b0279..7e5a89c 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -2907,7 +2907,7 @@ static BlockDriver vvfat_write_target = { static int enable_write_target(BDRVVVFATState *s) { BlockDriver *bdrv_qcow; - QEMUOptionParameter *options; + QemuOpts *opts; int ret; int size = sector2cluster(s, s->sector_count); s->used_clusters = calloc(size, 1); @@ -2923,12 +2923,13 @@ static int enable_write_target(BDRVVVFATState *s) } bdrv_qcow = bdrv_find_format("qcow"); - options = parse_option_parameters("", bdrv_qcow->create_options, NULL); - set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512); - set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:"); + opts = qemu_opts_create_nofail(bdrv_qcow->bdrv_create_opts); + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512); + qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:"); - if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0) + if (bdrv_create(bdrv_qcow, s->qcow_filename, opts) < 0) { return -1; + } s->qcow = bdrv_new(""); if (s->qcow == NULL) { diff --git a/include/block/block.h b/include/block/block.h index 2307f67..54f1f76 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -115,9 +115,8 @@ BlockDriver *bdrv_find_protocol(const char *filename); BlockDriver *bdrv_find_format(const char *format_name); BlockDriver *bdrv_find_whitelisted_format(const char *format_name, bool readonly); -int bdrv_create(BlockDriver *drv, const char* filename, - QEMUOptionParameter *options); -int bdrv_create_file(const char* filename, QEMUOptionParameter *options); +int bdrv_create(BlockDriver *drv, const char* filename, QemuOpts *opts); +int bdrv_create_file(const char *filename, QemuOpts *opts); BlockDriverState *bdrv_new(const char *device_name); void bdrv_make_anon(BlockDriverState *bs); void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old); diff --git a/include/block/block_int.h b/include/block/block_int.h index ba52247..41311e2 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -95,7 +95,7 @@ struct BlockDriver { const uint8_t *buf, int nb_sectors); void (*bdrv_close)(BlockDriverState *bs); void (*bdrv_rebind)(BlockDriverState *bs); - int (*bdrv_create)(const char *filename, QEMUOptionParameter *options); + int (*bdrv_create)(const char *filename, QemuOpts *opts); int (*bdrv_set_key)(BlockDriverState *bs, const char *key); int (*bdrv_make_empty)(BlockDriverState *bs); /* aio */ @@ -184,9 +184,7 @@ struct BlockDriver { unsigned long int req, void *buf, BlockDriverCompletionFunc *cb, void *opaque); - /* List of options for creating images, terminated by name == NULL */ - QEMUOptionParameter *create_options; - + QemuOptsList *bdrv_create_opts; /* * Returns 0 for completed check, -errno for internal errors. diff --git a/qemu-img.c b/qemu-img.c index 809b4f1..711de5c 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -231,7 +231,7 @@ static int read_password(char *buf, int buf_size) static int print_block_option_help(const char *filename, const char *fmt) { BlockDriver *drv, *proto_drv; - QEMUOptionParameter *create_options = NULL; + QemuOptsList *create_opts = NULL; /* Find driver and parse its options */ drv = bdrv_find_format(fmt); @@ -246,12 +246,10 @@ static int print_block_option_help(const char *filename, const char *fmt) return 1; } - create_options = append_option_parameters(create_options, - drv->create_options); - create_options = append_option_parameters(create_options, - proto_drv->create_options); - print_option_help(create_options); - free_option_parameters(create_options); + create_opts = qemu_opts_append(drv->bdrv_create_opts, + proto_drv->bdrv_create_opts); + qemu_opts_print_help(create_opts); + qemu_opts_free(create_opts); return 0; } @@ -303,19 +301,19 @@ fail: return NULL; } -static int add_old_style_options(const char *fmt, QEMUOptionParameter *list, +static int add_old_style_options(const char *fmt, QemuOpts *list, const char *base_filename, const char *base_fmt) { if (base_filename) { - if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) { + if (qemu_opt_set(list, BLOCK_OPT_BACKING_FILE, base_filename)) { error_report("Backing file not supported for file format '%s'", fmt); return -1; } } if (base_fmt) { - if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) { + if (qemu_opt_set(list, BLOCK_OPT_BACKING_FMT, base_fmt)) { error_report("Backing file format not supported for file " "format '%s'", fmt); return -1; @@ -1123,8 +1121,9 @@ static int img_convert(int argc, char **argv) uint8_t * buf = NULL; const uint8_t *buf1; BlockDriverInfo bdi; - QEMUOptionParameter *param = NULL, *create_options = NULL; - QEMUOptionParameter *out_baseimg_param; + QemuOpts *opts = NULL; + QemuOptsList *create_opts = NULL; + const char *out_baseimg_param; char *options = NULL; const char *snapshot_name = NULL; float local_progress = 0; @@ -1268,40 +1267,36 @@ static int img_convert(int argc, char **argv) goto out; } - create_options = append_option_parameters(create_options, - drv->create_options); - create_options = append_option_parameters(create_options, - proto_drv->create_options); + create_opts = qemu_opts_append(drv->bdrv_create_opts, + proto_drv->bdrv_create_opts); if (options) { - param = parse_option_parameters(options, create_options, param); - if (param == NULL) { + if (qemu_opts_do_parse_replace(opts, options, NULL) != 0) { error_report("Invalid options for file format '%s'.", out_fmt); ret = -1; goto out; } } else { - param = parse_option_parameters("", create_options, param); + opts = qemu_opts_create_nofail(create_opts); } - - set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512); - ret = add_old_style_options(out_fmt, param, out_baseimg, NULL); + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_sectors * 512); + ret = add_old_style_options(out_fmt, opts, out_baseimg, NULL); if (ret < 0) { goto out; } /* Get backing file name if -o backing_file was used */ - out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE); + out_baseimg_param = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE); if (out_baseimg_param) { - out_baseimg = out_baseimg_param->value.s; + out_baseimg = out_baseimg_param; } /* Check if compression is supported */ if (compress) { - QEMUOptionParameter *encryption = - get_option_parameter(param, BLOCK_OPT_ENCRYPT); - QEMUOptionParameter *preallocation = - get_option_parameter(param, BLOCK_OPT_PREALLOC); + bool encryption = + qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, false); + const char *preallocation = + qemu_opt_get(opts, BLOCK_OPT_PREALLOC); if (!drv->bdrv_write_compressed) { error_report("Compression not supported for this file format"); @@ -1309,15 +1304,15 @@ static int img_convert(int argc, char **argv) goto out; } - if (encryption && encryption->value.n) { + if (encryption) { error_report("Compression and encryption not supported at " "the same time"); ret = -1; goto out; } - if (preallocation && preallocation->value.s - && strcmp(preallocation->value.s, "off")) + if (preallocation + && strcmp(preallocation, "off")) { error_report("Compression and preallocation not supported at " "the same time"); @@ -1327,7 +1322,7 @@ static int img_convert(int argc, char **argv) } /* Create the new image */ - ret = bdrv_create(drv, out_filename, param); + ret = bdrv_create(drv, out_filename, opts); if (ret < 0) { if (ret == -ENOTSUP) { error_report("Formatting not supported for file format '%s'", @@ -1531,8 +1526,10 @@ static int img_convert(int argc, char **argv) } out: qemu_progress_end(); - free_option_parameters(create_options); - free_option_parameters(param); + qemu_opts_free(create_opts); + if (opts) { + qemu_opts_del(opts); + } qemu_vfree(buf); if (out_bs) { bdrv_delete(out_bs);