From patchwork Fri Oct 9 02:07:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 303385 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1032EC433E7 for ; Fri, 9 Oct 2020 02:09:07 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4E23C22255 for ; Fri, 9 Oct 2020 02:09:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="TQsBruUa" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4E23C22255 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:43162 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kQhqD-0007ia-3p for qemu-devel@archiver.kernel.org; Thu, 08 Oct 2020 22:09:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33008) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kQhoj-000641-Bg for qemu-devel@nongnu.org; Thu, 08 Oct 2020 22:07:33 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:29875) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kQhoc-0006r9-QS for qemu-devel@nongnu.org; Thu, 08 Oct 2020 22:07:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602209243; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=g1ucFuGfhU/BqCiWWn+eDAP0WvHa+lARbgBQwFWqJw8=; b=TQsBruUaSHRY38eKuYTR6Ty3wNWEc3GqvwOOVOql8bmobssfCWxkKjMJpk94t2z3MHnAW1 4BMNZlxI6j5wRPa6fs8yjOT+RFqeOCcMKQuTRQrMGN6ZJqUrF6RdNzhsQByExyG1g2/bly AHiasRtGPAphW29IqlpUifodPvaAP8M= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-186-OoemS4o0M2-1Ia4nRS_sTg-1; Thu, 08 Oct 2020 22:07:22 -0400 X-MC-Unique: OoemS4o0M2-1Ia4nRS_sTg-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E570618C5201; Fri, 9 Oct 2020 02:07:20 +0000 (UTC) Received: from blue.redhat.com (ovpn-113-14.phx2.redhat.com [10.3.113.14]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1801476650; Fri, 9 Oct 2020 02:07:20 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Subject: [PATCH v3 1/6] nbd: Add new qemu:allocation-depth metacontext Date: Thu, 8 Oct 2020 21:07:09 -0500 Message-Id: <20201009020714.1074061-2-eblake@redhat.com> In-Reply-To: <20201009020714.1074061-1-eblake@redhat.com> References: <20201009020714.1074061-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=eblake@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/08 01:56:49 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] 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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, 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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, qemu-block@nongnu.org, rjones@redhat.com, Max Reitz , stefanha@redhat.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 'qemu-img map' provides a way to determine which extents of an image come from the top layer vs. inherited from a backing chain. This is useful information worth exposing over NBD. There is a proposal to add a QMP command block-dirty-bitmap-populate which can create a dirty bitmap that reflects allocation information, at which point qemu:dirty-bitmap:NAME can expose that information via the creation of a temporary bitmap, but we can shorten the effort by adding a new qemu:allocation-depth context that does the same thing without an intermediate bitmap (this patch does not eliminate the need for that proposal, as it will have other uses as well). For this patch, I just encoded a tri-state value (unallocated, from this layer, from any of the backing layers); an obvious extension would be to provide the actual depth in bits 31-4 while keeping bits 1-0 as a tri-state (leaving bits 3-2 unused, for ease of reading depth from a hex number). But this extension would require bdrv_is_allocated_above to return a depth number. Note that this patch does not actually enable any way to request a server to enable this context; that will come in the next patch. Signed-off-by: Eric Blake --- docs/interop/nbd.txt | 23 +++++++++-- include/block/nbd.h | 8 +++- nbd/server.c | 92 ++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 111 insertions(+), 12 deletions(-) diff --git a/docs/interop/nbd.txt b/docs/interop/nbd.txt index f3b3cacc9621..ea1ee94cac9b 100644 --- a/docs/interop/nbd.txt +++ b/docs/interop/nbd.txt @@ -17,9 +17,9 @@ namespace "qemu". == "qemu" namespace == -The "qemu" namespace currently contains only one type of context, -related to exposing the contents of a dirty bitmap alongside the -associated disk contents. That context has the following form: +The "qemu" namespace currently contains two types of context. The +first is related to exposing the contents of a dirty bitmap alongside +the associated disk contents. That context has the following form: qemu:dirty-bitmap: @@ -28,8 +28,22 @@ in reply for NBD_CMD_BLOCK_STATUS: bit 0: NBD_STATE_DIRTY, means that the extent is "dirty" +The second is related to exposing the source of various extents within +the image, with a single context named: + + qemu:allocation-depth + +In the allocation depth context, bits 0 and 1 form a tri-state value: + + bits 0-1 clear: NBD_STATE_DEPTH_UNALLOC, the extent is unallocated + bit 0 set: NBD_STATE_DEPTH_LOCAL, the extent is allocated in the + top level of the image + bit 1 set: NBD_STATE_DEPTH_BACKING, the extent is inherited from a + backing layer + For NBD_OPT_LIST_META_CONTEXT the following queries are supported -in addition to "qemu:dirty-bitmap:": +in addition to the specific "qemu:allocation-depth" and +"qemu:dirty-bitmap:": * "qemu:" - returns list of all available metadata contexts in the namespace. @@ -55,3 +69,4 @@ the operation of that feature. NBD_CMD_BLOCK_STATUS for "qemu:dirty-bitmap:", NBD_CMD_CACHE * 4.2: NBD_FLAG_CAN_MULTI_CONN for shareable read-only exports, NBD_CMD_FLAG_FAST_ZERO +* 5.2: NBD_CMD_BLOCK_STATUS for "qemu:allocation-depth" diff --git a/include/block/nbd.h b/include/block/nbd.h index 3dd9a04546ec..06208bc25027 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2019 Red Hat, Inc. + * Copyright (C) 2016-2020 Red Hat, Inc. * Copyright (C) 2005 Anthony Liguori * * Network Block Device @@ -259,6 +259,12 @@ enum { /* Extent flags for qemu:dirty-bitmap in NBD_REPLY_TYPE_BLOCK_STATUS */ #define NBD_STATE_DIRTY (1 << 0) +/* Extent flags for qemu:allocation-depth in NBD_REPLY_TYPE_BLOCK_STATUS */ +#define NBD_STATE_DEPTH_UNALLOC (0 << 0) +#define NBD_STATE_DEPTH_LOCAL (1 << 0) +#define NBD_STATE_DEPTH_BACKING (2 << 0) +#define NBD_STATE_DEPTH_MASK (0x3) + static inline bool nbd_reply_type_is_error(int type) { return type & (1 << 15); diff --git a/nbd/server.c b/nbd/server.c index e75c825879aa..59533090f5ce 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -27,7 +27,8 @@ #include "qemu/units.h" #define NBD_META_ID_BASE_ALLOCATION 0 -#define NBD_META_ID_DIRTY_BITMAP 1 +#define NBD_META_ID_ALLOCATION_DEPTH 1 +#define NBD_META_ID_DIRTY_BITMAP 2 /* * NBD_MAX_BLOCK_STATUS_EXTENTS: 1 MiB of extents data. An empirical @@ -94,6 +95,7 @@ struct NBDExport { BlockBackend *eject_notifier_blk; Notifier eject_notifier; + bool alloc_context; BdrvDirtyBitmap *export_bitmap; char *export_bitmap_context; }; @@ -108,6 +110,7 @@ typedef struct NBDExportMetaContexts { bool valid; /* means that negotiation of the option finished without errors */ bool base_allocation; /* export base:allocation context (block status) */ + bool allocation_depth; /* export qemu:allocation-depth */ bool bitmap; /* export qemu:dirty-bitmap: */ } NBDExportMetaContexts; @@ -852,7 +855,8 @@ static bool nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *meta, /* nbd_meta_qemu_query * * Handle queries to 'qemu' namespace. For now, only the qemu:dirty-bitmap: - * context is available. Return true if @query has been handled. + * and qemu:allocation-depth contexts are available. Return true if @query + * has been handled. */ static bool nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta, const char *query) @@ -864,12 +868,19 @@ static bool nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta, if (!*query) { if (client->opt == NBD_OPT_LIST_META_CONTEXT) { + meta->allocation_depth = meta->exp->alloc_context; meta->bitmap = !!meta->exp->export_bitmap; } trace_nbd_negotiate_meta_query_parse("empty"); return true; } + if (strcmp(query, "allocation-depth") == 0) { + trace_nbd_negotiate_meta_query_parse("allocation-depth"); + meta->allocation_depth = meta->exp->alloc_context; + return true; + } + if (nbd_strshift(&query, "dirty-bitmap:")) { trace_nbd_negotiate_meta_query_parse("dirty-bitmap:"); if (!meta->exp->export_bitmap) { @@ -884,7 +895,7 @@ static bool nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta, return true; } - trace_nbd_negotiate_meta_query_skip("not dirty-bitmap"); + trace_nbd_negotiate_meta_query_skip("unknown qemu context"); return true; } @@ -984,6 +995,7 @@ static int nbd_negotiate_meta_queries(NBDClient *client, if (client->opt == NBD_OPT_LIST_META_CONTEXT && !nb_queries) { /* enable all known contexts */ meta->base_allocation = true; + meta->allocation_depth = meta->exp->alloc_context; meta->bitmap = !!meta->exp->export_bitmap; } else { for (i = 0; i < nb_queries; ++i) { @@ -1003,6 +1015,15 @@ static int nbd_negotiate_meta_queries(NBDClient *client, } } + if (meta->allocation_depth) { + ret = nbd_negotiate_send_meta_context(client, "qemu:allocation-depth", + NBD_META_ID_ALLOCATION_DEPTH, + errp); + if (ret < 0) { + return ret; + } + } + if (meta->bitmap) { ret = nbd_negotiate_send_meta_context(client, meta->exp->export_bitmap_context, @@ -1961,6 +1982,40 @@ static int blockstatus_to_extents(BlockDriverState *bs, uint64_t offset, return 0; } +static int blockalloc_to_extents(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, NBDExtentArray *ea) +{ + while (bytes) { + uint32_t flags; + int64_t num; + int ret = bdrv_is_allocated(bs, offset, bytes, &num); + + if (ret < 0) { + return ret; + } + + if (ret == 1) { + flags = NBD_STATE_DEPTH_LOCAL; + } else { + ret = bdrv_is_allocated_above(bs, NULL, false, offset, num, + &num); + if (ret < 0) { + return ret; + } + flags = ret ? NBD_STATE_DEPTH_BACKING : NBD_STATE_DEPTH_UNALLOC; + } + + if (nbd_extent_array_add(ea, num, flags) < 0) { + return 0; + } + + offset += num; + bytes -= num; + } + + return 0; +} + /* * nbd_co_send_extents * @@ -2000,7 +2055,11 @@ static int nbd_co_send_block_status(NBDClient *client, uint64_t handle, unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BLOCK_STATUS_EXTENTS; g_autoptr(NBDExtentArray) ea = nbd_extent_array_new(nb_extents); - ret = blockstatus_to_extents(bs, offset, length, ea); + if (context_id == NBD_META_ID_BASE_ALLOCATION) { + ret = blockstatus_to_extents(bs, offset, length, ea); + } else { + ret = blockalloc_to_extents(bs, offset, length, ea); + } if (ret < 0) { return nbd_co_send_structured_error( client, handle, -ret, "can't get block status", errp); @@ -2335,16 +2394,20 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, } if (client->export_meta.valid && (client->export_meta.base_allocation || + client->export_meta.allocation_depth || client->export_meta.bitmap)) { bool dont_fragment = request->flags & NBD_CMD_FLAG_REQ_ONE; + int contexts_remaining = client->export_meta.base_allocation + + client->export_meta.allocation_depth + + client->export_meta.bitmap; if (client->export_meta.base_allocation) { ret = nbd_co_send_block_status(client, request->handle, blk_bs(exp->common.blk), request->from, request->len, dont_fragment, - !client->export_meta.bitmap, + !--contexts_remaining, NBD_META_ID_BASE_ALLOCATION, errp); if (ret < 0) { @@ -2352,17 +2415,32 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, } } + if (client->export_meta.allocation_depth) { + ret = nbd_co_send_block_status(client, request->handle, + blk_bs(exp->common.blk), + request->from, request->len, + dont_fragment, + !--contexts_remaining, + NBD_META_ID_ALLOCATION_DEPTH, + errp); + if (ret < 0) { + return ret; + } + } + if (client->export_meta.bitmap) { ret = nbd_co_send_bitmap(client, request->handle, client->exp->export_bitmap, request->from, request->len, - dont_fragment, - true, NBD_META_ID_DIRTY_BITMAP, errp); + dont_fragment, !--contexts_remaining, + NBD_META_ID_DIRTY_BITMAP, errp); if (ret < 0) { return ret; } } + assert(!contexts_remaining); + return 0; } else { return nbd_send_generic_reply(client, request->handle, -EINVAL, From patchwork Fri Oct 9 02:07:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 303384 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F0922C433E7 for ; Fri, 9 Oct 2020 02:09:13 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5A02422258 for ; Fri, 9 Oct 2020 02:09:13 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="ACRoYdwJ" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5A02422258 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:43888 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kQhqK-00082M-Cf for qemu-devel@archiver.kernel.org; Thu, 08 Oct 2020 22:09:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33086) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kQhop-00067y-7r for qemu-devel@nongnu.org; Thu, 08 Oct 2020 22:07:40 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:59445) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kQhog-0006rh-2y for qemu-devel@nongnu.org; Thu, 08 Oct 2020 22:07:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602209246; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=QrTMWedCM9pBx2HlLDUiTnnnlwYXrVKOcHV7S5yHwfM=; b=ACRoYdwJ5ggPe5sCnKD8pKVxcAEakYPIb7hP8zQhuI1s1FUvboKJpefA592ppR1DsijO0A k4UhMCQwACS+AIxpV2ReQZ4HmV4cIxANSqQ+rAYb86xDRRwfdPu1qtOPDDBchFvjg0PWDD M9NxWz6MZeY2qWhi5s19VXXn33sSFz0= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-171-c1MrSq-YO02YXHi17Z-_Hw-1; Thu, 08 Oct 2020 22:07:23 -0400 X-MC-Unique: c1MrSq-YO02YXHi17Z-_Hw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id CE20E64144; Fri, 9 Oct 2020 02:07:21 +0000 (UTC) Received: from blue.redhat.com (ovpn-113-14.phx2.redhat.com [10.3.113.14]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3291E76653; Fri, 9 Oct 2020 02:07:21 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Subject: [PATCH v3 2/6] nbd: Add 'qemu-nbd -A' to expose allocation depth Date: Thu, 8 Oct 2020 21:07:10 -0500 Message-Id: <20201009020714.1074061-3-eblake@redhat.com> In-Reply-To: <20201009020714.1074061-1-eblake@redhat.com> References: <20201009020714.1074061-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=eblake@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/08 22:07:25 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] 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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, 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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, qemu-block@nongnu.org, Markus Armbruster , rjones@redhat.com, Max Reitz , stefanha@redhat.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Allow the server to expose an additional metacontext to be requested by savvy clients. qemu-nbd adds a new option -A to expose the qemu:allocation-depth metacontext through NBD_CMD_BLOCK_STATUS; this can also be set via QMP when using block-export-add. qemu as client can be hacked into viewing this new context by using the now-misnamed x-dirty-bitmap option when creating an NBD blockdev (even though our x- naming means we could rename it, I did not think it worth breaking back-compat of tools that have been using it while waiting for a better solution). It is worth noting the decoding of how such context information will appear in 'qemu-img map --output=json': NBD_STATE_DEPTH_UNALLOC => "zero":false, "data":true NBD_STATE_DEPTH_LOCAL => "zero":false, "data":false NBD_STATE_DEPTH_BACKING => "zero":true, "data":true libnbd as client is probably a nicer way to get at the information without having to decipher such hacks in qemu as client. ;) Signed-off-by: Eric Blake Message-Id: <20200930121105.667049-6-eblake@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy [eblake: comment tweak suggested by Vladimir] Signed-off-by: Eric Blake --- docs/tools/qemu-nbd.rst | 6 ++++ qapi/block-core.json | 7 ++-- qapi/block-export.json | 6 +++- blockdev-nbd.c | 2 ++ nbd/server.c | 2 ++ qemu-nbd.c | 14 ++++++-- tests/qemu-iotests/309 | 73 ++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/309.out | 22 ++++++++++++ tests/qemu-iotests/group | 1 + 9 files changed, 127 insertions(+), 6 deletions(-) create mode 100755 tests/qemu-iotests/309 create mode 100644 tests/qemu-iotests/309.out diff --git a/docs/tools/qemu-nbd.rst b/docs/tools/qemu-nbd.rst index 667861cb22e9..0e545a97cfa3 100644 --- a/docs/tools/qemu-nbd.rst +++ b/docs/tools/qemu-nbd.rst @@ -72,6 +72,12 @@ driver options if ``--image-opts`` is specified. Export the disk as read-only. +.. option:: -A, --allocation-depth + + Expose allocation depth information via the + ``qemu:allocation-depth`` context accessible through + NBD_OPT_SET_META_CONTEXT. + .. option:: -B, --bitmap=NAME If *filename* has a qcow2 persistent bitmap *NAME*, expose diff --git a/qapi/block-core.json b/qapi/block-core.json index 3758ea991269..249bd434f4eb 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3882,9 +3882,12 @@ # # @tls-creds: TLS credentials ID # -# @x-dirty-bitmap: A "qemu:dirty-bitmap:NAME" string to query in place of +# @x-dirty-bitmap: A metacontext name such as "qemu:dirty-bitmap:NAME" or +# "qemu:allocation-depth" to query in place of the # traditional "base:allocation" block status (see -# NBD_OPT_LIST_META_CONTEXT in the NBD protocol) (since 3.0) +# NBD_OPT_LIST_META_CONTEXT in the NBD protocol; and +# yes, naming this option x-context would have made +# more sense) (since 3.0) # # @reconnect-delay: On an unexpected disconnect, the nbd client tries to # connect again until succeeding or encountering a serious diff --git a/qapi/block-export.json b/qapi/block-export.json index 65804834d905..524cd3a94400 100644 --- a/qapi/block-export.json +++ b/qapi/block-export.json @@ -78,11 +78,15 @@ # NBD client can use NBD_OPT_SET_META_CONTEXT with # "qemu:dirty-bitmap:NAME" to inspect the bitmap. (since 4.0) # +# @alloc: Also export the allocation map for @device, so the NBD client +# can use NBD_OPT_SET_META_CONTEXT with "qemu:allocation-depth" +# to inspect allocation details. (since 5.2) +# # Since: 5.0 ## { 'struct': 'BlockExportOptionsNbd', 'data': { '*name': 'str', '*description': 'str', - '*bitmap': 'str' } } + '*bitmap': 'str', '*alloc': 'bool' } } ## # @NbdServerAddOptions: diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 8174023e5c47..f9012f93e2bb 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -212,6 +212,8 @@ void qmp_nbd_server_add(NbdServerAddOptions *arg, Error **errp) .description = g_strdup(arg->description), .has_bitmap = arg->has_bitmap, .bitmap = g_strdup(arg->bitmap), + .has_alloc = arg->alloc, + .alloc = arg->alloc, }, }; diff --git a/nbd/server.c b/nbd/server.c index 59533090f5ce..e24495d93e2e 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1597,6 +1597,8 @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args, assert(strlen(exp->export_bitmap_context) < NBD_MAX_STRING_SIZE); } + exp->alloc_context = arg->alloc; + blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp); QTAILQ_INSERT_TAIL(&exports, exp, next); diff --git a/qemu-nbd.c b/qemu-nbd.c index c731dda04ec0..e3cff17d6760 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -99,6 +99,7 @@ static void usage(const char *name) "\n" "Exposing part of the image:\n" " -o, --offset=OFFSET offset into the image\n" +" -A, --allocation-depth expose the allocation depth\n" " -B, --bitmap=NAME expose a persistent dirty bitmap\n" "\n" "General purpose options:\n" @@ -519,7 +520,7 @@ int main(int argc, char **argv) char *device = NULL; QemuOpts *sn_opts = NULL; const char *sn_id_or_name = NULL; - const char *sopt = "hVb:o:p:rsnc:dvk:e:f:tl:x:T:D:B:L"; + const char *sopt = "hVb:o:p:rsnc:dvk:e:f:tl:x:T:D:AB:L"; struct option lopt[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, @@ -528,6 +529,7 @@ int main(int argc, char **argv) { "socket", required_argument, NULL, 'k' }, { "offset", required_argument, NULL, 'o' }, { "read-only", no_argument, NULL, 'r' }, + { "allocation-depth", no_argument, NULL, 'A' }, { "bitmap", required_argument, NULL, 'B' }, { "connect", required_argument, NULL, 'c' }, { "disconnect", no_argument, NULL, 'd' }, @@ -569,6 +571,7 @@ int main(int argc, char **argv) QDict *options = NULL; const char *export_name = NULL; /* defaults to "" later for server mode */ const char *export_description = NULL; + bool alloc_depth = false; const char *bitmap = NULL; const char *tlscredsid = NULL; bool imageOpts = false; @@ -694,6 +697,9 @@ int main(int argc, char **argv) readonly = true; flags &= ~BDRV_O_RDWR; break; + case 'A': + alloc_depth = true; + break; case 'B': bitmap = optarg; break; @@ -791,8 +797,8 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } if (export_name || export_description || dev_offset || - device || disconnect || fmt || sn_id_or_name || bitmap || - seen_aio || seen_discard || seen_cache) { + device || disconnect || fmt || sn_id_or_name || alloc_depth || + bitmap || seen_aio || seen_discard || seen_cache) { error_report("List mode is incompatible with per-device settings"); exit(EXIT_FAILURE); } @@ -1078,6 +1084,8 @@ int main(int argc, char **argv) .description = g_strdup(export_description), .has_bitmap = !!bitmap, .bitmap = g_strdup(bitmap), + .has_alloc = alloc_depth, + .alloc = alloc_depth, }, }; blk_exp_add(export_opts, &error_fatal); diff --git a/tests/qemu-iotests/309 b/tests/qemu-iotests/309 new file mode 100755 index 000000000000..b6734794bb68 --- /dev/null +++ b/tests/qemu-iotests/309 @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# +# Test qemu-nbd -A +# +# Copyright (C) 2018-2020 Red Hat, Inc. +# +# 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 . +# + +seq="$(basename $0)" +echo "QA output created by $seq" + +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img + nbd_server_stop +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter +. ./common.nbd + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux +_require_command QEMU_NBD + +echo +echo "=== Initial image setup ===" +echo + +TEST_IMG="$TEST_IMG.base" _make_test_img 4M +$QEMU_IO -c 'w 0 2M' -f $IMGFMT "$TEST_IMG.base" | _filter_qemu_io +_make_test_img -b "$TEST_IMG.base" -F $IMGFMT 4M +$QEMU_IO -c 'w 1M 2M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io + +echo +echo "=== Check allocation over NBD ===" +echo + +$QEMU_IMG map --output=json -f qcow2 "$TEST_IMG" +IMG="driver=nbd,server.type=unix,server.path=$nbd_unix_socket" +nbd_server_start_unix_socket -r -f qcow2 -A "$TEST_IMG" +# Normal -f raw NBD block status loses access to allocation information +$QEMU_IMG map --output=json --image-opts \ + "$IMG" | _filter_qemu_img_map +# But since we used -A, and use x-dirty-bitmap as a hack for reading bitmaps, +# we can reconstruct it, by abusing block status to report: +# NBD_STATE_DEPTH_UNALLOC => "zero":false, "data":true +# NBD_STATE_DEPTH_LOCAL => "zero":false, "data":false +# NBD_STATE_DEPTH_BACKING => "zero":true, "data":true +$QEMU_IMG map --output=json --image-opts \ + "$IMG,x-dirty-bitmap=qemu:allocation-depth" | _filter_qemu_img_map + +# success, all done +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/309.out b/tests/qemu-iotests/309.out new file mode 100644 index 000000000000..db75bb6b0df9 --- /dev/null +++ b/tests/qemu-iotests/309.out @@ -0,0 +1,22 @@ +QA output created by 309 + +=== Initial image setup === + +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=4194304 +wrote 2097152/2097152 bytes at offset 0 +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT +wrote 2097152/2097152 bytes at offset 1048576 +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=== Check allocation over NBD === + +[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}, +{ "start": 1048576, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}, +{ "start": 3145728, "length": 1048576, "depth": 1, "zero": true, "data": false}] +[{ "start": 0, "length": 3145728, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, +{ "start": 3145728, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": true, "offset": OFFSET}, +{ "start": 1048576, "length": 2097152, "depth": 0, "zero": false, "data": false}, +{ "start": 3145728, "length": 1048576, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 9e4f7c01530d..a567fa97d7e5 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -315,3 +315,4 @@ 304 rw quick 305 rw quick 307 rw quick export +309 rw auto quick From patchwork Fri Oct 9 02:07:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 271781 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 51032C433DF for ; Fri, 9 Oct 2020 02:09:13 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BFE8C22255 for ; Fri, 9 Oct 2020 02:09:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="dJs60tdh" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BFE8C22255 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:43824 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kQhqJ-00080O-HW for qemu-devel@archiver.kernel.org; Thu, 08 Oct 2020 22:09:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33034) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kQhol-00064P-Tt for qemu-devel@nongnu.org; Thu, 08 Oct 2020 22:07:37 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:48069) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kQhoc-0006rc-Rs for qemu-devel@nongnu.org; Thu, 08 Oct 2020 22:07:35 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602209245; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=T8wFYhrz/v4NI8FMXE3LWRphbgaidPX9Bd0i6MQ1Gp0=; b=dJs60tdh5sOpsv1A+gXLhSErzFA0Cjr1he3yBD4RWUpFg6XZAb10qsltjEXish8USe3LtG 0YzQjaxL7AleLGB1oFrRQXZ174JxMBfMgDMd32T4bMWktgez88Up1mFMqMAFDglrDu4sZp x2FnS4RP0cpWc/bCWLESLa0rkrPBctY= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-183-dAk286DAPpOFQKKYM0Y4Kw-1; Thu, 08 Oct 2020 22:07:23 -0400 X-MC-Unique: dAk286DAPpOFQKKYM0Y4Kw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A9DA564143; Fri, 9 Oct 2020 02:07:22 +0000 (UTC) Received: from blue.redhat.com (ovpn-113-14.phx2.redhat.com [10.3.113.14]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0FEAA76650; Fri, 9 Oct 2020 02:07:22 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Subject: [PATCH v3 3/6] nbd: Update qapi to support multiple bitmaps Date: Thu, 8 Oct 2020 21:07:11 -0500 Message-Id: <20201009020714.1074061-4-eblake@redhat.com> In-Reply-To: <20201009020714.1074061-1-eblake@redhat.com> References: <20201009020714.1074061-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=eblake@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/08 22:07:25 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] 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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, 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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, qemu-block@nongnu.org, Markus Armbruster , rjones@redhat.com, Max Reitz , stefanha@redhat.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Since 'nbd-server-add' is deprecated, and 'block-export-add' is new to 5.2, we can still tweak the interface. Allowing 'bitmaps':['str'] is nicer than 'bitmap':'str'. This wires up the qapi and qemu-nbd changes to permit passing multiple bitmaps, but the actual support will require a further patch to the server. Signed-off-by: Eric Blake --- qapi/block-export.json | 16 +++++++++++----- blockdev-nbd.c | 18 ++++++++++++++++-- nbd/server.c | 19 +++++++++++++------ qemu-nbd.c | 13 ++++++++----- 4 files changed, 48 insertions(+), 18 deletions(-) diff --git a/qapi/block-export.json b/qapi/block-export.json index 524cd3a94400..2dc45a54e364 100644 --- a/qapi/block-export.json +++ b/qapi/block-export.json @@ -74,9 +74,9 @@ # @description: Free-form description of the export, up to 4096 bytes. # (Since 5.0) # -# @bitmap: Also export the dirty bitmap reachable from @device, so the -# NBD client can use NBD_OPT_SET_META_CONTEXT with -# "qemu:dirty-bitmap:NAME" to inspect the bitmap. (since 4.0) +# @bitmaps: Also export each of the named dirty bitmaps reachable from +# @device, so the NBD client can use NBD_OPT_SET_META_CONTEXT with +# "qemu:dirty-bitmap:BITMAP" to inspect each bitmap. (since 5.2) # # @alloc: Also export the allocation map for @device, so the NBD client # can use NBD_OPT_SET_META_CONTEXT with "qemu:allocation-depth" @@ -86,7 +86,7 @@ ## { 'struct': 'BlockExportOptionsNbd', 'data': { '*name': 'str', '*description': 'str', - '*bitmap': 'str', '*alloc': 'bool' } } + '*bitmaps': ['str'], '*alloc': 'bool' } } ## # @NbdServerAddOptions: @@ -98,12 +98,18 @@ # @writable: Whether clients should be able to write to the device via the # NBD connection (default false). # +# @bitmap: Also export a single dirty bitmap reachable from @device, so the +# NBD client can use NBD_OPT_SET_META_CONTEXT with +# "qemu:dirty-bitmap:BITMAP" to inspect the bitmap (since 4.0); +# mutually exclusive with @bitmaps, and newer clients should use +# that instead. +# # Since: 5.0 ## { 'struct': 'NbdServerAddOptions', 'base': 'BlockExportOptionsNbd', 'data': { 'device': 'str', - '*writable': 'bool' } } + '*writable': 'bool', '*bitmap': 'str' } } ## # @nbd-server-add: diff --git a/blockdev-nbd.c b/blockdev-nbd.c index f9012f93e2bb..f0a03c830c5f 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -190,6 +190,20 @@ void qmp_nbd_server_add(NbdServerAddOptions *arg, Error **errp) return; } + /* + * New code should use the list 'bitmaps'; but until this code is + * gone, we must support the older single 'bitmap'. Use only one. + */ + if (arg->has_bitmap) { + if (arg->has_bitmaps) { + error_setg(errp, "Can't mix 'bitmap' and 'bitmaps'"); + return; + } + arg->has_bitmaps = true; + arg->bitmaps = g_new0(strList, 1); + arg->bitmaps->value = g_strdup(arg->bitmap); + } + /* * block-export-add would default to the node-name, but we may have to use * the device name as a default here for compatibility. @@ -210,8 +224,8 @@ void qmp_nbd_server_add(NbdServerAddOptions *arg, Error **errp) .name = g_strdup(arg->name), .has_description = arg->has_description, .description = g_strdup(arg->description), - .has_bitmap = arg->has_bitmap, - .bitmap = g_strdup(arg->bitmap), + .has_bitmaps = arg->has_bitmaps, + .bitmaps = g_steal_pointer(&arg->bitmaps), .has_alloc = arg->alloc, .alloc = arg->alloc, }, diff --git a/nbd/server.c b/nbd/server.c index e24495d93e2e..ea5de0b503cd 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1495,6 +1495,7 @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args, uint64_t perm, shared_perm; bool readonly = !exp_args->writable; bool shared = !exp_args->writable; + strList *bitmaps; int ret; assert(exp_args->type == BLOCK_EXPORT_TYPE_NBD); @@ -1556,12 +1557,18 @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args, } exp->size = QEMU_ALIGN_DOWN(size, BDRV_SECTOR_SIZE); - if (arg->bitmap) { + /* XXX Allow more than one bitmap */ + if (arg->bitmaps && arg->bitmaps->next) { + error_setg(errp, "multiple bitmaps per export not supported yet"); + return -EOPNOTSUPP; + } + for (bitmaps = arg->bitmaps; bitmaps; bitmaps = bitmaps->next) { + const char *bitmap = bitmaps->value; BlockDriverState *bs = blk_bs(blk); BdrvDirtyBitmap *bm = NULL; while (bs) { - bm = bdrv_find_dirty_bitmap(bs, arg->bitmap); + bm = bdrv_find_dirty_bitmap(bs, bitmap); if (bm != NULL) { break; } @@ -1571,7 +1578,7 @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args, if (bm == NULL) { ret = -ENOENT; - error_setg(errp, "Bitmap '%s' is not found", arg->bitmap); + error_setg(errp, "Bitmap '%s' is not found", bitmap); goto fail; } @@ -1585,15 +1592,15 @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args, ret = -EINVAL; error_setg(errp, "Enabled bitmap '%s' incompatible with readonly export", - arg->bitmap); + bitmap); goto fail; } bdrv_dirty_bitmap_set_busy(bm, true); exp->export_bitmap = bm; - assert(strlen(arg->bitmap) <= BDRV_BITMAP_MAX_NAME_SIZE); + assert(strlen(bitmap) <= BDRV_BITMAP_MAX_NAME_SIZE); exp->export_bitmap_context = g_strdup_printf("qemu:dirty-bitmap:%s", - arg->bitmap); + bitmap); assert(strlen(exp->export_bitmap_context) < NBD_MAX_STRING_SIZE); } diff --git a/qemu-nbd.c b/qemu-nbd.c index e3cff17d6760..8648a39d0ab9 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -572,7 +572,7 @@ int main(int argc, char **argv) const char *export_name = NULL; /* defaults to "" later for server mode */ const char *export_description = NULL; bool alloc_depth = false; - const char *bitmap = NULL; + strList *bitmaps = NULL, *tmp; const char *tlscredsid = NULL; bool imageOpts = false; bool writethrough = true; @@ -701,7 +701,10 @@ int main(int argc, char **argv) alloc_depth = true; break; case 'B': - bitmap = optarg; + tmp = g_new(strList, 1); + tmp->value = g_strdup(optarg); + tmp->next = bitmaps; + bitmaps = tmp; break; case 'k': sockpath = optarg; @@ -798,7 +801,7 @@ int main(int argc, char **argv) } if (export_name || export_description || dev_offset || device || disconnect || fmt || sn_id_or_name || alloc_depth || - bitmap || seen_aio || seen_discard || seen_cache) { + bitmaps || seen_aio || seen_discard || seen_cache) { error_report("List mode is incompatible with per-device settings"); exit(EXIT_FAILURE); } @@ -1082,8 +1085,8 @@ int main(int argc, char **argv) .name = g_strdup(export_name), .has_description = !!export_description, .description = g_strdup(export_description), - .has_bitmap = !!bitmap, - .bitmap = g_strdup(bitmap), + .has_bitmaps = !!bitmaps, + .bitmaps = bitmaps, .has_alloc = alloc_depth, .alloc = alloc_depth, }, From patchwork Fri Oct 9 02:07:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 303382 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0D426C433E7 for ; Fri, 9 Oct 2020 02:16:22 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3F5DA22255 for ; Fri, 9 Oct 2020 02:16:20 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="YyDFGE8S" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3F5DA22255 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:56630 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kQhxE-00058A-07 for qemu-devel@archiver.kernel.org; Thu, 08 Oct 2020 22:16:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33106) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kQhor-00068Y-3P for qemu-devel@nongnu.org; Thu, 08 Oct 2020 22:07:41 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:34539) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kQhog-0006sU-4M for qemu-devel@nongnu.org; Thu, 08 Oct 2020 22:07:40 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602209248; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=c1fuJa5ieggS4PhAR64buGO6f6hS+qiZSVSigdWVwXs=; b=YyDFGE8S1UT6BlC8bFX56XybNCokNZu4jJE3MWF7culVRHBuEhTgsrxDwqx3/HbcUQsL+8 ErbEs6zo2XUCHg0lSJsk/u+EorMMzugdxHCbmlystXmUM/wSIZZzL8SJG1EwYmGIpizhsU bkjJFQG7jaSwPL+qCGt+s/QyTDYtk1w= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-164-4fvjKXScNESPioRLWtuYRQ-1; Thu, 08 Oct 2020 22:07:24 -0400 X-MC-Unique: 4fvjKXScNESPioRLWtuYRQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 6148387951D; Fri, 9 Oct 2020 02:07:23 +0000 (UTC) Received: from blue.redhat.com (ovpn-113-14.phx2.redhat.com [10.3.113.14]) by smtp.corp.redhat.com (Postfix) with ESMTP id D674076650; Fri, 9 Oct 2020 02:07:22 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Subject: [PATCH v3 4/6] nbd: Simplify qemu bitmap context name Date: Thu, 8 Oct 2020 21:07:12 -0500 Message-Id: <20201009020714.1074061-5-eblake@redhat.com> In-Reply-To: <20201009020714.1074061-1-eblake@redhat.com> References: <20201009020714.1074061-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=eblake@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/08 01:56:49 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] 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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, 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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-block@nongnu.org, vsementsov@virtuozzo.com, rjones@redhat.com, stefanha@redhat.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Each dirty bitmap already knows its name; by reducing the scope of the places where we construct "qemu:dirty-bitmap:NAME" strings, tracking the name is more localized, and there are fewer per-export fields to worry about. This in turn will make it easier for an upcoming patch to export more than one bitmap at once. Signed-off-by: Eric Blake --- nbd/server.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index ea5de0b503cd..6326d6fe3f3a 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -97,7 +97,6 @@ struct NBDExport { bool alloc_context; BdrvDirtyBitmap *export_bitmap; - char *export_bitmap_context; }; static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports); @@ -882,14 +881,15 @@ static bool nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta, } if (nbd_strshift(&query, "dirty-bitmap:")) { + const char *bm_name; + trace_nbd_negotiate_meta_query_parse("dirty-bitmap:"); if (!meta->exp->export_bitmap) { trace_nbd_negotiate_meta_query_skip("no dirty-bitmap exported"); return true; } - if (nbd_meta_empty_or_pattern(client, - meta->exp->export_bitmap_context + - strlen("qemu:dirty-bitmap:"), query)) { + bm_name = bdrv_dirty_bitmap_name(meta->exp->export_bitmap); + if (nbd_meta_empty_or_pattern(client, bm_name, query)) { meta->bitmap = true; } return true; @@ -1025,8 +1025,11 @@ static int nbd_negotiate_meta_queries(NBDClient *client, } if (meta->bitmap) { - ret = nbd_negotiate_send_meta_context(client, - meta->exp->export_bitmap_context, + const char *bm_name = bdrv_dirty_bitmap_name(meta->exp->export_bitmap); + g_autofree char *context = g_strdup_printf("qemu:dirty-bitmap:%s", + bm_name); + + ret = nbd_negotiate_send_meta_context(client, context, NBD_META_ID_DIRTY_BITMAP, errp); if (ret < 0) { @@ -1599,9 +1602,6 @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args, bdrv_dirty_bitmap_set_busy(bm, true); exp->export_bitmap = bm; assert(strlen(bitmap) <= BDRV_BITMAP_MAX_NAME_SIZE); - exp->export_bitmap_context = g_strdup_printf("qemu:dirty-bitmap:%s", - bitmap); - assert(strlen(exp->export_bitmap_context) < NBD_MAX_STRING_SIZE); } exp->alloc_context = arg->alloc; @@ -1681,7 +1681,6 @@ static void nbd_export_delete(BlockExport *blk_exp) if (exp->export_bitmap) { bdrv_dirty_bitmap_set_busy(exp->export_bitmap, false); - g_free(exp->export_bitmap_context); } } From patchwork Fri Oct 9 02:07:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 271780 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0FF62C433DF for ; Fri, 9 Oct 2020 02:11:16 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6751F22255 for ; Fri, 9 Oct 2020 02:11:15 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="fdd893Yf" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6751F22255 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:48830 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kQhsI-0001l8-6R for qemu-devel@archiver.kernel.org; Thu, 08 Oct 2020 22:11:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33016) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kQhok-00064C-3I for qemu-devel@nongnu.org; Thu, 08 Oct 2020 22:07:34 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:59799) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kQhoe-0006rx-BF for qemu-devel@nongnu.org; Thu, 08 Oct 2020 22:07:33 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602209247; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vG0I0HjYl4mejjSAY6yzegAgNTK5VqTkPp1ggnR2ORk=; b=fdd893YfugqZxdEYilepn/NRQ1TT+AlG2EwOZMtUzDnoUTq/2JYaTwJYWumdUWS8/vnr/G l8RBLCmGPHdNMrFzksxsOf4qupDezpI+9HpgOy4ZWGs/y/DGPNTCVg0Dy+II9iT/yVliOk tAIvbfWq69nwyatGTIoc0Wg0QxP/m1s= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-571-Q6WsIC9dM6eVzZ-U6xUS0w-1; Thu, 08 Oct 2020 22:07:25 -0400 X-MC-Unique: Q6WsIC9dM6eVzZ-U6xUS0w-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1627518C520C; Fri, 9 Oct 2020 02:07:24 +0000 (UTC) Received: from blue.redhat.com (ovpn-113-14.phx2.redhat.com [10.3.113.14]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8D95976650; Fri, 9 Oct 2020 02:07:23 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Subject: [PATCH v3 5/6] nbd: Refactor counting of meta contexts Date: Thu, 8 Oct 2020 21:07:13 -0500 Message-Id: <20201009020714.1074061-6-eblake@redhat.com> In-Reply-To: <20201009020714.1074061-1-eblake@redhat.com> References: <20201009020714.1074061-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=eblake@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/08 22:07:25 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] 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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, 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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-block@nongnu.org, vsementsov@virtuozzo.com, rjones@redhat.com, stefanha@redhat.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Rather than open-code the count of negotiated contexts at several sites, embed it directly into the struct. Signed-off-by: Eric Blake --- nbd/server.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index 6326d6fe3f3a..3664f9e744b4 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -106,8 +106,7 @@ static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports); * NBD_OPT_LIST_META_CONTEXT. */ typedef struct NBDExportMetaContexts { NBDExport *exp; - bool valid; /* means that negotiation of the option finished without - errors */ + size_t count; /* number of negotiated contexts */ bool base_allocation; /* export base:allocation context (block status) */ bool allocation_depth; /* export qemu:allocation-depth */ bool bitmap; /* export qemu:dirty-bitmap: */ @@ -448,7 +447,9 @@ static int nbd_negotiate_handle_list(NBDClient *client, Error **errp) static void nbd_check_meta_export(NBDClient *client) { - client->export_meta.valid &= client->exp == client->export_meta.exp; + if (client->exp != client->export_meta.exp) { + client->export_meta.count = 0; + } } /* Send a reply to NBD_OPT_EXPORT_NAME. @@ -956,6 +957,7 @@ static int nbd_negotiate_meta_queries(NBDClient *client, NBDExportMetaContexts local_meta; uint32_t nb_queries; int i; + size_t count = 0; if (!client->structured_reply) { return nbd_opt_invalid(client, errp, @@ -1013,6 +1015,7 @@ static int nbd_negotiate_meta_queries(NBDClient *client, if (ret < 0) { return ret; } + count++; } if (meta->allocation_depth) { @@ -1022,6 +1025,7 @@ static int nbd_negotiate_meta_queries(NBDClient *client, if (ret < 0) { return ret; } + count++; } if (meta->bitmap) { @@ -1035,11 +1039,12 @@ static int nbd_negotiate_meta_queries(NBDClient *client, if (ret < 0) { return ret; } + count++; } ret = nbd_negotiate_send_rep(client, NBD_REP_ACK, errp); if (ret == 0) { - meta->valid = true; + meta->count = count; } return ret; @@ -2400,15 +2405,9 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, return nbd_send_generic_reply(client, request->handle, -EINVAL, "need non-zero length", errp); } - if (client->export_meta.valid && - (client->export_meta.base_allocation || - client->export_meta.allocation_depth || - client->export_meta.bitmap)) - { + if (client->export_meta.count) { bool dont_fragment = request->flags & NBD_CMD_FLAG_REQ_ONE; - int contexts_remaining = client->export_meta.base_allocation + - client->export_meta.allocation_depth + - client->export_meta.bitmap; + int contexts_remaining = client->export_meta.count; if (client->export_meta.base_allocation) { ret = nbd_co_send_block_status(client, request->handle, From patchwork Fri Oct 9 02:07:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 271779 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E388DC433E7 for ; Fri, 9 Oct 2020 02:13:32 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id F3CF322255 for ; Fri, 9 Oct 2020 02:13:31 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="LEzdxmN/" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F3CF322255 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:52612 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kQhuU-0003Ms-Md for qemu-devel@archiver.kernel.org; Thu, 08 Oct 2020 22:13:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33074) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kQhoo-00067C-P7 for qemu-devel@nongnu.org; Thu, 08 Oct 2020 22:07:38 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:49063) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kQhog-0006sB-2e for qemu-devel@nongnu.org; Thu, 08 Oct 2020 22:07:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602209247; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jnj9zIISjvynJAb3iL34smTPNKHTz5UdnoDisyXaetk=; b=LEzdxmN/2c9Ys+gXQF5381sjWcIghqYcNB4yVUFVRVilNDxZfxHXuooEJ+DweQfoTiq/5L rew+uSQvCIlH7ePEqo6TFTRnKlBD3U786fzxmZsk7dGrG8MCJvqLDRxXhk6bSMQaSm5wei SePPNoEwZiYt95l7oSDNWWhgFp1u0K8= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-583-gdennriqMnOyb5osbg190Q-1; Thu, 08 Oct 2020 22:07:25 -0400 X-MC-Unique: gdennriqMnOyb5osbg190Q-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id CA7D084A5F7; Fri, 9 Oct 2020 02:07:24 +0000 (UTC) Received: from blue.redhat.com (ovpn-113-14.phx2.redhat.com [10.3.113.14]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3F9FB76650; Fri, 9 Oct 2020 02:07:24 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Subject: [PATCH v3 6/6] nbd: Allow export of multiple bitmaps for one device Date: Thu, 8 Oct 2020 21:07:14 -0500 Message-Id: <20201009020714.1074061-7-eblake@redhat.com> In-Reply-To: <20201009020714.1074061-1-eblake@redhat.com> References: <20201009020714.1074061-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=eblake@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=216.205.24.124; envelope-from=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/08 22:07:25 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] 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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, 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.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, qemu-block@nongnu.org, rjones@redhat.com, Max Reitz , stefanha@redhat.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" With this, 'qemu-nbd -B b0 -B b1 -f qcow2 img.qcow2' can let you sniff out multiple bitmaps from one server. qemu-img as client can still only read one bitmap per client connection, but other NBD clients (hello libnbd) can now read multiple bitmaps in a single pass. Signed-off-by: Eric Blake --- nbd/server.c | 89 +++++++++++++++++++++++++++++------------- tests/qemu-iotests/291 | 6 +-- 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index 3664f9e744b4..0017e18254a3 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -96,7 +96,8 @@ struct NBDExport { Notifier eject_notifier; bool alloc_context; - BdrvDirtyBitmap *export_bitmap; + BdrvDirtyBitmap **export_bitmaps; + size_t nr_export_bitmaps; }; static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports); @@ -109,7 +110,10 @@ typedef struct NBDExportMetaContexts { size_t count; /* number of negotiated contexts */ bool base_allocation; /* export base:allocation context (block status) */ bool allocation_depth; /* export qemu:allocation-depth */ - bool bitmap; /* export qemu:dirty-bitmap: */ + bool *bitmaps; /* + * export qemu:dirty-bitmap:, + * sized by exp->nr_export_bitmaps + */ } NBDExportMetaContexts; struct NBDClient { @@ -861,6 +865,8 @@ static bool nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *meta, static bool nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta, const char *query) { + size_t i; + if (!nbd_strshift(&query, "qemu:")) { return false; } @@ -869,7 +875,7 @@ static bool nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta, if (!*query) { if (client->opt == NBD_OPT_LIST_META_CONTEXT) { meta->allocation_depth = meta->exp->alloc_context; - meta->bitmap = !!meta->exp->export_bitmap; + memset(meta->bitmaps, 1, meta->exp->nr_export_bitmaps); } trace_nbd_negotiate_meta_query_parse("empty"); return true; @@ -882,17 +888,26 @@ static bool nbd_meta_qemu_query(NBDClient *client, NBDExportMetaContexts *meta, } if (nbd_strshift(&query, "dirty-bitmap:")) { - const char *bm_name; - trace_nbd_negotiate_meta_query_parse("dirty-bitmap:"); - if (!meta->exp->export_bitmap) { - trace_nbd_negotiate_meta_query_skip("no dirty-bitmap exported"); + if (!*query) { + if (client->opt == NBD_OPT_LIST_META_CONTEXT) { + memset(meta->bitmaps, 1, meta->exp->nr_export_bitmaps); + } + trace_nbd_negotiate_meta_query_parse("empty"); return true; } - bm_name = bdrv_dirty_bitmap_name(meta->exp->export_bitmap); - if (nbd_meta_empty_or_pattern(client, bm_name, query)) { - meta->bitmap = true; + + for (i = 0; i < meta->exp->nr_export_bitmaps; i++) { + const char *bm_name; + + bm_name = bdrv_dirty_bitmap_name(meta->exp->export_bitmaps[i]); + if (strcmp(bm_name, query) == 0) { + meta->bitmaps[i] = true; + trace_nbd_negotiate_meta_query_parse(query); + return true; + } } + trace_nbd_negotiate_meta_query_skip("no dirty-bitmap match"); return true; } @@ -954,9 +969,10 @@ static int nbd_negotiate_meta_queries(NBDClient *client, { int ret; g_autofree char *export_name = NULL; - NBDExportMetaContexts local_meta; + g_autofree bool *bitmaps = NULL; + NBDExportMetaContexts local_meta = {0}; uint32_t nb_queries; - int i; + size_t i; size_t count = 0; if (!client->structured_reply) { @@ -971,6 +987,7 @@ static int nbd_negotiate_meta_queries(NBDClient *client, meta = &local_meta; } + g_free(meta->bitmaps); memset(meta, 0, sizeof(*meta)); ret = nbd_opt_read_name(client, &export_name, NULL, errp); @@ -985,6 +1002,10 @@ static int nbd_negotiate_meta_queries(NBDClient *client, return nbd_opt_drop(client, NBD_REP_ERR_UNKNOWN, errp, "export '%s' not present", sane_name); } + meta->bitmaps = g_new0(bool, meta->exp->nr_export_bitmaps); + if (client->opt == NBD_OPT_LIST_META_CONTEXT) { + bitmaps = meta->bitmaps; + } ret = nbd_opt_read(client, &nb_queries, sizeof(nb_queries), false, errp); if (ret <= 0) { @@ -998,7 +1019,7 @@ static int nbd_negotiate_meta_queries(NBDClient *client, /* enable all known contexts */ meta->base_allocation = true; meta->allocation_depth = meta->exp->alloc_context; - meta->bitmap = !!meta->exp->export_bitmap; + memset(meta->bitmaps, 1, meta->exp->nr_export_bitmaps); } else { for (i = 0; i < nb_queries; ++i) { ret = nbd_negotiate_meta_query(client, meta, errp); @@ -1028,13 +1049,19 @@ static int nbd_negotiate_meta_queries(NBDClient *client, count++; } - if (meta->bitmap) { - const char *bm_name = bdrv_dirty_bitmap_name(meta->exp->export_bitmap); - g_autofree char *context = g_strdup_printf("qemu:dirty-bitmap:%s", - bm_name); + for (i = 0; i < meta->exp->nr_export_bitmaps; i++) { + const char *bm_name; + g_autofree char *context = NULL; + + if (!meta->bitmaps[i]) { + continue; + } + + bm_name = bdrv_dirty_bitmap_name(meta->exp->export_bitmaps[i]); + context = g_strdup_printf("qemu:dirty-bitmap:%s", bm_name); ret = nbd_negotiate_send_meta_context(client, context, - NBD_META_ID_DIRTY_BITMAP, + NBD_META_ID_DIRTY_BITMAP + i, errp); if (ret < 0) { return ret; @@ -1388,6 +1415,7 @@ void nbd_client_put(NBDClient *client) QTAILQ_REMOVE(&client->exp->clients, client, next); blk_exp_unref(&client->exp->common); } + g_free(client->export_meta.bitmaps); g_free(client); } } @@ -1565,11 +1593,11 @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args, } exp->size = QEMU_ALIGN_DOWN(size, BDRV_SECTOR_SIZE); - /* XXX Allow more than one bitmap */ - if (arg->bitmaps && arg->bitmaps->next) { - error_setg(errp, "multiple bitmaps per export not supported yet"); - return -EOPNOTSUPP; + for (bitmaps = arg->bitmaps; bitmaps; bitmaps = bitmaps->next) { + exp->nr_export_bitmaps++; } + exp->export_bitmaps = g_new0(BdrvDirtyBitmap *, exp->nr_export_bitmaps); + exp->nr_export_bitmaps = 0; for (bitmaps = arg->bitmaps; bitmaps; bitmaps = bitmaps->next) { const char *bitmap = bitmaps->value; BlockDriverState *bs = blk_bs(blk); @@ -1605,7 +1633,7 @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args, } bdrv_dirty_bitmap_set_busy(bm, true); - exp->export_bitmap = bm; + exp->export_bitmaps[exp->nr_export_bitmaps++] = bm; assert(strlen(bitmap) <= BDRV_BITMAP_MAX_NAME_SIZE); } @@ -1667,6 +1695,7 @@ static void nbd_export_request_shutdown(BlockExport *blk_exp) static void nbd_export_delete(BlockExport *blk_exp) { + size_t i; NBDExport *exp = container_of(blk_exp, NBDExport, common); assert(exp->name == NULL); @@ -1684,8 +1713,8 @@ static void nbd_export_delete(BlockExport *blk_exp) blk_aio_detach, exp); } - if (exp->export_bitmap) { - bdrv_dirty_bitmap_set_busy(exp->export_bitmap, false); + for (i = 0; i < exp->nr_export_bitmaps; i++) { + bdrv_dirty_bitmap_set_busy(exp->export_bitmaps[i], false); } } @@ -2332,6 +2361,7 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, int flags; NBDExport *exp = client->exp; char *msg; + size_t i; switch (request->type) { case NBD_CMD_CACHE: @@ -2435,12 +2465,15 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, } } - if (client->export_meta.bitmap) { + for (i = 0; i < client->exp->nr_export_bitmaps; i++) { + if (!client->export_meta.bitmaps[i]) { + continue; + } ret = nbd_co_send_bitmap(client, request->handle, - client->exp->export_bitmap, + client->exp->export_bitmaps[i], request->from, request->len, dont_fragment, !--contexts_remaining, - NBD_META_ID_DIRTY_BITMAP, errp); + NBD_META_ID_DIRTY_BITMAP + i, errp); if (ret < 0) { return ret; } diff --git a/tests/qemu-iotests/291 b/tests/qemu-iotests/291 index 4f837b205655..37848ac60bba 100755 --- a/tests/qemu-iotests/291 +++ b/tests/qemu-iotests/291 @@ -107,16 +107,14 @@ echo # x-dirty-bitmap is a hack for reading bitmaps; it abuses block status to # report "data":false for portions of the bitmap which are set IMG="driver=nbd,server.type=unix,server.path=$nbd_unix_socket" -nbd_server_start_unix_socket -r -f qcow2 -B b0 "$TEST_IMG" +nbd_server_start_unix_socket -r -f qcow2 \ + -B b0 -B b1 -B b2 -B b3 "$TEST_IMG" $QEMU_IMG map --output=json --image-opts \ "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b0" | _filter_qemu_img_map -nbd_server_start_unix_socket -r -f qcow2 -B b1 "$TEST_IMG" $QEMU_IMG map --output=json --image-opts \ "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b1" | _filter_qemu_img_map -nbd_server_start_unix_socket -r -f qcow2 -B b2 "$TEST_IMG" $QEMU_IMG map --output=json --image-opts \ "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b2" | _filter_qemu_img_map -nbd_server_start_unix_socket -r -f qcow2 -B b3 "$TEST_IMG" $QEMU_IMG map --output=json --image-opts \ "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b3" | _filter_qemu_img_map