From nobody Tue May 7 08:43:42 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.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=virtuozzo.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 152086877160864.45713942433247; Mon, 12 Mar 2018 08:32:51 -0700 (PDT) Received: from localhost ([::1]:59596 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPRN-00026r-Nv for importer@patchew.org; Mon, 12 Mar 2018 11:32:45 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52200) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPGY-0000sR-AN for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evPGU-0006cF-U5 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:34 -0400 Received: from relay.sw.ru ([185.231.240.75]:55756) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evPGU-0006ZT-Kd; Mon, 12 Mar 2018 11:21:30 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.89) (envelope-from ) id 1evPGR-0005yw-27; Mon, 12 Mar 2018 18:21:27 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Mon, 12 Mar 2018 18:21:19 +0300 Message-Id: <20180312152126.286890-2-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180312152126.286890-1-vsementsov@virtuozzo.com> References: <20180312152126.286890-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v2 1/8] nbd/server: add nbd_opt_invalid helper 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, vsementsov@virtuozzo.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.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" NBD_REP_ERR_INVALID is often parameter to nbd_opt_drop and it would be used more in following patches. So, let's add a helper. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- v2: add Eric's r-b nbd/server.c | 50 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index 2846ae46c5..d163964cf9 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -218,22 +218,46 @@ nbd_negotiate_send_rep_err(NBDClient *client, uint32_= t type, /* Drop remainder of the current option, and send a reply with the * given error type and message. Return -errno on read or write * failure; or 0 if connection is still live. */ -static int GCC_FMT_ATTR(4, 5) -nbd_opt_drop(NBDClient *client, uint32_t type, Error **errp, - const char *fmt, ...) +static int GCC_FMT_ATTR(4, 0) +nbd_opt_vdrop(NBDClient *client, uint32_t type, Error **errp, + const char *fmt, va_list va) { int ret =3D nbd_drop(client->ioc, client->optlen, errp); - va_list va; =20 client->optlen =3D 0; if (!ret) { - va_start(va, fmt); ret =3D nbd_negotiate_send_rep_verr(client, type, errp, fmt, va); - va_end(va); } return ret; } =20 +static int GCC_FMT_ATTR(4, 5) +nbd_opt_drop(NBDClient *client, uint32_t type, Error **errp, + const char *fmt, ...) +{ + int ret; + va_list va; + + va_start(va, fmt); + ret =3D nbd_opt_vdrop(client, type, errp, fmt, va); + va_end(va); + + return ret; +} + +static int GCC_FMT_ATTR(3, 4) +nbd_opt_invalid(NBDClient *client, Error **errp, const char *fmt, ...) +{ + int ret; + va_list va; + + va_start(va, fmt); + ret =3D nbd_opt_vdrop(client, NBD_REP_ERR_INVALID, errp, fmt, va); + va_end(va); + + return ret; +} + /* Read size bytes from the unparsed payload of the current option. * Return -errno on I/O error, 0 if option was completely handled by * sending a reply about inconsistent lengths, or 1 on success. */ @@ -241,9 +265,9 @@ static int nbd_opt_read(NBDClient *client, void *buffer= , size_t size, Error **errp) { if (size > client->optlen) { - return nbd_opt_drop(client, NBD_REP_ERR_INVALID, errp, - "Inconsistent lengths in option %s", - nbd_opt_lookup(client->opt)); + return nbd_opt_invalid(client, errp, + "Inconsistent lengths in option %s", + nbd_opt_lookup(client->opt)); } client->optlen -=3D size; return qio_channel_read_all(client->ioc, buffer, size, errp) < 0 ? -EI= O : 1; @@ -398,9 +422,8 @@ static int nbd_reject_length(NBDClient *client, bool fa= tal, Error **errp) int ret; =20 assert(client->optlen); - ret =3D nbd_opt_drop(client, NBD_REP_ERR_INVALID, errp, - "option '%s' has unexpected length", - nbd_opt_lookup(client->opt)); + ret =3D nbd_opt_invalid(client, errp, "option '%s' has unexpected leng= th", + nbd_opt_lookup(client->opt)); if (fatal && !ret) { error_setg(errp, "option '%s' has unexpected length", nbd_opt_lookup(client->opt)); @@ -438,8 +461,7 @@ static int nbd_negotiate_handle_info(NBDClient *client,= uint16_t myflags, } be32_to_cpus(&namelen); if (namelen >=3D sizeof(name)) { - return nbd_opt_drop(client, NBD_REP_ERR_INVALID, errp, - "name too long for qemu"); + return nbd_opt_invalid(client, errp, "name too long for qemu"); } rc =3D nbd_opt_read(client, name, namelen, errp); if (rc <=3D 0) { --=20 2.11.1 From nobody Tue May 7 08:43:42 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.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=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 152086850675977.71995781077885; Mon, 12 Mar 2018 08:28:26 -0700 (PDT) Received: from localhost ([::1]:59544 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPNB-0006k8-Up for importer@patchew.org; Mon, 12 Mar 2018 11:28:25 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52197) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPGY-0000sP-9D for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evPGU-0006cK-VD for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:34 -0400 Received: from relay.sw.ru ([185.231.240.75]:55744) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evPGU-0006ZV-KT; Mon, 12 Mar 2018 11:21:30 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.89) (envelope-from ) id 1evPGR-0005yw-5i; Mon, 12 Mar 2018 18:21:27 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Mon, 12 Mar 2018 18:21:20 +0300 Message-Id: <20180312152126.286890-3-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180312152126.286890-1-vsementsov@virtuozzo.com> References: <20180312152126.286890-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v2 2/8] nbd/server: add nbd_read_opt_name helper 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, vsementsov@virtuozzo.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.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" Add helper to read name in format: uint32 len (<=3D NBD_MAX_NAME_SIZE) len bytes string (not 0-terminated) The helper would be reused in following patch. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- v2: splitted and changed a lot helper from larger patch of v1 nbd/server.c | 55 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index d163964cf9..085e14afbf 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -273,6 +273,47 @@ static int nbd_opt_read(NBDClient *client, void *buffe= r, size_t size, return qio_channel_read_all(client->ioc, buffer, size, errp) < 0 ? -EI= O : 1; } =20 +/* nbd_opt_read_name + * + * Read string in format: + * uint32_t len (<=3D NBD_MAX_NAME_SIZE) + * len bytes string (not 0-terminated) + * + * @name should be enough to store NBD_MAX_NAME_SIZE+1. + * if @length is non-zero, it would be set to read string length. + * + * Return -errno on I/O error, 0 if option was completely handled by + * sending a reply about inconsistent lengths, or 1 on success. */ +static int nbd_opt_read_name(NBDClient *client, char *name, uint32_t *leng= th, + Error **errp) +{ + int ret; + uint32_t len; + + ret =3D nbd_opt_read(client, &len, sizeof(len), errp); + if (ret <=3D 0) { + return ret; + } + cpu_to_be32s(&len); + + if (len > NBD_MAX_NAME_SIZE) { + return nbd_opt_invalid(client, errp, + "Invalid name length: %" PRIu32, len); + } + + ret =3D nbd_opt_read(client, name, len, errp); + if (ret <=3D 0) { + return ret; + } + name[len] =3D '\0'; + + if (length) { + *length =3D len; + } + + return 1; +} + /* Send a single NBD_REP_SERVER reply to NBD_OPT_LIST, including payload. * Return -errno on error, 0 on success. */ static int nbd_negotiate_send_rep_list(NBDClient *client, NBDExport *exp, @@ -455,19 +496,7 @@ static int nbd_negotiate_handle_info(NBDClient *client= , uint16_t myflags, 2 bytes: N, number of requests (can be 0) N * 2 bytes: N requests */ - rc =3D nbd_opt_read(client, &namelen, sizeof(namelen), errp); - if (rc <=3D 0) { - return rc; - } - be32_to_cpus(&namelen); - if (namelen >=3D sizeof(name)) { - return nbd_opt_invalid(client, errp, "name too long for qemu"); - } - rc =3D nbd_opt_read(client, name, namelen, errp); - if (rc <=3D 0) { - return rc; - } - name[namelen] =3D '\0'; + rc =3D nbd_opt_read_name(client, name, &namelen, errp); trace_nbd_negotiate_handle_export_name_request(name); =20 rc =3D nbd_opt_read(client, &requests, sizeof(requests), errp); --=20 2.11.1 From nobody Tue May 7 08:43:42 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.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=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520868246806169.13051185620157; Mon, 12 Mar 2018 08:24:06 -0700 (PDT) Received: from localhost ([::1]:59511 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPIz-0002Xh-Rw for importer@patchew.org; Mon, 12 Mar 2018 11:24:05 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52210) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPGY-0000sV-Hp for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evPGV-0006dD-35 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:34 -0400 Received: from relay.sw.ru ([185.231.240.75]:55736) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evPGU-0006ZW-Km; Mon, 12 Mar 2018 11:21:31 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.89) (envelope-from ) id 1evPGR-0005yw-8y; Mon, 12 Mar 2018 18:21:27 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Mon, 12 Mar 2018 18:21:21 +0300 Message-Id: <20180312152126.286890-4-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180312152126.286890-1-vsementsov@virtuozzo.com> References: <20180312152126.286890-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v2 3/8] nbd: BLOCK_STATUS for standard get_block_status function: server part 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, vsementsov@virtuozzo.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.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" Minimal realization: only one extent in server answer is supported. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- v2: - constants and type defs were splitted out by Eric, except for=20 NBD_META_ID_BASE_ALLOCATION - add nbd_opt_skip, to skip meta query remainder, if we are already sur= e, that the query selects nothing - check meta export name in OPT_EXPORT_NAME and OPT_GO - always set context_id =3D 0 for NBD_OPT_LIST_META_CONTEXT - negotiation rewritten to avoid wasting time and memory on reading lon= g, obviously invalid meta queries - fixed ERR_INVALID->ERR_UNKNOWN if export not found in nbd_negotiate_m= eta_queries - check client->export_meta.valid in "case NBD_CMD_BLOCK_STATUS" include/block/nbd.h | 2 + nbd/server.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 312 insertions(+) diff --git a/include/block/nbd.h b/include/block/nbd.h index 2285637e67..9f2be18186 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -188,6 +188,8 @@ typedef struct NBDExtent { #define NBD_CMD_FLAG_REQ_ONE (1 << 3) /* only one extent in BLOCK_STATUS * reply chunk */ =20 +#define NBD_META_ID_BASE_ALLOCATION 0 + /* Supported request types */ enum { NBD_CMD_READ =3D 0, diff --git a/nbd/server.c b/nbd/server.c index 085e14afbf..16d7388085 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -82,6 +82,16 @@ struct NBDExport { =20 static QTAILQ_HEAD(, NBDExport) exports =3D QTAILQ_HEAD_INITIALIZER(export= s); =20 +/* NBDExportMetaContexts represents a list of contexts to be exported, + * as selected by NBD_OPT_SET_META_CONTEXT. Also used for + * NBD_OPT_LIST_META_CONTEXT. */ +typedef struct NBDExportMetaContexts { + char export_name[NBD_MAX_NAME_SIZE + 1]; + bool valid; /* means that negotiation of the option finished without + errors */ + bool base_allocation; /* export base:allocation context (block status)= */ +} NBDExportMetaContexts; + struct NBDClient { int refcount; void (*close_fn)(NBDClient *client, bool negotiated); @@ -102,6 +112,7 @@ struct NBDClient { bool closing; =20 bool structured_reply; + NBDExportMetaContexts export_meta; =20 uint32_t opt; /* Current option being negotiated */ uint32_t optlen; /* remaining length of data in ioc for the option bei= ng @@ -273,6 +284,20 @@ static int nbd_opt_read(NBDClient *client, void *buffe= r, size_t size, return qio_channel_read_all(client->ioc, buffer, size, errp) < 0 ? -EI= O : 1; } =20 +/* Drop size bytes from the unparsed payload of the current option. + * Return -errno on I/O error, 0 if option was completely handled by + * sending a reply about inconsistent lengths, or 1 on success. */ +static int nbd_opt_skip(NBDClient *client, size_t size, Error **errp) +{ + if (size > client->optlen) { + return nbd_opt_invalid(client, errp, + "Inconsistent lengths in option %s", + nbd_opt_lookup(client->opt)); + } + client->optlen -=3D size; + return nbd_drop(client->ioc, size, errp) < 0 ? -EIO : 1; +} + /* nbd_opt_read_name * * Read string in format: @@ -371,6 +396,12 @@ static int nbd_negotiate_handle_list(NBDClient *client= , Error **errp) return nbd_negotiate_send_rep(client, NBD_REP_ACK, errp); } =20 +static void nbd_check_meta_export_name(NBDClient *client) +{ + client->export_meta.valid =3D client->export_meta.valid && + strcmp(client->exp->name, client->export_meta.export_name) =3D=3D = 0; +} + /* Send a reply to NBD_OPT_EXPORT_NAME. * Return -errno on error, 0 on success. */ static int nbd_negotiate_handle_export_name(NBDClient *client, @@ -422,6 +453,7 @@ static int nbd_negotiate_handle_export_name(NBDClient *= client, =20 QTAILQ_INSERT_TAIL(&client->exp->clients, client, next); nbd_export_get(client->exp); + nbd_check_meta_export_name(client); =20 return 0; } @@ -612,6 +644,7 @@ static int nbd_negotiate_handle_info(NBDClient *client,= uint16_t myflags, client->exp =3D exp; QTAILQ_INSERT_TAIL(&client->exp->clients, client, next); nbd_export_get(client->exp); + nbd_check_meta_export_name(client); rc =3D 1; } return rc; @@ -666,6 +699,181 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDC= lient *client, return QIO_CHANNEL(tioc); } =20 +/* nbd_negotiate_send_meta_context + * + * Send one chunk of reply to NBD_OPT_{LIST,SET}_META_CONTEXT + * + * For NBD_OPT_LIST_META_CONTEXT @context_id is ignored, 0 is used instead. + */ +static int nbd_negotiate_send_meta_context(NBDClient *client, + const char *context, + uint32_t context_id, + Error **errp) +{ + NBDOptionReplyMetaContext opt; + struct iovec iov[] =3D { + {.iov_base =3D &opt, .iov_len =3D sizeof(opt)}, + {.iov_base =3D (void *)context, .iov_len =3D strlen(context)} + }; + + if (client->opt =3D=3D NBD_OPT_LIST_META_CONTEXT) { + context_id =3D 0; + } + + set_be_option_rep(&opt.h, client->opt, NBD_REP_META_CONTEXT, + sizeof(opt) - sizeof(opt.h) + iov[1].iov_len); + stl_be_p(&opt.context_id, context_id); + + return qio_channel_writev_all(client->ioc, iov, 2, errp) < 0 ? -EIO : = 0; +} + +/* nbd_meta_base_query + * + * Handle query to 'base' namespace. For now, only base:allocation context= is + * available in it. + * + * Return -errno on I/O error, 0 if option was completely handled by + * sending a reply about inconsistent lengths, or 1 on success. */ +static int nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *m= eta, + uint32_t len, Error **errp) +{ + int ret; + char query[sizeof("allocation") - 1]; + size_t alen =3D strlen("allocation"); + + if (len =3D=3D 0) { + if (client->opt =3D=3D NBD_OPT_LIST_META_CONTEXT) { + meta->base_allocation =3D true; + } + return 1; + } + + if (len !=3D alen) { + return nbd_opt_skip(client, len, errp); + } + + ret =3D nbd_opt_read(client, query, len, errp); + if (ret <=3D 0) { + return ret; + } + + if (strncmp(query, "allocation", alen) =3D=3D 0) { + meta->base_allocation =3D true; + } + + return 1; +} + +/* nbd_negotiate_meta_query + * + * Parse namespace name and call corresponding function to parse body of t= he + * query. + * + * The only supported namespace now is 'base'. + * + * The function aims not wasting time and memory to read long unknown name= space + * names. + * + * Return -errno on I/O error, 0 if option was completely handled by + * sending a reply about inconsistent lengths, or 1 on success. */ +static int nbd_negotiate_meta_query(NBDClient *client, + NBDExportMetaContexts *meta, Error **e= rrp) +{ + int ret; + char query[sizeof("base:") - 1]; + size_t baselen =3D strlen("base:"); + uint32_t len; + + ret =3D nbd_opt_read(client, &len, sizeof(len), errp); + if (ret <=3D 0) { + return ret; + } + cpu_to_be32s(&len); + + /* The only supported namespace for now is 'base'. So query should sta= rt + * with 'base:'. Otherwise, we can ignore it and skip the remainder. */ + if (len < baselen) { + return nbd_opt_skip(client, len, errp); + } + + len -=3D baselen; + ret =3D nbd_opt_read(client, query, baselen, errp); + if (ret <=3D 0) { + return ret; + } + if (strncmp(query, "base:", baselen) !=3D 0) { + return nbd_opt_skip(client, len, errp); + } + + return nbd_meta_base_query(client, meta, len, errp); +} + +/* nbd_negotiate_meta_queries + * Handle NBD_OPT_LIST_META_CONTEXT and NBD_OPT_SET_META_CONTEXT + * + * @meta may be NULL, if caller isn't interested in selected contexts (for + * NBD_OPT_LIST_META_CONTEXT) + * + * Return -errno on I/O error, 0 if option was completely handled by + * sending a reply about inconsistent lengths, or 1 on success. */ +static int nbd_negotiate_meta_queries(NBDClient *client, + NBDExportMetaContexts *meta, Error *= *errp) +{ + int ret; + NBDExport *exp; + NBDExportMetaContexts local_meta; + uint32_t nb_queries; + int i; + + assert(client->structured_reply); + + if (!meta) { + meta =3D &local_meta; + } + + memset(meta, 0, sizeof(*meta)); + + ret =3D nbd_opt_read_name(client, meta->export_name, NULL, errp); + if (ret <=3D 0) { + return ret; + } + + exp =3D nbd_export_find(meta->export_name); + if (exp =3D=3D NULL) { + return nbd_opt_drop(client, NBD_REP_ERR_UNKNOWN, errp, + "export '%s' not present", meta->export_name); + } + + ret =3D nbd_opt_read(client, &nb_queries, sizeof(nb_queries), errp); + if (ret <=3D 0) { + return ret; + } + cpu_to_be32s(&nb_queries); + + for (i =3D 0; i < nb_queries; ++i) { + ret =3D nbd_negotiate_meta_query(client, meta, errp); + if (ret <=3D 0) { + return ret; + } + } + + if (meta->base_allocation) { + ret =3D nbd_negotiate_send_meta_context(client, "base:allocation", + NBD_META_ID_BASE_ALLOCATION, + errp); + if (ret < 0) { + return ret; + } + } + + ret =3D nbd_negotiate_send_rep(client, NBD_REP_ACK, errp); + if (ret =3D=3D 0) { + meta->valid =3D true; + } + + return ret; +} + /* nbd_negotiate_options * Process all NBD_OPT_* client option commands, during fixed newstyle * negotiation. @@ -856,6 +1064,22 @@ static int nbd_negotiate_options(NBDClient *client, u= int16_t myflags, } break; =20 + case NBD_OPT_LIST_META_CONTEXT: + case NBD_OPT_SET_META_CONTEXT: + if (!client->structured_reply) { + ret =3D nbd_opt_invalid( + client, errp, + "request option '%s' when structured reply " + "is not negotiated", nbd_opt_lookup(option)); + } else if (option =3D=3D NBD_OPT_LIST_META_CONTEXT) { + ret =3D nbd_negotiate_meta_queries(client, NULL, errp); + } else { + ret =3D nbd_negotiate_meta_queries(client, + &client->export_meta, + errp); + } + break; + default: ret =3D nbd_opt_drop(client, NBD_REP_ERR_UNSUP, errp, "Unsupported option %" PRIu32 " (%s)", @@ -1485,6 +1709,79 @@ static int coroutine_fn nbd_co_send_sparse_read(NBDC= lient *client, return ret; } =20 +static int blockstatus_to_extent_be(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, NBDExtent *extent) +{ + uint64_t remaining_bytes =3D bytes; + + while (remaining_bytes) { + uint32_t flags; + int64_t num; + int ret =3D bdrv_block_status_above(bs, NULL, offset, remaining_by= tes, + &num, NULL, NULL); + if (ret < 0) { + return ret; + } + + flags =3D (ret & BDRV_BLOCK_ALLOCATED ? 0 : NBD_STATE_HOLE) | + (ret & BDRV_BLOCK_ZERO ? NBD_STATE_ZERO : 0); + + if (remaining_bytes =3D=3D bytes) { + extent->flags =3D flags; + } + + if (flags !=3D extent->flags) { + break; + } + + offset +=3D num; + remaining_bytes -=3D num; + } + + cpu_to_be32s(&extent->flags); + extent->length =3D cpu_to_be32(bytes - remaining_bytes); + + return 0; +} + +/* nbd_co_send_extents + * @extents should be in big-endian */ +static int nbd_co_send_extents(NBDClient *client, uint64_t handle, + NBDExtent *extents, unsigned nb_extents, + uint32_t context_id, Error **errp) +{ + NBDStructuredMeta chunk; + + struct iovec iov[] =3D { + {.iov_base =3D &chunk, .iov_len =3D sizeof(chunk)}, + {.iov_base =3D extents, .iov_len =3D nb_extents * sizeof(extents[0= ])} + }; + + set_be_chunk(&chunk.h, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_BLOCK_STATU= S, + handle, sizeof(chunk) - sizeof(chunk.h) + iov[1].iov_len); + stl_be_p(&chunk.context_id, context_id); + + return nbd_co_send_iov(client, iov, 2, errp); +} + +/* Get block status from the exported device and send it to the client */ +static int nbd_co_send_block_status(NBDClient *client, uint64_t handle, + BlockDriverState *bs, uint64_t offset, + uint64_t length, uint32_t context_id, + Error **errp) +{ + int ret; + NBDExtent extent; + + ret =3D blockstatus_to_extent_be(bs, offset, length, &extent); + if (ret < 0) { + return nbd_co_send_structured_error( + client, handle, -ret, "can't get block status", errp); + } + + return nbd_co_send_extents(client, handle, &extent, 1, context_id, err= p); +} + /* nbd_co_receive_request * Collect a client request. Return 0 if request looks valid, -EIO to drop * connection right away, and any other negative value to report an error = to @@ -1562,6 +1859,8 @@ static int nbd_co_receive_request(NBDRequestData *req= , NBDRequest *request, valid_flags |=3D NBD_CMD_FLAG_DF; } else if (request->type =3D=3D NBD_CMD_WRITE_ZEROES) { valid_flags |=3D NBD_CMD_FLAG_NO_HOLE; + } else if (request->type =3D=3D NBD_CMD_BLOCK_STATUS) { + valid_flags |=3D NBD_CMD_FLAG_REQ_ONE; } if (request->flags & ~valid_flags) { error_setg(errp, "unsupported flags for command %s (got 0x%x)", @@ -1690,6 +1989,17 @@ static coroutine_fn int nbd_handle_request(NBDClient= *client, =20 return nbd_send_generic_reply(client, request->handle, ret, "discard failed", errp); + case NBD_CMD_BLOCK_STATUS: + if (client->export_meta.valid && client->export_meta.base_allocati= on) { + return nbd_co_send_block_status(client, request->handle, + blk_bs(exp->blk), request->fro= m, + request->len, + NBD_META_ID_BASE_ALLOCATION, e= rrp); + } else { + return nbd_send_generic_reply(client, request->handle, -EINVAL, + "CMD_BLOCK_STATUS not negotiated= ", + errp); + } default: msg =3D g_strdup_printf("invalid request type (%" PRIu32 ") receiv= ed", request->type); --=20 2.11.1 From nobody Tue May 7 08:43:42 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.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=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520868346557892.9714584361975; Mon, 12 Mar 2018 08:25:46 -0700 (PDT) Received: from localhost ([::1]:59524 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPKb-0004GQ-P9 for importer@patchew.org; Mon, 12 Mar 2018 11:25:45 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52196) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPGY-0000sO-7y for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evPGU-0006cE-U1 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:34 -0400 Received: from relay.sw.ru ([185.231.240.75]:55752) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evPGU-0006ZR-Kc; Mon, 12 Mar 2018 11:21:30 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.89) (envelope-from ) id 1evPGR-0005yw-CD; Mon, 12 Mar 2018 18:21:27 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Mon, 12 Mar 2018 18:21:22 +0300 Message-Id: <20180312152126.286890-5-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180312152126.286890-1-vsementsov@virtuozzo.com> References: <20180312152126.286890-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v2 4/8] block/nbd-client: save first fatal error in nbd_iter_error 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, vsementsov@virtuozzo.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.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" It is ok, that fatal error hides previous not fatal, but hiding first fatal error is a bad feature. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- v2: add Eric's r-b block/nbd-client.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index 7b68499b76..0d9f73a137 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -481,6 +481,7 @@ static coroutine_fn int nbd_co_receive_one_chunk( =20 typedef struct NBDReplyChunkIter { int ret; + bool fatal; Error *err; bool done, only_structured; } NBDReplyChunkIter; @@ -490,11 +491,12 @@ static void nbd_iter_error(NBDReplyChunkIter *iter, b= ool fatal, { assert(ret < 0); =20 - if (fatal || iter->ret =3D=3D 0) { + if ((fatal && !iter->fatal) || iter->ret =3D=3D 0) { if (iter->ret !=3D 0) { error_free(iter->err); iter->err =3D NULL; } + iter->fatal =3D fatal; iter->ret =3D ret; error_propagate(&iter->err, *local_err); } else { --=20 2.11.1 From nobody Tue May 7 08:43:42 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.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=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520868456011803.8549757544582; Mon, 12 Mar 2018 08:27:36 -0700 (PDT) Received: from localhost ([::1]:59536 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPMN-0005vC-5E for importer@patchew.org; Mon, 12 Mar 2018 11:27:35 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52202) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPGY-0000sS-Bu for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evPGV-0006d7-39 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:34 -0400 Received: from relay.sw.ru ([185.231.240.75]:55760) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evPGU-0006ZS-Kh; Mon, 12 Mar 2018 11:21:30 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.89) (envelope-from ) id 1evPGR-0005yw-Hr; Mon, 12 Mar 2018 18:21:27 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Mon, 12 Mar 2018 18:21:23 +0300 Message-Id: <20180312152126.286890-6-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180312152126.286890-1-vsementsov@virtuozzo.com> References: <20180312152126.286890-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v2 5/8] nbd: BLOCK_STATUS for standard get_block_status function: client part 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, vsementsov@virtuozzo.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.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" Minimal realization: only one extent in server answer is supported. Flag NBD_CMD_FLAG_REQ_ONE is used to force this behavior. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- v2: - drop iotests changes, as server is fixed in 03 - rebase to byte-based block status - use payload_advance32 - check extent->length for zero and for alignment (not sure about zero, but, we do not send block status with zero-length, so reply should not be zero-length too) - handle max_block in nbd_client_co_block_status - handle zero-length request in nbd_client_co_block_status - do not use magic numbers in nbd_negotiate_simple_meta_context ? Hm, don't remember, what we decided about DATA/HOLE flags mapping.. block/nbd-client.h | 6 +++ include/block/nbd.h | 3 ++ block/nbd-client.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++= ++++ block/nbd.c | 3 ++ nbd/client.c | 117 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 273 insertions(+) diff --git a/block/nbd-client.h b/block/nbd-client.h index 612c4c21a0..0ece76e5af 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -61,4 +61,10 @@ void nbd_client_detach_aio_context(BlockDriverState *bs); void nbd_client_attach_aio_context(BlockDriverState *bs, AioContext *new_context); =20 +int coroutine_fn nbd_client_co_block_status(BlockDriverState *bs, + bool want_zero, + int64_t offset, int64_t bytes, + int64_t *pnum, int64_t *map, + BlockDriverState **file); + #endif /* NBD_CLIENT_H */ diff --git a/include/block/nbd.h b/include/block/nbd.h index 9f2be18186..3b34233dd4 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -262,6 +262,7 @@ struct NBDExportInfo { /* In-out fields, set by client before nbd_receive_negotiate() and * updated by server results during nbd_receive_negotiate() */ bool structured_reply; + bool base_allocation; /* base:allocation context for NBD_CMD_BLOCK_STA= TUS */ =20 /* Set by server results during nbd_receive_negotiate() */ uint64_t size; @@ -269,6 +270,8 @@ struct NBDExportInfo { uint32_t min_block; uint32_t opt_block; uint32_t max_block; + + uint32_t meta_base_allocation_id; }; typedef struct NBDExportInfo NBDExportInfo; =20 diff --git a/block/nbd-client.c b/block/nbd-client.c index 0d9f73a137..b7683707b0 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -228,6 +228,47 @@ static int nbd_parse_offset_hole_payload(NBDStructured= ReplyChunk *chunk, return 0; } =20 +/* nbd_parse_blockstatus_payload + * support only one extent in reply and only for + * base:allocation context + */ +static int nbd_parse_blockstatus_payload(NBDClientSession *client, + NBDStructuredReplyChunk *chunk, + uint8_t *payload, uint64_t orig_l= ength, + NBDExtent *extent, Error **errp) +{ + uint32_t context_id; + + if (chunk->length !=3D sizeof(context_id) + sizeof(extent)) { + error_setg(errp, "Protocol error: invalid payload for " + "NBD_REPLY_TYPE_BLOCK_STATUS"); + return -EINVAL; + } + + context_id =3D payload_advance32(&payload); + if (client->info.meta_base_allocation_id !=3D context_id) { + error_setg(errp, "Protocol error: unexpected context id: %d for " + "NBD_REPLY_TYPE_BLOCK_STATUS, when negotiated con= text " + "id is %d", context_id, + client->info.meta_base_allocation_id); + return -EINVAL; + } + + extent->length =3D payload_advance32(&payload); + extent->flags =3D payload_advance32(&payload); + + if (extent->length =3D=3D 0 || + extent->length % client->info.min_block !=3D 0 || + extent->length > orig_length) + { + /* TODO: clarify in NBD spec the second requirement about min_bloc= k */ + error_setg(errp, "Protocol error: server sent chunk of invalid len= gth"); + return -EINVAL; + } + + return 0; +} + /* nbd_parse_error_payload * on success @errp contains message describing nbd error reply */ @@ -642,6 +683,61 @@ static int nbd_co_receive_cmdread_reply(NBDClientSessi= on *s, uint64_t handle, return iter.ret; } =20 +static int nbd_co_receive_blockstatus_reply(NBDClientSession *s, + uint64_t handle, uint64_t leng= th, + NBDExtent *extent, Error **err= p) +{ + NBDReplyChunkIter iter; + NBDReply reply; + void *payload =3D NULL; + Error *local_err =3D NULL; + bool received =3D false; + + NBD_FOREACH_REPLY_CHUNK(s, iter, handle, s->info.structured_reply, + NULL, &reply, &payload) + { + int ret; + NBDStructuredReplyChunk *chunk =3D &reply.structured; + + assert(nbd_reply_is_structured(&reply)); + + switch (chunk->type) { + case NBD_REPLY_TYPE_BLOCK_STATUS: + if (received) { + s->quit =3D true; + error_setg(&local_err, "Several BLOCK_STATUS chunks in rep= ly"); + nbd_iter_error(&iter, true, -EINVAL, &local_err); + } + received =3D true; + + ret =3D nbd_parse_blockstatus_payload(s, &reply.structured, + payload, length, extent, + &local_err); + if (ret < 0) { + s->quit =3D true; + nbd_iter_error(&iter, true, ret, &local_err); + } + break; + default: + if (!nbd_reply_type_is_error(chunk->type)) { + /* not allowed reply type */ + s->quit =3D true; + error_setg(&local_err, + "Unexpected reply type: %d (%s) " + "for CMD_BLOCK_STATUS", + chunk->type, nbd_reply_type_lookup(chunk->type)= ); + nbd_iter_error(&iter, true, -EINVAL, &local_err); + } + } + + g_free(payload); + payload =3D NULL; + } + + error_propagate(errp, iter.err); + return iter.ret; +} + static int nbd_co_request(BlockDriverState *bs, NBDRequest *request, QEMUIOVector *write_qiov) { @@ -784,6 +880,53 @@ int nbd_client_co_pdiscard(BlockDriverState *bs, int64= _t offset, int bytes) return nbd_co_request(bs, &request, NULL); } =20 +int coroutine_fn nbd_client_co_block_status(BlockDriverState *bs, + bool want_zero, + int64_t offset, int64_t bytes, + int64_t *pnum, int64_t *map, + BlockDriverState **file) +{ + int64_t ret; + NBDExtent extent; + NBDClientSession *client =3D nbd_get_client_session(bs); + Error *local_err =3D NULL; + + NBDRequest request =3D { + .type =3D NBD_CMD_BLOCK_STATUS, + .from =3D offset, + .len =3D MIN(bytes, MIN_NON_ZERO(INT_MAX, client->info.max_block)), + .flags =3D NBD_CMD_FLAG_REQ_ONE, + }; + + if (!bytes) { + *pnum =3D 0; + return 0; + } + + if (!client->info.base_allocation) { + *pnum =3D bytes; + return BDRV_BLOCK_DATA; + } + + ret =3D nbd_co_send_request(bs, &request, NULL); + if (ret < 0) { + return ret; + } + + ret =3D nbd_co_receive_blockstatus_reply(client, request.handle, bytes, + &extent, &local_err); + if (local_err) { + error_report_err(local_err); + } + if (ret < 0) { + return ret; + } + + *pnum =3D extent.length; + return (extent.flags & NBD_STATE_HOLE ? 0 : BDRV_BLOCK_DATA) | + (extent.flags & NBD_STATE_ZERO ? BDRV_BLOCK_ZERO : 0); +} + void nbd_client_detach_aio_context(BlockDriverState *bs) { NBDClientSession *client =3D nbd_get_client_session(bs); @@ -828,6 +971,7 @@ int nbd_client_init(BlockDriverState *bs, =20 client->info.request_sizes =3D true; client->info.structured_reply =3D true; + client->info.base_allocation =3D true; ret =3D nbd_receive_negotiate(QIO_CHANNEL(sioc), export, tlscreds, hostname, &client->ioc, &client->info, errp); diff --git a/block/nbd.c b/block/nbd.c index d4e4172c08..1e2b3ba2d3 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -585,6 +585,7 @@ static BlockDriver bdrv_nbd =3D { .bdrv_detach_aio_context =3D nbd_detach_aio_context, .bdrv_attach_aio_context =3D nbd_attach_aio_context, .bdrv_refresh_filename =3D nbd_refresh_filename, + .bdrv_co_block_status =3D nbd_client_co_block_status, }; =20 static BlockDriver bdrv_nbd_tcp =3D { @@ -604,6 +605,7 @@ static BlockDriver bdrv_nbd_tcp =3D { .bdrv_detach_aio_context =3D nbd_detach_aio_context, .bdrv_attach_aio_context =3D nbd_attach_aio_context, .bdrv_refresh_filename =3D nbd_refresh_filename, + .bdrv_co_block_status =3D nbd_client_co_block_status, }; =20 static BlockDriver bdrv_nbd_unix =3D { @@ -623,6 +625,7 @@ static BlockDriver bdrv_nbd_unix =3D { .bdrv_detach_aio_context =3D nbd_detach_aio_context, .bdrv_attach_aio_context =3D nbd_attach_aio_context, .bdrv_refresh_filename =3D nbd_refresh_filename, + .bdrv_co_block_status =3D nbd_client_co_block_status, }; =20 static void bdrv_nbd_init(void) diff --git a/nbd/client.c b/nbd/client.c index dcad23a053..daf1ae2af5 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -595,6 +595,111 @@ static QIOChannel *nbd_receive_starttls(QIOChannel *i= oc, return QIO_CHANNEL(tioc); } =20 +/* nbd_negotiate_simple_meta_context: + * Set one meta context. Simple means that reply must contain zero (not + * negotiated) or one (negotiated) contexts. More contexts would be consid= ered + * as a protocol error. It's also implied, that meta-data query equals que= ried + * context name, so, if server replies with something different then @cont= ext, + * it considered as error too. + * return 1 for successful negotiation, context_id is set + * 0 if operation is unsupported, + * -errno with errp set for any other error + */ +static int nbd_negotiate_simple_meta_context(QIOChannel *ioc, + const char *export, + const char *context, + uint32_t *context_id, + Error **errp) +{ + int ret; + NBDOptionReply reply; + uint32_t received_id; + bool received; + uint32_t export_len =3D strlen(export); + uint32_t context_len =3D strlen(context); + uint32_t data_len =3D sizeof(export_len) + export_len + + sizeof(uint32_t) + /* number of queries */ + sizeof(context_len) + context_len; + char *data =3D g_malloc(data_len); + char *p =3D data; + + stl_be_p(p, export_len); + memcpy(p +=3D sizeof(export_len), export, export_len); + stl_be_p(p +=3D export_len, 1); + stl_be_p(p +=3D sizeof(uint32_t), context_len); + memcpy(p +=3D sizeof(context_len), context, context_len); + + ret =3D nbd_send_option_request(ioc, NBD_OPT_SET_META_CONTEXT, data_le= n, data, + errp); + g_free(data); + if (ret < 0) { + return ret; + } + + if (nbd_receive_option_reply(ioc, NBD_OPT_SET_META_CONTEXT, &reply, + errp) < 0) + { + return -1; + } + + ret =3D nbd_handle_reply_err(ioc, &reply, errp); + if (ret <=3D 0) { + return ret; + } + + if (reply.type =3D=3D NBD_REP_META_CONTEXT) { + char *name; + size_t len; + + if (nbd_read(ioc, &received_id, sizeof(received_id), errp) < 0) { + return -EIO; + } + be32_to_cpus(&received_id); + + len =3D reply.length - sizeof(received_id); + name =3D g_malloc(len + 1); + if (nbd_read(ioc, name, len, errp) < 0) { + g_free(name); + return -EIO; + } + name[len] =3D '\0'; + if (strcmp(context, name)) { + error_setg(errp, "Failed to negotiate meta context '%s', serve= r " + "answered with different context '%s'", context, + name); + g_free(name); + return -1; + } + g_free(name); + + received =3D true; + + /* receive NBD_REP_ACK */ + if (nbd_receive_option_reply(ioc, NBD_OPT_SET_META_CONTEXT, &reply, + errp) < 0) + { + return -1; + } + + ret =3D nbd_handle_reply_err(ioc, &reply, errp); + if (ret <=3D 0) { + return ret; + } + } + + if (reply.type !=3D NBD_REP_ACK) { + error_setg(errp, "Unexpected reply type %" PRIx32 " expected %x", + reply.type, NBD_REP_ACK); + return -1; + } + + if (received) { + *context_id =3D received_id; + return 1; + } + + return 0; +} =20 int nbd_receive_negotiate(QIOChannel *ioc, const char *name, QCryptoTLSCreds *tlscreds, const char *hostname, @@ -606,10 +711,12 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char= *name, int rc; bool zeroes =3D true; bool structured_reply =3D info->structured_reply; + bool base_allocation =3D info->base_allocation; =20 trace_nbd_receive_negotiate(tlscreds, hostname ? hostname : ""); =20 info->structured_reply =3D false; + info->base_allocation =3D false; rc =3D -EINVAL; =20 if (outioc) { @@ -700,6 +807,16 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char = *name, info->structured_reply =3D result =3D=3D 1; } =20 + if (info->structured_reply && base_allocation) { + result =3D nbd_negotiate_simple_meta_context( + ioc, name, "base:allocation", + &info->meta_base_allocation_id, errp); + if (result < 0) { + goto fail; + } + info->base_allocation =3D result =3D=3D 1; + } + /* Try NBD_OPT_GO first - if it works, we are done (it * also gives us a good message if the server requires * TLS). If it is not available, fall back to --=20 2.11.1 From nobody Tue May 7 08:43:42 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.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=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520868288028366.14603496015604; Mon, 12 Mar 2018 08:24:48 -0700 (PDT) Received: from localhost ([::1]:59515 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPJf-0003Ph-6D for importer@patchew.org; Mon, 12 Mar 2018 11:24:47 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52208) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPGY-0000sU-GV for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evPGV-0006cg-0J for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:34 -0400 Received: from relay.sw.ru ([185.231.240.75]:55734) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evPGU-0006ZP-Kj; Mon, 12 Mar 2018 11:21:30 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.89) (envelope-from ) id 1evPGR-0005yw-MS; Mon, 12 Mar 2018 18:21:27 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Mon, 12 Mar 2018 18:21:24 +0300 Message-Id: <20180312152126.286890-7-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180312152126.286890-1-vsementsov@virtuozzo.com> References: <20180312152126.286890-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v2 6/8] iotests.py: tiny refactor: move system imports up 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, vsementsov@virtuozzo.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.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" Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- v2: add Eric's r-b tests/qemu-iotests/iotests.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 1bcc9ca57d..c1302a2f9b 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -23,13 +23,14 @@ import subprocess import string import unittest import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scrip= ts')) -import qtest import struct import json import signal import logging =20 +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scrip= ts')) +import qtest + =20 # This will not work if arguments contain spaces but is necessary if we # want to support the override options that ./check supports. --=20 2.11.1 From nobody Tue May 7 08:43:42 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.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=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520868385490611.3991992051868; Mon, 12 Mar 2018 08:26:25 -0700 (PDT) Received: from localhost ([::1]:59532 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPLE-0004ru-IC for importer@patchew.org; Mon, 12 Mar 2018 11:26:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52204) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPGY-0000sT-Bk for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evPGU-0006cW-Um for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:34 -0400 Received: from relay.sw.ru ([185.231.240.75]:55742) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evPGU-0006ZQ-Kc; Mon, 12 Mar 2018 11:21:30 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.89) (envelope-from ) id 1evPGR-0005yw-RJ; Mon, 12 Mar 2018 18:21:27 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Mon, 12 Mar 2018 18:21:25 +0300 Message-Id: <20180312152126.286890-8-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180312152126.286890-1-vsementsov@virtuozzo.com> References: <20180312152126.286890-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v2 7/8] iotests: add file_path helper 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, vsementsov@virtuozzo.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.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" Simple way to have auto generated filenames with auto cleanup. Like FilePath but without using 'with' statement and without additional indentation of the whole test. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- v2: fix type in commit message tests/qemu-iotests/iotests.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index c1302a2f9b..f2d05ca3fd 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -27,6 +27,7 @@ import struct import json import signal import logging +import atexit =20 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scrip= ts')) import qtest @@ -250,6 +251,37 @@ class FilePath(object): return False =20 =20 +def file_path_remover(): + for path in reversed(file_path_remover.paths): + try: + os.remove(path) + except OSError: + pass + + +def file_path(*names): + ''' Another way to get auto-generated filename that cleans itself up. + + Use it as simple as: + + img_a, img_b =3D file_path('a.img', 'b.img') + sock =3D file_path('socket') + ''' + + if not hasattr(file_path_remover, 'paths'): + file_path_remover.paths =3D [] + atexit.register(file_path_remover) + + paths =3D [] + for name in names: + filename =3D '{0}-{1}'.format(os.getpid(), name) + path =3D os.path.join(test_dir, filename) + file_path_remover.paths.append(path) + paths.append(path) + + return paths[0] if len(paths) =3D=3D 1 else paths + + class VM(qtest.QEMUQtestMachine): '''A QEMU VM''' =20 --=20 2.11.1 From nobody Tue May 7 08:43:42 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.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=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520868650992306.58266821207326; Mon, 12 Mar 2018 08:30:50 -0700 (PDT) Received: from localhost ([::1]:59583 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPPV-0000bC-Mp for importer@patchew.org; Mon, 12 Mar 2018 11:30:49 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52212) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evPGY-0000sb-LQ for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evPGV-0006cj-0b for qemu-devel@nongnu.org; Mon, 12 Mar 2018 11:21:34 -0400 Received: from relay.sw.ru ([185.231.240.75]:55762) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1evPGU-0006ZX-Kh; Mon, 12 Mar 2018 11:21:30 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.89) (envelope-from ) id 1evPGS-0005yw-0R; Mon, 12 Mar 2018 18:21:28 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Mon, 12 Mar 2018 18:21:26 +0300 Message-Id: <20180312152126.286890-9-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180312152126.286890-1-vsementsov@virtuozzo.com> References: <20180312152126.286890-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v2 8/8] iotests: new test 209 for NBD BLOCK_STATUS 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, vsementsov@virtuozzo.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.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" Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- v2: mv 206 209, make test file executable tests/qemu-iotests/209 | 34 ++++++++++++++++++++++++++++++++++ tests/qemu-iotests/209.out | 2 ++ tests/qemu-iotests/group | 1 + 3 files changed, 37 insertions(+) create mode 100755 tests/qemu-iotests/209 create mode 100644 tests/qemu-iotests/209.out diff --git a/tests/qemu-iotests/209 b/tests/qemu-iotests/209 new file mode 100755 index 0000000000..259e991ec6 --- /dev/null +++ b/tests/qemu-iotests/209 @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# +# Tests for NBD BLOCK_STATUS extension +# +# Copyright (c) 2018 Virtuozzo International GmbH +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import iotests +from iotests import qemu_img_create, qemu_io, qemu_img_verbose, qemu_nbd, \ + file_path + +iotests.verify_image_format(supported_fmts=3D['qcow2']) + +disk, nbd_sock =3D file_path('disk', 'nbd-sock') +nbd_uri =3D 'nbd+unix:///exp?socket=3D' + nbd_sock + +qemu_img_create('-f', iotests.imgfmt, disk, '1M') +qemu_io('-f', iotests.imgfmt, '-c', 'write 0 512K', disk) + +qemu_nbd('-k', nbd_sock, '-x', 'exp', '-f', iotests.imgfmt, disk) +qemu_img_verbose('map', '-f', 'raw', '--output=3Djson', nbd_uri) diff --git a/tests/qemu-iotests/209.out b/tests/qemu-iotests/209.out new file mode 100644 index 0000000000..0d29724e84 --- /dev/null +++ b/tests/qemu-iotests/209.out @@ -0,0 +1,2 @@ +[{ "start": 0, "length": 524288, "depth": 0, "zero": false, "data": true}, +{ "start": 524288, "length": 524288, "depth": 0, "zero": true, "data": fal= se}] diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index a2dfe79d86..c16343016c 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -202,3 +202,4 @@ 203 rw auto 204 rw auto quick 205 rw auto quick +209 rw auto quick --=20 2.11.1