From nobody Sun May 5 05:14:44 2024 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1488180994833700.313703671803; Sun, 26 Feb 2017 23:36:34 -0800 (PST) Received: from localhost ([::1]:50842 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciFrF-0002M1-G8 for importer@patchew.org; Mon, 27 Feb 2017 02:36:33 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53445) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciFlk-0006iJ-3a for qemu-devel@nongnu.org; Mon, 27 Feb 2017 02:30:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciFli-0006vw-Rd for qemu-devel@nongnu.org; Mon, 27 Feb 2017 02:30:52 -0500 Received: from mx1.redhat.com ([209.132.183.28]:36596) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciFlc-0006r1-KM; Mon, 27 Feb 2017 02:30:44 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BDC5E8123F; Mon, 27 Feb 2017 07:30:44 +0000 (UTC) Received: from localhost (ovpn-116-95.phx2.redhat.com [10.3.116.95]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1R7Uhri012254 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 02:30:44 -0500 From: Jeff Cody To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 02:30:38 -0500 Message-Id: <25ccaa9f42f7efdac608cb6f779b144a87529138.1488180142.git.jcody@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Mon, 27 Feb 2017 07:30:44 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 1/4] block/rbd: don't copy strings in qemu_rbd_next_tok() 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: armbru@redhat.com, qemu-block@nongnu.org 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 patch is prep work for parsing options for .bdrv_parse_filename, and using QDict options. The function qemu_rbd_next_tok() searched for various key/value pairs, and copied them into buffers. This will soon be an unnecessary extra step, so we will now return found strings by reference only, and offload the responsibility for safely handling/coping these strings to the caller. This also cleans up error handling some, as the callers now rely on the Error object to determine if there is a parse error. Signed-off-by: Jeff Cody --- block/rbd.c | 99 +++++++++++++++++++++++++++++++++++++++------------------= ---- 1 file changed, 64 insertions(+), 35 deletions(-) diff --git a/block/rbd.c b/block/rbd.c index 22e8e69..3f1a9de 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -102,10 +102,10 @@ typedef struct BDRVRBDState { char *snap; } BDRVRBDState; =20 -static int qemu_rbd_next_tok(char *dst, int dst_len, - char *src, char delim, - const char *name, - char **p, Error **errp) +static char *qemu_rbd_next_tok(int max_len, + char *src, char delim, + const char *name, + char **p, Error **errp) { int l; char *end; @@ -127,17 +127,15 @@ static int qemu_rbd_next_tok(char *dst, int dst_len, } } l =3D strlen(src); - if (l >=3D dst_len) { + if (l >=3D max_len) { error_setg(errp, "%s too long", name); - return -EINVAL; + return NULL; } else if (l =3D=3D 0) { error_setg(errp, "%s too short", name); - return -EINVAL; + return NULL; } =20 - pstrcpy(dst, dst_len, src); - - return 0; + return src; } =20 static void qemu_rbd_unescape(char *src) @@ -162,7 +160,9 @@ static int qemu_rbd_parsename(const char *filename, { const char *start; char *p, *buf; - int ret; + int ret =3D 0; + char *found_str; + Error *local_err =3D NULL; =20 if (!strstart(filename, "rbd:", &start)) { error_setg(errp, "File name must start with 'rbd:'"); @@ -174,36 +174,60 @@ static int qemu_rbd_parsename(const char *filename, *snap =3D '\0'; *conf =3D '\0'; =20 - ret =3D qemu_rbd_next_tok(pool, pool_len, p, - '/', "pool name", &p, errp); - if (ret < 0 || !p) { + found_str =3D qemu_rbd_next_tok(pool_len, p, + '/', "pool name", &p, &local_err); + if (local_err) { + goto done; + } + if (!p) { ret =3D -EINVAL; + error_setg(errp, "Pool name is required"); goto done; } - qemu_rbd_unescape(pool); + qemu_rbd_unescape(found_str); + g_strlcpy(pool, found_str, pool_len); =20 if (strchr(p, '@')) { - ret =3D qemu_rbd_next_tok(name, name_len, p, - '@', "object name", &p, errp); - if (ret < 0) { + found_str =3D qemu_rbd_next_tok(name_len, p, + '@', "object name", &p, &local_err); + if (local_err) { goto done; } - ret =3D qemu_rbd_next_tok(snap, snap_len, p, - ':', "snap name", &p, errp); - qemu_rbd_unescape(snap); + qemu_rbd_unescape(found_str); + g_strlcpy(name, found_str, name_len); + + found_str =3D qemu_rbd_next_tok(snap_len, p, + ':', "snap name", &p, &local_err); + if (local_err) { + goto done; + } + qemu_rbd_unescape(found_str); + g_strlcpy(snap, found_str, snap_len); } else { - ret =3D qemu_rbd_next_tok(name, name_len, p, - ':', "object name", &p, errp); + found_str =3D qemu_rbd_next_tok(name_len, p, + ':', "object name", &p, &local_err); + if (local_err) { + goto done; + } + qemu_rbd_unescape(found_str); + g_strlcpy(name, found_str, name_len); } - qemu_rbd_unescape(name); - if (ret < 0 || !p) { + if (!p) { goto done; } =20 - ret =3D qemu_rbd_next_tok(conf, conf_len, p, - '\0', "configuration", &p, errp); + found_str =3D qemu_rbd_next_tok(conf_len, p, + '\0', "configuration", &p, &local_err); + if (local_err) { + goto done; + } + g_strlcpy(conf, found_str, conf_len); =20 done: + if (local_err) { + ret =3D -EINVAL; + error_propagate(errp, local_err); + } g_free(buf); return ret; } @@ -262,17 +286,18 @@ static int qemu_rbd_set_conf(rados_t cluster, const c= har *conf, Error **errp) { char *p, *buf; - char name[RBD_MAX_CONF_NAME_SIZE]; - char value[RBD_MAX_CONF_VAL_SIZE]; + char *name; + char *value; + Error *local_err =3D NULL; int ret =3D 0; =20 buf =3D g_strdup(conf); p =3D buf; =20 while (p) { - ret =3D qemu_rbd_next_tok(name, sizeof(name), p, - '=3D', "conf option name", &p, errp); - if (ret < 0) { + name =3D qemu_rbd_next_tok(RBD_MAX_CONF_NAME_SIZE, p, + '=3D', "conf option name", &p, &local_err= ); + if (local_err) { break; } qemu_rbd_unescape(name); @@ -283,9 +308,9 @@ static int qemu_rbd_set_conf(rados_t cluster, const cha= r *conf, break; } =20 - ret =3D qemu_rbd_next_tok(value, sizeof(value), p, - ':', "conf option value", &p, errp); - if (ret < 0) { + value =3D qemu_rbd_next_tok(RBD_MAX_CONF_VAL_SIZE, p, + ':', "conf option value", &p, &local_err= ); + if (local_err) { break; } qemu_rbd_unescape(value); @@ -313,6 +338,10 @@ static int qemu_rbd_set_conf(rados_t cluster, const ch= ar *conf, } } =20 + if (local_err) { + error_propagate(errp, local_err); + ret =3D -EINVAL; + } g_free(buf); return ret; } --=20 2.9.3 From nobody Sun May 5 05:14:44 2024 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1488180995134692.4968227175762; Sun, 26 Feb 2017 23:36:35 -0800 (PST) Received: from localhost ([::1]:50843 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciFrF-0002MB-QA for importer@patchew.org; Mon, 27 Feb 2017 02:36:33 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53431) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciFlj-0006ha-Is for qemu-devel@nongnu.org; Mon, 27 Feb 2017 02:30:52 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciFli-0006vk-Mm for qemu-devel@nongnu.org; Mon, 27 Feb 2017 02:30:51 -0500 Received: from mx1.redhat.com ([209.132.183.28]:36598) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciFld-0006ra-Pj; Mon, 27 Feb 2017 02:30:45 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E344581236; Mon, 27 Feb 2017 07:30:45 +0000 (UTC) Received: from localhost (ovpn-116-95.phx2.redhat.com [10.3.116.95]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1R7Uibb023830 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 02:30:45 -0500 From: Jeff Cody To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 02:30:39 -0500 Message-Id: <6f1d60bdbbb4e82991c699d4aa6666c4317a1c5d.1488180142.git.jcody@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Mon, 27 Feb 2017 07:30:45 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 2/4] block/rbd: code movement 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: armbru@redhat.com, qemu-block@nongnu.org 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" Signed-off-by: Jeff Cody --- block/rbd.c | 64 +++++++++++++++++++++++++++++++++++++++++++--------------= ---- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/block/rbd.c b/block/rbd.c index 3f1a9de..c8d4eb1 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -357,6 +357,51 @@ static void qemu_rbd_memset(RADOSCB *rcb, int64_t offs) } } =20 +static QemuOptsList runtime_opts =3D { + .name =3D "rbd", + .head =3D QTAILQ_HEAD_INITIALIZER(runtime_opts.head), + .desc =3D { + { + .name =3D "filename", + .type =3D QEMU_OPT_STRING, + .help =3D "Specification of the rbd image", + }, + { + .name =3D "password-secret", + .type =3D QEMU_OPT_STRING, + .help =3D "ID of secret providing the password", + }, + { + .name =3D "conf", + .type =3D QEMU_OPT_STRING, + }, + { + .name =3D "pool", + .type =3D QEMU_OPT_STRING, + }, + { + .name =3D "image", + .type =3D QEMU_OPT_STRING, + }, + { + .name =3D "snapshot", + .type =3D QEMU_OPT_STRING, + }, + { + /* you might be tempted to call this 'id' to match + * the ceph documentation, but then it'll get gobbled + * up in the block layer before it gets to the image driver */ + .name =3D "rbd-id", + .type =3D QEMU_OPT_STRING, + }, + { + .name =3D "keyvalue-pairs", + .type =3D QEMU_OPT_STRING, + }, + { /* end of list */ } + }, +}; + static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **e= rrp) { Error *local_err =3D NULL; @@ -500,25 +545,6 @@ static void qemu_rbd_complete_aio(RADOSCB *rcb) qemu_aio_unref(acb); } =20 -/* TODO Convert to fine grained options */ -static QemuOptsList runtime_opts =3D { - .name =3D "rbd", - .head =3D QTAILQ_HEAD_INITIALIZER(runtime_opts.head), - .desc =3D { - { - .name =3D "filename", - .type =3D QEMU_OPT_STRING, - .help =3D "Specification of the rbd image", - }, - { - .name =3D "password-secret", - .type =3D QEMU_OPT_STRING, - .help =3D "ID of secret providing the password", - }, - { /* end of list */ } - }, -}; - static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { --=20 2.9.3 From nobody Sun May 5 05:14:44 2024 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1488180980606217.8862552762655; Sun, 26 Feb 2017 23:36:20 -0800 (PST) Received: from localhost ([::1]:50841 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciFr1-0002AA-5k for importer@patchew.org; Mon, 27 Feb 2017 02:36:19 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53469) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciFll-0006jg-Fv for qemu-devel@nongnu.org; Mon, 27 Feb 2017 02:30:55 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciFlj-0006wS-FL for qemu-devel@nongnu.org; Mon, 27 Feb 2017 02:30:53 -0500 Received: from mx1.redhat.com ([209.132.183.28]:55690) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciFlf-0006su-4N; Mon, 27 Feb 2017 02:30:47 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 50C0B7E9C4; Mon, 27 Feb 2017 07:30:47 +0000 (UTC) Received: from localhost (ovpn-116-95.phx2.redhat.com [10.3.116.95]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1R7UkBQ006120 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 02:30:46 -0500 From: Jeff Cody To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 02:30:40 -0500 Message-Id: <2b61d5edaab9b15472b72689089f73613cc44fc9.1488180142.git.jcody@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Mon, 27 Feb 2017 07:30:47 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 3/4] block/rbd: parse all options via bdrv_parse_filename 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: armbru@redhat.com, qemu-block@nongnu.org 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" Get rid of qemu_rbd_parsename in favor of bdrv_parse_filename. This simplifies a lot of the parsing as well, as we can treat everything a bit simpler since nonexistent options are simply NULL pointers instead of empy strings. An important item to note: Ceph has many extra option values that can be specified as key/value pairs. This was handled previously in the driver by extracting the values that the QEMU driver cared about, and then blindly passing all extra options to rbd after splitting them into key/value pairs, and cleaning up any special character escaping. The practice is continued in this patch; there is an option "keyvalue-pairs" that is populated with all the key/value pairs that the QEMU driver does not care about. These key/value pairs will override any settings in the 'conf' configuration file, just as they did before. Signed-off-by: Jeff Cody --- block/rbd.c | 296 ++++++++++++++++++++++++++++++--------------------------= ---- 1 file changed, 148 insertions(+), 148 deletions(-) diff --git a/block/rbd.c b/block/rbd.c index c8d4eb1..2eee502 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -18,6 +18,7 @@ #include "block/block_int.h" #include "crypto/secret.h" #include "qemu/cutils.h" +#include "qapi/qmp/qstring.h" =20 #include =20 @@ -151,113 +152,129 @@ static void qemu_rbd_unescape(char *src) *p =3D '\0'; } =20 -static int qemu_rbd_parsename(const char *filename, - char *pool, int pool_len, - char *snap, int snap_len, - char *name, int name_len, - char *conf, int conf_len, - Error **errp) +static void qemu_rbd_parse_filename(const char *filename, QDict *options, + Error **errp) { const char *start; - char *p, *buf; - int ret =3D 0; + char *p, *buf, *keypairs; char *found_str; + size_t max_keypair_size; Error *local_err =3D NULL; =20 if (!strstart(filename, "rbd:", &start)) { error_setg(errp, "File name must start with 'rbd:'"); - return -EINVAL; + return; } =20 + max_keypair_size =3D strlen(start) + 1; buf =3D g_strdup(start); + keypairs =3D g_malloc0(max_keypair_size); p =3D buf; - *snap =3D '\0'; - *conf =3D '\0'; =20 - found_str =3D qemu_rbd_next_tok(pool_len, p, + found_str =3D qemu_rbd_next_tok(RBD_MAX_POOL_NAME_SIZE, p, '/', "pool name", &p, &local_err); if (local_err) { goto done; } if (!p) { - ret =3D -EINVAL; error_setg(errp, "Pool name is required"); goto done; } qemu_rbd_unescape(found_str); - g_strlcpy(pool, found_str, pool_len); + qdict_put(options, "pool", qstring_from_str(found_str)); =20 if (strchr(p, '@')) { - found_str =3D qemu_rbd_next_tok(name_len, p, + found_str =3D qemu_rbd_next_tok(RBD_MAX_IMAGE_NAME_SIZE, p, '@', "object name", &p, &local_err); if (local_err) { goto done; } qemu_rbd_unescape(found_str); - g_strlcpy(name, found_str, name_len); + qdict_put(options, "image", qstring_from_str(found_str)); =20 - found_str =3D qemu_rbd_next_tok(snap_len, p, + found_str =3D qemu_rbd_next_tok(RBD_MAX_SNAP_NAME_SIZE, p, ':', "snap name", &p, &local_err); if (local_err) { goto done; } qemu_rbd_unescape(found_str); - g_strlcpy(snap, found_str, snap_len); + qdict_put(options, "snapshot", qstring_from_str(found_str)); } else { - found_str =3D qemu_rbd_next_tok(name_len, p, + found_str =3D qemu_rbd_next_tok(RBD_MAX_IMAGE_NAME_SIZE, p, ':', "object name", &p, &local_err); if (local_err) { goto done; } qemu_rbd_unescape(found_str); - g_strlcpy(name, found_str, name_len); + qdict_put(options, "image", qstring_from_str(found_str)); } if (!p) { goto done; } =20 - found_str =3D qemu_rbd_next_tok(conf_len, p, + found_str =3D qemu_rbd_next_tok(RBD_MAX_CONF_NAME_SIZE, p, '\0', "configuration", &p, &local_err); if (local_err) { goto done; } - g_strlcpy(conf, found_str, conf_len); + + p =3D found_str; + + /* The following are essentially all key/value pairs, and we treat + * 'id' and 'conf' a bit special. Key/value pairs may be in any order= . */ + while (p) { + char *name, *value; + name =3D qemu_rbd_next_tok(RBD_MAX_CONF_NAME_SIZE, p, + '=3D', "conf option name", &p, &local_err= ); + if (local_err) { + break; + } + + if (!p) { + error_setg(errp, "conf option %s has no value", name); + break; + } + + qemu_rbd_unescape(name); + + value =3D qemu_rbd_next_tok(RBD_MAX_CONF_VAL_SIZE, p, + ':', "conf option value", &p, &local_err= ); + if (local_err) { + break; + } + qemu_rbd_unescape(value); + + if (!strcmp(name, "conf")) { + qdict_put(options, "conf", qstring_from_str(value)); + } else if (!strcmp(name, "id")) { + qdict_put(options, "rbd-id" , qstring_from_str(value)); + } else { + char *tmp =3D g_malloc0(max_keypair_size); + /* only use a delimiter if it is not the first keypair found */ + /* These are sets of unknown key/value pairs we'll pass along + * to ceph */ + if (keypairs[0]) { + snprintf(tmp, max_keypair_size, ":%s=3D%s", name, value); + pstrcat(keypairs, max_keypair_size, tmp); + } else { + snprintf(keypairs, max_keypair_size, "%s=3D%s", name, valu= e); + } + g_free(tmp); + } + } + + if (keypairs[0]) { + qdict_put(options, "keyvalue-pairs", qstring_from_str(keypairs)); + } + =20 done: if (local_err) { - ret =3D -EINVAL; error_propagate(errp, local_err); } g_free(buf); - return ret; -} - -static char *qemu_rbd_parse_clientname(const char *conf, char *clientname) -{ - const char *p =3D conf; - - while (*p) { - int len; - const char *end =3D strchr(p, ':'); - - if (end) { - len =3D end - p; - } else { - len =3D strlen(p); - } - - if (strncmp(p, "id=3D", 3) =3D=3D 0) { - len -=3D 3; - strncpy(clientname, p + 3, len); - clientname[len] =3D '\0'; - return clientname; - } - if (end =3D=3D NULL) { - break; - } - p =3D end + 1; - } - return NULL; + g_free(keypairs); + return; } =20 =20 @@ -280,10 +297,8 @@ static int qemu_rbd_set_auth(rados_t cluster, const ch= ar *secretid, return 0; } =20 - -static int qemu_rbd_set_conf(rados_t cluster, const char *conf, - bool only_read_conf_file, - Error **errp) +static int qemu_rbd_set_keypairs(rados_t cluster, const char *keypairs, + Error **errp) { char *p, *buf; char *name; @@ -291,7 +306,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const cha= r *conf, Error *local_err =3D NULL; int ret =3D 0; =20 - buf =3D g_strdup(conf); + buf =3D g_strdup(keypairs); p =3D buf; =20 while (p) { @@ -315,26 +330,11 @@ static int qemu_rbd_set_conf(rados_t cluster, const c= har *conf, } qemu_rbd_unescape(value); =20 - if (strcmp(name, "conf") =3D=3D 0) { - /* read the conf file alone, so it doesn't override more - specific settings for a particular device */ - if (only_read_conf_file) { - ret =3D rados_conf_read_file(cluster, value); - if (ret < 0) { - error_setg_errno(errp, -ret, "error reading conf file = %s", - value); - break; - } - } - } else if (strcmp(name, "id") =3D=3D 0) { - /* ignore, this is parsed by qemu_rbd_parse_clientname() */ - } else if (!only_read_conf_file) { - ret =3D rados_conf_set(cluster, name, value); - if (ret < 0) { - error_setg_errno(errp, -ret, "invalid conf option %s", nam= e); - ret =3D -EINVAL; - break; - } + ret =3D rados_conf_set(cluster, name, value); + if (ret < 0) { + error_setg_errno(errp, -ret, "invalid conf option %s", name); + ret =3D -EINVAL; + break; } } =20 @@ -408,27 +408,16 @@ static int qemu_rbd_create(const char *filename, Qemu= Opts *opts, Error **errp) int64_t bytes =3D 0; int64_t objsize; int obj_order =3D 0; - char pool[RBD_MAX_POOL_NAME_SIZE]; - char name[RBD_MAX_IMAGE_NAME_SIZE]; - char snap_buf[RBD_MAX_SNAP_NAME_SIZE]; - char conf[RBD_MAX_CONF_SIZE]; - char clientname_buf[RBD_MAX_CONF_SIZE]; - char *clientname; + const char *pool, *name, *conf, *clientname, *keypairs; const char *secretid; rados_t cluster; rados_ioctx_t io_ctx; - int ret; + QDict *options =3D NULL; + QemuOpts *rbd_opts =3D NULL; + int ret =3D 0; =20 secretid =3D qemu_opt_get(opts, "password-secret"); =20 - if (qemu_rbd_parsename(filename, pool, sizeof(pool), - snap_buf, sizeof(snap_buf), - name, sizeof(name), - conf, sizeof(conf), &local_err) < 0) { - error_propagate(errp, local_err); - return -EINVAL; - } - /* Read out options */ bytes =3D ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), BDRV_SECTOR_SIZE); @@ -436,35 +425,55 @@ static int qemu_rbd_create(const char *filename, Qemu= Opts *opts, Error **errp) if (objsize) { if ((objsize - 1) & objsize) { /* not a power of 2? */ error_setg(errp, "obj size needs to be power of 2"); - return -EINVAL; + ret =3D -EINVAL; + goto exit; } if (objsize < 4096) { error_setg(errp, "obj size too small"); - return -EINVAL; + ret =3D -EINVAL; + goto exit; } obj_order =3D ctz32(objsize); } =20 - clientname =3D qemu_rbd_parse_clientname(conf, clientname_buf); + options =3D qdict_new(); + qemu_rbd_parse_filename(filename, options, &local_err); + if (local_err) { + ret =3D -EINVAL; + error_propagate(errp, local_err); + goto exit; + } + + rbd_opts =3D qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); + qemu_opts_absorb_qdict(rbd_opts, options, &local_err); + if (local_err) { + error_propagate(errp, local_err); + ret =3D -EINVAL; + goto exit; + } + + pool =3D qemu_opt_get(rbd_opts, "pool"); + conf =3D qemu_opt_get(rbd_opts, "conf"); + clientname =3D qemu_opt_get(rbd_opts, "rbd-id"); + name =3D qemu_opt_get(rbd_opts, "image"); + keypairs =3D qemu_opt_get(rbd_opts, "keyvalue-pairs"); + ret =3D rados_create(&cluster, clientname); if (ret < 0) { error_setg_errno(errp, -ret, "error initializing"); - return ret; + goto exit; } =20 - if (strstr(conf, "conf=3D") =3D=3D NULL) { - /* try default location, but ignore failure */ - rados_conf_read_file(cluster, NULL); - } else if (conf[0] !=3D '\0' && - qemu_rbd_set_conf(cluster, conf, true, &local_err) < 0) { - error_propagate(errp, local_err); + /* try default location when conf=3DNULL, but ignore failure */ + ret =3D rados_conf_read_file(cluster, conf); + if (conf && ret < 0) { + error_setg_errno(errp, -ret, "error reading conf file %s", conf); ret =3D -EIO; goto shutdown; } =20 - if (conf[0] !=3D '\0' && - qemu_rbd_set_conf(cluster, conf, false, &local_err) < 0) { - error_propagate(errp, local_err); + ret =3D qemu_rbd_set_keypairs(cluster, keypairs, errp); + if (ret < 0) { ret =3D -EIO; goto shutdown; } @@ -495,6 +504,10 @@ static int qemu_rbd_create(const char *filename, QemuO= pts *opts, Error **errp) =20 shutdown: rados_shutdown(cluster); + +exit: + QDECREF(options); + qemu_opts_del(rbd_opts); return ret; } =20 @@ -549,15 +562,10 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict = *options, int flags, Error **errp) { BDRVRBDState *s =3D bs->opaque; - char pool[RBD_MAX_POOL_NAME_SIZE]; - char snap_buf[RBD_MAX_SNAP_NAME_SIZE]; - char conf[RBD_MAX_CONF_SIZE]; - char clientname_buf[RBD_MAX_CONF_SIZE]; - char *clientname; + const char *pool, *snap, *conf, *clientname, *name, *keypairs; const char *secretid; QemuOpts *opts; Error *local_err =3D NULL; - const char *filename; int r; =20 opts =3D qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); @@ -568,44 +576,36 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict = *options, int flags, return -EINVAL; } =20 - filename =3D qemu_opt_get(opts, "filename"); secretid =3D qemu_opt_get(opts, "password-secret"); =20 - if (qemu_rbd_parsename(filename, pool, sizeof(pool), - snap_buf, sizeof(snap_buf), - s->name, sizeof(s->name), - conf, sizeof(conf), errp) < 0) { - r =3D -EINVAL; - goto failed_opts; - } + pool =3D qemu_opt_get(opts, "pool"); + conf =3D qemu_opt_get(opts, "conf"); + snap =3D qemu_opt_get(opts, "snapshot"); + clientname =3D qemu_opt_get(opts, "rbd-id"); + name =3D qemu_opt_get(opts, "image"); + keypairs =3D qemu_opt_get(opts, "keyvalue-pairs"); =20 - clientname =3D qemu_rbd_parse_clientname(conf, clientname_buf); r =3D rados_create(&s->cluster, clientname); if (r < 0) { error_setg_errno(errp, -r, "error initializing"); goto failed_opts; } =20 - s->snap =3D NULL; - if (snap_buf[0] !=3D '\0') { - s->snap =3D g_strdup(snap_buf); + s->snap =3D g_strdup(snap); + if (name) { + pstrcpy(s->name, RBD_MAX_IMAGE_NAME_SIZE, name); } =20 - if (strstr(conf, "conf=3D") =3D=3D NULL) { - /* try default location, but ignore failure */ - rados_conf_read_file(s->cluster, NULL); - } else if (conf[0] !=3D '\0') { - r =3D qemu_rbd_set_conf(s->cluster, conf, true, errp); - if (r < 0) { - goto failed_shutdown; - } + /* try default location when conf=3DNULL, but ignore failure */ + r =3D rados_conf_read_file(s->cluster, conf); + if (conf && r < 0) { + error_setg_errno(errp, -r, "error reading conf file %s", conf); + goto failed_shutdown; } =20 - if (conf[0] !=3D '\0') { - r =3D qemu_rbd_set_conf(s->cluster, conf, false, errp); - if (r < 0) { - goto failed_shutdown; - } + r =3D qemu_rbd_set_keypairs(s->cluster, keypairs, errp); + if (r < 0) { + goto failed_shutdown; } =20 if (qemu_rbd_set_auth(s->cluster, secretid, errp) < 0) { @@ -1059,18 +1059,18 @@ static QemuOptsList qemu_rbd_create_opts =3D { }; =20 static BlockDriver bdrv_rbd =3D { - .format_name =3D "rbd", - .instance_size =3D sizeof(BDRVRBDState), - .bdrv_needs_filename =3D true, - .bdrv_file_open =3D qemu_rbd_open, - .bdrv_close =3D qemu_rbd_close, - .bdrv_create =3D qemu_rbd_create, - .bdrv_has_zero_init =3D bdrv_has_zero_init_1, - .bdrv_get_info =3D qemu_rbd_getinfo, - .create_opts =3D &qemu_rbd_create_opts, - .bdrv_getlength =3D qemu_rbd_getlength, - .bdrv_truncate =3D qemu_rbd_truncate, - .protocol_name =3D "rbd", + .format_name =3D "rbd", + .instance_size =3D sizeof(BDRVRBDState), + .bdrv_parse_filename =3D qemu_rbd_parse_filename, + .bdrv_file_open =3D qemu_rbd_open, + .bdrv_close =3D qemu_rbd_close, + .bdrv_create =3D qemu_rbd_create, + .bdrv_has_zero_init =3D bdrv_has_zero_init_1, + .bdrv_get_info =3D qemu_rbd_getinfo, + .create_opts =3D &qemu_rbd_create_opts, + .bdrv_getlength =3D qemu_rbd_getlength, + .bdrv_truncate =3D qemu_rbd_truncate, + .protocol_name =3D "rbd", =20 .bdrv_aio_readv =3D qemu_rbd_aio_readv, .bdrv_aio_writev =3D qemu_rbd_aio_writev, --=20 2.9.3 From nobody Sun May 5 05:14:44 2024 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 148818076366640.10225605871335; Sun, 26 Feb 2017 23:32:43 -0800 (PST) Received: from localhost ([::1]:50820 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciFnV-0007t6-LI for importer@patchew.org; Mon, 27 Feb 2017 02:32:41 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53430) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciFlj-0006hZ-Il for qemu-devel@nongnu.org; Mon, 27 Feb 2017 02:30:52 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciFli-0006vc-Jz for qemu-devel@nongnu.org; Mon, 27 Feb 2017 02:30:51 -0500 Received: from mx1.redhat.com ([209.132.183.28]:55504) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ciFlg-0006tb-CJ; Mon, 27 Feb 2017 02:30:48 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 85621DB014; Mon, 27 Feb 2017 07:30:48 +0000 (UTC) Received: from localhost (ovpn-116-95.phx2.redhat.com [10.3.116.95]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1R7UlgQ012328 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Feb 2017 02:30:48 -0500 From: Jeff Cody To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 02:30:41 -0500 Message-Id: <08786526aec147544588ab3e885a984e7d0d1c69.1488180142.git.jcody@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Mon, 27 Feb 2017 07:30:48 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 4/4] block/rbd: Add blockdev-add support 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: armbru@redhat.com, qemu-block@nongnu.org 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" Signed-off-by: Jeff Cody --- qapi/block-core.json | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 5f82d35..08a1419 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2111,6 +2111,7 @@ # @replication: Since 2.8 # @ssh: Since 2.8 # @iscsi: Since 2.9 +# @rbd: Since 2.9 # # Since: 2.0 ## @@ -2120,7 +2121,7 @@ 'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'parallels', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'replication', 'ssh', 'vdi', 'vhdx', 'vmdk', - 'vpc', 'vvfat' ] } + 'vpc', 'vvfat', 'rbd' ] } =20 ## # @BlockdevOptionsFile: @@ -2376,7 +2377,6 @@ 'path': 'str', '*user': 'str' } } =20 - ## # @BlkdebugEvent: # @@ -2666,6 +2666,47 @@ '*timeout': 'int' } } =20 ## +# @BlockdevOptionsRbd: +# +# @pool: Ceph pool name +# +# @image: Image name in the Ceph pool +# +# @conf: # optional path to Ceph configuration file. Values +# in the configuration file will be overridden by +# options specified via QAPI. +# +# @snapshot: #optional Ceph snapshot name +# +# @rbd-id: #optional Ceph id name +# +# @password-secret: #optional The ID of a QCryptoSecret object providing +# the password for the login. +# +# @keyvalue-pairs: #optional string containing key/value pairs for +# additional Ceph configuration, not including "id" o= r "conf" +# options. This can be used to specify any of the opt= ions +# that Ceph supports. The format is of the form: +# key1=3Dvalue1:key2=3Dvalue2:[...] +# +# Special characters such as ":" and "=3D" can be esc= aped +# with a '\' character, which means the QAPI needs an +# extra '\' character to pass the needed escape chara= cter. +# For example: +# "keyvalue-pairs": "mon_host=3D127.0.0.1\\:632= 1" +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsRbd', + 'data': { 'pool': 'str', + 'image': 'str', + '*conf': 'str', + '*snapshot': 'str', + '*rbd-id': 'str', + '*password-secret': 'str', + '*keyvalue-pairs': 'str' } } + +## # @ReplicationMode: # # An enumeration of replication modes. @@ -2863,7 +2904,7 @@ 'qed': 'BlockdevOptionsGenericCOWFormat', 'quorum': 'BlockdevOptionsQuorum', 'raw': 'BlockdevOptionsRaw', -# TODO rbd: Wait for structured options + 'rbd': 'BlockdevOptionsRbd', 'replication':'BlockdevOptionsReplication', # TODO sheepdog: Wait for structured options 'ssh': 'BlockdevOptionsSsh', --=20 2.9.3