From nobody Mon Feb 9 20:31:53 2026 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; dkim=fail; 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 1499957639068623.246301003668; Thu, 13 Jul 2017 07:53:59 -0700 (PDT) Received: from localhost ([::1]:60496 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dVfV7-0002dt-Kf for importer@patchew.org; Thu, 13 Jul 2017 10:53:57 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52015) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dVf4n-0002El-Du for qemu-devel@nongnu.org; Thu, 13 Jul 2017 10:26:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dVf4j-0004Tm-Ce for qemu-devel@nongnu.org; Thu, 13 Jul 2017 10:26:45 -0400 Received: from mail-wr0-f175.google.com ([209.85.128.175]:33463) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dVf4j-0004TW-3E for qemu-devel@nongnu.org; Thu, 13 Jul 2017 10:26:41 -0400 Received: by mail-wr0-f175.google.com with SMTP id r103so54034866wrb.0 for ; Thu, 13 Jul 2017 07:26:41 -0700 (PDT) Received: from 640k.lan (94-39-191-51.adsl-ull.clienti.tiscali.it. [94.39.191.51]) by smtp.gmail.com with ESMTPSA id k75sm6042448wmh.10.2017.07.13.07.25.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 13 Jul 2017 07:25:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=Q5wKEy57GqaTZdhIHUdLeTbO6rMjrs4pKNCYTYdQsyA=; b=dQTQiPQaECz42IfM5lt5HoVJVruYtmOORCdcl7Cy0dRBWKW9OASpFp+0wo4KDDW81d C2HAhQDVSPuQQREHqaR8Q4/EejO8nLTeYl1utrKIDKIpundSfIFKSbp2Ikn7aRn22Q57 33k+XJluJodcVuKINvs2SO7Wgz6YTUcr5F/xCchw6QfHv5BtMTg/7/ZiqNco1mnejHAH vWx8/F+tx7eaGmNDaydJZE+nsk4Z7oM/do6X8Fk6eKxt7Eb2pbFzd/WFi/pBqA6cHoQo WmiB7FZsu9qyLpM1z9gkTXoN0HPNoW3RJGd1y5bvZ87zBHqop9DvCoGPA9gkm2JkWMnK U3yw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=Q5wKEy57GqaTZdhIHUdLeTbO6rMjrs4pKNCYTYdQsyA=; b=GKyZaymjUOPVHU4HWRYcVy4F9m7YqDknunhS/6PhQglQHXHG4lGg1SJ4EccOX/spLJ h4ANXW4kMmUp3POogMY+DURaDkFTWO1EfHGRoTVlwv+4d9azyESAtJABb+Y9lnCNA/52 v3akjsJJ8WxA1tvxcuDXGhJ/tS9C+h7Gjy1EAhxdJc6VFTKrcW9jdANdUbIEvgkQvLBn MBmwmiSgCzo56Jt4rLYL3Xr2t4RNsgGvaU0GdbrNNUkLWVkJWIMEFbNQVKO2XGVcKYcj 5kPvBdgqTsfpMBnMU+Scq7viObIY3UtqcYe7MMxKaRJzb4TnrZ9+X4cYq39PbZPkJCJw oSlw== X-Gm-Message-State: AIVw110ccGDnXvoOcVxvXnPd3Bvrb6eB186gIv2yTVVGS0mh3TS0t/Fq 7mLxnFSVN+iKQQlk1Ug= X-Received: by 10.223.136.212 with SMTP id g20mr2019018wrg.96.1499955939745; Thu, 13 Jul 2017 07:25:39 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 13 Jul 2017 16:24:31 +0200 Message-Id: <1499955874-10954-39-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1499955874-10954-1-git-send-email-pbonzini@redhat.com> References: <1499955874-10954-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.128.175 Subject: [Qemu-devel] [PULL 38/41] nbd: Implement NBD_INFO_BLOCK_SIZE on server 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Eric Blake The upstream NBD Protocol has defined a new extension to allow the server to advertise block sizes to the client, as well as a way for the client to inform the server that it intends to obey block sizes. Thanks to a recent fix (commit df7b97ff), our real minimum transfer size is always 1 (the block layer takes care of read-modify-write on our behalf), but we're still more efficient if we advertise 512 when the client supports it, as follows: - OPT_INFO, but no NBD_INFO_BLOCK_SIZE: advertise 512, then fail with NBD_REP_ERR_BLOCK_SIZE_REQD; client is free to try something else since we don't disconnect - OPT_INFO with NBD_INFO_BLOCK_SIZE: advertise 512 - OPT_GO, but no NBD_INFO_BLOCK_SIZE: advertise 1 - OPT_GO with NBD_INFO_BLOCK_SIZE: advertise 512 We can also advertise the optimum block size (presumably the cluster size, when exporting a qcow2 file), and our absolute maximum transfer size of 32M, to help newer clients avoid EINVAL failures or abrupt disconnects on oversize requests. We do not reject clients for using the older NBD_OPT_EXPORT_NAME; we are no worse off for those clients than we used to be. Signed-off-by: Eric Blake Message-Id: <20170707203049.534-9-eblake@redhat.com> Signed-off-by: Paolo Bonzini --- nbd/server.c | 48 ++++++++++++++++++++++++++++++++++++++++++++---- nbd/trace-events | 1 + 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index e84d012..49ed574 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -365,6 +365,8 @@ static int nbd_negotiate_handle_info(NBDClient *client,= uint32_t length, uint16_t request; uint32_t namelen; bool sendname =3D false; + bool blocksize =3D false; + uint32_t sizes[3]; char buf[sizeof(uint64_t) + sizeof(uint16_t)]; const char *msg; =20 @@ -412,11 +414,16 @@ static int nbd_negotiate_handle_info(NBDClient *clien= t, uint32_t length, length -=3D sizeof(request); trace_nbd_negotiate_handle_info_request(request, nbd_info_lookup(request)); - /* For now, we only care about NBD_INFO_NAME; everything else - * is either a request we don't know or something we send - * regardless of request. */ - if (request =3D=3D NBD_INFO_NAME) { + /* We care about NBD_INFO_NAME and NBD_INFO_BLOCK_SIZE; + * everything else is either a request we don't know or + * something we send regardless of request */ + switch (request) { + case NBD_INFO_NAME: sendname =3D true; + break; + case NBD_INFO_BLOCK_SIZE: + blocksize =3D true; + break; } } =20 @@ -448,6 +455,27 @@ static int nbd_negotiate_handle_info(NBDClient *client= , uint32_t length, } } =20 + /* Send NBD_INFO_BLOCK_SIZE always, but tweak the minimum size + * according to whether the client requested it, and according to + * whether this is OPT_INFO or OPT_GO. */ + /* minimum - 1 for back-compat, or 512 if client is new enough. + * TODO: consult blk_bs(blk)->bl.request_alignment? */ + sizes[0] =3D (opt =3D=3D NBD_OPT_INFO || blocksize) ? BDRV_SECTOR_SIZE= : 1; + /* preferred - Hard-code to 4096 for now. + * TODO: is blk_bs(blk)->bl.opt_transfer appropriate? */ + sizes[1] =3D 4096; + /* maximum - At most 32M, but smaller as appropriate. */ + sizes[2] =3D MIN(blk_get_max_transfer(exp->blk), NBD_MAX_BUFFER_SIZE); + trace_nbd_negotiate_handle_info_block_size(sizes[0], sizes[1], sizes[2= ]); + cpu_to_be32s(&sizes[0]); + cpu_to_be32s(&sizes[1]); + cpu_to_be32s(&sizes[2]); + rc =3D nbd_negotiate_send_info(client, opt, NBD_INFO_BLOCK_SIZE, + sizeof(sizes), sizes, errp); + if (rc < 0) { + return rc; + } + /* Send NBD_INFO_EXPORT always */ trace_nbd_negotiate_new_style_size_flags(exp->size, exp->nbdflags | myflags); @@ -459,6 +487,18 @@ static int nbd_negotiate_handle_info(NBDClient *client= , uint32_t length, return rc; } =20 + /* If the client is just asking for NBD_OPT_INFO, but forgot to + * request block sizes, return an error. + * TODO: consult blk_bs(blk)->request_align, and only error if it + * is not 1? */ + if (opt =3D=3D NBD_OPT_INFO && !blocksize) { + return nbd_negotiate_send_rep_err(client->ioc, + NBD_REP_ERR_BLOCK_SIZE_REQD, opt, + errp, + "request NBD_INFO_BLOCK_SIZE to " + "use this export"); + } + /* Final reply */ rc =3D nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, opt, errp); if (rc < 0) { diff --git a/nbd/trace-events b/nbd/trace-events index bd09fab..be3dce7 100644 --- a/nbd/trace-events +++ b/nbd/trace-events @@ -39,6 +39,7 @@ nbd_negotiate_handle_export_name_request(const char *name= ) "Client requested exp nbd_negotiate_send_info(int info, const char *name, uint32_t length) "Send= ing NBD_REP_INFO type %d (%s) with remaining length %" PRIu32 nbd_negotiate_handle_info_requests(int requests) "Client requested %d item= s of info" nbd_negotiate_handle_info_request(int request, const char *name) "Client r= equested info %d (%s)" +nbd_negotiate_handle_info_block_size(uint32_t minimum, uint32_t preferred,= uint32_t maximum) "advertising minimum 0x%" PRIx32 ", preferred 0x%" PRIx3= 2 ", maximum 0x%" PRIx32 nbd_negotiate_handle_starttls(void) "Setting up TLS" nbd_negotiate_handle_starttls_handshake(void) "Starting TLS handshake" nbd_negotiate_options_flags(uint32_t flags) "Received client flags 0x%" PR= Ix32 --=20 1.8.3.1