From nobody Sun Oct 5 15:37:39 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1515425750505126.08922522867579; Mon, 8 Jan 2018 07:35:50 -0800 (PST) Received: from localhost ([::1]:40788 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eYZSn-0005Ks-QC for importer@patchew.org; Mon, 08 Jan 2018 10:35:49 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36931) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eYZOu-0002Su-5H for qemu-devel@nongnu.org; Mon, 08 Jan 2018 10:31:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eYZOs-0007jm-Re for qemu-devel@nongnu.org; Mon, 08 Jan 2018 10:31:48 -0500 Received: from mx1.redhat.com ([209.132.183.28]:38392) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eYZOo-0007ep-AU; Mon, 08 Jan 2018 10:31:42 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5F6B94D2ED; Mon, 8 Jan 2018 15:31:41 +0000 (UTC) Received: from red.redhat.com (ovpn-124-124.rdu2.redhat.com [10.10.124.124]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6731F60C8A; Mon, 8 Jan 2018 15:31:40 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 8 Jan 2018 09:31:35 -0600 Message-Id: <20180108153137.5195-2-eblake@redhat.com> In-Reply-To: <20180108153137.5195-1-eblake@redhat.com> References: <20180108153137.5195-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Mon, 08 Jan 2018 15:31:41 +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] [PULL 1/3] nbd/server: Implement sparse reads atop structured reply 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: Paolo Bonzini , "open list:Network Block Dev..." 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" The reason that NBD added structured reply in the first place was to allow for efficient reads of sparse files, by allowing the reply to include chunks to quickly communicate holes to the client without sending lots of zeroes over the wire. Time to implement this in the server; our client can already read such data. We can only skip holes insofar as the block layer can query them; and only if the client is okay with a fragmented request (if a client requests NBD_CMD_FLAG_DF and the entire read is a hole, we could technically return a single NBD_REPLY_TYPE_OFFSET_HOLE, but that's a fringe case not worth catering to here). Sadly, the control flow is a bit wonkier than I would have preferred, but it was minimally invasive to have a split in the action between a fragmented read (handled directly where we recognize NBD_CMD_READ with the right conditions, and sending multiple chunks) vs. a single read (handled at the end of nbd_trip, for both simple and structured replies, when we know there is only one thing being read). Likewise, I didn't make any effort to optimize the final chunk of a fragmented read to set the NBD_REPLY_FLAG_DONE, but unconditionally send that as a separate NBD_REPLY_TYPE_NONE. Signed-off-by: Eric Blake Message-Id: <20171107030912.23930-2-eblake@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy --- nbd/server.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++= +--- nbd/trace-events | 1 + 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index 92c0fdd03b..be7310cb41 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1303,6 +1303,7 @@ static int coroutine_fn nbd_co_send_structured_read(N= BDClient *client, uint64_t offset, void *data, size_t size, + bool final, Error **errp) { NBDStructuredReadData chunk; @@ -1313,13 +1314,73 @@ static int coroutine_fn nbd_co_send_structured_read= (NBDClient *client, assert(size); trace_nbd_co_send_structured_read(handle, offset, data, size); - set_be_chunk(&chunk.h, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_OFFSET_DATA, - handle, sizeof(chunk) - sizeof(chunk.h) + size); + set_be_chunk(&chunk.h, final ? NBD_REPLY_FLAG_DONE : 0, + NBD_REPLY_TYPE_OFFSET_DATA, handle, + sizeof(chunk) - sizeof(chunk.h) + size); stq_be_p(&chunk.offset, offset); return nbd_co_send_iov(client, iov, 2, errp); } +static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client, + uint64_t handle, + uint64_t offset, + uint8_t *data, + size_t size, + Error **errp) +{ + int ret =3D 0; + NBDExport *exp =3D client->exp; + size_t progress =3D 0; + + while (progress < size) { + int64_t pnum; + int status =3D bdrv_block_status_above(blk_bs(exp->blk), NULL, + offset + progress, + size - progress, &pnum, NULL, + NULL); + + if (status < 0) { + error_setg_errno(errp, -status, "unable to check for holes"); + return status; + } + assert(pnum && pnum <=3D size - progress); + if (status & BDRV_BLOCK_ZERO) { + NBDStructuredReadHole chunk; + struct iovec iov[] =3D { + {.iov_base =3D &chunk, .iov_len =3D sizeof(chunk)}, + }; + + trace_nbd_co_send_structured_read_hole(handle, offset + progre= ss, + pnum); + set_be_chunk(&chunk.h, 0, NBD_REPLY_TYPE_OFFSET_HOLE, + handle, sizeof(chunk) - sizeof(chunk.h)); + stq_be_p(&chunk.offset, offset + progress); + stl_be_p(&chunk.length, pnum); + ret =3D nbd_co_send_iov(client, iov, 1, errp); + } else { + ret =3D blk_pread(exp->blk, offset + progress + exp->dev_offse= t, + data + progress, pnum); + if (ret < 0) { + error_setg_errno(errp, -ret, "reading from file failed"); + break; + } + ret =3D nbd_co_send_structured_read(client, handle, offset + p= rogress, + data + progress, pnum, false, + errp); + } + + if (ret < 0) { + break; + } + progress +=3D pnum; + } + if (!ret) { + ret =3D nbd_co_send_structured_done(client, handle, errp); + } + return ret; +} + static int coroutine_fn nbd_co_send_structured_error(NBDClient *client, uint64_t handle, uint32_t error, @@ -1481,6 +1542,16 @@ static coroutine_fn void nbd_trip(void *opaque) } } + if (client->structured_reply && !(request.flags & NBD_CMD_FLAG_DF)= ) { + ret =3D nbd_co_send_sparse_read(req->client, request.handle, + request.from, req->data, request= .len, + &local_err); + if (ret < 0) { + goto reply; + } + goto done; + } + ret =3D blk_pread(exp->blk, request.from + exp->dev_offset, req->data, request.len); if (ret < 0) { @@ -1561,7 +1632,8 @@ reply: } else if (reply_data_len) { ret =3D nbd_co_send_structured_read(req->client, request.handl= e, request.from, req->data, - reply_data_len, &local_err); + reply_data_len, true, + &local_err); } else { ret =3D nbd_co_send_structured_done(req->client, request.handl= e, &local_err); diff --git a/nbd/trace-events b/nbd/trace-events index 92568edce5..2b8268ce8c 100644 --- a/nbd/trace-events +++ b/nbd/trace-events @@ -57,6 +57,7 @@ nbd_blk_aio_detach(const char *name, void *ctx) "Export %= s: Detaching clients fr nbd_co_send_simple_reply(uint64_t handle, uint32_t error, const char *errn= ame, int len) "Send simple reply: handle =3D %" PRIu64 ", error =3D %" PRIu= 32 " (%s), len =3D %d" nbd_co_send_structured_done(uint64_t handle) "Send structured reply done: = handle =3D %" PRIu64 nbd_co_send_structured_read(uint64_t handle, uint64_t offset, void *data, = size_t size) "Send structured read data reply: handle =3D %" PRIu64 ", offs= et =3D %" PRIu64 ", data =3D %p, len =3D %zu" +nbd_co_send_structured_read_hole(uint64_t handle, uint64_t offset, size_t = size) "Send structured read hole reply: handle =3D %" PRIu64 ", offset =3D = %" PRIu64 ", len =3D %zu" nbd_co_send_structured_error(uint64_t handle, int err, const char *errname= , const char *msg) "Send structured error reply: handle =3D %" PRIu64 ", er= ror =3D %d (%s), msg =3D '%s'" nbd_co_receive_request_decode_type(uint64_t handle, uint16_t type, const c= har *name) "Decoding type: handle =3D %" PRIu64 ", type =3D %" PRIu16 " (%s= )" nbd_co_receive_request_payload_received(uint64_t handle, uint32_t len) "Pa= yload received: handle =3D %" PRIu64 ", len =3D %" PRIu32 --=20 2.14.3 From nobody Sun Oct 5 15:37:39 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1515425640532571.4096250022652; Mon, 8 Jan 2018 07:34:00 -0800 (PST) Received: from localhost ([::1]:40655 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eYZQy-0003hY-2M for importer@patchew.org; Mon, 08 Jan 2018 10:33:56 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36895) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eYZOt-0002Rk-6b for qemu-devel@nongnu.org; Mon, 08 Jan 2018 10:31:48 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eYZOs-0007jS-A9 for qemu-devel@nongnu.org; Mon, 08 Jan 2018 10:31:47 -0500 Received: from mx1.redhat.com ([209.132.183.28]:36168) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eYZOp-0007fD-0t; Mon, 08 Jan 2018 10:31:43 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 37C2A780DD; Mon, 8 Jan 2018 15:31:42 +0000 (UTC) Received: from red.redhat.com (ovpn-124-124.rdu2.redhat.com [10.10.124.124]) by smtp.corp.redhat.com (Postfix) with ESMTP id 97A7760C4E; Mon, 8 Jan 2018 15:31:41 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 8 Jan 2018 09:31:36 -0600 Message-Id: <20180108153137.5195-3-eblake@redhat.com> In-Reply-To: <20180108153137.5195-1-eblake@redhat.com> References: <20180108153137.5195-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Mon, 08 Jan 2018 15:31:42 +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] [PULL 2/3] nbd/server: Optimize final chunk of sparse read 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: Paolo Bonzini , "open list:Network Block Dev..." 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" If we are careful to handle 0-length read requests correctly, we can optimize our sparse read to send the NBD_REPLY_FLAG_DONE bit on our last OFFSET_DATA or OFFSET_HOLE chunk rather than needing a separate chunk. Signed-off-by: Eric Blake Message-Id: <20171107030912.23930-3-eblake@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy --- nbd/server.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index be7310cb41..e443b3cf5c 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1339,12 +1339,14 @@ static int coroutine_fn nbd_co_send_sparse_read(NBD= Client *client, offset + progress, size - progress, &pnum, NULL, NULL); + bool final; if (status < 0) { error_setg_errno(errp, -status, "unable to check for holes"); return status; } assert(pnum && pnum <=3D size - progress); + final =3D progress + pnum =3D=3D size; if (status & BDRV_BLOCK_ZERO) { NBDStructuredReadHole chunk; struct iovec iov[] =3D { @@ -1353,7 +1355,8 @@ static int coroutine_fn nbd_co_send_sparse_read(NBDCl= ient *client, trace_nbd_co_send_structured_read_hole(handle, offset + progre= ss, pnum); - set_be_chunk(&chunk.h, 0, NBD_REPLY_TYPE_OFFSET_HOLE, + set_be_chunk(&chunk.h, final ? NBD_REPLY_FLAG_DONE : 0, + NBD_REPLY_TYPE_OFFSET_HOLE, handle, sizeof(chunk) - sizeof(chunk.h)); stq_be_p(&chunk.offset, offset + progress); stl_be_p(&chunk.length, pnum); @@ -1366,7 +1369,7 @@ static int coroutine_fn nbd_co_send_sparse_read(NBDCl= ient *client, break; } ret =3D nbd_co_send_structured_read(client, handle, offset + p= rogress, - data + progress, pnum, false, + data + progress, pnum, final, errp); } @@ -1375,9 +1378,6 @@ static int coroutine_fn nbd_co_send_sparse_read(NBDCl= ient *client, } progress +=3D pnum; } - if (!ret) { - ret =3D nbd_co_send_structured_done(client, handle, errp); - } return ret; } @@ -1542,7 +1542,8 @@ static coroutine_fn void nbd_trip(void *opaque) } } - if (client->structured_reply && !(request.flags & NBD_CMD_FLAG_DF)= ) { + if (client->structured_reply && !(request.flags & NBD_CMD_FLAG_DF)= && + request.len) { ret =3D nbd_co_send_sparse_read(req->client, request.handle, request.from, req->data, request= .len, &local_err); --=20 2.14.3 From nobody Sun Oct 5 15:37:39 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1515425636959179.38253466762262; Mon, 8 Jan 2018 07:33:56 -0800 (PST) Received: from localhost ([::1]:40656 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eYZQy-0003i4-7O for importer@patchew.org; Mon, 08 Jan 2018 10:33:56 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36930) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eYZOu-0002St-59 for qemu-devel@nongnu.org; Mon, 08 Jan 2018 10:31:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eYZOt-0007jy-6J for qemu-devel@nongnu.org; Mon, 08 Jan 2018 10:31:48 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49758) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eYZOq-0007hg-M4; Mon, 08 Jan 2018 10:31:44 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D4FB380472; Mon, 8 Jan 2018 15:31:43 +0000 (UTC) Received: from red.redhat.com (ovpn-124-124.rdu2.redhat.com [10.10.124.124]) by smtp.corp.redhat.com (Postfix) with ESMTP id C2D3C60C8A; Mon, 8 Jan 2018 15:31:42 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 8 Jan 2018 09:31:37 -0600 Message-Id: <20180108153137.5195-4-eblake@redhat.com> In-Reply-To: <20180108153137.5195-1-eblake@redhat.com> References: <20180108153137.5195-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Mon, 08 Jan 2018 15:31:43 +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] [PULL 3/3] block/nbd: fix segmentation fault when .desc is not null-terminated 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: Kevin Wolf , "open list:Network Block Dev..." , qemu-stable@nongnu.org, Max Reitz , Paolo Bonzini , Murilo Opsfelder Araujo 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" From: Murilo Opsfelder Araujo The find_desc_by_name() from util/qemu-option.c relies on the .name not bei= ng NULL to call strcmp(). This check becomes unsafe when the list is not NULL-terminated, which is the case of nbd_runtime_opts in block/nbd.c, and = can result in segmentation fault when strcmp() tries to access an invalid memor= y: #0 0x00007fff8c75f7d4 in __strcmp_power9 () from /lib64/libc.so.6 #1 0x00000000102d3ec8 in find_desc_by_name (desc=3D0x1036d6f0, name=3D0= x28e46670 "server.path") at util/qemu-option.c:166 #2 0x00000000102d93e0 in qemu_opts_absorb_qdict (opts=3D0x28e47a80, qdi= ct=3D0x28e469a0, errp=3D0x7fffec247c98) at util/qemu-option.c:1026 #3 0x000000001012a2e4 in nbd_open (bs=3D0x28e42290, options=3D0x28e469a= 0, flags=3D24578, errp=3D0x7fffec247d80) at block/nbd.c:406 #4 0x00000000100144e8 in bdrv_open_driver (bs=3D0x28e42290, drv=3D0x103= 6e070 , node_name=3D0x0, options=3D0x28e469a0, open_flags=3D= 24578, errp=3D0x7fffec247f50) at block.c:1135 #5 0x0000000010015b04 in bdrv_open_common (bs=3D0x28e42290, file=3D0x0,= options=3D0x28e469a0, errp=3D0x7fffec247f50) at block.c:1395 >From gdb, the desc[i].name was not NULL and resulted in strcmp() accessing= an invalid memory: >>> p desc[5] $8 =3D { name =3D 0x1037f098 "R27A", type =3D 1561964883, help =3D 0xc0bbb23e , def_value_str =3D 0x2 } >>> p desc[6] $9 =3D { name =3D 0x103dac78 <__gcov0.do_qemu_init_bdrv_nbd_init> "\001", type =3D 272101528, help =3D 0x29ec0b754403e31f , def_value_str =3D 0x81f343b9 } This patch fixes the segmentation fault in strcmp() by adding a NULL elemen= t at the end of nbd_runtime_opts.desc list, which is the common practice to most= of other structs like runtime_opts in block/null.c. Thus, the desc[i].name != =3D NULL check becomes safe because it will not evaluate to true when .desc list rea= ched its end. Reported-by: R. Nageswara Sastry Buglink: https://bugs.launchpad.net/qemu/+bug/1727259 Signed-off-by: Murilo Opsfelder Araujo Message-Id: <20180105133241.14141-2-muriloo@linux.vnet.ibm.com> CC: qemu-stable@nongnu.org Fixes: 7ccc44fd7d1dfa62c4d6f3a680df809d6e7068ce Signed-off-by: Eric Blake --- block/nbd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/nbd.c b/block/nbd.c index a50d24b50a..8b8ba56cdd 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -388,6 +388,7 @@ static QemuOptsList nbd_runtime_opts =3D { .type =3D QEMU_OPT_STRING, .help =3D "ID of the TLS credentials to use", }, + { /* end of list */ } }, }; --=20 2.14.3