From nobody Mon Sep 28 00:10:22 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=openvz.org ARC-Seal: i=1; a=rsa-sha256; t=1787847053; cv=none; d=zohomail.com; s=zohoarc; b=cgsTdrhg/X8l+13MLEkhsqU+FgCFIjlj+o2aEu3zttEeYgjyJseYTMNbIr9pgme88+XfoEI/bMB1DrXsNfZqFjmBk6xnFufYKFbjDAlSJ8MSv6DK+2oHpGDaP8f6hD/0urXxvo614m4Z8jq4JYch1+FJUk9nQrwVfQVZG6WW9jA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787847053; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=QohvP1NuFolML60rOIlVMw7WVZtA/95muTj1bso9dvQ=; b=EiQybVX9ICH3WEymxPMp0Yu23uqy56c/JBXbgIQgBll4PZzjWPl/ZE7YkEUh7yTZhf73q3zC7dlZ6vv9eirKic1d8OhW18XZWDh4JqX8Jc1rHIuI8KecNT8NpaaDzFdy/jgELO3ywU2QP+9HWpfLZM3vGfk8a5xE0vVsGSoQkEc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787847053664986.4393872400312; Thu, 27 Aug 2026 09:10:53 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wzcgD-0004ZB-SK; Thu, 27 Aug 2026 12:10:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wzcg9-0004Xx-Ts for qemu-devel@nongnu.org; Thu, 27 Aug 2026 12:10:13 -0400 Received: from mail-wm1-x32e.google.com ([2a00:1450:4864:20::32e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wzcg6-0007uO-TS for qemu-devel@nongnu.org; Thu, 27 Aug 2026 12:10:13 -0400 Received: by mail-wm1-x32e.google.com with SMTP id 5b1f17b1804b1-49a97714f5dso12491275e9.0 for ; Thu, 27 Aug 2026 09:10:10 -0700 (PDT) Received: from athena ([2a06:5b06:b600:300:e57e:de8:330d:26d0]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-499dd5771a3sm71359465e9.4.2026.08.27.09.10.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 27 Aug 2026 09:10:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvz.org; s=google; t=1787847009; x=1788451809; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=QohvP1NuFolML60rOIlVMw7WVZtA/95muTj1bso9dvQ=; b=S+d4HHWMcYfGcXKDzbtrKBajXnVr+55GvUQw6ra2nc0/xS1xi696OUxBtVlrFsbNze QLBaA0JSTiAp/0N5bbc+bDpu3bOUJAj5VVdC+Q2DrroLFWYl1p255tTkoog7JAAaztT1 IK9djovtuvHn9ii3Bp7FEEDA7j3Df3tIcecn64BMbkfX3qPK43q9X4qsjceTKrKYZPCI 8QWGeOE44iPXi6GfjsRfUZqLcouuaWb36nwRC3HIJSZDwkeb2H2fnlO7wcZby0sm8237 GVLhIlwDpdMf0F2rcXgT6YFs3rXvcIBr10Q8Gl6ouQtEAEpK0S8YCqDPrHakrNPRu9Ih Xaiw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787847009; x=1788451809; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=QohvP1NuFolML60rOIlVMw7WVZtA/95muTj1bso9dvQ=; b=MJSjHvD1Xek0tOuelNKM7lejbLXh8+esRnyakO4W4KQPytY5tsTxWylG5mn1+oYbnv eP3kXsTqN22ENMIYulhf/oPn8QHxg9GOyTj/svVXoMOZSL0tZ7Qm1YqsGM4g3jWK8tXm SlRbZNFtw0bxTHbgprFYpINT9sdYFZLXkeTcLdY8tfMJ4iHhdYhOaIElgzQnyHOJ32eo H2fWDjSff/PmibV/BGaC/nKY0v74RvtOE4CkexwiPTFs7KiEiC5OU4I3woA0exGmX+Ed I6xtJw6atLvoYVRokPiw4HGX1QSp27rZLHWKvutcNlT83rKMets459bt+hzEyOPp227T B7fQ== X-Gm-Message-State: AFuF++k21akTEPgeL3Cn5t2/MeE6OQZW4X+csZFLLgTdplw0D/RhRDvK xwTpOr6DDDZEEG9zLaF+kUHd0lH+wd6XbXYH67jrVjhrhWch5T19NSGEZ9CiYoWZLhJWQeDwj5R yybv2 X-Gm-Gg: AR+sD104KzlB9umEd14ynAUKvZE2T2rOr9loOiLyuAKMHBXSgWOy+hOSWz14Vyp9umP N2saaVmZ0oNXX8A4TROtzv91WFVz7ykYNqXqscK/QP9zS1VUkbPtwauBKKZKri9LkvJzMgjqTVJ Lr95ZLeYT+o/yRnmEOl6Rbx3pzLD7fGnKX7NpghmIAT6PLOJNE3+1bwqec9274QWkf7kxp7ugvB 5VOX8jJNwAyJ4m8+8Bq+2h80lpTgV69DoVVMIozeDbo/ynlBTY40BZgon/LVEKNNnZq7n3wsAUi 9c/meLXOmbhnHzF9sTp4LKVpMS6LvaOVLGyrveQM720vdulOtBwGXoM9pgqgGpYPzrk/f3UCt6Y i3Z3w9GvfYZqyMKxawVBPaUraaDTtk6Ltez4LZ+fg6eLmh+E96IGOGC/dbLpOa/KvZKm3zp/Mch nY4uLHGkJBud4MXFxmLMJoA9KYZ79GK0xnGAfHR5fml7KlhcxY X-Received: by 2002:a05:600c:3546:b0:499:bdf1:7578 with SMTP id 5b1f17b1804b1-49b91c19d68mr366395e9.3.1787847009265; Thu, 27 Aug 2026 09:10:09 -0700 (PDT) From: "Denis V. Lunev" To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, "Denis V. Lunev" , Eric Blake , Vladimir Sementsov-Ogievskiy Subject: [PATCH v2 1/5] iotests: add coverage for NBD transmission commands Date: Thu, 27 Aug 2026 18:09:58 +0200 Message-ID: <20260827161002.310688-2-den@openvz.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260827161002.310688-1-den@openvz.org> References: <20260827161002.310688-1-den@openvz.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::32e; envelope-from=den@openvz.org; helo=mail-wm1-x32e.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @openvz.org) X-ZM-MESSAGEID: 1787847054928158500 Content-Type: text/plain; charset="utf-8" From: Denis V. Lunev NBD_CMD_CACHE has no coverage anywhere in the tree. Nothing ever sends it: our own NBD client does not implement the command, and neither qemu-io nor 'qemu-nbd --list' can issue one, so the only clients reaching this server path are external ones. Add a test driven by libnbd, gated the way nbd-multiconn already is, and start it with the case the command exists for. The export is a qcow2 image over a fully written backing file, so a prefetch has visible work to do. Signed-off-by: Denis V. Lunev CC: Eric Blake CC: Vladimir Sementsov-Ogievskiy Reviewed-by: Vladimir Sementsov-Ogievskiy --- tests/qemu-iotests/tests/nbd-commands | 140 ++++++++++++++++++++++ tests/qemu-iotests/tests/nbd-commands.out | 5 + 2 files changed, 145 insertions(+) create mode 100755 tests/qemu-iotests/tests/nbd-commands create mode 100644 tests/qemu-iotests/tests/nbd-commands.out diff --git a/tests/qemu-iotests/tests/nbd-commands b/tests/qemu-iotests/tes= ts/nbd-commands new file mode 100755 index 0000000000..4c1cd33db7 --- /dev/null +++ b/tests/qemu-iotests/tests/nbd-commands @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +# group: rw auto quick +# +# Test NBD transmission commands against a qemu NBD export +# +# Copyright (C) 2026 Virtuozzo International GmbH +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +from types import ModuleType + +import iotests +from iotests import qemu_img_create, qemu_img_map, qemu_io + + +base =3D os.path.join(iotests.test_dir, 'base') +top =3D os.path.join(iotests.test_dir, 'top') +# Larger than the maximum payload size an export can advertise +size =3D 64 * 1024 * 1024 +pattern =3D 0xa5 +nbd_sock =3D os.path.join(iotests.sock_dir, 'nbd_sock') +nbd_uri =3D 'nbd+unix:///exp?socket=3D' + nbd_sock +nbd: ModuleType + +DEPTH_LOCAL =3D 1 +DEPTH_BACKING =3D 2 + + +class TestNbdCommands(iotests.QMPTestCase): + def setUp(self): + qemu_img_create('-f', iotests.imgfmt, base, str(size)) + qemu_io('-c', f'write -P {pattern} 0 {size}', base) + qemu_img_create('-f', iotests.imgfmt, '-b', base, + '-F', iotests.imgfmt, top, str(size)) + + self.vm =3D iotests.VM() + self.vm.launch() + self.vm.cmd('blockdev-add', { + 'driver': iotests.imgfmt, + 'node-name': 'n', + 'file': {'driver': 'file', 'filename': top}, + 'backing': { + 'driver': iotests.imgfmt, + 'node-name': 'base', + 'file': {'driver': 'file', 'filename': base}, + }, + }) + self.vm.cmd('nbd-server-start', { + 'addr': {'type': 'unix', 'data': {'path': nbd_sock}} + }) + self.vm.cmd('block-export-add', { + 'type': 'nbd', + 'id': 'exp', + 'node-name': 'n', + 'name': 'exp', + 'writable': True, + 'allocation-depth': True, + }) + + self.h =3D None + self.connect() + + def tearDown(self): + self.disconnect() + self.vm.shutdown() + for f in (top, base, nbd_sock): + try: + os.remove(f) + except OSError: + pass + + def connect(self, structured=3DTrue, extended=3DTrue): + self.disconnect() + h =3D nbd.NBD() + h.set_request_structured_replies(structured) + h.set_request_extended_headers(extended) + h.add_meta_context('base:allocation') + h.add_meta_context('qemu:allocation-depth') + # Let the server, not libnbd, reject the out of range requests bel= ow + h.set_strict_mode(h.get_strict_mode() & + ~(nbd.STRICT_BOUNDS | nbd.STRICT_PAYLOAD)) + h.connect_uri(nbd_uri) + self.assertEqual(h.get_structured_replies_negotiated(), structured) + self.assertEqual(h.get_extended_headers_negotiated(), extended) + self.h =3D h + + def disconnect(self): + if self.h is not None: + self.h.shutdown() + self.h =3D None + + def block_status(self, count=3Dsize): + """Map each meta context in the reply to its list of extents.""" + reply =3D {} + + def cb(meta, _offset, entries, _err): + reply.setdefault(meta, []).extend(zip(entries[0::2], + entries[1::2])) + + self.h.block_status(count, 0, cb) + return reply + + def top_extents(self): + """Which parts of the top image are local, once qemu has let go.""" + self.disconnect() + self.vm.shutdown() + return [(e['start'], e['length'], e['depth']) + for e in qemu_img_map(top)] + + def test_cache_copies_on_read(self): + maximum =3D self.h.get_block_size(nbd.SIZE_MAXIMUM) + self.assertLess(maximum, size) + self.assertEqual(self.block_status()['qemu:allocation-depth'], + [(size, DEPTH_BACKING)]) + + self.h.cache(maximum, 0) + + self.assertEqual(self.top_extents(), + [(0, maximum, 0), (maximum, size - maximum, 1)]) + qemu_io('-c', f'read -P {pattern} 0 {size}', top) + + def test_cache_past_end_of_export(self): + self.assertRaises(nbd.Error, self.h.cache, size + 1, 0) + + def test_read_bound_by_max_payload(self): + maximum =3D self.h.get_block_size(nbd.SIZE_MAXIMUM) + self.assertRaises(nbd.Error, self.h.pread, maximum + 65536, 0) + + +if __name__ =3D=3D '__main__': + try: + # Easier to use libnbd than to try and set up parallel + # 'qemu-nbd --list' or 'qemu-io' processes, but not all systems + # have libnbd installed. + import nbd # type: ignore + + iotests.main(supported_fmts=3D['qcow2']) + except ImportError: + iotests.notrun('Python bindings to libnbd are not installed') diff --git a/tests/qemu-iotests/tests/nbd-commands.out b/tests/qemu-iotests= /tests/nbd-commands.out new file mode 100644 index 0000000000..8d7e996700 --- /dev/null +++ b/tests/qemu-iotests/tests/nbd-commands.out @@ -0,0 +1,5 @@ +... +---------------------------------------------------------------------- +Ran 3 tests + +OK --=20 2.53.0 From nobody Mon Sep 28 00:10:22 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=openvz.org ARC-Seal: i=1; a=rsa-sha256; t=1787847056; cv=none; d=zohomail.com; s=zohoarc; b=f8029DDIVuJbxZFxiN5Ho52GYPiNwQnsSb/vvlIrnnSSaTn/vy9OTzb7vPhAyPD5XBbpJ3Q95qJ/PHHXC2Dk02Sg00+2iWy+MvCBkEDNQfx1vgTLTNTIgowfGWantZjU1Kgdm7D4g1x3Z2AGPG6BQj086bqGHuBg7VuGg1DH3Iw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787847056; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=f5QFhAFnxCdd4h1trIbLuH4MIh6b8yqEQgKz02p+ZQ4=; b=Qv9ff4HIXkSFkqp2SBV/HzLCPELes1CCIkGA+HfNyr7dupwrnV84F/JV4yPKvkAQXZCVpmPNgBpeGaF3WEBdh4LytykACXREsbkfVSTFNCWjEeDb6jhHb31b9SuLveHcdMO/NwuXGZxGDlUhlscJPOhGCRbBEpB3bnbJLDqZMI8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787847056618155.53244585479797; Thu, 27 Aug 2026 09:10:56 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wzcgD-0004ZZ-VR; Thu, 27 Aug 2026 12:10:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wzcgA-0004YG-Ms for qemu-devel@nongnu.org; Thu, 27 Aug 2026 12:10:14 -0400 Received: from mail-wm1-x32c.google.com ([2a00:1450:4864:20::32c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wzcg8-0007uc-OY for qemu-devel@nongnu.org; Thu, 27 Aug 2026 12:10:14 -0400 Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-4957eefd361so16124715e9.1 for ; Thu, 27 Aug 2026 09:10:12 -0700 (PDT) Received: from athena ([2a06:5b06:b600:300:e57e:de8:330d:26d0]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-499dd5771a3sm71359465e9.4.2026.08.27.09.10.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 27 Aug 2026 09:10:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvz.org; s=google; t=1787847011; x=1788451811; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=f5QFhAFnxCdd4h1trIbLuH4MIh6b8yqEQgKz02p+ZQ4=; b=JPbgWoogH8QRf8d7KApWKb4aSbZFRRHBFof58OhHBlYNyXosNjWI7GkluiglEU4unx gNnSu5x398+DF5mH4AVCCkN+cTq09xMrIsFAt0qjb595jeBragCc5FXDK5ojcu/v6jgO GvAjwQ5r1tYcmCsfwQmGr7Wgf8cMh4nvd/7wAMxhQxiIjE61eCqeMhvsuTGCr6itwD/6 bzmOGCvQRjdi+2xyqSXDjh9u43SASik8SM6IrDadfA1MA5N26YSyACgXWA8dKfh276Pb e/4eM2fuS04gaPBHgUt1HMRUqvM9w4VYc0byZczKNCsyq/W7yallVLayQbVQC/O3/G0G vYiA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787847011; x=1788451811; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=f5QFhAFnxCdd4h1trIbLuH4MIh6b8yqEQgKz02p+ZQ4=; b=BMHp9ww0BTgyAP2/v5ob6hAr8VNlUKLS1kHdTnq6soiPUOH4RwMrhJi2xi5FU6QNRn QRD0fyRlxPoIRGHx5ohjpE/3T5yNuB9gidQkNgXzjM4YxuEGs5+WOaD1pm29V45Nx9hQ s49nmIZoq9y1+Gs4s+tjXwPab5XxCfwWM/OdEJjh+k8jkSPLgUuj5rnKOBQ7dYje9exN NIBNZj1FmEkqMRyo6RF5m+twIF1SekQwaUtqinFyww61ANIXAaOI1EBSbbYWttZIP7AA /QSlYshREA7IgTneLkuDLkSKQgIkiHc7XQc0KCnIaSwmBlU7k+wlHJzALcUYEyioRiYr pILw== X-Gm-Message-State: AFuF++nAXyKrB6wOLsUPCSsClmeQqQnWzU6KlKiMYV7Qmxpm6grzV+Uh /nIo0Q/wQdOFb5TETwsCZC1jOlFj8pJq1l8WDT8JVshhgf7QeAn24HejNqjEOr8v/qy7tTdy49t HwoJW X-Gm-Gg: AR+sD13J6dUJEWiIDT7lF20EHUBpwu5FISRxvymg4+h5nPSymCGDR/Ssm0tsvcl2q2c 6NHmvluBQ1lZv1II7g4qqJbzoS1gKzFwJvLwFHgewxNzCUO88mCZfRe5vVLh15X0dCvKsYpzjyi P2rKmFqRByqk9fNrnzLYqS8HUaehNLtNgsBtqyfdO6qxhhtYBBqMWdAzyP7vgqVSFhDt1cCzeRR P0dW+RcNzs/Md+5NjszRGTAzl1ft2kaLYdWQFSEAhn2k5f4pbMjBJKbzp9f5rVfeiiZtWPLwFX/ GAJm/AUdVa5YhBZrC2woPRxccW/da+nWmf9WGwnzyN16ncpOmSfP3haApoBIH6en5oBzhRO8G/R AEPcEtTa9lQVB1GYHaqM2oCHsWKTGpddkQlJ8MIj1qyOP29aQu2JfdKu9mxfxTnqeUeK9/JPQk+ vwkietBJxd+fZoBHELmzZNRjsi0D+w4rv8s79MQ4rU2uJaOY0HRQ== X-Received: by 2002:a05:600c:37c9:b0:49b:2796:be30 with SMTP id 5b1f17b1804b1-49b2796c07cmr118083215e9.11.1787847011061; Thu, 27 Aug 2026 09:10:11 -0700 (PDT) From: "Denis V. Lunev" To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, "Denis V. Lunev" , Vladimir Sementsov-Ogievskiy , Eric Blake Subject: [PATCH v2 2/5] nbd/server: accept NBD_CMD_CACHE above the maximum payload size Date: Thu, 27 Aug 2026 18:09:59 +0200 Message-ID: <20260827161002.310688-3-den@openvz.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260827161002.310688-1-den@openvz.org> References: <20260827161002.310688-1-den@openvz.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::32c; envelope-from=den@openvz.org; helo=mail-wm1-x32c.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @openvz.org) X-ZM-MESSAGEID: 1787847059203158500 Content-Type: text/plain; charset="utf-8" From: Denis V. Lunev NBD_CMD_CACHE carries no payload in either direction. The request is a header only, nbd_do_cmd_cache() passes a NULL qiov to blk_co_preadv(), and the reply is a bare status. Still the server rejects any effect length above NBD_MAX_BUFFER_SIZE with EINVAL, which forces a client to split a large prefetch into 32 MiB pieces. The specification does not ask for this. The constraint was renamed from "maximum block size" to "maximum payload size" precisely to separate payload length from effect length, and it says: For commands that do not require a payload in either direction (such as NBD_CMD_TRIM or NBD_CMD_WRITE_ZEROES), the client MAY request an effect length larger than the maximum payload size; the server SHOULD NOT disconnect, but MAY reply with an NBD_EOVERFLOW or NBD_EINVAL error if the oversize request would require too many server resources when compared to the same command with an effect length limited to the maximum payload size (such as an implementation of NBD_CMD_WRITE_ZEROES that utilizes a scratch buffer). We already follow that for NBD_CMD_TRIM and NBD_CMD_WRITE_ZEROES, which carry no length check at all, and our client assumes a server supporting extended headers takes unlimited zero and trim lengths. Handle NBD_CMD_CACHE in the same way. Signed-off-by: Denis V. Lunev Reviewed-by: Vladimir Sementsov-Ogievskiy CC: Eric Blake CC: Vladimir Sementsov-Ogievskiy --- nbd/server.c | 4 +--- tests/qemu-iotests/tests/nbd-commands | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index 78ec984409..e6c47f8c2e 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -2718,7 +2718,6 @@ static int coroutine_fn nbd_co_receive_request(NBDReq= uestData *req, break; =20 case NBD_CMD_CACHE: - check_length =3D true; break; =20 case NBD_CMD_WRITE_ZEROES: @@ -2752,7 +2751,7 @@ static int coroutine_fn nbd_co_receive_request(NBDReq= uestData *req, req->complete =3D true; } if (check_length && request->len > NBD_MAX_BUFFER_SIZE) { - /* READ, WRITE, CACHE */ + /* READ, WRITE */ error_setg(errp, "len (%" PRIu64 ") is larger than max len (%u)", request->len, NBD_MAX_BUFFER_SIZE); return -EINVAL; @@ -2908,7 +2907,6 @@ static coroutine_fn int nbd_do_cmd_cache(NBDClient *c= lient, NBDRequest *request, NBDExport *exp =3D client->exp; =20 assert(request->type =3D=3D NBD_CMD_CACHE); - assert(request->len <=3D NBD_MAX_BUFFER_SIZE); =20 ret =3D blk_co_preadv(exp->common.blk, request->from, request->len, NULL, BDRV_REQ_COPY_ON_READ | BDRV_REQ_PREFETCH); diff --git a/tests/qemu-iotests/tests/nbd-commands b/tests/qemu-iotests/tes= ts/nbd-commands index 4c1cd33db7..cbfc47782f 100755 --- a/tests/qemu-iotests/tests/nbd-commands +++ b/tests/qemu-iotests/tests/nbd-commands @@ -114,10 +114,9 @@ class TestNbdCommands(iotests.QMPTestCase): self.assertEqual(self.block_status()['qemu:allocation-depth'], [(size, DEPTH_BACKING)]) =20 - self.h.cache(maximum, 0) + self.h.cache(size, 0) =20 - self.assertEqual(self.top_extents(), - [(0, maximum, 0), (maximum, size - maximum, 1)]) + self.assertEqual(self.top_extents(), [(0, size, 0)]) qemu_io('-c', f'read -P {pattern} 0 {size}', top) =20 def test_cache_past_end_of_export(self): --=20 2.53.0 From nobody Mon Sep 28 00:10:22 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=openvz.org ARC-Seal: i=1; a=rsa-sha256; t=1787847036; cv=none; d=zohomail.com; s=zohoarc; b=R4bX7htfbEhPrmIzVAVajUsp+vhebtquGmAB+2uVRFnTEA6pGmggip3BkmOZPsGaVaNJGNiOVGQhzeT1ep/EG1BTkLLgbQ5VS5ZtOl0lVCeDB9iT0SySe4tG4k5AhWKiWqla059dXMH/SfL9S41Lm3Xc28Q54zfrnmdymOMK6hY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787847036; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=y8pOTuQTygf728JvHILh6d5V4mR5TMERZeFgcXgTwJQ=; b=BT1cdBE7yds29s/iFpAtSiVTXghxIqFtgkLCrBfdHuxkPkwdbVCGTNV7ibTJwZfFY83dSyEpXCe5GMYruSWmETCGjh3vNH9vDcXkfQj5eZ8LglBginDjkyrdLEyZm3tbq4kwVOiLj06sSt5ttJbKFYQ8oWo8a7EA+Y9A6uiNNlg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787847036629163.07081806999713; Thu, 27 Aug 2026 09:10:36 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wzcgH-0004ab-ED; Thu, 27 Aug 2026 12:10:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wzcgC-0004Yq-4m for qemu-devel@nongnu.org; Thu, 27 Aug 2026 12:10:16 -0400 Received: from mail-wm1-x32b.google.com ([2a00:1450:4864:20::32b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wzcgA-0007uz-CE for qemu-devel@nongnu.org; Thu, 27 Aug 2026 12:10:15 -0400 Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-499ac87c92bso21224225e9.1 for ; Thu, 27 Aug 2026 09:10:13 -0700 (PDT) Received: from athena ([2a06:5b06:b600:300:e57e:de8:330d:26d0]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-499dd5771a3sm71359465e9.4.2026.08.27.09.10.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 27 Aug 2026 09:10:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvz.org; s=google; t=1787847012; x=1788451812; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=y8pOTuQTygf728JvHILh6d5V4mR5TMERZeFgcXgTwJQ=; b=ZQylZqanSZIoofCcHAksuE21pnNbeCtx3C4g5echx28s5qa/bNKdVDSfl80qdWUope aYRluoWq7cRSj/Yqu7qdURldJ7CkCOAq3iG/MyrTrjfSbf/gm5yffycIW/5zGapEEOTH Icyw+uaKRA0ebEoCxJitJ5D1bTEQsaPrZ4pEQllLnoR/YA/OC7wMRFrgRI1BuVuuSB2R v70HfazpTGKf5uQhAXElPgXaHWG+cfAHC5oJ3xUbgwFxbURJ7s3PHo2lXn+ES/IhRVBi tA4NZD0QvUAQm8QIg6GliFK6Mn7+ZPh6xvhFXtq5zD3YydkR08n33CCWreRGWG0p2mPD otAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787847012; x=1788451812; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=y8pOTuQTygf728JvHILh6d5V4mR5TMERZeFgcXgTwJQ=; b=gmkfMT3uvn0hSZm0tk8p0pHTRyMdZOC18XwaxNHbOUk3rlH/8Nieng9vK/F/grr7h2 ARPnYLn/TZtL55D98c+rhDzlnCHJj/XEU0JBTu05ajz1ys90LjLJl14/LMPkFq5wFBuN GK8DtHF+2r/7CVMTDmPiWWObezZkQ1SYmM+Hyew1xRehq9GxpYbazfTi4GazfUD/sYC0 GKgeaphTsR3DusH2Gx/byuqXk39Kr+/L3ovtnuax9/jMJz/E9WVGrVBFr83ayAURlLjx bMt1klPKbRnupMf07odAuK0ySP5bRQpu4GoSla5HobzWjf1oSK3ep42Z7WZXwt2xrYoi ym0w== X-Gm-Message-State: AFuF++m4GcEKPRZSdwrvZd/pPD/plrdSs9WGTKAjCCrfmvRGR7XuQtdu X/uXOYf4bL8QJ8DRBLzOAQHZ5b4Xpps+uKiYlGpxZFCOpD0C0H+iGD9atil5MCHyODkbHBeA1iC 94Eju X-Gm-Gg: AR+sD13m4JD4p9asqQdaJyoNhP78CLVrtp+UGDdi/c/2N37tkN5PnSbyF/hIBgXh1Kx eHzt60jqMgovwpvFsDaG5819PVLPYRYP0jdWjQ4ppzrdZNa2PxxsgL2dIUytjGtNlEOi7C5fsYF w/nHMw9YBY1yQqcHBqVJRuWWMcfkOjStKJD56p2nKm4PsM1V8St2YGO0rp2O/CJ82H00OL5FZR5 nukKpCqibmcBYIux+/2znZncnEH40HM9PUuwlyrG4UJU7xiGJKj1HoH83btEr5LeC/GSGEomjZA ragV7blmByJbs/aCwpNWdma/xrLHuFogVjlYB/FlKLsBgvK5fY7wi9AqT9qt+/7FMc8nMgygSOW Riz971uF7FIl6QZG9jbYyYdOd2gB7e8REHhyvbVzVnQz5mRHcdRU1WpcGncTR8Pwzcqa3pcE6ym 5ToG1PxpCeq3z4EpCCaWIXkahTd1aQY8a+QNx9HrFr4xAHlw8T X-Received: by 2002:a05:600c:8b6b:b0:49b:c8e:8e6 with SMTP id 5b1f17b1804b1-49b91bd99b7mr1848545e9.0.1787847012489; Thu, 27 Aug 2026 09:10:12 -0700 (PDT) From: "Denis V. Lunev" To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, "Denis V. Lunev" , Eric Blake , Vladimir Sementsov-Ogievskiy Subject: [PATCH v2 3/5] iotests/nbd-commands: exercise the simple and structured reply modes Date: Thu, 27 Aug 2026 18:10:00 +0200 Message-ID: <20260827161002.310688-4-den@openvz.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260827161002.310688-1-den@openvz.org> References: <20260827161002.310688-1-den@openvz.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::32b; envelope-from=den@openvz.org; helo=mail-wm1-x32b.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @openvz.org) X-ZM-MESSAGEID: 1787847039500158500 Content-Type: text/plain; charset="utf-8" From: Denis V. Lunev Every NBD request the iotests send arrives in NBD_MODE_EXTENDED, so the server paths kept for older clients are never taken. Instrumenting nbd_co_receive_request() over the whole auto group and every test that touches NBD gives mode 4 for all of them, which leaves nbd_co_send_simple_reply() and the compact header handling dead under test. A regression there would only show against a third party client. libnbd can negotiate down, so run the same command set three times, once per mode, and assert the mode that was actually reached. Block status is limited to the two modes that can negotiate a meta context. Signed-off-by: Denis V. Lunev CC: Eric Blake CC: Vladimir Sementsov-Ogievskiy Reviewed-by: Vladimir Sementsov-Ogievskiy --- tests/qemu-iotests/tests/nbd-commands | 29 +++++++++++++++++++++++ tests/qemu-iotests/tests/nbd-commands.out | 4 ++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/tests/qemu-iotests/tests/nbd-commands b/tests/qemu-iotests/tes= ts/nbd-commands index cbfc47782f..3dfe913190 100755 --- a/tests/qemu-iotests/tests/nbd-commands +++ b/tests/qemu-iotests/tests/nbd-commands @@ -119,6 +119,35 @@ class TestNbdCommands(iotests.QMPTestCase): self.assertEqual(self.top_extents(), [(0, size, 0)]) qemu_io('-c', f'read -P {pattern} 0 {size}', top) =20 + def check_commands(self, structured, extended): + self.connect(structured, extended) + + self.assertEqual(self.h.pread(4096, 4096), bytes([pattern]) * 4096) + + self.h.cache(size, 0) + + self.h.pwrite(b'x' * 4096, 4096) + self.h.flush() + self.assertEqual(self.h.pread(4096, 4096), b'x' * 4096) + + self.h.zero(4096, 8192) + self.assertEqual(self.h.pread(4096, 8192), bytes(4096)) + + self.h.trim(4096, 16384) + + if structured: + self.assertEqual(self.block_status()['qemu:allocation-depth'], + [(size, DEPTH_LOCAL)]) + + def test_commands_simple_replies(self): + self.check_commands(structured=3DFalse, extended=3DFalse) + + def test_commands_structured_replies(self): + self.check_commands(structured=3DTrue, extended=3DFalse) + + def test_commands_extended_headers(self): + self.check_commands(structured=3DTrue, extended=3DTrue) + def test_cache_past_end_of_export(self): self.assertRaises(nbd.Error, self.h.cache, size + 1, 0) =20 diff --git a/tests/qemu-iotests/tests/nbd-commands.out b/tests/qemu-iotests= /tests/nbd-commands.out index 8d7e996700..3f8a935a08 100644 --- a/tests/qemu-iotests/tests/nbd-commands.out +++ b/tests/qemu-iotests/tests/nbd-commands.out @@ -1,5 +1,5 @@ -... +...... ---------------------------------------------------------------------- -Ran 3 tests +Ran 6 tests =20 OK --=20 2.53.0 From nobody Mon Sep 28 00:10:22 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=openvz.org ARC-Seal: i=1; a=rsa-sha256; t=1787847053; cv=none; d=zohomail.com; s=zohoarc; b=hi6VL9LLOyjnH0PVbhEh/WN7Dzcj8JGs9kR5PmjEcLxBTaPaTnFV7GYCGghQdy2Z0JZ1j+SWKMz76skIGL5kBF7QmVUsdpY0fFgOEWBRGAt2ix9Z+18RwKVuMWO5xwdHK4yVxQKiyMjR55Kp+N5WqgLm+obrCBbvYYKD8dCFIso= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787847053; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Uz+m+PYTKCS5EAzXIW/GJIgQvknTl5oB//P+gzk9O0A=; b=jYWO4oEle9reFMkuyHfugxUpF21S+HnRInbUn5N4dnoOORD1+IGJDCx01H1YPPXEBMbdEYGC6uWyKU/arTjxbhOF73wLMCSiNEAODibh+2Vxq+b+nimZRoOA94BlQ2gt8FlYlgfPZRedyJLmK0B9+FQyInxtBsvm/xhaexMXkL4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787847053434947.9977614706982; Thu, 27 Aug 2026 09:10:53 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wzcgN-0004i9-UF; Thu, 27 Aug 2026 12:10:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wzcgE-0004a6-RF for qemu-devel@nongnu.org; Thu, 27 Aug 2026 12:10:20 -0400 Received: from mail-wm1-x330.google.com ([2a00:1450:4864:20::330]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wzcgD-0007vn-5P for qemu-devel@nongnu.org; Thu, 27 Aug 2026 12:10:18 -0400 Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-49b0d8bc2aaso14770735e9.0 for ; Thu, 27 Aug 2026 09:10:16 -0700 (PDT) Received: from athena ([2a06:5b06:b600:300:e57e:de8:330d:26d0]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-499dd5771a3sm71359465e9.4.2026.08.27.09.10.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 27 Aug 2026 09:10:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvz.org; s=google; t=1787847015; x=1788451815; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Uz+m+PYTKCS5EAzXIW/GJIgQvknTl5oB//P+gzk9O0A=; b=sO0spgSHGmQ2dG0FxFh+QVfXUZpc1vCkh9ac/Z6FFRleePHn11NxLmcZMkZDVhIpg6 s3lJySpyEgm435mjRqSvTiScfT3XE2/gjBMq5bxkGIlQP+dVqGHqg/M1LsJn/GN7HTKG oQ0bK/i8Q3ZQiQIk9DTJDkhnWKVqm2Rgqz7FKp0g/K0sa/c4FtdfDsyhK6O2Kk7sR/u1 /kZd+IuTBdG5z43cvIemf350tbiZt3DMGpDx42aZw+ZxLabW87LwP1kQRvc8mCHUHQQv 5sMHO3oO4N0VK22Wc0nmwEtY7WlYI2QL47KLxkNVRtmKaPew/f2uzbBgLJtO+FDBSe96 jwbw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787847015; x=1788451815; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=Uz+m+PYTKCS5EAzXIW/GJIgQvknTl5oB//P+gzk9O0A=; b=We2cLI+fw7r9z1quTI/3Rg8G8PZwZZJDcClkhbUBLaN5nGDX8widOUOBf0VolnVRzy w485JBBMzdZNmPgO3e7/6Nm0+6k08qA9fj1n4BYJaj3cAHUzBNPWGY/yZmpWcmIrmXoX VvnN5iM1i52n6YRrjuzp5AZuIg2SpYxrkq6xdE0ohZJXZm1+OM48WlauVqXTaRAE5mr0 xiakefrMkbQzZAMcS8umfKpbkpe3eURTA1+wtKh53U4N8D6+0i6Cc1dtRgUCL8dVrgQr kln5rRWv0VU4agaZKJ27WwxsAKoGYIbEkbwTcZLBKVBqswXOW95xvDcfrHHpUQRq14pa qssQ== X-Gm-Message-State: AFuF++nBCRmfuOjiLyJUeBCySbITd30J61WBO0PW3jq80dG1vGynLAOn ebLQ6eOjURbxmM7LsxkNKnIDj/Idcp10PzAFmKDR81+d8YorOi8Ft5NqI2NtkPYX/EsNn/AJ0Rg NPzje X-Gm-Gg: AR+sD129xHvgr3FdzpmysvTK4vDLFp5rHImcujRjgqYZv44Udf7EDIQDN96whT8Q4bh eMXRqxeDrKq9ikR4CGR18/itC+VWXYE72rBez5xe7LRQOQ88ZrU3Eukz5Pbw+g9hcZ5NmRqqMMt k9QIlAD8fIxkjdymA/V2wvbOU2oO6MUcThoyDQ6uQFJdU8sXTQb2p2iQFjKliUaU+2XmtiBtINf gI+cMQYDl98mvLFKMpXbn3W/Os1DNxFKiLT+Lns8Jgta91GbofnCJaFy/OieqUCCIbPes/yXXeJ NQp5dU8NgmXmjVMlrjZQGHGJzVrNHUCOb2T7l0ozZsZfGjUTGToE7Y1h2dj1Y7WY7rAJIDrb6Qn woFWJd5sd78n/aZSwsHAvHTQcgUM7b0kTMZfvVVcohEZBSGfG8lsI9xmUeWRmovH1k9K8CJpqOX BpX6yND5Y29ctrl8EkMD7XQdNU919o15k1vSFjgQFvtYmTqR1+ X-Received: by 2002:a05:600c:4744:b0:499:8b13:3a98 with SMTP id 5b1f17b1804b1-49b91c2479amr117785e9.4.1787847015288; Thu, 27 Aug 2026 09:10:15 -0700 (PDT) From: "Denis V. Lunev" To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, "Denis V. Lunev" , Eric Blake , Vladimir Sementsov-Ogievskiy Subject: [PATCH v2 4/5] iotests/nbd-commands: cover NBD_CMD_BLOCK_STATUS with a payload Date: Thu, 27 Aug 2026 18:10:01 +0200 Message-ID: <20260827161002.310688-5-den@openvz.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260827161002.310688-1-den@openvz.org> References: <20260827161002.310688-1-den@openvz.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::330; envelope-from=den@openvz.org; helo=mail-wm1-x330.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @openvz.org) X-ZM-MESSAGEID: 1787847054884158500 Content-Type: text/plain; charset="utf-8" From: Denis V. Lunev With extended headers a client may name the meta contexts it wants in a request payload. Our own client never sends one, so the server side of it, nbd_co_block_status_payload_read(), is not exercised anywhere. Export two meta contexts and ask libnbd for each of them in turn, which is only answerable through that path. Signed-off-by: Denis V. Lunev CC: Eric Blake CC: Vladimir Sementsov-Ogievskiy Reviewed-by: Vladimir Sementsov-Ogievskiy --- tests/qemu-iotests/tests/nbd-commands | 14 ++++++++++++-- tests/qemu-iotests/tests/nbd-commands.out | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/qemu-iotests/tests/nbd-commands b/tests/qemu-iotests/tes= ts/nbd-commands index 3dfe913190..09e811724b 100755 --- a/tests/qemu-iotests/tests/nbd-commands +++ b/tests/qemu-iotests/tests/nbd-commands @@ -90,7 +90,7 @@ class TestNbdCommands(iotests.QMPTestCase): self.h.shutdown() self.h =3D None =20 - def block_status(self, count=3Dsize): + def block_status(self, count=3Dsize, wanted=3DNone): """Map each meta context in the reply to its list of extents.""" reply =3D {} =20 @@ -98,7 +98,10 @@ class TestNbdCommands(iotests.QMPTestCase): reply.setdefault(meta, []).extend(zip(entries[0::2], entries[1::2])) =20 - self.h.block_status(count, 0, cb) + if wanted is None: + self.h.block_status(count, 0, cb) + else: + self.h.block_status_filter(count, 0, wanted, cb) return reply =20 def top_extents(self): @@ -148,6 +151,13 @@ class TestNbdCommands(iotests.QMPTestCase): def test_commands_extended_headers(self): self.check_commands(structured=3DTrue, extended=3DTrue) =20 + def test_block_status_payload_filter(self): + self.assertEqual(sorted(self.block_status()), + ['base:allocation', 'qemu:allocation-depth']) + + for wanted in (['base:allocation'], ['qemu:allocation-depth']): + self.assertEqual(sorted(self.block_status(wanted=3Dwanted)), w= anted) + def test_cache_past_end_of_export(self): self.assertRaises(nbd.Error, self.h.cache, size + 1, 0) =20 diff --git a/tests/qemu-iotests/tests/nbd-commands.out b/tests/qemu-iotests= /tests/nbd-commands.out index 3f8a935a08..2f7d3902f2 100644 --- a/tests/qemu-iotests/tests/nbd-commands.out +++ b/tests/qemu-iotests/tests/nbd-commands.out @@ -1,5 +1,5 @@ -...... +....... ---------------------------------------------------------------------- -Ran 6 tests +Ran 7 tests =20 OK --=20 2.53.0 From nobody Mon Sep 28 00:10:22 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=openvz.org ARC-Seal: i=1; a=rsa-sha256; t=1787847058; cv=none; d=zohomail.com; s=zohoarc; b=SV5grRIPibQ/vczqqPptwRZE5lTbanjqhWZBRtWMEYN1DEZgHBaGlG+RVMwdoScibnsQE0Xa/Jj5whTr0kOphK5PCGmHs+upo7lTsAVFU1fRL1JIbXa+5n06S6kMzQg2VNDjm4h2ldwCIRLOFRAEWRDFZrhc2DTkfop/ZIqD5cY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1787847058; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=BwRgMbNoY8A7dFSglbkxKQAAAXinbP9BQT6ju2m4fTE=; b=R6Wq9KQMVF6b16tn/D3mGi/2CuSWj7nMqMB6Wc4JbGivD8qq36CHhDDGLn/NF/gsLCAHzZBQWWmqnPMfSOIPqtuUdiYQN8Rpsmnj+Ow0Wd+GRnl1SeXdAgsk3AMMoDStV/26EzCL1VVVAij/mAVVQV+fxfzeWr1d9sgodAX8SBs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1787847058959586.1239803909111; Thu, 27 Aug 2026 09:10:58 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wzcgP-0004nf-81; Thu, 27 Aug 2026 12:10:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wzcgH-0004bF-VW for qemu-devel@nongnu.org; Thu, 27 Aug 2026 12:10:25 -0400 Received: from mail-wm1-x333.google.com ([2a00:1450:4864:20::333]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wzcgG-0007wG-5R for qemu-devel@nongnu.org; Thu, 27 Aug 2026 12:10:21 -0400 Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-49b0dbfbf7bso9973495e9.2 for ; Thu, 27 Aug 2026 09:10:19 -0700 (PDT) Received: from athena ([2a06:5b06:b600:300:e57e:de8:330d:26d0]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-499dd5771a3sm71359465e9.4.2026.08.27.09.10.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 27 Aug 2026 09:10:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvz.org; s=google; t=1787847018; x=1788451818; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=BwRgMbNoY8A7dFSglbkxKQAAAXinbP9BQT6ju2m4fTE=; b=gia/bR4HPnqJkyzeIaQxABP6BXwq8arVUE6vQBI5Envp5+0K4f6bUirdbzAsB8JB7U AhsSijUA+/fMVemuo4gO32pDVNN5W/zFjUEo7aDwI+RZ4Vej21az5YCsBW/5FEOf5gqc LJZ3XAXzsPu4mOtFp48xhhEp08nA02jdJvZKgfFq8mUd85qx/RvcNnCVQv9vdv7+H1db uqWIboCDC3XY4Oui/ls5aQZClcji/AoU8qNf2nfFByis1XM+MvrKYAInLo6AA1HmRHoI VCqJ7T+Y5C6tgj6VC9HValFpzQGnppzu4TAOWjPvQ57+DGP43yehbmlYb6dYNhVuV/wo zDjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787847018; x=1788451818; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=BwRgMbNoY8A7dFSglbkxKQAAAXinbP9BQT6ju2m4fTE=; b=p7rFzgAV8+hfqdNwqVPBIKb4FgrmFDexx3iG2QRS3aLT9UTR9v1ROW84QGdJqgBuUj CsvOeKDFit2BOThfnZ0r9GZhe/4EiZ7B+e4DZ8lF2Xoaudi0WXAxW+p3bwm64h9Lz6tX 1OGv/1564SYNbuvRl93KsuJHn+lhlUq9Z0M9tHjZ8Qk0KPojLHWkL7QRplj0NUdzHnoa Fd6SmWsQQe/MzVQRMzSUD7cJRSD3M37X7cyVC1hII2faiglyN0LNpGXhv+9e7St6z+/2 cRAAR11TCSR4YTWUONA4YFdyyfRdZXWh1uCxh1x200lZa7Oe7BDOTNNm/ofdJeHxNkxj 1Mrg== X-Gm-Message-State: AFuF++ksdjDStNybHebdKrV1erXCx4Irc/6ISLXQFCb1+MH7+w9aHgpF NYjOrDiism/iiM7qHU6l8G5gIZGSGJMtr0AmpN+9GR23bwSMxy9SAgxLh3SJR/ujM4+TBisg9RL 8/w0i X-Gm-Gg: AR+sD10lKuDeTbyO4SQWjl9jJeZxTN+/aWj6GfuW2JgqT8RQk63uJvKyadG0DVP4eVZ 1c0V0SwSx4BOVjDRAQ+L9wCbqyWPzUihixhVWOOaV+yh8RTmjniVTYu6FA4oV6urB9p0/B1rBdj D0Fy1B+eZsKWbu2D60KEOIq2/wakBOZLuo1kHeG1io2RShuhFxrliUJBrTYQm3oYFjwHe6GcgB4 a9g7dw14m3JfN0RvzKK8VZ2TWi7Kr9FpftNOIPs4s0YrzBBlDR6Dz0eiZ2ftRqNh0gHuCTguAEi E4IUSz+Pv9bd26WUfDxaq/s56cCADMkmsN/97BliuJflElwBXMLaHSg5hmufU2RSmNnykjPamS3 8uW/1vFqHyK4qQ4PNsoiTx0XHdQgLK79qFGOyqNXTtQZKllS56lHucCczGwrhZCdZDOb3OOgzwn 9pyCUSKQMj+YQde26e4IG2LJ0PGQ4GOPhqR92kulgbNMHFKJqJ X-Received: by 2002:a05:600c:46cc:b0:49b:909e:922e with SMTP id 5b1f17b1804b1-49b909e92aamr39758705e9.10.1787847018030; Thu, 27 Aug 2026 09:10:18 -0700 (PDT) From: "Denis V. Lunev" To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, "Denis V. Lunev" , Eric Blake , Vladimir Sementsov-Ogievskiy Subject: [PATCH v2 5/5] iotests/nbd-commands: cover the command flags and sparse replies Date: Thu, 27 Aug 2026 18:10:02 +0200 Message-ID: <20260827161002.310688-6-den@openvz.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260827161002.310688-1-den@openvz.org> References: <20260827161002.310688-1-den@openvz.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::333; envelope-from=den@openvz.org; helo=mail-wm1-x333.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @openvz.org) X-ZM-MESSAGEID: 1787847060913158500 Content-Type: text/plain; charset="utf-8" From: Denis V. Lunev No test sends the NBD command flags, so the server paths behind them go unexercised. Send them from the new client. A structured read answers a hole with an offset and a length rather than a cluster of zeroes. Lay out data, a hole and data again, and read the three arrangements a hole can appear in, since a leading hole and a hole between two extents take different turns through nbd_co_send_sparse_read(). NBD_CMD_FLAG_DF asks for one chunk instead, which is the same layout sent as real zeroes. Check the chunk boundaries in both forms, and that the data still reads back. NBD_CMD_FLAG_REQ_ONE caps the extent array at one entry, so the block status reply covers only the first cluster of the three asked about. That a reply may describe less than was requested is also how the server keeps NBD_MAX_BLOCK_STATUS_EXTENTS from being exceeded on a long fragmented range, and a client assuming full coverage believes stale status. NBD_CMD_FLAG_FAST_ZERO becomes BDRV_REQ_NO_FALLBACK. A cluster aligned zero can be done by marking the cluster, while zeroing part of a cluster over a backing file needs the read modify write the flag forbids, so check both the success and the ENOTSUP. NBD_CMD_FLAG_FUA is added to a write and a trim. Signed-off-by: Denis V. Lunev CC: Eric Blake CC: Vladimir Sementsov-Ogievskiy Reviewed-by: Vladimir Sementsov-Ogievskiy --- tests/qemu-iotests/tests/nbd-commands | 72 ++++++++++++++++++++++- tests/qemu-iotests/tests/nbd-commands.out | 4 +- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/tests/qemu-iotests/tests/nbd-commands b/tests/qemu-iotests/tes= ts/nbd-commands index 09e811724b..adfd4a495c 100755 --- a/tests/qemu-iotests/tests/nbd-commands +++ b/tests/qemu-iotests/tests/nbd-commands @@ -25,6 +25,7 @@ nbd: ModuleType =20 DEPTH_LOCAL =3D 1 DEPTH_BACKING =3D 2 +CLUSTER =3D 65536 =20 =20 class TestNbdCommands(iotests.QMPTestCase): @@ -90,7 +91,7 @@ class TestNbdCommands(iotests.QMPTestCase): self.h.shutdown() self.h =3D None =20 - def block_status(self, count=3Dsize, wanted=3DNone): + def block_status(self, count=3Dsize, wanted=3DNone, flags=3D0): """Map each meta context in the reply to its list of extents.""" reply =3D {} =20 @@ -99,9 +100,9 @@ class TestNbdCommands(iotests.QMPTestCase): entries[1::2])) =20 if wanted is None: - self.h.block_status(count, 0, cb) + self.h.block_status(count, 0, cb, flags) else: - self.h.block_status_filter(count, 0, wanted, cb) + self.h.block_status_filter(count, 0, wanted, cb, flags) return reply =20 def top_extents(self): @@ -158,6 +159,71 @@ class TestNbdCommands(iotests.QMPTestCase): for wanted in (['base:allocation'], ['qemu:allocation-depth']): self.assertEqual(sorted(self.block_status(wanted=3Dwanted)), w= anted) =20 + def read_chunks(self, count, offset, flags=3D0): + chunks =3D [] + + def cb(subbuf, off, status, _err): + chunks.append((off, len(subbuf), status)) + + self.h.pread_structured(count, offset, cb, flags) + return chunks + + def make_sparse(self): + """Lay out data, a hole and data again, one cluster each.""" + self.h.pwrite(b'z' * CLUSTER, 0) + self.h.zero(CLUSTER, CLUSTER) + self.h.pwrite(b'z' * CLUSTER, 2 * CLUSTER) + + def test_read_sparse_chunks(self): + self.make_sparse() + + first =3D (0, CLUSTER, nbd.READ_DATA) + hole =3D (CLUSTER, CLUSTER, nbd.READ_HOLE) + second =3D (2 * CLUSTER, CLUSTER, nbd.READ_DATA) + + # A hole is an offset and a length, not a cluster of zeroes, + # wherever it falls in the reply + self.assertEqual(self.read_chunks(2 * CLUSTER, 0), [first, hole]) + self.assertEqual(self.read_chunks(2 * CLUSTER, CLUSTER), + [hole, second]) + self.assertEqual(self.read_chunks(3 * CLUSTER, 0), + [first, hole, second]) + + self.assertEqual(self.h.pread(CLUSTER, CLUSTER), bytes(CLUSTER)) + self.assertEqual(self.h.pread(CLUSTER, 0), b'z' * CLUSTER) + + def test_read_dont_fragment(self): + self.make_sparse() + + self.assertEqual(self.read_chunks(3 * CLUSTER, 0, nbd.CMD_FLAG_DF), + [(0, 3 * CLUSTER, nbd.READ_DATA)]) + + def test_block_status_req_one(self): + hole =3D nbd.STATE_HOLE | nbd.STATE_ZERO + self.make_sparse() + + alloc =3D self.block_status(3 * CLUSTER)['base:allocation'] + self.assertEqual(alloc, [(CLUSTER, 0), (CLUSTER, hole), (CLUSTER, = 0)]) + + # One extent, so the reply covers less than was asked for and the + # client has to come back for the rest + alloc =3D self.block_status(3 * CLUSTER, flags=3Dnbd.CMD_FLAG_REQ_= ONE) + self.assertEqual(alloc['base:allocation'], [(CLUSTER, 0)]) + + def test_write_and_trim_fua(self): + self.h.pwrite(b'y' * 4096, 4096, nbd.CMD_FLAG_FUA) + self.assertEqual(self.h.pread(4096, 4096), b'y' * 4096) + self.h.trim(4096, 4096, nbd.CMD_FLAG_FUA) + + def test_fast_zero(self): + self.h.zero(CLUSTER, CLUSTER, nbd.CMD_FLAG_FAST_ZERO) + self.assertEqual(self.h.pread(CLUSTER, CLUSTER), bytes(CLUSTER)) + + # Zeroing part of a cluster needs the fallback the flag forbids + with self.assertRaises(nbd.Error) as caught: + self.h.zero(4096, 4096, nbd.CMD_FLAG_FAST_ZERO) + self.assertEqual(caught.exception.errno, 'ENOTSUP') + def test_cache_past_end_of_export(self): self.assertRaises(nbd.Error, self.h.cache, size + 1, 0) =20 diff --git a/tests/qemu-iotests/tests/nbd-commands.out b/tests/qemu-iotests= /tests/nbd-commands.out index 2f7d3902f2..281b69efea 100644 --- a/tests/qemu-iotests/tests/nbd-commands.out +++ b/tests/qemu-iotests/tests/nbd-commands.out @@ -1,5 +1,5 @@ -....... +............ ---------------------------------------------------------------------- -Ran 7 tests +Ran 12 tests =20 OK --=20 2.53.0