From patchwork Tue Oct 13 21:42:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Fomichev X-Patchwork-Id: 11836131 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E2E74139F for ; Tue, 13 Oct 2020 21:50:31 +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 8412C20872 for ; Tue, 13 Oct 2020 21:50:31 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="YXnQteqd" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8412C20872 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=wdc.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:44350 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kSSBi-0006lh-L4 for patchwork-qemu-devel@patchwork.kernel.org; Tue, 13 Oct 2020 17:50:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:47208) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kSS49-0005kY-U2; Tue, 13 Oct 2020 17:42:45 -0400 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:45657) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kSS46-0001p9-9f; Tue, 13 Oct 2020 17:42:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1602625358; x=1634161358; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=HYiq0JK4dRwQV6ig2IjA1t2BEXwoUc+F9PcNVyweUws=; b=YXnQteqdImDjgJSDAgXUowp48JMG3Go8D8egOSjS9Ss1W+EGGxV2KQ3g Y0sX+IUebZFVc5LXtoLuYnOox+7vPT+0BY+WjNy1MCkg0aUlx3xb78Auh L6nJ7ZJOlfgThSYo+8LPAhXMHIOCoEm02VYH3Fg0y5HKKgZsCpryceDY4 rU7BSCKyL1GLCD9xgEf5HMP+CGrX6HRyzM/MBdf3QAtQfoEJyxVZojVm7 FlI1yZ4R4gUhg+cxVbZwTqK8p6FygXOR5ViROwNzv0Wux+k18ifu0FahV AW7BTa7wnOAKKnoY8EEPbqn+JrKkRVCQcQyuS2JYrJzAe1XOiDUTRDqMp A==; IronPort-SDR: ZbzC3cobtEbj8wUdkABcuXSyIrTQeUjF0bcLOkx+XDKn1vJK19x/VjrfHgAUJqOwOx9L2OQWiN rFj7kKlBc0zZjpKdqwAubjP/5mrwHkhIHwoLuU9JVnRn3Dy2pAo27urEH11k/3vY6IkGXuN3LC GENWPTEkFDajUYybuRAgc+cjYyzVbL7UGoDKjT6f9yFlYZmX252L+b+QZ6YvKSl614WqLWfQ28 jKbnxh2CicRAO6I8xqVTL7ikhJaGRKB67nKKK/w6q0UWxhcAU8Vib63pzaSRVTcprDEPcEQE3l toQ= X-IronPort-AV: E=Sophos;i="5.77,371,1596470400"; d="scan'208";a="154185940" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 14 Oct 2020 05:42:37 +0800 IronPort-SDR: uUm5oWQTKCbO13xx63WkqMsbjmulaubNm3lpwD2EABtfw4iX8lmbNXVfyvX/BYXgAXj3swnko8 IfJYLXhm5pzDkpR81cntYt2nDZM4tlpwL9ykWdV17jbIIH1WfHxIQRlg2dV7ThCXFSzHK0CNT0 58meP3g/zdz2Jnzo+XYlQWIOa2gjwHSkyK8n8fj9gtz86NoZ7y6oW7QFCWxjq+r4aCjtMRwFSC vZNaIvTupyoTj12mzfydKN8l5Gb8cVkSDhwOs5jhgQrSKd3TDW1GaxUh152jVdgDoLswoqBPlP 293I5lTs29nuAqaLYaJStEsl Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Oct 2020 14:29:10 -0700 IronPort-SDR: EvFUMEPrO/1mkt6j+ljpg8Z8ju8ltTzQTtbc0sVUPxNaIc0vLJaIXNSpRHVo2YCkPZmsKuppw6 Ty6UD7DzshCsu+v47/xUAs/J5lpfC70xa9MLqT3u2TXviDYj90LR7LoTnBuhVxpE2JSP4WKf3o jr+eVGRW+MS5lkWF13ul/RiKu1haFOqVSdLsSkhtw6Mb872MW1myMZE130c+PcIvoQQWtVM43x gTtTFHTT1WXpVBBCFvdOQUYf8ufhPs/mVBMQiUE80rTWbpgkB+xeBgiABuXDffD3KSIBwRTwfb oOA= WDCIronportException: Internal Received: from unknown (HELO redsun50.ssa.fujisawa.hgst.com) ([10.149.66.24]) by uls-op-cesaip02.wdc.com with ESMTP; 13 Oct 2020 14:42:35 -0700 From: Dmitry Fomichev To: Keith Busch , Klaus Jensen , Kevin Wolf , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Maxim Levitsky , Fam Zheng Subject: [PATCH v6 08/11] hw/block/nvme: Add injection of Offline/Read-Only zones Date: Wed, 14 Oct 2020 06:42:09 +0900 Message-Id: <20201013214212.2152-9-dmitry.fomichev@wdc.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20201013214212.2152-1-dmitry.fomichev@wdc.com> References: <20201013214212.2152-1-dmitry.fomichev@wdc.com> MIME-Version: 1.0 Received-SPF: pass client-ip=216.71.153.141; envelope-from=prvs=5487bf209=dmitry.fomichev@wdc.com; helo=esa3.hgst.iphmx.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/10/13 17:42:19 X-ACL-Warn: Detected OS = FreeBSD 9.x or newer [fuzzy] X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-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: Niklas Cassel , Damien Le Moal , qemu-block@nongnu.org, Dmitry Fomichev , qemu-devel@nongnu.org, Alistair Francis , Matias Bjorling Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" ZNS specification defines two zone conditions for the zones that no longer can function properly, possibly because of flash wear or other internal fault. It is useful to be able to "inject" a small number of such zones for testing purposes. This commit defines two optional device properties, "offline_zones" and "rdonly_zones". Users can assign non-zero values to these variables to specify the number of zones to be initialized as Offline or Read-Only. The actual number of injected zones may be smaller than the requested amount - Read-Only and Offline counts are expected to be much smaller than the total number of zones on a drive. Signed-off-by: Dmitry Fomichev --- hw/block/nvme-ns.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++ hw/block/nvme-ns.h | 2 ++ 2 files changed, 66 insertions(+) diff --git a/hw/block/nvme-ns.c b/hw/block/nvme-ns.c index 255ded2b43..d050f97909 100644 --- a/hw/block/nvme-ns.c +++ b/hw/block/nvme-ns.c @@ -21,6 +21,7 @@ #include "sysemu/sysemu.h" #include "sysemu/block-backend.h" #include "qapi/error.h" +#include "crypto/random.h" #include "hw/qdev-properties.h" #include "hw/qdev-core.h" @@ -132,6 +133,32 @@ static int nvme_calc_zone_geometry(NvmeNamespace *ns, Error **errp) return -1; } + if (ns->params.zd_extension_size) { + if (ns->params.zd_extension_size & 0x3f) { + error_setg(errp, + "zone descriptor extension size must be a multiple of 64B"); + return -1; + } + if ((ns->params.zd_extension_size >> 6) > 0xff) { + error_setg(errp, "zone descriptor extension size is too large"); + return -1; + } + } + + if (ns->params.max_open_zones < nz) { + if (ns->params.nr_offline_zones > nz - ns->params.max_open_zones) { + error_setg(errp, "offline_zones value %u is too large", + ns->params.nr_offline_zones); + return -1; + } + if (ns->params.nr_rdonly_zones > + nz - ns->params.max_open_zones - ns->params.nr_offline_zones) { + error_setg(errp, "rdonly_zones value %u is too large", + ns->params.nr_rdonly_zones); + return -1; + } + } + return 0; } @@ -140,7 +167,9 @@ static void nvme_init_zone_state(NvmeNamespace *ns) uint64_t start = 0, zone_size = ns->zone_size; uint64_t capacity = ns->num_zones * zone_size; NvmeZone *zone; + uint32_t rnd; int i; + uint16_t zs; ns->zone_array = g_malloc0(ns->zone_array_size); if (ns->params.zd_extension_size) { @@ -167,6 +196,37 @@ static void nvme_init_zone_state(NvmeNamespace *ns) zone->w_ptr = start; start += zone_size; } + + /* If required, make some zones Offline or Read Only */ + + for (i = 0; i < ns->params.nr_offline_zones; i++) { + do { + qcrypto_random_bytes(&rnd, sizeof(rnd), NULL); + rnd %= ns->num_zones; + } while (rnd < ns->params.max_open_zones); + zone = &ns->zone_array[rnd]; + zs = nvme_get_zone_state(zone); + if (zs != NVME_ZONE_STATE_OFFLINE) { + nvme_set_zone_state(zone, NVME_ZONE_STATE_OFFLINE); + } else { + i--; + } + } + + for (i = 0; i < ns->params.nr_rdonly_zones; i++) { + do { + qcrypto_random_bytes(&rnd, sizeof(rnd), NULL); + rnd %= ns->num_zones; + } while (rnd < ns->params.max_open_zones); + zone = &ns->zone_array[rnd]; + zs = nvme_get_zone_state(zone); + if (zs != NVME_ZONE_STATE_OFFLINE && + zs != NVME_ZONE_STATE_READ_ONLY) { + nvme_set_zone_state(zone, NVME_ZONE_STATE_READ_ONLY); + } else { + i--; + } + } } static int nvme_zoned_init_ns(NvmeCtrl *n, NvmeNamespace *ns, int lba_index, @@ -360,6 +420,10 @@ static Property nvme_ns_props[] = { DEFINE_PROP_UINT32("max_open", NvmeNamespace, params.max_open_zones, 0), DEFINE_PROP_UINT32("zone_descr_ext_size", NvmeNamespace, params.zd_extension_size, 0), + DEFINE_PROP_UINT32("offline_zones", NvmeNamespace, + params.nr_offline_zones, 0), + DEFINE_PROP_UINT32("rdonly_zones", NvmeNamespace, + params.nr_rdonly_zones, 0), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/block/nvme-ns.h b/hw/block/nvme-ns.h index 2d70a13701..d65d8b0930 100644 --- a/hw/block/nvme-ns.h +++ b/hw/block/nvme-ns.h @@ -37,6 +37,8 @@ typedef struct NvmeNamespaceParams { uint32_t max_active_zones; uint32_t max_open_zones; uint32_t zd_extension_size; + uint32_t nr_offline_zones; + uint32_t nr_rdonly_zones; } NvmeNamespaceParams; typedef struct NvmeNamespace {