From nobody Sun May 5 13:29:53 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1664446395; cv=none; d=zohomail.com; s=zohoarc; b=hTnAr3Gp/Iig3qnsSvgZ20gnHdJFZprAdT5ogtD21/t7NNLlamYWsrGbXc+kf+pVd+RqWipXlbU1qssk4PCnU06p8Kg2dPbNcUCTg3AiQX/pPao0w4Dg41UeeerHWtDHGfFXl5BuLftfvrkqU2fDyANIqgD2lHec9Ff8IQh3zuI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1664446395; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=8c/2JO7aXR36MrY5r0dDCGE7kIU1nzjPXj33yEUQe4g=; b=d0edHD0l3PdxfAeqtOnXOTA36i3HT3T3dGlMgIADIMsc0jKYEVTklAqbdu67VwOiLLg2WcuaDpsiCPF6LYtiXLYVBATkWLkZwP2zz/ii8nbXgDRas4UFVOP+Y55n9mwj/bt16r6EV/cnTEqTEumVdmyvIsVKKFDC4DJKo6/qL2g= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1664446395876519.1294735496488; Thu, 29 Sep 2022 03:13:15 -0700 (PDT) Received: from localhost ([::1]:58686 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1odqXa-0000WH-1G for importer@patchew.org; Thu, 29 Sep 2022 06:13:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57316) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1odq9s-0001bs-GF; Thu, 29 Sep 2022 05:48:46 -0400 Received: from mail-pj1-x1035.google.com ([2607:f8b0:4864:20::1035]:39836) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1odq9q-0004J9-Hi; Thu, 29 Sep 2022 05:48:44 -0400 Received: by mail-pj1-x1035.google.com with SMTP id v10-20020a17090a634a00b00205e48cf845so5407606pjs.4; Thu, 29 Sep 2022 02:48:41 -0700 (PDT) Received: from roots.. ([112.44.202.63]) by smtp.gmail.com with ESMTPSA id f4-20020a170902ce8400b00178b06fea7asm5574515plg.148.2022.09.29.02.48.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Sep 2022 02:48:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date; bh=8c/2JO7aXR36MrY5r0dDCGE7kIU1nzjPXj33yEUQe4g=; b=AbC0Y0a6sfhbe4nT6x6BSe3LYxaBOxIG76nWhKdIf1g+3nP1N8lMTtYfz0AbmpS4Kl j8M/aqkkDuj7JHcTVqZR2USHu9VDv/WCNg/GQJJRBlX4XgStghSpcKTG18raIUlrILUC wHWh4sPQ37nOoVXrDFzdOYY2j9vA+cVAdyL+wi1m/ESurKkWkbr9GUo/0sKCQqFUF0rO oHG4uF2f9Ydy49JIh9iPKnWf/4wjEpgnLcQ53fdtT4zGKbTNXb1j9X9r8JOOHNxe3E// kfeZ8NmoOf/qq+M1kP3yncZ0CiUInXD/cPl7f7zVZsCDq0Y8lic9U+yLEMstxtH7jWnV EoeQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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; bh=8c/2JO7aXR36MrY5r0dDCGE7kIU1nzjPXj33yEUQe4g=; b=lwfjg4mkCyVc1HJwFjcwQqoL5kkTPyilVTD3uY3H/hG2NyHgd7nSPx2ffpf7ITTGSH 2rbflt4PwrOocyDNUzhW5/jlbrekR+YNDv/IGpNYnahOc/0O5m3n0sgdsUBVGkdesPR0 EWu4aBJNnFZmsTR6fRGCvuSR1bzIVp8e39awFat0Owyui/12pBWUf89n15EWOVHx7i74 nKBiTswnRE9O8lYO7YPxN+E/9LHk3Q3/kRK7a/eYeo0a7MVd9fK+TujkkF0pyh06ruLc 0DCDX6EgagCBPhU1Nu8o6TKZXNcHqy3LH/kt88ennhfKB0f21D8he+RMca32PcVCruR8 ozsQ== X-Gm-Message-State: ACrzQf1x5Hs5K10GGXmq311gpQgA6yF4R4bctDzINcph5QQ42ioM+mc0 VJ6SDopjl9PU/j/Q04FHA6LkSRgrn066Zw== X-Google-Smtp-Source: AMsMyM4BWQqoluWMqiz6dhKYgww/t1L94kZRIExXlrIG8jtdFHnfLp48l++ruRujp70tezH55Mg+Jg== X-Received: by 2002:a17:90b:4b0d:b0:203:690d:9f7f with SMTP id lx13-20020a17090b4b0d00b00203690d9f7fmr15168606pjb.145.1664444920601; Thu, 29 Sep 2022 02:48:40 -0700 (PDT) From: Sam Li To: qemu-devel@nongnu.org Cc: dmitry.fomichev@wdc.com, damien.lemoal@opensource.wdc.com, qemu-block@nongnu.org, stefanha@redhat.com, Hanna Reitz , Kevin Wolf , "Michael S. Tsirkin" , hare@suse.de, Sam Li Subject: [PATCH v2 1/2] include: update virtio_blk headers from Linux 5.19-rc2+ Date: Thu, 29 Sep 2022 17:48:20 +0800 Message-Id: <20220929094821.78596-2-faithilikerun@gmail.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20220929094821.78596-1-faithilikerun@gmail.com> References: <20220929094821.78596-1-faithilikerun@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1035; envelope-from=faithilikerun@gmail.com; helo=mail-pj1-x1035.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 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+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1664446397395100001 Content-Type: text/plain; charset="utf-8" Use scripts/update-linux-headers.sh to update virtio-blk headers from Dmitry's "virtio-blk:add support for zoned block devices" linux patch. There is a link for more information: https://github.com/dmitry-fomichev/virtblk-zbd Signed-off-by: Sam Li Reviewed-by: Stefan Hajnoczi --- include/standard-headers/linux/virtio_blk.h | 109 ++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/include/standard-headers/linux/virtio_blk.h b/include/standard= -headers/linux/virtio_blk.h index 2dcc90826a..490bd21c76 100644 --- a/include/standard-headers/linux/virtio_blk.h +++ b/include/standard-headers/linux/virtio_blk.h @@ -40,6 +40,7 @@ #define VIRTIO_BLK_F_MQ 12 /* support more than one vq */ #define VIRTIO_BLK_F_DISCARD 13 /* DISCARD is supported */ #define VIRTIO_BLK_F_WRITE_ZEROES 14 /* WRITE ZEROES is supported */ +#define VIRTIO_BLK_F_ZONED 17 /* Zoned block device */ =20 /* Legacy feature bits */ #ifndef VIRTIO_BLK_NO_LEGACY @@ -119,6 +120,20 @@ struct virtio_blk_config { uint8_t write_zeroes_may_unmap; =20 uint8_t unused1[3]; + + /* Secure erase fields that are defined in the virtio spec */ + uint8_t sec_erase[12]; + + /* Zoned block device characteristics (if VIRTIO_BLK_F_ZONED) */ + struct virtio_blk_zoned_characteristics { + __virtio32 zone_sectors; + __virtio32 max_open_zones; + __virtio32 max_active_zones; + __virtio32 max_append_sectors; + __virtio32 write_granularity; + uint8_t model; + uint8_t unused2[3]; + } zoned; } QEMU_PACKED; =20 /* @@ -153,6 +168,27 @@ struct virtio_blk_config { /* Write zeroes command */ #define VIRTIO_BLK_T_WRITE_ZEROES 13 =20 +/* Zone append command */ +#define VIRTIO_BLK_T_ZONE_APPEND 15 + +/* Report zones command */ +#define VIRTIO_BLK_T_ZONE_REPORT 16 + +/* Open zone command */ +#define VIRTIO_BLK_T_ZONE_OPEN 18 + +/* Close zone command */ +#define VIRTIO_BLK_T_ZONE_CLOSE 20 + +/* Finish zone command */ +#define VIRTIO_BLK_T_ZONE_FINISH 22 + +/* Reset zone command */ +#define VIRTIO_BLK_T_ZONE_RESET 24 + +/* Reset All zones command */ +#define VIRTIO_BLK_T_ZONE_RESET_ALL 26 + #ifndef VIRTIO_BLK_NO_LEGACY /* Barrier before this op. */ #define VIRTIO_BLK_T_BARRIER 0x80000000 @@ -172,6 +208,72 @@ struct virtio_blk_outhdr { __virtio64 sector; }; =20 +/* + * Supported zoned device models. + */ + +/* Regular block device */ +#define VIRTIO_BLK_Z_NONE 0 +/* Host-managed zoned device */ +#define VIRTIO_BLK_Z_HM 1 +/* Host-aware zoned device */ +#define VIRTIO_BLK_Z_HA 2 + +/* + * Zone descriptor. A part of VIRTIO_BLK_T_ZONE_REPORT command reply. + */ +struct virtio_blk_zone_descriptor { + /* Zone capacity */ + __virtio64 z_cap; + /* The starting sector of the zone */ + __virtio64 z_start; + /* Zone write pointer position in sectors */ + __virtio64 z_wp; + /* Zone type */ + uint8_t z_type; + /* Zone state */ + uint8_t z_state; + uint8_t reserved[38]; +}; + +struct virtio_blk_zone_report { + __virtio64 nr_zones; + uint8_t reserved[56]; + struct virtio_blk_zone_descriptor zones[]; +}; + +/* + * Supported zone types. + */ + +/* Conventional zone */ +#define VIRTIO_BLK_ZT_CONV 1 +/* Sequential Write Required zone */ +#define VIRTIO_BLK_ZT_SWR 2 +/* Sequential Write Preferred zone */ +#define VIRTIO_BLK_ZT_SWP 3 + +/* + * Zone states that are available for zones of all types. + */ + +/* Not a write pointer (conventional zones only) */ +#define VIRTIO_BLK_ZS_NOT_WP 0 +/* Empty */ +#define VIRTIO_BLK_ZS_EMPTY 1 +/* Implicitly Open */ +#define VIRTIO_BLK_ZS_IOPEN 2 +/* Explicitly Open */ +#define VIRTIO_BLK_ZS_EOPEN 3 +/* Closed */ +#define VIRTIO_BLK_ZS_CLOSED 4 +/* Read-Only */ +#define VIRTIO_BLK_ZS_RDONLY 13 +/* Full */ +#define VIRTIO_BLK_ZS_FULL 14 +/* Offline */ +#define VIRTIO_BLK_ZS_OFFLINE 15 + /* Unmap this range (only valid for write zeroes command) */ #define VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP 0x00000001 =20 @@ -198,4 +300,11 @@ struct virtio_scsi_inhdr { #define VIRTIO_BLK_S_OK 0 #define VIRTIO_BLK_S_IOERR 1 #define VIRTIO_BLK_S_UNSUPP 2 + +/* Error codes that are specific to zoned block devices */ +#define VIRTIO_BLK_S_ZONE_INVALID_CMD 3 +#define VIRTIO_BLK_S_ZONE_UNALIGNED_WP 4 +#define VIRTIO_BLK_S_ZONE_OPEN_RESOURCE 5 +#define VIRTIO_BLK_S_ZONE_ACTIVE_RESOURCE 6 + #endif /* _LINUX_VIRTIO_BLK_H */ --=20 2.37.3 From nobody Sun May 5 13:29:53 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1664445828; cv=none; d=zohomail.com; s=zohoarc; b=W9Ss0YgjJKmUS5a1HzjvRavo0ygCXPuXLhW545iRVFbrz8QRkE79N8Di3r698MOBOv7eZw0NTdAyWDXw5Y6tndi31minDZZEeXZUf3oEF4c3CAM5CUQnkQ1XsG9IYsczrMviM5EzMNNJt+SVR0848G/QTz2Ru7zujTNXX8rSiZk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1664445828; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=K1ntGVwpQwsU1bse0bYbK8dSP/GMyhTPpVHaJElj3ts=; b=Wlt4DAOX5ZCeVYDEayIIZPRUhCf8bZvdNu7OurpOqnQL+IyAZxIOdoobZcXtg/xdDMIZHm8L3vh/3j/SfUevDecyncJiK6Zy8Zk8eSGBOdF3UFHEQrlRMKjn0ekQ6bncfItv4veQ5qsYQATqIu4RQffjGEf1eQHiv7QaqtljKdU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1664445828713900.911697934785; Thu, 29 Sep 2022 03:03:48 -0700 (PDT) Received: from localhost ([::1]:35500 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1odqOR-0008Vr-LP for importer@patchew.org; Thu, 29 Sep 2022 06:03:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53996) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1odq9z-0001cp-8r; Thu, 29 Sep 2022 05:48:54 -0400 Received: from mail-pg1-x52e.google.com ([2607:f8b0:4864:20::52e]:45701) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1odq9w-0004Jq-Dx; Thu, 29 Sep 2022 05:48:50 -0400 Received: by mail-pg1-x52e.google.com with SMTP id r62so965219pgr.12; Thu, 29 Sep 2022 02:48:47 -0700 (PDT) Received: from roots.. ([112.44.202.63]) by smtp.gmail.com with ESMTPSA id f4-20020a170902ce8400b00178b06fea7asm5574515plg.148.2022.09.29.02.48.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Sep 2022 02:48:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date; bh=K1ntGVwpQwsU1bse0bYbK8dSP/GMyhTPpVHaJElj3ts=; b=ObDRiWbAei0Htgy14JQQ28BWfeNrE0Yb0osOkxHFZ6hOC60nhMgzRHHjGhy4htNTwE A+KYFyteJYFTmgCc8pBhLou2l6hd/QDgXAyz83BM6NUVhH3dgdDZZ+DEohpjvww1ZUGq /0To/LVPsZe9L3m/+vKJxDAR0w+jkQKpyDMh9nRsg5tvim8UcE37tgAGO2cGKF2FG207 SqJTOkTLaCdClKkeKVq6N3PXC/TG9TpCWforolzYvmXvcmLvXuuPyEOW1rVbBBJlWZqY vD4s3YP5JH7n1lPV9a9CSKh9rtOd9McU5+XVYjflY46tnRrK0+TjbdkZq8k97DQnacR+ LXDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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; bh=K1ntGVwpQwsU1bse0bYbK8dSP/GMyhTPpVHaJElj3ts=; b=hB7CxgP+uZEM/hjvGL8t4C79ilNs4zm85K4ZXnBsaw6T0hw1z9yI43FmzvrCr8RhUT xerwA9gf8aDvmQM5ZOahET+q8heBi8ZqVZsNmoeHAiQvrdK3a2RS/ScJqWcz4EIZnVXm v3rEt2oy3Wg9ibXPjPmdELPDOhF9Q6W9cI2RAWb9J4Aq7R/x4HfMxzCnlkIkp8nUSu/R WuWboPunfnwRiVZY8tPUvbwYb6wgsYrPhzZTUbdvHlW/ICKr3RUNvqCrwBfyIPbtt5Wu FaNxXnTI615bhNWaGxAI/wJjkFC/XQOG2InWUrKGk+CQXsOEzxfcmON4nuQ0UsyLXGaB nA6g== X-Gm-Message-State: ACrzQf3EZGNnuHaNUyCSzwIr56I1MKa91ptHgJegnwv3wt3ZgJ+eFFT5 FJDQiqlnzOhzq9lsPbbFfnUDvasr16oMyA== X-Google-Smtp-Source: AMsMyM6XCdPz3KCFaa8vN2J6WWAEQk81tS+98mtYz0k04yyGzVhU0VpwMaUu1OLvQbM8nXBizRfFLw== X-Received: by 2002:a63:5a0b:0:b0:434:4748:4e7a with SMTP id o11-20020a635a0b000000b0043447484e7amr2083517pgb.561.1664444926232; Thu, 29 Sep 2022 02:48:46 -0700 (PDT) From: Sam Li To: qemu-devel@nongnu.org Cc: dmitry.fomichev@wdc.com, damien.lemoal@opensource.wdc.com, qemu-block@nongnu.org, stefanha@redhat.com, Hanna Reitz , Kevin Wolf , "Michael S. Tsirkin" , hare@suse.de, Sam Li Subject: [PATCH v2 2/2] virtio-blk: add zoned storage emulation for zoned devices Date: Thu, 29 Sep 2022 17:48:21 +0800 Message-Id: <20220929094821.78596-3-faithilikerun@gmail.com> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20220929094821.78596-1-faithilikerun@gmail.com> References: <20220929094821.78596-1-faithilikerun@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::52e; envelope-from=faithilikerun@gmail.com; helo=mail-pg1-x52e.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 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+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1664445828959100001 Content-Type: text/plain; charset="utf-8" This patch extends virtio-blk emulation to handle zoned device commands by calling the new block layer APIs to perform zoned device I/O on behalf of the guest. It supports Report Zone, four zone oparations (open, close, finish, reset), and Append Zone. The VIRTIO_BLK_F_ZONED feature bit will only be set if the host does support zoned block devices. Regular block devices(conventional zones) will not be set. The guest os having zoned device support can use blkzone(8) to test those commands. Furthermore, using zonefs to test zone append write is also supported. Signed-off-by: Sam Li --- hw/block/virtio-blk.c | 393 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 393 insertions(+) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index e9ba752f6b..1c2535bfeb 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -26,6 +26,9 @@ #include "hw/virtio/virtio-blk.h" #include "dataplane/virtio-blk.h" #include "scsi/constants.h" +#if defined(CONFIG_BLKZONED) +#include +#endif #ifdef __linux__ # include #endif @@ -46,6 +49,8 @@ static const VirtIOFeature feature_sizes[] =3D { .end =3D endof(struct virtio_blk_config, discard_sector_alignment)}, {.flags =3D 1ULL << VIRTIO_BLK_F_WRITE_ZEROES, .end =3D endof(struct virtio_blk_config, write_zeroes_may_unmap)}, + {.flags =3D 1ULL << VIRTIO_BLK_F_ZONED, + .end =3D endof(struct virtio_blk_config, zoned)}, {} }; =20 @@ -614,6 +619,340 @@ err: return err_status; } =20 +typedef struct ZoneCmdData { + VirtIOBlockReq *req; + union { + struct { + unsigned int nr_zones; + BlockZoneDescriptor *zones; + } zone_report_data; + struct { + int64_t append_sector; + } zone_append_data; + }; +} ZoneCmdData; + +/* + * check zoned_request: error checking before issuing requests. If all che= cks + * passed, return true. + * append: true if only zone append requests issued. + */ +static bool check_zoned_request(VirtIOBlock *s, int64_t offset, int64_t le= n, + bool append, uint8_t *status) { + BlockDriverState *bs =3D blk_bs(s->blk); + int index =3D offset / bs->bl.zone_size; + + if (offset < 0 || offset + len > bs->bl.capacity) { + *status =3D VIRTIO_BLK_S_ZONE_INVALID_CMD; + return false; + } + + if (!virtio_has_feature(s->host_features, VIRTIO_BLK_F_ZONED)) { + *status =3D VIRTIO_BLK_S_UNSUPP; + return false; + } + + if (append) { + if ((offset % bs->bl.write_granularity) !=3D 0) { + *status =3D VIRTIO_BLK_S_ZONE_UNALIGNED_WP; + return false; + } + + if (!BDRV_ZT_IS_SWR(bs->bl.wps->wp[index])) { + *status =3D VIRTIO_BLK_S_ZONE_INVALID_CMD; + return false; + } + + if (len / 512 > bs->bl.max_append_sectors) { + if (bs->bl.max_append_sectors =3D=3D 0) { + *status =3D VIRTIO_BLK_S_UNSUPP; + } else { + *status =3D VIRTIO_BLK_S_ZONE_INVALID_CMD; + } + return false; + } + } + return true; +} + +static void virtio_blk_zone_report_complete(void *opaque, int ret) +{ + ZoneCmdData *data =3D opaque; + VirtIOBlockReq *req =3D data->req; + VirtIOBlock *s =3D req->dev; + VirtIODevice *vdev =3D VIRTIO_DEVICE(req->dev); + struct iovec *in_iov =3D req->elem.in_sg; + unsigned in_num =3D req->elem.in_num; + int64_t zrp_size, nz, n, j =3D 0; + int8_t err_status =3D VIRTIO_BLK_S_OK; + + if (ret) { + err_status =3D VIRTIO_BLK_S_ZONE_INVALID_CMD; + goto out; + } + + nz =3D data->zone_report_data.nr_zones; + struct virtio_blk_zone_report zrp_hdr =3D (struct virtio_blk_zone_repo= rt) { + .nr_zones =3D cpu_to_le64(nz), + }; + + zrp_size =3D sizeof(struct virtio_blk_zone_report) + + sizeof(struct virtio_blk_zone_descriptor) * nz; + n =3D iov_from_buf(in_iov, in_num, 0, &zrp_hdr, sizeof(zrp_hdr)); + if (n !=3D sizeof(zrp_hdr)) { + virtio_error(vdev, "Driver provided intput buffer that is too smal= l!"); + err_status =3D VIRTIO_BLK_S_ZONE_INVALID_CMD; + goto out; + } + + for (size_t i =3D sizeof(zrp_hdr); i < zrp_size; i +=3D sizeof(struct = virtio_blk_zone_descriptor), ++j) { + struct virtio_blk_zone_descriptor desc =3D + (struct virtio_blk_zone_descriptor) { + .z_start =3D cpu_to_le64(data->zone_report_data.zo= nes[j].start) >> BDRV_SECTOR_BITS, + .z_cap =3D cpu_to_le64(data->zone_report_data.zone= s[j].cap) >> BDRV_SECTOR_BITS, + .z_wp =3D cpu_to_le64(data->zone_report_data.zones= [j].wp) >> BDRV_SECTOR_BITS, + }; + + switch (data->zone_report_data.zones[j].type) { + case BLK_ZT_CONV: + desc.z_type =3D BLK_ZONE_TYPE_CONVENTIONAL; + break; + case BLK_ZT_SWR: + desc.z_type =3D BLK_ZONE_TYPE_SEQWRITE_REQ; + break; + case BLK_ZT_SWP: + desc.z_type =3D BLK_ZONE_TYPE_SEQWRITE_PREF; + break; + default: + g_assert_not_reached(); + } + + switch (data->zone_report_data.zones[j].cond) { + case BLK_ZS_RDONLY: + desc.z_state =3D BLK_ZONE_COND_READONLY; + break; + case BLK_ZS_OFFLINE: + desc.z_state =3D BLK_ZONE_COND_OFFLINE; + break; + case BLK_ZS_EMPTY: + desc.z_state =3D BLK_ZONE_COND_EMPTY; + break; + case BLK_ZS_CLOSED: + desc.z_state =3D BLK_ZONE_COND_CLOSED; + break; + case BLK_ZS_FULL: + desc.z_state =3D BLK_ZONE_COND_FULL; + break; + case BLK_ZS_EOPEN: + desc.z_state =3D BLK_ZONE_COND_EXP_OPEN; + break; + case BLK_ZS_IOPEN: + desc.z_state =3D BLK_ZONE_COND_IMP_OPEN; + break; + case BLK_ZS_NOT_WP: + desc.z_state =3D BLK_ZONE_COND_NOT_WP; + break; + default: + g_assert_not_reached(); + break; + } + + /* TODO: it takes O(n^2) time complexity. Optimizations required h= ere. */ + n =3D iov_from_buf(in_iov, in_num, i, &desc, sizeof(desc)); + if (n !=3D sizeof(desc)) { + virtio_error(vdev, "Driver provided input buffer " + "for descriptors that is too small!"); + err_status =3D VIRTIO_BLK_S_ZONE_INVALID_CMD; + goto out; + } + } + goto out; + +out: + aio_context_acquire(blk_get_aio_context(s->conf.conf.blk)); + virtio_blk_req_complete(req, err_status); + virtio_blk_free_request(req); + aio_context_release(blk_get_aio_context(s->conf.conf.blk)); + g_free(data->zone_report_data.zones); + g_free(data); +} + +static int virtio_blk_handle_zone_report(VirtIOBlockReq *req) { + VirtIOBlock *s =3D req->dev; + VirtIODevice *vdev =3D VIRTIO_DEVICE(s); + unsigned int nr_zones; + ZoneCmdData *data; + int64_t zone_size, offset; + uint8_t err_status; + + if (req->in_len < sizeof(struct virtio_blk_inhdr) + + sizeof(struct virtio_blk_zone_report) + + sizeof(struct virtio_blk_zone_descriptor)) { + virtio_error(vdev, "in buffer too small for zone report"); + return -1; + } + + /* start byte offset of the zone report */ + offset =3D virtio_ldq_p(vdev, &req->out.sector) * 512; + if (!check_zoned_request(s, offset, 0, false, &err_status)) { + goto out; + } + + nr_zones =3D (req->in_len - sizeof(struct virtio_blk_inhdr) - + sizeof(struct virtio_blk_zone_report)) / + sizeof(struct virtio_blk_zone_descriptor); + + zone_size =3D sizeof(BlockZoneDescriptor) * nr_zones; + data =3D g_malloc(sizeof(ZoneCmdData)); + data->req =3D req; + data->zone_report_data.nr_zones =3D nr_zones; + data->zone_report_data.zones =3D g_malloc(zone_size), + + blk_aio_zone_report(s->blk, offset, &data->zone_report_data.nr_zones, + data->zone_report_data.zones, + virtio_blk_zone_report_complete, data); + return 0; + +out: + aio_context_acquire(blk_get_aio_context(s->conf.conf.blk)); + virtio_blk_req_complete(req, err_status); + virtio_blk_free_request(req); + aio_context_release(blk_get_aio_context(s->conf.conf.blk)); + return err_status; +} + +static void virtio_blk_zone_mgmt_complete(void *opaque, int ret) { + ZoneCmdData *data =3D opaque; + VirtIOBlockReq *req =3D data->req; + VirtIOBlock *s =3D req->dev; + int8_t err_status =3D VIRTIO_BLK_S_OK; + + if (ret) { + err_status =3D VIRTIO_BLK_S_ZONE_INVALID_CMD; + goto out; + } + goto out; + +out: + aio_context_acquire(blk_get_aio_context(s->conf.conf.blk)); + virtio_blk_req_complete(req, err_status); + virtio_blk_free_request(req); + aio_context_release(blk_get_aio_context(s->conf.conf.blk)); + g_free(data); +} + +static int virtio_blk_handle_zone_mgmt(VirtIOBlockReq *req, BlockZoneOp op= ) { + VirtIOBlock *s =3D req->dev; + VirtIODevice *vdev =3D VIRTIO_DEVICE(s); + BlockDriverState *bs =3D blk_bs(s->blk); + int64_t offset =3D virtio_ldq_p(vdev, &req->out.sector) * 512; + uint64_t len; + uint32_t type; + uint8_t err_status =3D VIRTIO_BLK_S_OK; + + if (!check_zoned_request(s, offset, 0, false, &err_status)) { + goto out; + } + + ZoneCmdData *data =3D g_malloc(sizeof(ZoneCmdData)); + data->req =3D req; + + type =3D virtio_ldl_p(vdev, &req->out.type); + if (type =3D=3D VIRTIO_BLK_T_ZONE_RESET_ALL) { + /* Entire drive capacity */ + offset =3D 0; + len =3D bs->bl.capacity; + } else { + if (bs->bl.zone_size * bs->bl.nr_zones =3D=3D bs->bl.capacity) { + len =3D bs->bl.zone_size; + } else { + /* when the SWR drive has one last small zone, calculate its l= en */ + len =3D bs->bl.capacity - bs->bl.zone_size * (bs->bl.nr_zones = - 1); + } + if (offset + len > bs->bl.capacity) { + err_status =3D VIRTIO_BLK_S_ZONE_INVALID_CMD; + goto out; + } + } + + blk_aio_zone_mgmt(s->blk, op, offset, len, + virtio_blk_zone_mgmt_complete, data); + + return 0; +out: + aio_context_acquire(blk_get_aio_context(s->conf.conf.blk)); + virtio_blk_req_complete(req, err_status); + virtio_blk_free_request(req); + aio_context_release(blk_get_aio_context(s->conf.conf.blk)); + return err_status; +} + +static void virtio_blk_zone_append_complete(void *opaque, int ret) { + ZoneCmdData *data =3D opaque; + VirtIOBlockReq *req =3D data->req; + VirtIOBlock *s =3D req->dev; + VirtIODevice *vdev =3D VIRTIO_DEVICE(req->dev); + int64_t append_sector, n; + struct iovec *out_iov =3D req->elem.out_sg; + unsigned out_num =3D req->elem.out_num; + uint8_t err_status =3D VIRTIO_BLK_S_OK; + + if (ret) { + err_status =3D VIRTIO_BLK_S_ZONE_INVALID_CMD; + goto out; + } + + virtio_stl_p(vdev, &append_sector, data->zone_append_data.append_secto= r); + n =3D iov_to_buf(out_iov, out_num, 0, &append_sector, sizeof(append_se= ctor)); + if (n !=3D sizeof(append_sector)) { + virtio_error(vdev, "Driver provided input buffer less than size of= " + "append_sector"); + err_status =3D VIRTIO_BLK_S_ZONE_INVALID_CMD; + goto out; + } + goto out; + +out: + aio_context_acquire(blk_get_aio_context(s->conf.conf.blk)); + virtio_blk_req_complete(req, err_status); + virtio_blk_free_request(req); + aio_context_release(blk_get_aio_context(s->conf.conf.blk)); + g_free(data); +} + +static int virtio_blk_handle_zone_append(VirtIOBlockReq *req) { + VirtIOBlock *s =3D req->dev; + VirtIODevice *vdev =3D VIRTIO_DEVICE(s); + uint64_t niov =3D req->elem.out_num; + struct iovec *out_iov =3D req->elem.out_sg; + uint8_t err_status =3D VIRTIO_BLK_S_OK; + + int64_t offset =3D virtio_ldq_p(vdev, &req->out.sector) * 512; + int64_t len =3D 0; + for (int i =3D 1; i < niov; ++i) { + len +=3D out_iov[i].iov_len; + } + + if (!check_zoned_request(s, offset, len, true, &err_status)) { + goto out; + } + + ZoneCmdData *data =3D g_malloc(sizeof(ZoneCmdData)); + data->req =3D req; + data->zone_append_data.append_sector =3D offset; + qemu_iovec_init_external(&req->qiov, &out_iov[1], niov-1); + blk_aio_zone_append(s->blk, &data->zone_append_data.append_sector, &re= q->qiov, 0, + virtio_blk_zone_append_complete, data); + return 0; + +out: + aio_context_acquire(blk_get_aio_context(s->conf.conf.blk)); + virtio_blk_req_complete(req, err_status); + virtio_blk_free_request(req); + aio_context_release(blk_get_aio_context(s->conf.conf.blk)); + return err_status; +} + static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *= mrb) { uint32_t type; @@ -700,6 +1039,24 @@ static int virtio_blk_handle_request(VirtIOBlockReq *= req, MultiReqBuffer *mrb) case VIRTIO_BLK_T_FLUSH: virtio_blk_handle_flush(req, mrb); break; + case VIRTIO_BLK_T_ZONE_REPORT: + virtio_blk_handle_zone_report(req); + break; + case VIRTIO_BLK_T_ZONE_OPEN: + virtio_blk_handle_zone_mgmt(req, BLK_ZO_OPEN); + break; + case VIRTIO_BLK_T_ZONE_CLOSE: + virtio_blk_handle_zone_mgmt(req, BLK_ZO_CLOSE); + break; + case VIRTIO_BLK_T_ZONE_FINISH: + virtio_blk_handle_zone_mgmt(req, BLK_ZO_FINISH); + break; + case VIRTIO_BLK_T_ZONE_RESET: + virtio_blk_handle_zone_mgmt(req, BLK_ZO_RESET); + break; + case VIRTIO_BLK_T_ZONE_RESET_ALL: + virtio_blk_handle_zone_mgmt(req, BLK_ZO_RESET_ALL); + break; case VIRTIO_BLK_T_SCSI_CMD: virtio_blk_handle_scsi(req); break; @@ -718,6 +1075,9 @@ static int virtio_blk_handle_request(VirtIOBlockReq *r= eq, MultiReqBuffer *mrb) virtio_blk_free_request(req); break; } + case VIRTIO_BLK_T_ZONE_APPEND & ~VIRTIO_BLK_T_OUT: + virtio_blk_handle_zone_append(req); + break; /* * VIRTIO_BLK_T_DISCARD and VIRTIO_BLK_T_WRITE_ZEROES are defined with * VIRTIO_BLK_T_OUT flag set. We masked this flag in the switch statem= ent, @@ -917,6 +1277,7 @@ static void virtio_blk_update_config(VirtIODevice *vde= v, uint8_t *config) { VirtIOBlock *s =3D VIRTIO_BLK(vdev); BlockConf *conf =3D &s->conf.conf; + BlockDriverState *bs =3D blk_bs(s->blk); struct virtio_blk_config blkcfg; uint64_t capacity; int64_t length; @@ -976,6 +1337,30 @@ static void virtio_blk_update_config(VirtIODevice *vd= ev, uint8_t *config) blkcfg.write_zeroes_may_unmap =3D 1; virtio_stl_p(vdev, &blkcfg.max_write_zeroes_seg, 1); } + if (bs->bl.zoned !=3D BLK_Z_NONE) { + switch (bs->bl.zoned) { + case BLK_Z_HM: + blkcfg.zoned.model =3D VIRTIO_BLK_Z_HM; + break; + case BLK_Z_HA: + blkcfg.zoned.model =3D VIRTIO_BLK_Z_HA; + break; + default: + g_assert_not_reached(); + } + + virtio_stl_p(vdev, &blkcfg.zoned.zone_sectors, + bs->bl.zone_size / 512); + virtio_stl_p(vdev, &blkcfg.zoned.max_active_zones, + bs->bl.max_active_zones); + virtio_stl_p(vdev, &blkcfg.zoned.max_open_zones, + bs->bl.max_open_zones); + virtio_stl_p(vdev, &blkcfg.zoned.write_granularity, blk_size); + virtio_stl_p(vdev, &blkcfg.zoned.max_append_sectors, + bs->bl.max_append_sectors); + } else { + blkcfg.zoned.model =3D VIRTIO_BLK_Z_NONE; + } memcpy(config, &blkcfg, s->config_size); } =20 @@ -1140,6 +1525,7 @@ static void virtio_blk_device_realize(DeviceState *de= v, Error **errp) VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); VirtIOBlock *s =3D VIRTIO_BLK(dev); VirtIOBlkConf *conf =3D &s->conf; + BlockDriverState *bs =3D blk_bs(conf->conf.blk); Error *err =3D NULL; unsigned i; =20 @@ -1185,6 +1571,13 @@ static void virtio_blk_device_realize(DeviceState *d= ev, Error **errp) return; } =20 + if (bs->bl.zoned !=3D BLK_Z_NONE) { + virtio_add_feature(&s->host_features, VIRTIO_BLK_F_ZONED); + if (bs->bl.zoned =3D=3D BLK_Z_HM) { + virtio_clear_feature(&s->host_features, VIRTIO_BLK_F_DISCARD); + } + } + if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_DISCARD) && (!conf->max_discard_sectors || conf->max_discard_sectors > BDRV_REQUEST_MAX_SECTORS)) { --=20 2.37.3