From nobody Fri Oct 24 09:45:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 151941517892473.02967291103664; Fri, 23 Feb 2018 11:46:18 -0800 (PST) Received: from localhost ([::1]:46820 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1epJIO-0000pD-JE for importer@patchew.org; Fri, 23 Feb 2018 14:46:16 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50501) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1epIzg-0001IN-Ra for qemu-devel@nongnu.org; Fri, 23 Feb 2018 14:27:01 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1epIzf-0005GY-0x for qemu-devel@nongnu.org; Fri, 23 Feb 2018 14:26:56 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38880 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1epIza-00057c-Ll; Fri, 23 Feb 2018 14:26:50 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3D28940201A0; Fri, 23 Feb 2018 19:26:50 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-118.ams2.redhat.com [10.36.117.118]) by smtp.corp.redhat.com (Postfix) with ESMTP id A1CB22024CAC; Fri, 23 Feb 2018 19:26:48 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 23 Feb 2018 20:25:41 +0100 Message-Id: <20180223192549.26666-29-kwolf@redhat.com> In-Reply-To: <20180223192549.26666-1-kwolf@redhat.com> References: <20180223192549.26666-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Fri, 23 Feb 2018 19:26:50 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Fri, 23 Feb 2018 19:26:50 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 28/36] sheepdog: Support .bdrv_co_create X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, jdurgin@redhat.com, pkrempa@redhat.com, mitake.hitoshi@lab.ntt.co.jp, jcody@redhat.com, qemu-devel@nongnu.org, mreitz@redhat.com, namei.unix@gmail.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This adds the .bdrv_co_create driver callback to sheepdog, which enables image creation over QMP. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz --- qapi/block-core.json | 24 ++++- block/sheepdog.c | 242 +++++++++++++++++++++++++++++++++++------------= ---- 2 files changed, 191 insertions(+), 75 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 2b249c9e3d..f7679fce53 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3512,6 +3512,28 @@ 'erasure-coded': 'SheepdogRedundancyErasureCoded' } } =20 ## +# @BlockdevCreateOptionsSheepdog: +# +# Driver specific image creation options for Sheepdog. +# +# @location Where to store the new image file +# @size Size of the virtual disk in bytes +# @backing-file File name of a base image +# @preallocation Preallocation mode (allowed values: off, full) +# @redundancy Redundancy of the image +# @object-size Object size of the image +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsSheepdog', + 'data': { 'location': 'BlockdevOptionsSheepdog', + 'size': 'size', + '*backing-file': 'str', + '*preallocation': 'PreallocMode', + '*redundancy': 'SheepdogRedundancy', + '*object-size': 'size' } } + +## # @BlockdevCreateNotSupported: # # This is used for all drivers that don't support creating images. @@ -3562,7 +3584,7 @@ 'raw': 'BlockdevCreateNotSupported', 'rbd': 'BlockdevCreateOptionsRbd', 'replication': 'BlockdevCreateNotSupported', - 'sheepdog': 'BlockdevCreateNotSupported', + 'sheepdog': 'BlockdevCreateOptionsSheepdog', 'ssh': 'BlockdevCreateNotSupported', 'throttle': 'BlockdevCreateNotSupported', 'vdi': 'BlockdevCreateNotSupported', diff --git a/block/sheepdog.c b/block/sheepdog.c index 22df2ba9d0..83da6236ca 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -17,6 +17,7 @@ #include "qapi/error.h" #include "qapi/qmp/qdict.h" #include "qapi/qobject-input-visitor.h" +#include "qapi/qobject-output-visitor.h" #include "qemu/uri.h" #include "qemu/error-report.h" #include "qemu/option.h" @@ -533,23 +534,6 @@ static void sd_aio_setup(SheepdogAIOCB *acb, BDRVSheep= dogState *s, qemu_co_mutex_unlock(&s->queue_lock); } =20 -static SocketAddress *sd_socket_address(const char *path, - const char *host, const char *port) -{ - SocketAddress *addr =3D g_new0(SocketAddress, 1); - - if (path) { - addr->type =3D SOCKET_ADDRESS_TYPE_UNIX; - addr->u.q_unix.path =3D g_strdup(path); - } else { - addr->type =3D SOCKET_ADDRESS_TYPE_INET; - addr->u.inet.host =3D g_strdup(host ?: SD_DEFAULT_ADDR); - addr->u.inet.port =3D g_strdup(port ?: stringify(SD_DEFAULT_PORT)); - } - - return addr; -} - static SocketAddress *sd_server_config(QDict *options, Error **errp) { QDict *server =3D NULL; @@ -1882,6 +1866,44 @@ out_with_err_set: return ret; } =20 +static int sd_create_prealloc(BlockdevOptionsSheepdog *location, int64_t s= ize, + Error **errp) +{ + BlockDriverState *bs; + Visitor *v; + QObject *obj =3D NULL; + QDict *qdict; + Error *local_err =3D NULL; + int ret; + + v =3D qobject_output_visitor_new(&obj); + visit_type_BlockdevOptionsSheepdog(v, NULL, &location, &local_err); + visit_free(v); + + if (local_err) { + error_propagate(errp, local_err); + qobject_decref(obj); + return -EINVAL; + } + + qdict =3D qobject_to_qdict(obj); + qdict_flatten(qdict); + + qdict_put_str(qdict, "driver", "sheepdog"); + + bs =3D bdrv_open(NULL, NULL, qdict, BDRV_O_PROTOCOL | BDRV_O_RDWR, err= p); + if (bs =3D=3D NULL) { + ret =3D -EIO; + goto fail; + } + + ret =3D sd_prealloc(bs, 0, size, errp); +fail: + bdrv_unref(bs); + QDECREF(qdict); + return ret; +} + static int parse_redundancy(BDRVSheepdogState *s, SheepdogRedundancy *opt) { struct SheepdogInode *inode =3D &s->inode; @@ -1934,9 +1956,9 @@ static int parse_redundancy(BDRVSheepdogState *s, She= epdogRedundancy *opt) * # create a erasure coded vdi with x data strips and y parity strips * -o redundancy=3Dx:y (x must be one of {2,4,8,16} and 1 <=3D y < SD_EC_M= AX_STRIP) */ -static int parse_redundancy_str(BDRVSheepdogState *s, const char *opt) +static SheepdogRedundancy *parse_redundancy_str(const char *opt) { - struct SheepdogRedundancy redundancy; + SheepdogRedundancy *redundancy; const char *n1, *n2; long copy, parity; char p[10]; @@ -1947,26 +1969,27 @@ static int parse_redundancy_str(BDRVSheepdogState *= s, const char *opt) n2 =3D strtok(NULL, ":"); =20 if (!n1) { - return -EINVAL; + return NULL; } =20 ret =3D qemu_strtol(n1, NULL, 10, ©); if (ret < 0) { - return ret; + return NULL; } =20 + redundancy =3D g_new0(SheepdogRedundancy, 1); if (!n2) { - redundancy =3D (SheepdogRedundancy) { + *redundancy =3D (SheepdogRedundancy) { .type =3D SHEEPDOG_REDUNDANCY_TYPE_FULL, .u.full.copies =3D copy, }; } else { ret =3D qemu_strtol(n2, NULL, 10, &parity); if (ret < 0) { - return ret; + return NULL; } =20 - redundancy =3D (SheepdogRedundancy) { + *redundancy =3D (SheepdogRedundancy) { .type =3D SHEEPDOG_REDUNDANCY_TYPE_ERASURE_CODED, .u.erasure_coded =3D { .data_strips =3D copy, @@ -1975,17 +1998,19 @@ static int parse_redundancy_str(BDRVSheepdogState *= s, const char *opt) }; } =20 - return parse_redundancy(s, &redundancy); + return redundancy; } =20 -static int parse_block_size_shift(BDRVSheepdogState *s, QemuOpts *opt) +static int parse_block_size_shift(BDRVSheepdogState *s, + BlockdevCreateOptionsSheepdog *opts) { struct SheepdogInode *inode =3D &s->inode; uint64_t object_size; int obj_order; =20 - object_size =3D qemu_opt_get_size_del(opt, BLOCK_OPT_OBJECT_SIZE, 0); - if (object_size) { + if (opts->has_object_size) { + object_size =3D opts->object_size; + if ((object_size - 1) & object_size) { /* not a power of 2? */ return -EINVAL; } @@ -1999,57 +2024,55 @@ static int parse_block_size_shift(BDRVSheepdogState= *s, QemuOpts *opt) return 0; } =20 -static int sd_create(const char *filename, QemuOpts *opts, - Error **errp) +static int sd_co_create(BlockdevCreateOptions *options, Error **errp) { - Error *err =3D NULL; + BlockdevCreateOptionsSheepdog *opts =3D &options->u.sheepdog; int ret =3D 0; uint32_t vid =3D 0; char *backing_file =3D NULL; char *buf =3D NULL; BDRVSheepdogState *s; - SheepdogConfig cfg; uint64_t max_vdi_size; bool prealloc =3D false; =20 + assert(options->driver =3D=3D BLOCKDEV_DRIVER_SHEEPDOG); + s =3D g_new0(BDRVSheepdogState, 1); =20 - if (strstr(filename, "://")) { - sd_parse_uri(&cfg, filename, &err); - } else { - parse_vdiname(&cfg, filename, &err); - } - if (err) { - error_propagate(errp, err); + /* Steal SocketAddress from QAPI, set NULL to prevent double free */ + s->addr =3D opts->location->server; + opts->location->server =3D NULL; + + if (strlen(opts->location->vdi) >=3D sizeof(s->name)) { + error_setg(errp, "'vdi' string too long"); + ret =3D -EINVAL; goto out; } + pstrcpy(s->name, sizeof(s->name), opts->location->vdi); =20 - buf =3D cfg.port ? g_strdup_printf("%d", cfg.port) : NULL; - s->addr =3D sd_socket_address(cfg.path, cfg.host, buf); - g_free(buf); - strcpy(s->name, cfg.vdi); - sd_config_done(&cfg); + s->inode.vdi_size =3D opts->size; + backing_file =3D opts->backing_file; =20 - s->inode.vdi_size =3D ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_S= IZE, 0), - BDRV_SECTOR_SIZE); - backing_file =3D qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE); - buf =3D qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC); - if (!buf || !strcmp(buf, "off")) { + if (!opts->has_preallocation) { + opts->preallocation =3D PREALLOC_MODE_OFF; + } + switch (opts->preallocation) { + case PREALLOC_MODE_OFF: prealloc =3D false; - } else if (!strcmp(buf, "full")) { + break; + case PREALLOC_MODE_FULL: prealloc =3D true; - } else { - error_setg(errp, "Invalid preallocation mode: '%s'", buf); + break; + default: + error_setg(errp, "Preallocation mode not supported for Sheepdog"); ret =3D -EINVAL; goto out; } =20 - g_free(buf); - buf =3D qemu_opt_get_del(opts, BLOCK_OPT_REDUNDANCY); - if (buf) { - ret =3D parse_redundancy_str(s, buf); + if (opts->has_redundancy) { + ret =3D parse_redundancy(s, opts->redundancy); if (ret < 0) { - error_setg(errp, "Invalid redundancy mode: '%s'", buf); + error_setg(errp, "Invalid redundancy mode"); goto out; } } @@ -2061,20 +2084,20 @@ static int sd_create(const char *filename, QemuOpts= *opts, goto out; } =20 - if (backing_file) { + if (opts->has_backing_file) { BlockBackend *blk; BDRVSheepdogState *base; BlockDriver *drv; =20 /* Currently, only Sheepdog backing image is supported. */ - drv =3D bdrv_find_protocol(backing_file, true, NULL); + drv =3D bdrv_find_protocol(opts->backing_file, true, NULL); if (!drv || strcmp(drv->protocol_name, "sheepdog") !=3D 0) { error_setg(errp, "backing_file must be a sheepdog image"); ret =3D -EINVAL; goto out; } =20 - blk =3D blk_new_open(backing_file, NULL, NULL, + blk =3D blk_new_open(opts->backing_file, NULL, NULL, BDRV_O_PROTOCOL, errp); if (blk =3D=3D NULL) { ret =3D -EIO; @@ -2142,28 +2165,96 @@ static int sd_create(const char *filename, QemuOpts= *opts, } =20 if (prealloc) { - BlockDriverState *bs; - QDict *opts; - - opts =3D qdict_new(); - qdict_put_str(opts, "driver", "sheepdog"); - bs =3D bdrv_open(filename, NULL, opts, BDRV_O_PROTOCOL | BDRV_O_RD= WR, - errp); - if (!bs) { - goto out; - } - - ret =3D sd_prealloc(bs, 0, s->inode.vdi_size, errp); - - bdrv_unref(bs); + ret =3D sd_create_prealloc(opts->location, opts->size, errp); } out: g_free(backing_file); g_free(buf); + g_free(s->addr); g_free(s); return ret; } =20 +static int sd_create(const char *filename, QemuOpts *opts, + Error **errp) +{ + BlockdevCreateOptions *create_options =3D NULL; + QDict *qdict, *location_qdict; + QObject *crumpled; + Visitor *v; + const char *redundancy; + Error *local_err =3D NULL; + int ret; + + redundancy =3D qemu_opt_get_del(opts, BLOCK_OPT_REDUNDANCY); + + qdict =3D qemu_opts_to_qdict(opts, NULL); + qdict_put_str(qdict, "driver", "sheepdog"); + + location_qdict =3D qdict_new(); + qdict_put(qdict, "location", location_qdict); + + sd_parse_filename(filename, location_qdict, &local_err); + if (local_err) { + error_propagate(errp, local_err); + ret =3D -EINVAL; + goto fail; + } + + qdict_flatten(qdict); + + /* Change legacy command line options into QMP ones */ + static const QDictRenames opt_renames[] =3D { + { BLOCK_OPT_BACKING_FILE, "backing-file" }, + { BLOCK_OPT_OBJECT_SIZE, "object-size" }, + { NULL, NULL }, + }; + + if (!qdict_rename_keys(qdict, opt_renames, errp)) { + ret =3D -EINVAL; + goto fail; + } + + /* Get the QAPI object */ + crumpled =3D qdict_crumple(qdict, errp); + if (crumpled =3D=3D NULL) { + ret =3D -EINVAL; + goto fail; + } + + v =3D qobject_input_visitor_new_keyval(crumpled); + visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); + visit_free(v); + qobject_decref(crumpled); + + if (local_err) { + error_propagate(errp, local_err); + ret =3D -EINVAL; + goto fail; + } + + assert(create_options->driver =3D=3D BLOCKDEV_DRIVER_SHEEPDOG); + create_options->u.sheepdog.size =3D + ROUND_UP(create_options->u.sheepdog.size, BDRV_SECTOR_SIZE); + + if (redundancy) { + create_options->u.sheepdog.has_redundancy =3D true; + create_options->u.sheepdog.redundancy =3D + parse_redundancy_str(redundancy); + if (create_options->u.sheepdog.redundancy =3D=3D NULL) { + error_setg(errp, "Invalid redundancy mode"); + ret =3D -EINVAL; + goto fail; + } + } + + ret =3D sd_co_create(create_options, errp); +fail: + qapi_free_BlockdevCreateOptions(create_options); + QDECREF(qdict); + return ret; +} + static void sd_close(BlockDriverState *bs) { Error *local_err =3D NULL; @@ -3144,6 +3235,7 @@ static BlockDriver bdrv_sheepdog =3D { .bdrv_reopen_abort =3D sd_reopen_abort, .bdrv_close =3D sd_close, .bdrv_create =3D sd_create, + .bdrv_co_create =3D sd_co_create, .bdrv_has_zero_init =3D bdrv_has_zero_init_1, .bdrv_getlength =3D sd_getlength, .bdrv_get_allocated_file_size =3D sd_get_allocated_file_size, @@ -3180,6 +3272,7 @@ static BlockDriver bdrv_sheepdog_tcp =3D { .bdrv_reopen_abort =3D sd_reopen_abort, .bdrv_close =3D sd_close, .bdrv_create =3D sd_create, + .bdrv_co_create =3D sd_co_create, .bdrv_has_zero_init =3D bdrv_has_zero_init_1, .bdrv_getlength =3D sd_getlength, .bdrv_get_allocated_file_size =3D sd_get_allocated_file_size, @@ -3216,6 +3309,7 @@ static BlockDriver bdrv_sheepdog_unix =3D { .bdrv_reopen_abort =3D sd_reopen_abort, .bdrv_close =3D sd_close, .bdrv_create =3D sd_create, + .bdrv_co_create =3D sd_co_create, .bdrv_has_zero_init =3D bdrv_has_zero_init_1, .bdrv_getlength =3D sd_getlength, .bdrv_get_allocated_file_size =3D sd_get_allocated_file_size, --=20 2.13.6