From nobody Wed Nov 5 18:27:52 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; 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 1536943966917729.8677710847013; Fri, 14 Sep 2018 09:52:46 -0700 (PDT) Received: from localhost ([::1]:52591 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g0rKa-000707-NO for importer@patchew.org; Fri, 14 Sep 2018 12:52:32 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60414) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g0rJW-0006LB-8d for qemu-devel@nongnu.org; Fri, 14 Sep 2018 12:51:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g0rJS-0002Og-75 for qemu-devel@nongnu.org; Fri, 14 Sep 2018 12:51:26 -0400 Received: from relay.sw.ru ([185.231.240.75]:32892) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1g0rJR-0002L7-Um; Fri, 14 Sep 2018 12:51:22 -0400 Received: from [10.28.8.145] (helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1g0rJN-0005H0-OJ; Fri, 14 Sep 2018 19:51:18 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org, qemu-stable@nongnu.org Date: Fri, 14 Sep 2018 19:51:16 +0300 Message-Id: <20180914165116.23182-1-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH] nbd/server: fix bitmap export 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: pbonzini@redhat.com, vsementsov@virtuozzo.com, den@openvz.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" bitmap_to_extents function is broken: it switches dirty variable after every iteration, however it can process only part of dirty (or zero) area during one iteration in case when this area is too large for one extent. Fortunately, the bug don't produce wrong extents: it just inserts zero-length extents between sequential extents representing large dirty (or zero) area. However, zero-length extents are abandoned by NBD protocol. So, careful client should consider such replay as server fault and not-careful will likely ignore zero-length extents. Fix this by more careful handling of dirty variable. Bug was introduced in 3d068aff16 "nbd/server: implement dirty bitmap export", with the whole function. and presents in v3.0.0 release. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- nbd/server.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nbd/server.c b/nbd/server.c index ea5fe0eb33..12f721482d 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1951,6 +1951,8 @@ static unsigned int bitmap_to_extents(BdrvDirtyBitmap= *bitmap, uint64_t offset, =20 assert(begin < overall_end && nb_extents); while (begin < overall_end && i < nb_extents) { + bool next_dirty =3D !dirty; + if (dirty) { end =3D bdrv_dirty_bitmap_next_zero(bitmap, begin); } else { @@ -1962,6 +1964,7 @@ static unsigned int bitmap_to_extents(BdrvDirtyBitmap= *bitmap, uint64_t offset, end =3D MIN(bdrv_dirty_bitmap_size(bitmap), begin + UINT32_MAX + 1 - bdrv_dirty_bitmap_granularity(bitmap)); + next_dirty =3D dirty; } if (dont_fragment && end > overall_end) { end =3D overall_end; @@ -1971,7 +1974,7 @@ static unsigned int bitmap_to_extents(BdrvDirtyBitmap= *bitmap, uint64_t offset, extents[i].flags =3D cpu_to_be32(dirty ? NBD_STATE_DIRTY : 0); i++; begin =3D end; - dirty =3D !dirty; + dirty =3D next_dirty; } =20 bdrv_dirty_iter_free(it); --=20 2.18.0