From patchwork Mon Jun 5 10:41:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Li X-Patchwork-Id: 13267196 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id DC614C77B73 for ; Mon, 5 Jun 2023 10:42:13 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1q67eO-0001zs-Gp; Mon, 05 Jun 2023 06:41:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1q67eN-0001zb-3q; Mon, 05 Jun 2023 06:41:23 -0400 Received: from mail-pl1-x62b.google.com ([2607:f8b0:4864:20::62b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1q67eL-0006o9-IC; Mon, 05 Jun 2023 06:41:22 -0400 Received: by mail-pl1-x62b.google.com with SMTP id d9443c01a7336-1b075e13a5eso40043445ad.3; Mon, 05 Jun 2023 03:41:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1685961679; x=1688553679; 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; bh=7Tls8VZU7Ofv7la2Mwd3gt97iymWk+im8mzONkVgbMc=; b=YgbImyHDTIJg+IxVCdgR0ntfeVKUbiWFU9OkxIzX5YYKxD5nlcZKiXYo22xgeqKped XigWHvM1XDpyBE92uowUqPjI/4wHSCxFMsmCpqC4lVhkdhYtMVqvFFgDABYa9ewtDOS2 PHonyzMMyd3zL/23xWknLPCzHGIv5i5FLqvgW+aNUHIxE0aaYQTgEgeskLTjOFPl9fUX NiC8o7LBWRslq/M4oS4X8CMIiMvQIXAvRN0lhy35OMzGzRs+HPYtD47Tm/M3x8RxuYmP AhF3FZRSm9a5qumgTaLNPZyU9XsucaAAC1KZWWBXZa6MvbtB9HQ/p/E8nN5XdyeuQCIJ LBYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685961679; x=1688553679; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7Tls8VZU7Ofv7la2Mwd3gt97iymWk+im8mzONkVgbMc=; b=Y5N478DJ3pwUMLgvt6r07EQYTPv79uYRH84ZpHW5e55GTSrAU08rBpLULSwUINF4x2 umqwz1f13tMqyY23QXZpbi7vZEcaqb5639fg1IIws8QGvq52tjEIpsBJj7jFJ82BA5aS e2N85cqn5c8DZO/W072/fb9zAMO55PoDDsA7APGoSBzY2nbrmPVRmQMvpUA/99scyFfM CZkA3UN/f6tZH4ghT/0LHsP2LNIFlKIxujFQPsZwGGQ89iva0etUqw5H7DwgROolV/kY xxcdCpwa6Jow7reTJUopEuEAMy4ZLBNNhbZNINnGcFhlGX77YBHdug7av0CLYz4/PQ1t OcCQ== X-Gm-Message-State: AC+VfDysV5WwpcLxjFbNZgTGHR7ZAcHTQmyMI53KV5tgiSzAfa/c/SQ3 PPwzOtnebRIcMD6wrq5mgUohwfzxJbyNT8HO X-Google-Smtp-Source: ACHHUZ7sgsE/AXoKOFn3Kzn35zWWE8dmdnioEXjfeS2pQ/eDzYUUHQYJVNRh1Yo1wnrzxGEfpX7Hkw== X-Received: by 2002:a17:903:32c6:b0:1ad:cba5:5505 with SMTP id i6-20020a17090332c600b001adcba55505mr7989831plr.14.1685961679078; Mon, 05 Jun 2023 03:41:19 -0700 (PDT) Received: from fedlinux.. ([106.84.132.130]) by smtp.gmail.com with ESMTPSA id x4-20020a170902a38400b001b0457705e8sm6340141pla.140.2023.06.05.03.41.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Jun 2023 03:41:18 -0700 (PDT) From: Sam Li To: qemu-devel@nongnu.org Cc: dlemoal@kernel.org, dmitry.fomichev@wdc.com, hare@suse.de, stefanha@redhat.com, Markus Armbruster , Kevin Wolf , qemu-block@nongnu.org, Eric Blake , Hanna Reitz , Sam Li Subject: [RFC 1/4] docs/qcow2: add the zoned format feature Date: Mon, 5 Jun 2023 18:41:05 +0800 Message-Id: <20230605104108.125270-2-faithilikerun@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230605104108.125270-1-faithilikerun@gmail.com> References: <20230605104108.125270-1-faithilikerun@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::62b; envelope-from=faithilikerun@gmail.com; helo=mail-pl1-x62b.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, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add the specs for the zoned format feature of the qcow2 driver. Once the zoned_profile is set to `zbc`, then the qcow2 file can be taken as zoned devices and passed through by virtio-blk device to the guest. Signed-off-by: Sam Li --- docs/system/qemu-block-drivers.rst.inc | 31 ++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/system/qemu-block-drivers.rst.inc b/docs/system/qemu-block-drivers.rst.inc index 105cb9679c..fdcf343652 100644 --- a/docs/system/qemu-block-drivers.rst.inc +++ b/docs/system/qemu-block-drivers.rst.inc @@ -172,6 +172,37 @@ This section describes each format and the options that are supported for it. filename`` to check if the NOCOW flag is set or not (Capital 'C' is NOCOW flag). + .. option:: zoned_profile + + The option configures the zoned format feature on the qcow2 driver. If + this is set to ``zbc``, then it follows the basics of ZBC/ZAC protocol. + + .. option:: zone_size + + The size of a zone of the zoned device. The zoned device have the same + size of zones with an optional smaller last zone. + + .. option:: zone_capacity + + The capacity of a zone of the zoned device. The zoned device follows the + ZBC protocol tends to have the same size as its zone. + + .. option:: zone_nr_conv + + The number of conventional zones of the zoned device. + + .. option:: max_open_zones + + The maximal allowed open zones. + + .. option:: max_active_zones + + The limit of the zones with implicit open, explicit open or closed state. + + .. option:: max_append_sectors + + The maximal sectors that is allowed to append to zones while writing. + .. program:: image-formats .. option:: qed From patchwork Mon Jun 5 10:41:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Li X-Patchwork-Id: 13267195 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id E0D3FC7EE23 for ; Mon, 5 Jun 2023 10:41:58 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1q67eS-00020f-KL; Mon, 05 Jun 2023 06:41:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1q67eR-00020T-Tb; Mon, 05 Jun 2023 06:41:27 -0400 Received: from mail-pl1-x634.google.com ([2607:f8b0:4864:20::634]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1q67eP-0006oP-MM; Mon, 05 Jun 2023 06:41:27 -0400 Received: by mail-pl1-x634.google.com with SMTP id d9443c01a7336-1b01bd7093aso22536655ad.1; Mon, 05 Jun 2023 03:41:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1685961683; x=1688553683; 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; bh=goJTDxs9Xmuwyx0WBKSy9HD+21mMLbHbT04tNXq0RDo=; b=jDa1fy/WXmYDNv5Gf5KiDirJG5luqMfErsyspYykpzsTcEUyT0xKBL4FCogRZBDO6t hPfKDQqOK4pH6NMrMe1fndd3MnfDNgnBQRQ6vng6RuaQw7tT19tgIkZ08sSt4HYbLa3y WpEiyUhYz7+J4fzTAR/8l4ctAxjVS18mHBBXdrcO5tkc1xmQLi+7jk+VPib3QKrRLRQs XNB5IbAfqQZMzjg/V4E8zjmimrcHH6xzw72Vbct+ICZJBfv8zWUnQSkdxavGeFAeq/PF pwwHPF4HurVVYj0z+BurNFU+ykmIRUdaEbllrxlc4Zp2jjtF7ZL6JIEcfgfw8hAOmPJY 9hUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685961683; x=1688553683; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=goJTDxs9Xmuwyx0WBKSy9HD+21mMLbHbT04tNXq0RDo=; b=Og79puopk4FU2gQc7QJABdh9ZlQacGqfEfkTfLZybaTOR5GdizmhSpn1sGPxP+vaOJ q03WLs8HHg/pHV8v73emr4/xgDeWyAiUt8xDcWyLgTPGnvhOSooXqIRGe+Dki7knKsiO Sz/imHAM+GkZU9RpSZObAeMuZOU3BWoNGqWVUVaA46j6fw9/+JIL4Xmk0k38B7Z0oZog TAGvU2i4zUebbKUISmnuOA8R5/k9q64QzUNIF1xA2X8hf05vzi2uyldkFoOYLM98sabL HG7DxIY7x3WPYMFykNdTfSCJ0eJCDMCXg0EAkfBYznirIfFZTRA818k9Z5XDAjyRYIAx I6pg== X-Gm-Message-State: AC+VfDznECrR+U3UzXWSlcbekHS5+QTuMyfMPYCfMia69+J/1stBfJtE ZnKfaU9DtLwtHs8ATSATbFjdK/lYJ8UhoNTS X-Google-Smtp-Source: ACHHUZ6obgohunX4fSDI49eieJ1ibAXItmgzbl+Eokssi05F8atZFxEfLzJyloIjoP7FC9r2DwxUMw== X-Received: by 2002:a17:902:e74a:b0:1b0:21c4:7272 with SMTP id p10-20020a170902e74a00b001b021c47272mr3754732plf.46.1685961683015; Mon, 05 Jun 2023 03:41:23 -0700 (PDT) Received: from fedlinux.. ([106.84.132.130]) by smtp.gmail.com with ESMTPSA id x4-20020a170902a38400b001b0457705e8sm6340141pla.140.2023.06.05.03.41.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Jun 2023 03:41:22 -0700 (PDT) From: Sam Li To: qemu-devel@nongnu.org Cc: dlemoal@kernel.org, dmitry.fomichev@wdc.com, hare@suse.de, stefanha@redhat.com, Markus Armbruster , Kevin Wolf , qemu-block@nongnu.org, Eric Blake , Hanna Reitz , Sam Li Subject: [RFC 2/4] qcow2: add configurations for zoned format extension Date: Mon, 5 Jun 2023 18:41:06 +0800 Message-Id: <20230605104108.125270-3-faithilikerun@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230605104108.125270-1-faithilikerun@gmail.com> References: <20230605104108.125270-1-faithilikerun@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::634; envelope-from=faithilikerun@gmail.com; helo=mail-pl1-x634.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, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org To configure the zoned format feature on the qcow2 driver, it requires following arguments: the device size, zoned profile, zoned model, zone size, zone capacity, number of conventional zones, limits on zone resources (max append sectors, max open zones, and max_active_zones). To create a qcow2 file with zoned format, use command like this: $ qemu-img create -f qcow2 test.qcow2 -o size=768M -o zone_size=64M -o zone_capacity=64M -o zone_nr_conv=0 -o max_append_sectors=512 -o max_open_zones=0 -o max_active_zones=0 -o zoned_profile=zbc Signed-off-by: Sam Li --- block/qcow2.c | 119 +++++++++++++++++++++++++++++++ block/qcow2.h | 21 ++++++ include/block/block-common.h | 5 ++ include/block/block_int-common.h | 8 +++ qapi/block-core.json | 46 ++++++++---- 5 files changed, 185 insertions(+), 14 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 7f3948360d..b886dab42b 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -73,6 +73,7 @@ typedef struct { #define QCOW2_EXT_MAGIC_CRYPTO_HEADER 0x0537be77 #define QCOW2_EXT_MAGIC_BITMAPS 0x23852875 #define QCOW2_EXT_MAGIC_DATA_FILE 0x44415441 +#define QCOW2_EXT_MAGIC_ZONED_FORMAT 0x7a6264 static int coroutine_fn qcow2_co_preadv_compressed(BlockDriverState *bs, @@ -210,6 +211,7 @@ qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, uint64_t offset; int ret; Qcow2BitmapHeaderExt bitmaps_ext; + Qcow2ZonedHeaderExtension zoned_ext; if (need_update_header != NULL) { *need_update_header = false; @@ -431,6 +433,37 @@ qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, break; } + case QCOW2_EXT_MAGIC_ZONED_FORMAT: + { + if (ext.len != sizeof(zoned_ext)) { + error_setg_errno(errp, -ret, "zoned_ext: " + "Invalid extension length"); + return -EINVAL; + } + ret = bdrv_pread(bs->file, offset, ext.len, &zoned_ext, 0); + if (ret < 0) { + error_setg_errno(errp, -ret, "zoned_ext: " + "Could not read ext header"); + return ret; + } + + zoned_ext.zone_size = be32_to_cpu(zoned_ext.zone_size); + zoned_ext.nr_zones = be32_to_cpu(zoned_ext.nr_zones); + zoned_ext.zone_nr_conv = be32_to_cpu(zoned_ext.zone_nr_conv); + zoned_ext.max_open_zones = be32_to_cpu(zoned_ext.max_open_zones); + zoned_ext.max_active_zones = + be32_to_cpu(zoned_ext.max_active_zones); + zoned_ext.max_append_sectors = + be32_to_cpu(zoned_ext.max_append_sectors); + s->zoned_header = zoned_ext; + +#ifdef DEBUG_EXT + printf("Qcow2: Got zoned format extension: " + "offset=%" PRIu32 "\n", offset); +#endif + break; + } + default: /* unknown magic - save it in case we need to rewrite the header */ /* If you add a new feature, make sure to also update the fast @@ -3071,6 +3104,31 @@ int qcow2_update_header(BlockDriverState *bs) buflen -= ret; } + /* Zoned devices header extension */ + if (s->zoned_header.zoned == BLK_Z_HM) { + Qcow2ZonedHeaderExtension zoned_header = { + .zoned_profile = s->zoned_header.zoned_profile, + .zoned = s->zoned_header.zoned, + .nr_zones = cpu_to_be32(s->zoned_header.nr_zones), + .zone_size = cpu_to_be32(s->zoned_header.zone_size), + .zone_capacity = cpu_to_be32(s->zoned_header.zone_capacity), + .zone_nr_conv = cpu_to_be32(s->zoned_header.zone_nr_conv), + .max_open_zones = cpu_to_be32(s->zoned_header.max_open_zones), + .max_active_zones = + cpu_to_be32(s->zoned_header.max_active_zones), + .max_append_sectors = + cpu_to_be32(s->zoned_header.max_append_sectors) + }; + ret = header_ext_add(buf, QCOW2_EXT_MAGIC_ZONED_FORMAT, + &zoned_header, sizeof(zoned_header), + buflen); + if (ret < 0) { + goto fail; + } + buf += ret; + buflen -= ret; + } + /* Keep unknown header extensions */ QLIST_FOREACH(uext, &s->unknown_header_ext, next) { ret = header_ext_add(buf, uext->magic, uext->data, uext->len, buflen); @@ -3755,6 +3813,18 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) s->image_data_file = g_strdup(data_bs->filename); } + if (!strcmp(qcow2_opts->zoned_profile, "zbc")) { + BDRVQcow2State *s = blk_bs(blk)->opaque; + s->zoned_header.zoned_profile = BLK_ZP_ZBC; + s->zoned_header.zoned = BLK_Z_HM; + s->zoned_header.zone_size = qcow2_opts->zone_size; + s->zoned_header.zone_capacity = qcow2_opts->zone_capacity; + s->zoned_header.zone_nr_conv = qcow2_opts->zone_nr_conv; + s->zoned_header.max_open_zones = qcow2_opts->max_open_zones; + s->zoned_header.max_active_zones = qcow2_opts->max_active_zones; + s->zoned_header.max_append_sectors = qcow2_opts->max_append_sectors; + } + /* Create a full header (including things like feature table) */ ret = qcow2_update_header(blk_bs(blk)); bdrv_graph_co_rdunlock(); @@ -3873,6 +3943,13 @@ qcow2_co_create_opts(BlockDriver *drv, const char *filename, QemuOpts *opts, qdict_put_str(qdict, BLOCK_OPT_COMPAT_LEVEL, "v3"); } + /* The available zoned-profile options are zbc, which stands for + * ZBC/ZAC standards, and zns following NVMe ZNS spec. */ + val = qdict_get_try_str(qdict, BLOCK_OPT_Z_PROFILE); + if (val) { + qdict_put_str(qdict, BLOCK_OPT_Z_PROFILE, val); + } + /* Change legacy command line options into QMP ones */ static const QDictRenames opt_renames[] = { { BLOCK_OPT_BACKING_FILE, "backing-file" }, @@ -3885,6 +3962,13 @@ qcow2_co_create_opts(BlockDriver *drv, const char *filename, QemuOpts *opts, { BLOCK_OPT_COMPAT_LEVEL, "version" }, { BLOCK_OPT_DATA_FILE_RAW, "data-file-raw" }, { BLOCK_OPT_COMPRESSION_TYPE, "compression-type" }, + { BLOCK_OPT_Z_PROFILE, "zoned-profile"}, + { BLOCK_OPT_Z_NR_COV, "zone-nr-conv"}, + { BLOCK_OPT_Z_MOZ, "max-open-zones"}, + { BLOCK_OPT_Z_MAZ, "max-active-zones"}, + { BLOCK_OPT_Z_MAS, "max-append-sectors"}, + { BLOCK_OPT_Z_SIZE, "zone-size"}, + { BLOCK_OPT_Z_CAP, "zone-capacity"}, { NULL, NULL }, }; @@ -6048,6 +6132,41 @@ static QemuOptsList qcow2_create_opts = { .help = "Compression method used for image cluster " \ "compression", \ .def_value_str = "zlib" \ + }, \ + { + .name = BLOCK_OPT_Z_PROFILE, \ + .type = QEMU_OPT_STRING, \ + .help = "zoned format option for the disk img", \ + }, \ + { \ + .name = BLOCK_OPT_Z_SIZE, \ + .type = QEMU_OPT_SIZE, \ + .help = "zone size", \ + }, \ + { \ + .name = BLOCK_OPT_Z_CAP, \ + .type = QEMU_OPT_SIZE, \ + .help = "zone capacity", \ + }, \ + { \ + .name = BLOCK_OPT_Z_NR_COV, \ + .type = QEMU_OPT_NUMBER, \ + .help = "numbers of conventional zones", \ + }, \ + { \ + .name = BLOCK_OPT_Z_MAS, \ + .type = QEMU_OPT_NUMBER, \ + .help = "max append sectors", \ + }, \ + { \ + .name = BLOCK_OPT_Z_MAZ, \ + .type = QEMU_OPT_NUMBER, \ + .help = "max active zones", \ + }, \ + { \ + .name = BLOCK_OPT_Z_MOZ, \ + .type = QEMU_OPT_NUMBER, \ + .help = "max open zones", \ }, QCOW_COMMON_OPTIONS, { /* end of list */ } diff --git a/block/qcow2.h b/block/qcow2.h index 4f67eb912a..fe18dc4d97 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -235,6 +235,20 @@ typedef struct Qcow2CryptoHeaderExtension { uint64_t length; } QEMU_PACKED Qcow2CryptoHeaderExtension; +typedef struct Qcow2ZonedHeaderExtension { + /* Zoned device attributes */ + BlockZonedProfile zoned_profile; + BlockZoneModel zoned; + uint32_t zone_size; + uint32_t zone_capacity; + uint32_t nr_zones; + uint32_t zone_nr_conv; + uint32_t max_active_zones; + uint32_t max_open_zones; + uint32_t max_append_sectors; + uint8_t padding[3]; +} QEMU_PACKED Qcow2ZonedHeaderExtension; + typedef struct Qcow2UnknownHeaderExtension { uint32_t magic; uint32_t len; @@ -419,6 +433,13 @@ typedef struct BDRVQcow2State { * is to convert the image with the desired compression type set. */ Qcow2CompressionType compression_type; + + /* States of zoned device */ + Qcow2ZonedHeaderExtension zoned_header; + uint32_t nr_zones_exp_open; + uint32_t nr_zones_imp_open; + uint32_t nr_zones_closed; + BlockZoneWps *wps; } BDRVQcow2State; typedef struct Qcow2COWRegion { diff --git a/include/block/block-common.h b/include/block/block-common.h index e15395f2cb..9f04a772f6 100644 --- a/include/block/block-common.h +++ b/include/block/block-common.h @@ -108,6 +108,11 @@ typedef enum BlockZoneType { BLK_ZT_SWP = 0x3, /* Sequential writes preferred */ } BlockZoneType; +typedef enum BlockZonedProfile { + BLK_ZP_ZBC = 0x1, + BLK_ZP_ZNS = 0x2, +} BlockZonedProfile; + /* * Zone descriptor data structure. * Provides information on a zone with all position and size values in bytes. diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 74195c3004..4be35feaf8 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -57,6 +57,14 @@ #define BLOCK_OPT_DATA_FILE_RAW "data_file_raw" #define BLOCK_OPT_COMPRESSION_TYPE "compression_type" #define BLOCK_OPT_EXTL2 "extended_l2" +#define BLOCK_OPT_Z_PROFILE "zoned_profile" +#define BLOCK_OPT_Z_MODEL "zoned" +#define BLOCK_OPT_Z_SIZE "zone_size" +#define BLOCK_OPT_Z_CAP "zone_capacity" +#define BLOCK_OPT_Z_NR_COV "zone_nr_conv" +#define BLOCK_OPT_Z_MAS "max_append_sectors" +#define BLOCK_OPT_Z_MAZ "max_active_zones" +#define BLOCK_OPT_Z_MOZ "max_open_zones" #define BLOCK_PROBE_BUF_SIZE 512 diff --git a/qapi/block-core.json b/qapi/block-core.json index 4bf89171c6..f9a584cbb3 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -5013,24 +5013,42 @@ # # @compression-type: The image cluster compression method # (default: zlib, since 5.1) +# @zoned-profile: Two zoned device protocol options, zbc or zns +# (default: off, since 8.0) +# @zone-size: The size of a zone of the zoned device (since 8.0) +# @zone-capacity: The capacity of a zone of the zoned device (since 8.0) +# @zone-nr-conv: The number of conventional zones of the zoned device +# (since 8.0) +# @max-open-zones: The maximal allowed open zones (since 8.0) +# @max-active-zones: The limit of the zones that have the implicit open, +# explicit open or closed state (since 8.0) +# @max-append-sectors: The maximal sectors that is allowed to append write +# (since 8.0) # # Since: 2.12 ## { 'struct': 'BlockdevCreateOptionsQcow2', - 'data': { 'file': 'BlockdevRef', - '*data-file': 'BlockdevRef', - '*data-file-raw': 'bool', - '*extended-l2': 'bool', - 'size': 'size', - '*version': 'BlockdevQcow2Version', - '*backing-file': 'str', - '*backing-fmt': 'BlockdevDriver', - '*encrypt': 'QCryptoBlockCreateOptions', - '*cluster-size': 'size', - '*preallocation': 'PreallocMode', - '*lazy-refcounts': 'bool', - '*refcount-bits': 'int', - '*compression-type':'Qcow2CompressionType' } } + 'data': { 'file': 'BlockdevRef', + '*data-file': 'BlockdevRef', + '*data-file-raw': 'bool', + '*extended-l2': 'bool', + 'size': 'size', + '*version': 'BlockdevQcow2Version', + '*backing-file': 'str', + '*backing-fmt': 'BlockdevDriver', + '*encrypt': 'QCryptoBlockCreateOptions', + '*cluster-size': 'size', + '*preallocation': 'PreallocMode', + '*lazy-refcounts': 'bool', + '*refcount-bits': 'int', + '*compression-type': 'Qcow2CompressionType', + '*zoned-profile': 'str', + '*zone-size': 'size', + '*zone-capacity': 'size', + '*zone-nr-conv': 'uint32', + '*max-open-zones': 'uint32', + '*max-active-zones': 'uint32', + '*max-append-sectors': 'uint32'}} ## # @BlockdevCreateOptionsQed: From patchwork Mon Jun 5 10:41:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Li X-Patchwork-Id: 13267197 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 3B4A1C7EE23 for ; Mon, 5 Jun 2023 10:42:17 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1q67eZ-00022B-F3; Mon, 05 Jun 2023 06:41:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1q67eX-00021Q-Bz; Mon, 05 Jun 2023 06:41:33 -0400 Received: from mail-pl1-x629.google.com ([2607:f8b0:4864:20::629]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1q67eT-0006od-J2; Mon, 05 Jun 2023 06:41:33 -0400 Received: by mail-pl1-x629.google.com with SMTP id d9443c01a7336-1b011cffe7fso20104255ad.1; Mon, 05 Jun 2023 03:41:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1685961687; x=1688553687; 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; bh=zCAZUXLTmeQ5Y3VDSmv2i0uPn/Bo4eQsubZogaxs//c=; b=brW1iIpjn1F1L9odnsJSGXr1L7CB3O3mPLadETBQ5hSspwRbavUNNNlFb/w5xg/Oxy KBmDjiaCV01tBPt/SWwgOHGNmvpHV2sjDBeq+l+P/PZ+ZcH4VDFIq86yprcy6b/n6iU4 o1x2aJGaI3gfh2SK7FeXE4ajnXPppnjpehMfclrwOQmuzGwZxZQhCj2sJNZy5gDAouHk tyGmC1bUEgew7qCkcPSUr32mfzpw2++N/6S8ZJ8gFBOmivV16kcRyktqid2vgrPT5NQZ bW1vAKmgv488nLm+IRzsBBP/JlFhV3CBgcliriK4Asokljl8QMv9yWIGL3lONHG+Yhzz P7Fg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685961687; x=1688553687; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zCAZUXLTmeQ5Y3VDSmv2i0uPn/Bo4eQsubZogaxs//c=; b=bJmF0D7/dfa0jliU+ryqwS17I42bHh7WMn3AQzFZWZLAXNs/hE07TRD/0XwunKOJq9 dCOH0dQBB3P9jSb4p9g1eR8k5a1D0EnlH6FeiqzQBju6gycFZF/px6I32rNQ7/eMUGGk cTv6q/tuf/DnIhiFHR6C+fxN+oZ+nunCApGkxTDUQu5iTWKw3AUtFdkz15ZiyiKQUTGm 96Y/lXcQvJ1CKhBGXPDTDN4/4Ucw+l6/jWkJ4qT23csn3miBNKvbSkFvlovasSkPthwN 3bwonVWPqE11wajyzRAaJpPzTCYXO77uZ8xa1a5u3rB6zz87o1qL3Ne1vqNXmoQh2mWu 1BJg== X-Gm-Message-State: AC+VfDwJDkiQxY1lFrOrV/Y7uDvSl5cDafzZiA5RgZGZ2Yu84D7A91K3 9obnwS1LtDzbqyiGduPybwliG/B1r4bLyOlI X-Google-Smtp-Source: ACHHUZ510+PiOoLIxjTOUOqT18HguapbDHZA0v9XzZMHQD7CScvirCnDeV8FrfJBDXne/5+Jaj5taA== X-Received: by 2002:a17:902:d502:b0:1b0:2f03:8581 with SMTP id b2-20020a170902d50200b001b02f038581mr2694211plg.44.1685961686839; Mon, 05 Jun 2023 03:41:26 -0700 (PDT) Received: from fedlinux.. ([106.84.132.130]) by smtp.gmail.com with ESMTPSA id x4-20020a170902a38400b001b0457705e8sm6340141pla.140.2023.06.05.03.41.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Jun 2023 03:41:26 -0700 (PDT) From: Sam Li To: qemu-devel@nongnu.org Cc: dlemoal@kernel.org, dmitry.fomichev@wdc.com, hare@suse.de, stefanha@redhat.com, Markus Armbruster , Kevin Wolf , qemu-block@nongnu.org, Eric Blake , Hanna Reitz , Sam Li Subject: [RFC 3/4] qcow2: add zoned emulation capability Date: Mon, 5 Jun 2023 18:41:07 +0800 Message-Id: <20230605104108.125270-4-faithilikerun@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230605104108.125270-1-faithilikerun@gmail.com> References: <20230605104108.125270-1-faithilikerun@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::629; envelope-from=faithilikerun@gmail.com; helo=mail-pl1-x629.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, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org By adding zone operations and zoned metadata, the zoned emulation capability enables full emulation support of zoned device using a qcow2 file. The zoned device metadata includes zone type, zoned device state and write pointer of each zone, which is stored to an array of unsigned integers. Each zone of a zoned device makes state transitions following the zone state machine. The zone state machine mainly describes five states, IMPLICIT OPEN, EXPLICIT OPEN, FULL, EMPTY and CLOSED. READ ONLY and OFFLINE states will generally be affected by device internal events. The operations on zones cause corresponding state changing. Zoned devices have a limit on zone resources, which puts constraints on write operations into zones. Signed-off-by: Sam Li --- block/qcow2.c | 629 +++++++++++++++++++++++++++++++++++++++++++++++++- block/qcow2.h | 2 + 2 files changed, 629 insertions(+), 2 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index b886dab42b..f030965d5d 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -194,6 +194,164 @@ qcow2_extract_crypto_opts(QemuOpts *opts, const char *fmt, Error **errp) return cryptoopts_qdict; } +#define QCOW2_ZT_IS_CONV(wp) (wp & 1ULL << 59) + +static inline int qcow2_get_wp(uint64_t wp) +{ + /* clear state and type information */ + return ((wp << 5) >> 5); +} + +static inline int qcow2_get_zs(uint64_t wp) +{ + return (wp >> 60); +} + +static inline void qcow2_set_wp(uint64_t *wp, BlockZoneState zs) +{ + uint64_t addr = qcow2_get_wp(*wp); + addr |= ((uint64_t)zs << 60); + *wp = addr; +} + +/* + * File wp tracking: reset zone, finish zone and append zone can + * change the value of write pointer. All zone operations will change + * the state of that/those zone. + * */ +static inline void qcow2_wp_tracking_helper(int index, uint64_t wp) { + /* format: operations, the wp. */ + printf("wps[%d]: 0x%x\n", index, qcow2_get_wp(wp)>>BDRV_SECTOR_BITS); +} + +/* + * Perform a state assignment and a flush operation that writes the new wp + * value to the dedicated location of the disk file. + */ +static int qcow2_write_wp_at(BlockDriverState *bs, uint64_t *wp, + uint32_t index, BlockZoneState zs) { + BDRVQcow2State *s = bs->opaque; + int ret; + + qcow2_set_wp(wp, zs); + ret = bdrv_pwrite(bs->file, s->zoned_header.zonedmeta_offset + + sizeof(uint64_t) * index, sizeof(uint64_t), wp, 0); + + if (ret < 0) { + goto exit; + } + qcow2_wp_tracking_helper(index, *wp); + return ret; + +exit: + error_report("Failed to write metadata with file"); + return ret; +} + +static int qcow2_check_active(BlockDriverState *bs) +{ + BDRVQcow2State *s = bs->opaque; + + if (!s->zoned_header.max_active_zones) { + return 0; + } + + if (s->nr_zones_exp_open + s->nr_zones_imp_open + s->nr_zones_closed + < s->zoned_header.max_active_zones) { + return 0; + } + + return -1; +} + +static int qcow2_check_open(BlockDriverState *bs) +{ + BDRVQcow2State *s = bs->opaque; + int ret; + + if (!s->zoned_header.max_open_zones) { + return 0; + } + + if (s->nr_zones_exp_open + s->nr_zones_imp_open + < s->zoned_header.max_open_zones) { + return 0; + } + + if(s->nr_zones_imp_open) { + ret = qcow2_check_active(bs); + if (ret == 0) { + /* TODO: it takes O(n) time complexity (n = nr_zones). + * Optimizations required. */ + /* close one implicitly open zones to make it available */ + for (int i = s->zoned_header.zone_nr_conv; + i < bs->bl.nr_zones; ++i) { + uint64_t *wp = &s->wps->wp[i]; + if (qcow2_get_zs(*wp) == BLK_ZS_IOPEN) { + ret = qcow2_write_wp_at(bs, wp, i, BLK_ZS_CLOSED); + if (ret < 0) { + return ret; + } + s->wps->wp[i] = *wp; + s->nr_zones_imp_open--; + s->nr_zones_closed++; + break; + } + } + return 0; + } + return ret; + } + + return -1; +} + +/* + * The zoned device has limited zone resources of open, closed, active + * zones. + */ +static int qcow2_check_zone_resources(BlockDriverState *bs, + BlockZoneState zs) +{ + int ret; + + switch (zs) { + case BLK_ZS_EMPTY: + ret = qcow2_check_active(bs); + if (ret < 0) { + error_report("No enough active zones"); + return ret; + } + return ret; + case BLK_ZS_CLOSED: + ret = qcow2_check_open(bs); + if (ret < 0) { + error_report("No enough open zones"); + return ret; + } + return ret; + default: + return -EINVAL; + } + +} + +static inline int qcow2_refresh_zonedmeta(BlockDriverState *bs) +{ + int ret; + BDRVQcow2State *s = bs->opaque; + uint64_t *temp = g_malloc(s->zoned_header.zonedmeta_size); + ret = bdrv_pread(bs->file, s->zoned_header.zonedmeta_offset, + s->zoned_header.zonedmeta_size, temp, 0); + if (ret < 0) { + error_report("Can not read metadata\n"); + return ret; + } + + memcpy(s->wps->wp, temp, s->zoned_header.zonedmeta_size); + return 0; +} + /* * read qcow2 extension and fill bs * start reading from start_offset @@ -455,7 +613,19 @@ qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, be32_to_cpu(zoned_ext.max_active_zones); zoned_ext.max_append_sectors = be32_to_cpu(zoned_ext.max_append_sectors); + zoned_ext.zonedmeta_offset = + be64_to_cpu(zoned_ext.zonedmeta_offset); + zoned_ext.zonedmeta_size = be64_to_cpu(zoned_ext.zonedmeta_size); s->zoned_header = zoned_ext; + s->wps = g_malloc(sizeof(BlockZoneWps) + + s->zoned_header.zonedmeta_size); + ret = qcow2_refresh_zonedmeta(bs); + if (ret < 0) { + error_setg_errno(errp, -ret, "zonedmeta: " + "Could not update zoned meta"); + return ret; + } + qemu_co_mutex_init(&s->wps->colock); #ifdef DEBUG_EXT printf("Qcow2: Got zoned format extension: " @@ -1982,6 +2152,14 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp) } bs->bl.pwrite_zeroes_alignment = s->subcluster_size; bs->bl.pdiscard_alignment = s->cluster_size; + bs->bl.zoned = s->zoned_header.zoned; + bs->bl.nr_zones = s->zoned_header.nr_zones; + bs->wps = s->wps; + bs->bl.max_append_sectors = s->zoned_header.max_append_sectors; + bs->bl.max_active_zones = s->zoned_header.max_active_zones; + bs->bl.max_open_zones = s->zoned_header.max_open_zones; + bs->bl.zone_size = s->zoned_header.zone_size; + bs->bl.write_granularity = BDRV_SECTOR_SIZE; } static int qcow2_reopen_prepare(BDRVReopenState *state, @@ -2672,9 +2850,26 @@ qcow2_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes, uint64_t host_offset; QCowL2Meta *l2meta = NULL; AioTaskPool *aio = NULL; + int64_t start_offset, start_bytes; + BlockZoneState zs; + int64_t end; + uint64_t *wp; + int64_t zone_size = bs->bl.zone_size; + int index; trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes); + start_offset = offset; + start_bytes = bytes; + /* The offset should not less than the wp of that + * zone where offset starts. */ + if (zone_size) { + index = start_offset / zone_size; + wp = &s->wps->wp[index]; + if (offset < qcow2_get_wp(*wp)) { + return -EINVAL; + } + } while (bytes != 0 && aio_task_pool_status(aio) == 0) { l2meta = NULL; @@ -2720,6 +2915,47 @@ qcow2_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes, qiov_offset += cur_bytes; trace_qcow2_writev_done_part(qemu_coroutine_self(), cur_bytes); } + + if (zone_size) { + index = start_offset / zone_size; + wp = &s->wps->wp[index]; + uint64_t wpv = *wp; + if (!QCOW2_ZT_IS_CONV(wpv)) { + /* + * Implicitly open one closed zone to write if there are zone resources + * left. + */ + zs = qcow2_get_zs(wpv); + if (zs == BLK_ZS_CLOSED || zs == BLK_ZS_EMPTY) { + ret = qcow2_check_zone_resources(bs, zs); + if (ret < 0) { + goto fail_nometa; + } + + if (zs == BLK_ZS_CLOSED) { + s->nr_zones_closed--; + s->nr_zones_imp_open++; + } else { + s->nr_zones_imp_open++; + } + } + + /* align up (start_offset, zone_size), the start offset is not + * necessarily power of two. */ + end = ((start_offset + zone_size) / zone_size) * zone_size; + if (start_offset + start_bytes <= end) { + *wp = start_offset + start_bytes; + } else { + ret = -EINVAL; + goto fail_nometa; + } + + ret = qcow2_write_wp_at(bs, wp, index,BLK_ZS_IOPEN); + if (ret < 0) { + goto fail_nometa; + } + } + } ret = 0; qemu_co_mutex_lock(&s->lock); @@ -3117,7 +3353,9 @@ int qcow2_update_header(BlockDriverState *bs) .max_active_zones = cpu_to_be32(s->zoned_header.max_active_zones), .max_append_sectors = - cpu_to_be32(s->zoned_header.max_append_sectors) + cpu_to_be32(s->zoned_header.max_append_sectors), + .zonedmeta_offset = cpu_to_be64(s->zoned_header.zonedmeta_offset), + .zonedmeta_size = cpu_to_be64(s->zoned_header.zonedmeta_size) }; ret = header_ext_add(buf, QCOW2_EXT_MAGIC_ZONED_FORMAT, &zoned_header, sizeof(zoned_header), @@ -3522,7 +3760,8 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) int version; int refcount_order; uint64_t *refcount_table; - int ret; + uint64_t zoned_meta_size, zoned_clusterlen; + int ret, offset, i; uint8_t compression_type = QCOW2_COMPRESSION_TYPE_ZLIB; assert(create_options->driver == BLOCKDEV_DRIVER_QCOW2); @@ -3823,6 +4062,48 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) s->zoned_header.max_open_zones = qcow2_opts->max_open_zones; s->zoned_header.max_active_zones = qcow2_opts->max_active_zones; s->zoned_header.max_append_sectors = qcow2_opts->max_append_sectors; + s->zoned_header.nr_zones = qcow2_opts->size / qcow2_opts->zone_size; + + zoned_meta_size = sizeof(uint64_t) * s->zoned_header.nr_zones; + uint64_t meta[zoned_meta_size]; + memset(meta, 0, zoned_meta_size); + + for (i = 0; i < s->zoned_header.zone_nr_conv; ++i) { + meta[i] = i * s->zoned_header.zone_size; + meta[i] += 1ULL << 59; + } + for (; i < s->zoned_header.nr_zones; ++i) { + meta[i] = i * s->zoned_header.zone_size; + /* For sequential zones, the first four most significant bit + * indicates zone states. */ + meta[i] += ((uint64_t)BLK_ZS_EMPTY << 60); + } + + offset = qcow2_alloc_clusters(blk_bs(blk), zoned_meta_size); + if (offset < 0) { + error_setg_errno(errp, -offset, "Could not allocate clusters " + "for zoned metadata size"); + goto out; + } + s->zoned_header.zonedmeta_offset = offset; + s->zoned_header.zonedmeta_size = zoned_meta_size; + + zoned_clusterlen = size_to_clusters(s, zoned_meta_size) + * s->cluster_size; + assert(qcow2_pre_write_overlap_check(bs, 0, offset, + zoned_clusterlen,false) == 0); + ret = bdrv_pwrite_zeroes(blk_bs(blk)->file, offset, + zoned_clusterlen, 0); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not zero fill zoned metadata"); + goto out; + } + ret = bdrv_pwrite(blk_bs(blk)->file, offset, zoned_meta_size, meta, 0); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not write zoned metadata " + "to disk"); + goto out; + } } /* Create a full header (including things like feature table) */ @@ -4166,6 +4447,346 @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs, return ret; } +static int coroutine_fn +qcow2_co_zone_report(BlockDriverState *bs, int64_t offset, + unsigned int *nr_zones, BlockZoneDescriptor *zones) +{ + BDRVQcow2State *s = bs->opaque; + uint64_t zone_size = s->zoned_header.zone_size; + int64_t capacity = bs->total_sectors << BDRV_SECTOR_BITS; + int64_t size = bs->bl.nr_zones * zone_size; + int i = 0; + int si; + + if (zone_size > 0) { + si = offset / zone_size; + unsigned int nrz = *nr_zones; + qemu_co_mutex_lock(&s->wps->colock); + for (; i < nrz; ++i) { + zones[i].start = (si + i) * zone_size; + + /* The last zone can be smaller than the zone size */ + if ((si + i + 1) == bs->bl.nr_zones && size > capacity) { + zones[i].length = zone_size - (size - capacity); + } else { + zones[i].length = zone_size; + } + zones[i].cap = zone_size; + + uint64_t wp = s->wps->wp[si + i]; + if (QCOW2_ZT_IS_CONV(wp)) { + zones[i].type = BLK_ZT_CONV; + zones[i].state = BLK_ZS_NOT_WP; + /* Clear the zone type bit */ + wp &= ~(1ULL << 59); + } else { + zones[i].type = BLK_ZT_SWR; + zones[i].state = qcow2_get_zs(wp); + /* Clear the zone state bits */ + wp = qcow2_get_wp(wp); + } + + zones[i].wp = wp; + if (si + i == bs->bl.nr_zones) { + break; + } + } + qemu_co_mutex_unlock(&s->wps->colock); + } + *nr_zones = i; + return 0; +} + +static int qcow2_open_zone(BlockDriverState *bs, uint32_t index) { + BDRVQcow2State *s = bs->opaque; + int ret; + + qemu_co_mutex_lock(&s->wps->colock); + uint64_t *wp = &s->wps->wp[index]; + BlockZoneState zs = qcow2_get_zs(*wp); + + switch(zs) { + case BLK_ZS_EMPTY: + ret = qcow2_check_zone_resources(bs, BLK_ZS_EMPTY); + if (ret < 0) { + return ret; + } + break; + case BLK_ZS_IOPEN: + s->nr_zones_imp_open--; + break; + case BLK_ZS_EOPEN: + return 0; + case BLK_ZS_CLOSED: + ret = qcow2_check_zone_resources(bs, BLK_ZS_CLOSED); + if (ret < 0) { + return ret; + } + s->nr_zones_closed--; + break; + case BLK_ZS_FULL: + break; + default: + return -EINVAL; + } + ret = qcow2_write_wp_at(bs, wp, index, BLK_ZS_EOPEN); + if (!ret) { + s->nr_zones_exp_open++; + } + qemu_co_mutex_unlock(&s->wps->colock); + return ret; +} + +static int qcow2_close_zone(BlockDriverState *bs, uint32_t index) { + BDRVQcow2State *s = bs->opaque; + int ret; + + qemu_co_mutex_lock(&s->wps->colock); + uint64_t *wp = &s->wps->wp[index]; + BlockZoneState zs = qcow2_get_zs(*wp); + + switch(zs) { + case BLK_ZS_EMPTY: + break; + case BLK_ZS_IOPEN: + s->nr_zones_imp_open--; + break; + case BLK_ZS_EOPEN: + s->nr_zones_exp_open--; + break; + case BLK_ZS_CLOSED: + ret = qcow2_check_zone_resources(bs, BLK_ZS_CLOSED); + if (ret < 0) { + return ret; + } + s->nr_zones_closed--; + break; + case BLK_ZS_FULL: + break; + default: + return -EINVAL; + } + + if (zs == BLK_ZS_EMPTY) { + ret = qcow2_write_wp_at(bs, wp, index, BLK_ZS_EMPTY); + } else { + ret = qcow2_write_wp_at(bs, wp, index, BLK_ZS_CLOSED); + if (!ret) { + s->nr_zones_closed++; + } + } + qemu_co_mutex_unlock(&s->wps->colock); + return ret; +} + +static int qcow2_finish_zone(BlockDriverState *bs, uint32_t index) { + BDRVQcow2State *s = bs->opaque; + int ret; + + qemu_co_mutex_lock(&s->wps->colock); + uint64_t *wp = &s->wps->wp[index]; + BlockZoneState zs = qcow2_get_zs(*wp); + + switch(zs) { + case BLK_ZS_EMPTY: + ret = qcow2_check_zone_resources(bs, BLK_ZS_EMPTY); + if (ret < 0) { + return ret; + } + break; + case BLK_ZS_IOPEN: + s->nr_zones_imp_open--; + break; + case BLK_ZS_EOPEN: + s->nr_zones_exp_open--; + break; + case BLK_ZS_CLOSED: + ret = qcow2_check_zone_resources(bs, BLK_ZS_CLOSED); + if (ret < 0) { + return ret; + } + s->nr_zones_closed--; + break; + case BLK_ZS_FULL: + return 0; + default: + return -EINVAL; + } + + *wp = (index + 1) * s->zoned_header.zone_size; + ret = qcow2_write_wp_at(bs, wp, index, BLK_ZS_FULL); + qemu_co_mutex_unlock(&s->wps->colock); + return ret; +} + +static int qcow2_reset_zone(BlockDriverState *bs, uint32_t index, + int64_t len) { + BDRVQcow2State *s = bs->opaque; + int nrz = bs->bl.nr_zones; + int zone_size = bs->bl.zone_size; + int n, ret = 0; + + qemu_co_mutex_lock(&s->wps->colock); + uint64_t *wp = &s->wps->wp[index]; + if (len == bs->total_sectors << BDRV_SECTOR_BITS) { + n = nrz; + index = 0; + } else { + n = len / zone_size; + } + + for (int i = 0; i < n; ++i) { + uint64_t *wp_i = (uint64_t *)(wp + i); + uint64_t wpi_v = *wp_i; + if (QCOW2_ZT_IS_CONV(wpi_v)) { + continue; + } + + BlockZoneState zs = qcow2_get_zs(wpi_v); + switch (zs) { + case BLK_ZS_EMPTY: + break; + case BLK_ZS_IOPEN: + s->nr_zones_imp_open--; + break; + case BLK_ZS_EOPEN: + s->nr_zones_exp_open--; + break; + case BLK_ZS_CLOSED: + s->nr_zones_closed--; + break; + case BLK_ZS_FULL: + break; + default: + return -EINVAL; + } + + if (zs == BLK_ZS_EMPTY) { + continue; + } + + *wp_i = (index + i) * zone_size; + ret = qcow2_write_wp_at(bs, wp_i, index + i, BLK_ZS_EMPTY); + if (ret < 0) { + return ret; + } + /* clear data */ + ret = qcow2_co_pwrite_zeroes(bs, qcow2_get_wp(*wp_i), zone_size, 0); + if (ret < 0) { + error_report("Failed to reset zone at 0x%" PRIx64 "", *wp_i); + } + } + qemu_co_mutex_unlock(&s->wps->colock); + return ret; +} + +static int coroutine_fn qcow2_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op, + int64_t offset, int64_t len) +{ + BDRVQcow2State *s = bs->opaque; + int ret = 0; + int64_t capacity = bs->total_sectors << BDRV_SECTOR_BITS; + int64_t zone_size = s->zoned_header.zone_size; + int64_t zone_size_mask = zone_size - 1; + uint32_t index = offset / zone_size; + BlockZoneWps *wps = s->wps; + + if (offset & zone_size_mask) { + error_report("sector offset %" PRId64 " is not aligned to zone size" + " %" PRId64 "", offset / 512, zone_size / 512); + return -EINVAL; + } + + if (((offset + len) < capacity && len & zone_size_mask) || + offset + len > capacity) { + error_report("number of sectors %" PRId64 " is not aligned to zone" + " size %" PRId64 "", len / 512, zone_size / 512); + return -EINVAL; + } + + qemu_co_mutex_lock(&wps->colock); + uint64_t wpv = wps->wp[offset / zone_size]; + if (QCOW2_ZT_IS_CONV(wpv) && len != capacity) { + error_report("zone mgmt operations are not allowed for " + "conventional zones"); + ret = -EIO; + goto unlock; + } + qemu_co_mutex_unlock(&wps->colock); + + switch(op) { + case BLK_ZO_OPEN: + ret = qcow2_open_zone(bs, index); + break; + case BLK_ZO_CLOSE: + ret = qcow2_close_zone(bs, index); + break; + case BLK_ZO_FINISH: + ret = qcow2_finish_zone(bs, index); + break; + case BLK_ZO_RESET: + ret = qcow2_reset_zone(bs, index, len); + break; + default: + error_report("Unsupported zone op: 0x%x", op); + ret = -ENOTSUP; + break; + } + return ret; + +unlock: + qemu_co_mutex_unlock(&wps->colock); + return ret; +} + +static int coroutine_fn +qcow2_co_zone_append(BlockDriverState *bs, int64_t *offset, QEMUIOVector *qiov, + BdrvRequestFlags flags) +{ + assert(flags == 0); + BDRVQcow2State *s = bs->opaque; + int ret; + int64_t zone_size_mask = bs->bl.zone_size - 1; + int64_t iov_len = 0; + int64_t len = 0; + + /* offset + len should not pass the end of that zone starting from offset */ + if (*offset & zone_size_mask) { + error_report("sector offset %" PRId64 " is not aligned to zone size " + "%" PRId32 "", *offset / 512, bs->bl.zone_size / 512); + return -EINVAL; + } + + int64_t wg = bs->bl.write_granularity; + int64_t wg_mask = wg - 1; + for (int i = 0; i < qiov->niov; i++) { + iov_len = qiov->iov[i].iov_len; + if (iov_len & wg_mask) { + error_report("len of IOVector[%d] %" PRId64 " is not aligned to " + "block size %" PRId64 "", i, iov_len, wg); + return -EINVAL; + } + } + len = qiov->size; + + if ((len >> BDRV_SECTOR_BITS) > bs->bl.max_append_sectors) { + return -ENOTSUP; + } + + qemu_co_mutex_lock(&s->wps->colock); + uint64_t wp = s->wps->wp[*offset / bs->bl.zone_size]; + uint64_t wp_i = qcow2_get_wp(wp); + ret = qcow2_co_pwritev_part(bs, wp_i, len, qiov, 0, 0); + if (ret == 0) { + *offset = wp_i; + } else { + error_report("qcow2: zap failed"); + } + + qemu_co_mutex_unlock(&s->wps->colock); + return ret; +} + static int coroutine_fn GRAPH_RDLOCK qcow2_co_copy_range_from(BlockDriverState *bs, BdrvChild *src, int64_t src_offset, @@ -6214,6 +6835,10 @@ BlockDriver bdrv_qcow2 = { .bdrv_co_pwritev_part = qcow2_co_pwritev_part, .bdrv_co_flush_to_os = qcow2_co_flush_to_os, + .bdrv_co_zone_report = qcow2_co_zone_report, + .bdrv_co_zone_mgmt = qcow2_co_zone_mgmt, + .bdrv_co_zone_append = qcow2_co_zone_append, + .bdrv_co_pwrite_zeroes = qcow2_co_pwrite_zeroes, .bdrv_co_pdiscard = qcow2_co_pdiscard, .bdrv_co_copy_range_from = qcow2_co_copy_range_from, diff --git a/block/qcow2.h b/block/qcow2.h index fe18dc4d97..a3a96ddbce 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -246,6 +246,8 @@ typedef struct Qcow2ZonedHeaderExtension { uint32_t max_active_zones; uint32_t max_open_zones; uint32_t max_append_sectors; + uint64_t zonedmeta_offset; + uint64_t zonedmeta_size; uint8_t padding[3]; } QEMU_PACKED Qcow2ZonedHeaderExtension; From patchwork Mon Jun 5 10:41:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Li X-Patchwork-Id: 13267198 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 5E1E7C77B73 for ; Mon, 5 Jun 2023 10:42:19 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1q67ea-00022T-9u; Mon, 05 Jun 2023 06:41:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1q67eY-00021h-Ve; Mon, 05 Jun 2023 06:41:35 -0400 Received: from mail-pl1-x62d.google.com ([2607:f8b0:4864:20::62d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1q67eX-0006oj-3a; Mon, 05 Jun 2023 06:41:34 -0400 Received: by mail-pl1-x62d.google.com with SMTP id d9443c01a7336-1b01dac1a82so22443465ad.2; Mon, 05 Jun 2023 03:41:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1685961691; x=1688553691; 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; bh=UOv8zkJcKH4/kd6DqV4AbYXN/AcmdfjqqCG+nmVbJg4=; b=sTbmHbp/g2AzrMfrBw9aH6zQcN8YNo4bcEv9yrS7ettrcrB35SF44SkVhf7UuT7EoW z8XN6+xoVhI+JVpkdynbSq9ux4l0rZ0tB8VCSO0OFL+lZa3jAhC9ArfhiNjOl83j6M8k OtpUpjXPbr8/1oOSxA6Qfx7IL3bjqtKtducSjkC8x171FQVxKGtpLYDnNYZTxY0KAGxM 9vZwIAC1BZe11KD4ivsxcbvE+v3HcBU0AtJoBM7bTMKoRSq/SRimh71SxgON56i2ma4+ ul3l2k09J+skDS5tZyWm7+jpTOXuEAGlXsCk2oreNc+8YWUJeIHYlnAiV7DIjl53IGC4 0whw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685961691; x=1688553691; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=UOv8zkJcKH4/kd6DqV4AbYXN/AcmdfjqqCG+nmVbJg4=; b=ZTc0ncyN2Mpr8pumv3jUOar086SGWUqjhFbzsHGNUdHFRhYFT3geFeIZgU9aT+r782 0TG9CUTZfq6fRAIejWW6UjtRqt5jxIOsZcdciNx/uQi2jyQ8R/XIacykfvEW5Wt2KkQo v3ngGgbhIxaff9HsU/yqHTfg9SrNLCdxf4NwiP8slx2QmHp6xQOHOJBb4XB0U0YVmCT8 31asc+wTLCWZfURWY7cZ8JzpBu8+JoBPzMg5GvKdEhrd9YwS152bWYS5+dPHh3RSyTYj lvWqu8msesCKpHV1hlgtInQF/KtgpxMDxiPqgUusemDSgLifQ8XM483LjjN2IMlSoPqa 3vHQ== X-Gm-Message-State: AC+VfDyq579q3QOMquThLl6Ui9HkkEBHLk5DVvZ9aDBs2BoFK5s2KuYv 7MUjKJ3HNEfYeUVOHxJobwJe4WDg82WprJyT X-Google-Smtp-Source: ACHHUZ6T9tTsvLdpfxOAVj/y+9yK+t1F9p4QaOJEpns9Q/65dL8f96oUeC7BJ96x3NVr7R5eVxDkzA== X-Received: by 2002:a17:902:ed53:b0:1ab:160c:526d with SMTP id y19-20020a170902ed5300b001ab160c526dmr2774438plb.22.1685961690650; Mon, 05 Jun 2023 03:41:30 -0700 (PDT) Received: from fedlinux.. ([106.84.132.130]) by smtp.gmail.com with ESMTPSA id x4-20020a170902a38400b001b0457705e8sm6340141pla.140.2023.06.05.03.41.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Jun 2023 03:41:30 -0700 (PDT) From: Sam Li To: qemu-devel@nongnu.org Cc: dlemoal@kernel.org, dmitry.fomichev@wdc.com, hare@suse.de, stefanha@redhat.com, Markus Armbruster , Kevin Wolf , qemu-block@nongnu.org, Eric Blake , Hanna Reitz , Sam Li Subject: [RFC 4/4] iotests: test the zoned format feature for qcow2 file Date: Mon, 5 Jun 2023 18:41:08 +0800 Message-Id: <20230605104108.125270-5-faithilikerun@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230605104108.125270-1-faithilikerun@gmail.com> References: <20230605104108.125270-1-faithilikerun@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::62d; envelope-from=faithilikerun@gmail.com; helo=mail-pl1-x62d.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, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org The zoned format feature can be tested by: $ tests/qemu-iotests/check zoned-qcow2 Signed-off-by: Sam Li --- tests/qemu-iotests/tests/zoned-qcow2 | 110 +++++++++++++++++++++++ tests/qemu-iotests/tests/zoned-qcow2.out | 87 ++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100755 tests/qemu-iotests/tests/zoned-qcow2 create mode 100644 tests/qemu-iotests/tests/zoned-qcow2.out diff --git a/tests/qemu-iotests/tests/zoned-qcow2 b/tests/qemu-iotests/tests/zoned-qcow2 new file mode 100755 index 0000000000..6aa5ab3a03 --- /dev/null +++ b/tests/qemu-iotests/tests/zoned-qcow2 @@ -0,0 +1,110 @@ +#!/usr/bin/env bash +# +# Test zone management operations for qcow2 file. +# + +seq="$(basename $0)" +echo "QA output created by $seq" +status=1 # failure is the default! + +file_name="zbc.qcow2" +_cleanup() +{ + _cleanup_test_img + _rm_test_img "$file_name" +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ../common.rc +. ../common.filter +. ../common.qemu + +# This test only runs on Linux hosts with qcow2 image files. +_supported_proto file +_supported_os Linux + +echo +echo "=== Initial image setup ===" +echo + +$QEMU_IMG create -f qcow2 $file_name -o size=768M -o zone_size=64M \ +-o zone_capacity=64M -o zone_nr_conv=0 -o max_append_sectors=512 \ +-o max_open_zones=0 -o max_active_zones=0 -o zoned_profile=zbc + +IMG="--image-opts -n driver=qcow2,file.driver=file,file.filename=$file_name" +QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT + +echo +echo "=== Testing a qcow2 img with zoned format ===" +echo +echo "case 1: if the operations work" + +echo "(1) report the first zone:" +$QEMU_IO $IMG -c "zrp 0 1" +echo +echo "report the first 10 zones" +$QEMU_IO $IMG -c "zrp 0 10" +echo +echo "report the last zone:" +$QEMU_IO $IMG -c "zrp 0x2C000000 2" # 0x2C000000 / 512 = 0x160000 +echo +echo +echo "(2) opening the first zone" +$QEMU_IO $IMG -c "zo 0 0x4000000" # 0x4000000 / 512 = 0x20000 +echo "report after:" +$QEMU_IO $IMG -c "zrp 0 1" +echo +echo "opening the second zone" +$QEMU_IO $IMG -c "zo 0x4000000 0x4000000" +echo "report after:" +$QEMU_IO $IMG -c "zrp 0x4000000 1" +echo +echo "opening the last zone" +$QEMU_IO $IMG -c "zo 0x2C000000 0x4000000" +echo "report after:" +$QEMU_IO $IMG -c "zrp 0x2C000000 2" +echo +echo +echo "(3) closing the first zone" +$QEMU_IO $IMG -c "zc 0 0x4000000" +echo "report after:" +$QEMU_IO $IMG -c "zrp 0 1" +echo +echo "closing the last zone" +$QEMU_IO $IMG -c "zc 0x3e70000000 0x4000000" +echo "report after:" +$QEMU_IO $IMG -c "zrp 0x3e70000000 2" +echo +echo +echo "(4) finishing the second zone" +$QEMU_IO $IMG -c "zf 0x4000000 0x4000000" +echo "After finishing a zone:" +$QEMU_IO $IMG -c "zrp 0x4000000 1" +echo +echo +echo "(5) resetting the second zone" +$QEMU_IO $IMG -c "zrs 0x4000000 0x4000000" +echo "After resetting a zone:" +$QEMU_IO $IMG -c "zrp 0x4000000 1" +echo +echo +echo "(6) append write" # the physical block size of the device is 4096 +$QEMU_IO $IMG -c "zrp 0 1" +$QEMU_IO $IMG -c "zap -p 0 0x1000 0x2000" +echo "After appending the first zone firstly:" +$QEMU_IO $IMG -c "zrp 0 1" +$QEMU_IO $IMG -c "zap -p 0 0x1000 0x2000" +echo "After appending the first zone secondly:" +$QEMU_IO $IMG -c "zrp 0 1" +$QEMU_IO $IMG -c "zap -p 0x4000000 0x1000 0x2000" +echo "After appending the second zone firstly:" +$QEMU_IO $IMG -c "zrp 0x4000000 1" +$QEMU_IO $IMG -c "zap -p 0x4000000 0x1000 0x2000" +echo "After appending the second zone secondly:" +$QEMU_IO $IMG -c "zrp 0x4000000 1" + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/tests/zoned-qcow2.out b/tests/qemu-iotests/tests/zoned-qcow2.out new file mode 100644 index 0000000000..288bceffc4 --- /dev/null +++ b/tests/qemu-iotests/tests/zoned-qcow2.out @@ -0,0 +1,87 @@ +QA output created by zoned-qcow2 + +=== Initial image setup === + +Formatting 'zbc.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib zoned_profile=zbc zone_size=67108864 zone_capacity=67108864 zone_nr_conv=0 max_append_sectors=512 max_active_zones=0 max_open_zones=0 size=805306368 lazy_refcounts=off refcount_bits=16 + +=== Testing a qcow2 img with zoned format === + +case 1: if the operations work +(1) report the first zone: +start: 0x0, len 0x20000, cap 0x20000, wptr 0x0, zcond:1, [type: 2] + +report the first 10 zones +start: 0x0, len 0x20000, cap 0x20000, wptr 0x0, zcond:1, [type: 2] +start: 0x20000, len 0x20000, cap 0x20000, wptr 0x20000, zcond:1, [type: 2] +start: 0x40000, len 0x20000, cap 0x20000, wptr 0x40000, zcond:1, [type: 2] +start: 0x60000, len 0x20000, cap 0x20000, wptr 0x60000, zcond:1, [type: 2] +start: 0x80000, len 0x20000, cap 0x20000, wptr 0x80000, zcond:1, [type: 2] +start: 0xa0000, len 0x20000, cap 0x20000, wptr 0xa0000, zcond:1, [type: 2] +start: 0xc0000, len 0x20000, cap 0x20000, wptr 0xc0000, zcond:1, [type: 2] +start: 0xe0000, len 0x20000, cap 0x20000, wptr 0xe0000, zcond:1, [type: 2] +start: 0x100000, len 0x20000, cap 0x20000, wptr 0x100000, zcond:1, [type: 2] +start: 0x120000, len 0x20000, cap 0x20000, wptr 0x120000, zcond:1, [type: 2] + +report the last zone: +start: 0x160000, len 0x20000, cap 0x20000, wptr 0x160000, zcond:1, [type: 2] + + +(2) opening the first zone +wps[0]: 0x0 +report after: +start: 0x0, len 0x20000, cap 0x20000, wptr 0x0, zcond:3, [type: 2] + +opening the second zone +wps[1]: 0x20000 +report after: +start: 0x20000, len 0x20000, cap 0x20000, wptr 0x20000, zcond:3, [type: 2] + +opening the last zone +wps[11]: 0x160000 +report after: +start: 0x160000, len 0x20000, cap 0x20000, wptr 0x160000, zcond:3, [type: 2] + + +(3) closing the first zone +wps[0]: 0x0 +report after: +start: 0x0, len 0x20000, cap 0x20000, wptr 0x0, zcond:4, [type: 2] + +closing the last zone +zone close failed: Input/output error +report after: +start: 0x1f380000, len 0x20000, cap 0x20000, wptr 0x0, zcond:0, [type: 2] +start: 0x1f3a0000, len 0x20000, cap 0x20000, wptr 0x0, zcond:0, [type: 2] + + +(4) finishing the second zone +wps[1]: 0x40000 +After finishing a zone: +start: 0x20000, len 0x20000, cap 0x20000, wptr 0x40000, zcond:14, [type: 2] + + +(5) resetting the second zone +wps[1]: 0x20000 +After resetting a zone: +start: 0x20000, len 0x20000, cap 0x20000, wptr 0x20000, zcond:1, [type: 2] + + +(6) append write +start: 0x0, len 0x20000, cap 0x20000, wptr 0x0, zcond:4, [type: 2] +wps[0]: 0x18 +After zap done, the append sector is 0x0 +After appending the first zone firstly: +start: 0x0, len 0x20000, cap 0x20000, wptr 0x18, zcond:2, [type: 2] +wps[0]: 0x30 +After zap done, the append sector is 0x18 +After appending the first zone secondly: +start: 0x0, len 0x20000, cap 0x20000, wptr 0x30, zcond:2, [type: 2] +wps[1]: 0x20018 +After zap done, the append sector is 0x20000 +After appending the second zone firstly: +start: 0x20000, len 0x20000, cap 0x20000, wptr 0x20018, zcond:2, [type: 2] +wps[1]: 0x20030 +After zap done, the append sector is 0x20018 +After appending the second zone secondly: +start: 0x20000, len 0x20000, cap 0x20000, wptr 0x20030, zcond:2, [type: 2] +*** done