From patchwork Fri Aug 26 16:03:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Li X-Patchwork-Id: 12956262 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 5E131ECAAA3 for ; Fri, 26 Aug 2022 16:13:33 +0000 (UTC) Received: from localhost ([::1]:39904 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oRbxc-00027C-Dj for qemu-devel@archiver.kernel.org; Fri, 26 Aug 2022 12:13:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:54124) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oRbor-0002cb-No; Fri, 26 Aug 2022 12:04:30 -0400 Received: from mail-pf1-x435.google.com ([2607:f8b0:4864:20::435]:43703) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oRbom-0005NG-2t; Fri, 26 Aug 2022 12:04:25 -0400 Received: by mail-pf1-x435.google.com with SMTP id 142so1940302pfu.10; Fri, 26 Aug 2022 09:04:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc; bh=M+DatxmpZVPjexrzp79M4RQhH3Af/G9By4KEv/QeAgQ=; b=jio+ySrN6XLqf6846aO2H8jV0NhUTwqr/2z28yw0RvwS4ZsjdgbRovsquYdoLfDLef iEHTl8TkULVsdPLsFdmVWcCYmkhfY8Pz0way8W9CzkEZnkEZ4OsrgYfcTxMpgycCXtBo gagasZ4xY5q+NXUvu/CyeMyqvMEwqq77thDsr25Yoy88yVJh2BqxQCnJz3TvqzROb83c 21SKFykOmMSNiLLxG7U3dqwPoKFwSkWmimF4OMLhd/VFQSGONKpxn3okaRDQayq9/sMF 08Ud5UzTi8PnTxnFc+zi+eu85+hI/YE3Tt2qkWpjA5SuxFL69l5ZPGQ/EoDjFUxL27lY YyOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc; bh=M+DatxmpZVPjexrzp79M4RQhH3Af/G9By4KEv/QeAgQ=; b=vChH5iwYMXiwt0GqqmnOJ/3Co6RKdvjx5gAZnaBdZ/r0Je3jd4IUfTjzBWdYGOAiFC MwWK2ZREtvwag34fkTN0OTpbirWVI1C74PeJDNL3Stk4sr5+U1zn7TAEACDMgwLnwBCa TY2Okk6EJDufZjlcj4kMARgrKdukWHJa0iYF5HEmPLYwsBJDJZZnVcrijCQQDVeS1HGV SiM13H3dl6ei4WQYD7EAaHPZee1GS7nZNNXEcruJ7zy+LgiyWtuQfO0gBuRFun6A1DbX U5NCOfO7Xc3YpaZQy3qx3xlkwhay20cNoTGc/zXxntjQP33gc18vvGZi2s4/p7CpHQww CfhA== X-Gm-Message-State: ACgBeo0EjRXjS++9rM6ISLHcauBZYRBmtj2n+iThxcMy8jYiBwmlpntA 726Or3NSlz+4FsuwJa5Aktn7xIOdR/LWLw== X-Google-Smtp-Source: AA6agR7whGm5/vY30eibA3wApwlTKYJBb5c+r0TIJrqEw2wf/R7yvEZ9CZFlBx0X+tPUmvz6OFNOqg== X-Received: by 2002:a63:b03:0:b0:429:c549:d1f1 with SMTP id 3-20020a630b03000000b00429c549d1f1mr3823298pgl.131.1661529861268; Fri, 26 Aug 2022 09:04:21 -0700 (PDT) Received: from roots.. ([106.84.135.2]) by smtp.gmail.com with ESMTPSA id z14-20020a1709027e8e00b00172f0184b54sm1732002pla.156.2022.08.26.09.04.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 26 Aug 2022 09:04:20 -0700 (PDT) From: Sam Li To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, damien.lemoal@opensource.wdc.com, Dmitry.Fomichev@wdc.com, hare@suse.de, qemu-block@nongnu.org, hreitz@redhat.com, eblake@redhat.com, armbru@redhat.com, fam@euphon.net, kwolf@redhat.com, Sam Li Subject: [PATCH v8 1/7] include: add zoned device structs Date: Sat, 27 Aug 2022 00:03:56 +0800 Message-Id: <20220826160356.6437-1-faithilikerun@gmail.com> X-Mailer: git-send-email 2.37.2 MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::435; envelope-from=faithilikerun@gmail.com; helo=mail-pf1-x435.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" Signed-off-by: Sam Li Reviewed-by: Stefan Hajnoczi Reviewed-by: Damien Le Moal --- include/block/block-common.h | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/include/block/block-common.h b/include/block/block-common.h index fdb7306e78..36bd0e480e 100644 --- a/include/block/block-common.h +++ b/include/block/block-common.h @@ -49,6 +49,49 @@ typedef struct BlockDriver BlockDriver; typedef struct BdrvChild BdrvChild; typedef struct BdrvChildClass BdrvChildClass; +typedef enum BlockZoneOp { + BLK_ZO_OPEN, + BLK_ZO_CLOSE, + BLK_ZO_FINISH, + BLK_ZO_RESET, +} BlockZoneOp; + +typedef enum BlockZoneModel { + BLK_Z_NONE = 0x0, /* Regular block device */ + BLK_Z_HM = 0x1, /* Host-managed zoned block device */ + BLK_Z_HA = 0x2, /* Host-aware zoned block device */ +} BlockZoneModel; + +typedef enum BlockZoneCondition { + BLK_ZS_NOT_WP = 0x0, + BLK_ZS_EMPTY = 0x1, + BLK_ZS_IOPEN = 0x2, + BLK_ZS_EOPEN = 0x3, + BLK_ZS_CLOSED = 0x4, + BLK_ZS_RDONLY = 0xD, + BLK_ZS_FULL = 0xE, + BLK_ZS_OFFLINE = 0xF, +} BlockZoneCondition; + +typedef enum BlockZoneType { + BLK_ZT_CONV = 0x1, /* Conventional random writes supported */ + BLK_ZT_SWR = 0x2, /* Sequential writes required */ + BLK_ZT_SWP = 0x3, /* Sequential writes preferred */ +} BlockZoneType; + +/* + * Zone descriptor data structure. + * Provides information on a zone with all position and size values in bytes. + */ +typedef struct BlockZoneDescriptor { + uint64_t start; + uint64_t length; + uint64_t cap; + uint64_t wp; + BlockZoneType type; + BlockZoneCondition cond; +} BlockZoneDescriptor; + typedef struct BlockDriverInfo { /* in bytes, 0 if irrelevant */ int cluster_size; From patchwork Fri Aug 26 16:11:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Li X-Patchwork-Id: 12956266 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 2829FECAAD4 for ; Fri, 26 Aug 2022 16:24:24 +0000 (UTC) Received: from localhost ([::1]:34474 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oRc87-0004Yl-8t for qemu-devel@archiver.kernel.org; Fri, 26 Aug 2022 12:24:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51560) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oRbvj-0008Bw-RC; Fri, 26 Aug 2022 12:11:37 -0400 Received: from mail-pf1-x431.google.com ([2607:f8b0:4864:20::431]:35588) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oRbvg-0006yS-RV; Fri, 26 Aug 2022 12:11:34 -0400 Received: by mail-pf1-x431.google.com with SMTP id 199so1923295pfz.2; Fri, 26 Aug 2022 09:11:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc; bh=TiPxsOAYUYaytu8tcsbPD1oFoyNqMEh6TzFeGR7L5BQ=; b=Kw71fTCNUnBlDbQHegmJH2vc1L2uLnO+qSyDHNZJ3AIgkr3ECbDx3+ZARnuk2AjhbW zoDdiQecHjQIoQy16DYX1zzWHQotLrjJbz1+xP4ZuERitYTAcJT4LXrNcxDCzkux+3J3 IBBssN3p53Mp1gO4IjFg/SJKH3fN3QXX+zaO7C9F4ALWbgCjfWGwWzgD+NBOvGsp6zaS dhLyo4wq3gfFV9tS8VmFO655G9/F/RVTKZ0+cP1nvszk1gjSIm8xVH1T4Se6rhxP5ra0 JG6kkzF401d01It93JdXGBeqqSgWWD2HUgTp+XFOPxHSNJFhpd8liSscDTVkWQ/TcESa FU8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc; bh=TiPxsOAYUYaytu8tcsbPD1oFoyNqMEh6TzFeGR7L5BQ=; b=cGjho76s//JENOtdCyoOj52yioK6WZQdA2AuK/GDRvrxoE/2flDn5UDub5CXqB5Hfe 2SUQQjoL2lfLmPlF7banl9aAQxLlV2gRKRix8pkDDJlReSGa1h8tUkjOnXaEQKcBFZD6 SIuEB/OiEPNFwOVGcOuPwdgWbD6Cq5KkC/m7ZWzunxykGagqygK7xSc+b/SPcozrB7zi 5fy7/x00ebMe9VdEpQzMQmnPouDCJ6yk0crD9MGhiMHgM7BkPJlE0wp6u0I7gN3Qvasg o9u7lgKMqGLswVhfh1fxDZopWKMrYyxpl2Ae5iPIytM5aXsnnAzykIB8oTdb/cYcdCJr KIVg== X-Gm-Message-State: ACgBeo3SG3Mh+ZlvKsCv8m4LuqBvgA4Usa4XZCXq8eHSeysxMXrEGXc8 HiSZ65WccQigmthaM2JgU/QJhejjVWoqzA== X-Google-Smtp-Source: AA6agR77cvD1+iNK/TaOgNFryiVbe8GfgtO1BeJeaDRJlsMbre0VSlA6nZ2WLABK8vQhnaD+BkW0EA== X-Received: by 2002:a63:5fc2:0:b0:429:fe35:1bd6 with SMTP id t185-20020a635fc2000000b00429fe351bd6mr3785443pgb.315.1661530290792; Fri, 26 Aug 2022 09:11:30 -0700 (PDT) Received: from roots.. ([106.84.135.2]) by smtp.gmail.com with ESMTPSA id m15-20020a17090a2c0f00b001ef81574355sm1864587pjd.12.2022.08.26.09.11.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 26 Aug 2022 09:11:30 -0700 (PDT) From: Sam Li To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, damien.lemoal@opensource.wdc.com, Dmitry.Fomichev@wdc.com, hare@suse.de, qemu-block@nongnu.org, hreitz@redhat.com, eblake@redhat.com, armbru@redhat.com, fam@euphon.net, kwolf@redhat.com, Sam Li Subject: [PATCH v8 2/7] file-posix: introduce helper funcations for sysfs attributes Date: Sat, 27 Aug 2022 00:11:21 +0800 Message-Id: <20220826161121.7691-1-faithilikerun@gmail.com> X-Mailer: git-send-email 2.37.2 MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::431; envelope-from=faithilikerun@gmail.com; helo=mail-pf1-x431.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" Use get_sysfs_str_val() to get the string value of device zoned model. Then get_sysfs_zoned_model() can convert it to BlockZoneModel type in QEMU. Use get_sysfs_long_val() to get the long value of zoned device information. Signed-off-by: Sam Li Reviewed-by: Hannes Reinecke Reviewed-by: Stefan Hajnoczi --- block/file-posix.c | 121 ++++++++++++++++++++++--------- include/block/block_int-common.h | 3 + 2 files changed, 88 insertions(+), 36 deletions(-) diff --git a/block/file-posix.c b/block/file-posix.c index 48cd096624..0a8b4b426e 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -1210,66 +1210,109 @@ static int hdev_get_max_hw_transfer(int fd, struct stat *st) #endif } -static int hdev_get_max_segments(int fd, struct stat *st) -{ +/* + * Get a sysfs attribute value as character string. + */ +static int get_sysfs_str_val(struct stat *st, const char *attribute, + char **val) { #ifdef CONFIG_LINUX - char buf[32]; - const char *end; - char *sysfspath = NULL; + g_autofree char *sysfspath = NULL; int ret; - int sysfd = -1; - long max_segments; + size_t len; - if (S_ISCHR(st->st_mode)) { - if (ioctl(fd, SG_GET_SG_TABLESIZE, &ret) == 0) { - return ret; - } + if (!S_ISBLK(st->st_mode)) { return -ENOTSUP; } - if (!S_ISBLK(st->st_mode)) { - return -ENOTSUP; + sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/%s", + major(st->st_rdev), minor(st->st_rdev), + attribute); + ret = g_file_get_contents(sysfspath, val, &len, NULL); + if (ret == -1) { + return -ENOENT; } - sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/max_segments", - major(st->st_rdev), minor(st->st_rdev)); - sysfd = open(sysfspath, O_RDONLY); - if (sysfd == -1) { - ret = -errno; - goto out; + /* The file is ended with '\n' */ + char *p; + p = *val; + if (*(p + len - 1) == '\n') { + *(p + len - 1) = '\0'; } - do { - ret = read(sysfd, buf, sizeof(buf) - 1); - } while (ret == -1 && errno == EINTR); + return ret; +#else + return -ENOTSUP; +#endif +} + +static int get_sysfs_zoned_model(struct stat *st, BlockZoneModel *zoned) { + g_autofree char *val = NULL; + int ret; + + ret = get_sysfs_str_val(st, "zoned", &val); if (ret < 0) { - ret = -errno; - goto out; - } else if (ret == 0) { - ret = -EIO; - goto out; + return ret; } - buf[ret] = 0; - /* The file is ended with '\n', pass 'end' to accept that. */ - ret = qemu_strtol(buf, &end, 10, &max_segments); - if (ret == 0 && end && *end == '\n') { - ret = max_segments; + + if (strcmp(val, "host-managed") == 0) { + *zoned = BLK_Z_HM; + } else if (strcmp(val, "host-aware") == 0) { + *zoned = BLK_Z_HA; + } else if (strcmp(val, "none") == 0) { + *zoned = BLK_Z_NONE; + } else { + return -ENOTSUP; } + return 0; +} -out: - if (sysfd != -1) { - close(sysfd); +/* + * Get a sysfs attribute value as a long integer. + */ +static long get_sysfs_long_val(struct stat *st, const char *attribute) { +#ifdef CONFIG_LINUX + g_autofree char *str = NULL; + const char *end; + long val; + int ret; + + ret = get_sysfs_str_val(st, attribute, &str); + if (ret < 0) { + return ret; + } + + /* The file is ended with '\n', pass 'end' to accept that. */ + ret = qemu_strtol(str, &end, 10, &val); + if (ret == 0 && end && *end == '\0') { + ret = val; } - g_free(sysfspath); return ret; #else return -ENOTSUP; #endif } +static int hdev_get_max_segments(int fd, struct stat *st) { +#ifdef CONFIG_LINUX + int ret; + + if (S_ISCHR(st->st_mode)) { + if (ioctl(fd, SG_GET_SG_TABLESIZE, &ret) == 0) { + return ret; + } + return -ENOTSUP; + } + return get_sysfs_long_val(st, "max_segments"); +#else + return -ENOTSUP; +#endif +} + static void raw_refresh_limits(BlockDriverState *bs, Error **errp) { BDRVRawState *s = bs->opaque; struct stat st; + int ret; + BlockZoneModel zoned; s->needs_alignment = raw_needs_alignment(bs); raw_probe_alignment(bs, s->fd, errp); @@ -1307,6 +1350,12 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp) bs->bl.max_hw_iov = ret; } } + + ret = get_sysfs_zoned_model(&st, &zoned); + if (ret < 0) { + zoned = BLK_Z_NONE; + } + bs->bl.zoned = zoned; } static int check_for_dasd(int fd) diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 8947abab76..7f7863cc9e 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -825,6 +825,9 @@ typedef struct BlockLimits { /* maximum number of iovec elements */ int max_iov; + + /* device zone model */ + BlockZoneModel zoned; } BlockLimits; typedef struct BdrvOpBlocker BdrvOpBlocker; From patchwork Fri Aug 26 16:17:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Li X-Patchwork-Id: 12956274 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 5BBCEECAAA3 for ; Fri, 26 Aug 2022 16:27:55 +0000 (UTC) Received: from localhost ([::1]:35848 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oRcBW-0002P6-CW for qemu-devel@archiver.kernel.org; Fri, 26 Aug 2022 12:27:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38580) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oRc1g-0007Q6-6W; Fri, 26 Aug 2022 12:17:44 -0400 Received: from mail-pf1-x42e.google.com ([2607:f8b0:4864:20::42e]:42747) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oRc1X-0007ny-Qe; Fri, 26 Aug 2022 12:17:38 -0400 Received: by mail-pf1-x42e.google.com with SMTP id 72so1978299pfx.9; Fri, 26 Aug 2022 09:17:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc; bh=pjOAf3meefboePFVroJJ3QSKny8Lth68dMMtBVuEGYA=; b=mTL2mk9gq+uOP8UfyoK98TC/Oa4YUF8TkDWmQxv/t6ufymWOZTey+YmNXuakXVzUJ5 C5QTAoQdySAQnakhgkw1E/FH2VF2OtqqVcyvjAAwnGTKy0EGoCg61gQ1WZTIJ8QYfme4 2NS0oe1kHfdZoDZUhz4EKmS2BdHGgtALhQK3GS8m3R3CN4A1sEIgS7NFcBvuk9ZxAq6p iBMpDz6DWt3l9AqcLkrjBFzCmaIPGUNEXBGX6LO/0sz4FXEBa0t9WX90m3qF83ZpoRH3 F8UqtKU5ZrZ4y+gMUoZehqv8bwBq8igGNpIerWYmjKwlmiYPT9cvqrC1ECOZRtjukn6K 6y2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc; bh=pjOAf3meefboePFVroJJ3QSKny8Lth68dMMtBVuEGYA=; b=os60Sgc53eruTT2U/RleZskuaLxsxmCg+6c61yHhtKUDFLw95hrJVy7t4SgSpe4lyl QTBIG0AnwC2jymFGDbM4MJE8Rue4/GMiZlejRUey6hklqMXcUS2pF35gRNdVswQ8iX49 jyFatA3Pey5Nma734T6xmZcyI1AclHKX7MSFvZth5ty0W1g/w8s/v7Xdl5nDQ1IUkjWE 10UwzVwEzgKly5FLsojYa4M0Mw34f2ENjcRSVNn4xHFPc1stLqxaQpYTjZr6GpXEdwMi NgswfJkDbvPf+t/G1nLpM3bKJ4fNi5EEjL4Od0rYFOuxk9f3fYFDaTyUx0yZxQIfm3VN YmFg== X-Gm-Message-State: ACgBeo21tBMiDUzNhkAsX/Rb1zL8saHjG8sK836ZH981iEQiSxpWeyxw 9djDa0lzqMbtpPrTI2J7tlOX3TrB1L3fSg== X-Google-Smtp-Source: AA6agR5D+7xchBJzoz94bqm3ebiaNILi1vLyEtKmlN74zkPhTD2jLIxlnHyazkFqQWk1bzXwCMcugA== X-Received: by 2002:aa7:9ac5:0:b0:537:e34f:c09c with SMTP id x5-20020aa79ac5000000b00537e34fc09cmr332885pfp.63.1661530653498; Fri, 26 Aug 2022 09:17:33 -0700 (PDT) Received: from roots.. ([106.84.135.2]) by smtp.gmail.com with ESMTPSA id p9-20020a1709027ec900b00172c7d6badcsm1751483plb.251.2022.08.26.09.17.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 26 Aug 2022 09:17:32 -0700 (PDT) From: Sam Li To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, damien.lemoal@opensource.wdc.com, Dmitry.Fomichev@wdc.com, hare@suse.de, qemu-block@nongnu.org, hreitz@redhat.com, eblake@redhat.com, armbru@redhat.com, fam@euphon.net, kwolf@redhat.com, Sam Li Subject: [PATCH v8 3/7] block: add block layer APIs resembling Linux ZonedBlockDevice ioctls Date: Sat, 27 Aug 2022 00:17:04 +0800 Message-Id: <20220826161704.8076-1-faithilikerun@gmail.com> X-Mailer: git-send-email 2.37.2 MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::42e; envelope-from=faithilikerun@gmail.com; helo=mail-pf1-x42e.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" By adding zone management operations in BlockDriver, storage controller emulation can use the new block layer APIs including Report Zone and four zone management operations (open, close, finish, reset). Add zoned storage commands of the device: zone_report(zrp), zone_open(zo), zone_close(zc), zone_reset(zrs), zone_finish(zf). For example, to test zone_report, use following command: $ ./build/qemu-io --image-opts driver=zoned_host_device, filename=/dev/nullb0 -c "zrp offset nr_zones" Signed-off-by: Sam Li Reviewed-by: Hannes Reinecke --- block/block-backend.c | 51 +++++ block/file-posix.c | 326 +++++++++++++++++++++++++++++- block/io.c | 41 ++++ include/block/block-io.h | 7 + include/block/block_int-common.h | 21 ++ include/block/raw-aio.h | 6 +- include/sysemu/block-backend-io.h | 17 ++ meson.build | 1 + qapi/block-core.json | 8 +- qemu-io-cmds.c | 143 +++++++++++++ 10 files changed, 617 insertions(+), 4 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index d4a5df2ac2..c5798651df 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1775,6 +1775,57 @@ int coroutine_fn blk_co_flush(BlockBackend *blk) return ret; } +/* + * Send a zone_report command. + * offset is a byte offset from the start of the device. No alignment + * required for offset. + * nr_zones represents IN maximum and OUT actual. + */ +int coroutine_fn blk_co_zone_report(BlockBackend *blk, int64_t offset, + unsigned int *nr_zones, + BlockZoneDescriptor *zones) +{ + int ret; + IO_CODE(); + + blk_inc_in_flight(blk); /* increase before waiting */ + blk_wait_while_drained(blk); + if (!blk_is_available(blk)) { + blk_dec_in_flight(blk); + return -ENOMEDIUM; + } + ret = bdrv_co_zone_report(blk_bs(blk), offset, nr_zones, zones); + blk_dec_in_flight(blk); + return ret; +} + +/* + * Send a zone_management command. + * op is the zone operation. + * offset is the starting zone specified as a sector offset. + * len is the maximum number of sectors the command should operate on. It + * should be aligned with the zone sector size. + */ +int coroutine_fn blk_co_zone_mgmt(BlockBackend *blk, BlockZoneOp op, + int64_t offset, int64_t len) +{ + int ret; + IO_CODE(); + + + blk_inc_in_flight(blk); + blk_wait_while_drained(blk); + + ret = blk_check_byte_request(blk, offset, len); + if (ret < 0) { + return ret; + } + + ret = bdrv_co_zone_mgmt(blk_bs(blk), op, offset, len); + blk_dec_in_flight(blk); + return ret; +} + void blk_drain(BlockBackend *blk) { BlockDriverState *bs = blk_bs(blk); diff --git a/block/file-posix.c b/block/file-posix.c index 0a8b4b426e..e3efba6db7 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -67,6 +67,9 @@ #include #include #include +#if defined(CONFIG_BLKZONED) +#include +#endif #include #include #include @@ -216,6 +219,13 @@ typedef struct RawPosixAIOData { PreallocMode prealloc; Error **errp; } truncate; + struct { + unsigned int *nr_zones; + BlockZoneDescriptor *zones; + } zone_report; + struct { + unsigned long zone_op; + } zone_mgmt; }; } RawPosixAIOData; @@ -1339,7 +1349,7 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp) #endif if (bs->sg || S_ISBLK(st.st_mode)) { - int ret = hdev_get_max_hw_transfer(s->fd, &st); + ret = hdev_get_max_hw_transfer(s->fd, &st); if (ret > 0 && ret <= BDRV_REQUEST_MAX_BYTES) { bs->bl.max_hw_transfer = ret; @@ -1356,6 +1366,27 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp) zoned = BLK_Z_NONE; } bs->bl.zoned = zoned; + if (zoned != BLK_Z_NONE) { + ret = get_sysfs_long_val(&st, "chunk_sectors"); + if (ret > 0) { + bs->bl.zone_sectors = ret; + } + + ret = get_sysfs_long_val(&st, "zone_append_max_bytes"); + if (ret > 0) { + bs->bl.zone_append_max_bytes = ret; + } + + ret = get_sysfs_long_val(&st, "max_open_zones"); + if (ret >= 0) { + bs->bl.max_open_zones = ret; + } + + ret = get_sysfs_long_val(&st, "max_active_zones"); + if (ret >= 0) { + bs->bl.max_active_zones = ret; + } + } } static int check_for_dasd(int fd) @@ -1850,6 +1881,136 @@ static off_t copy_file_range(int in_fd, off_t *in_off, int out_fd, } #endif +/* + * parse_zone - Fill a zone descriptor + */ +#if defined(CONFIG_BLKZONED) +static inline void parse_zone(struct BlockZoneDescriptor *zone, + const struct blk_zone *blkz) { + zone->start = blkz->start; + zone->length = blkz->len; + zone->cap = blkz->capacity; + zone->wp = blkz->wp; + + switch (blkz->type) { + case BLK_ZONE_TYPE_SEQWRITE_REQ: + zone->type = BLK_ZT_SWR; + break; + case BLK_ZONE_TYPE_SEQWRITE_PREF: + zone->type = BLK_ZT_SWP; + break; + case BLK_ZONE_TYPE_CONVENTIONAL: + zone->type = BLK_ZT_CONV; + break; + default: + g_assert_not_reached(); + } + + switch (blkz->cond) { + case BLK_ZONE_COND_NOT_WP: + zone->cond = BLK_ZS_NOT_WP; + break; + case BLK_ZONE_COND_EMPTY: + zone->cond = BLK_ZS_EMPTY; + break; + case BLK_ZONE_COND_IMP_OPEN: + zone->cond =BLK_ZS_IOPEN; + break; + case BLK_ZONE_COND_EXP_OPEN: + zone->cond = BLK_ZS_EOPEN; + break; + case BLK_ZONE_COND_CLOSED: + zone->cond = BLK_ZS_CLOSED; + break; + case BLK_ZONE_COND_READONLY: + zone->cond = BLK_ZS_RDONLY; + break; + case BLK_ZONE_COND_FULL: + zone->cond = BLK_ZS_FULL; + break; + case BLK_ZONE_COND_OFFLINE: + zone->cond = BLK_ZS_OFFLINE; + break; + default: + g_assert_not_reached(); + } +} +#endif + +static int handle_aiocb_zone_report(void *opaque) { +#if defined(CONFIG_BLKZONED) + RawPosixAIOData *aiocb = opaque; + int fd = aiocb->aio_fildes; + unsigned int *nr_zones = aiocb->zone_report.nr_zones; + BlockZoneDescriptor *zones = aiocb->zone_report.zones; + /* zoned block devices use 512-byte sectors */ + int64_t sector = aiocb->aio_offset / 512; + + struct blk_zone *blkz; + int64_t rep_size; + unsigned int nrz; + int ret, n = 0, i = 0; + + nrz = *nr_zones; + rep_size = sizeof(struct blk_zone_report) + nrz * sizeof(struct blk_zone); + g_autofree struct blk_zone_report *rep = NULL; + rep = g_malloc(rep_size); + + blkz = (struct blk_zone *)(rep + 1); + while (n < nrz) { + memset(rep, 0, rep_size); + rep->sector = sector; + rep->nr_zones = nrz - n; + + do { + ret = ioctl(fd, BLKREPORTZONE, rep); + } while (ret != 0 && errno == EINTR); + if (ret != 0) { + error_report("%d: ioctl BLKREPORTZONE at %" PRId64 " failed %d", + fd, sector, errno); + return -errno; + } + + if (!rep->nr_zones) { + break; + } + + for (i = 0; i < rep->nr_zones; i++, n++) { + parse_zone(&zones[n], &blkz[i]); + /* The next report should start after the last zone reported */ + sector = blkz[i].start + blkz[i].len; + } + } + + *nr_zones = n; + return 0; +#else + return -ENOTSUP; +#endif +} + +static int handle_aiocb_zone_mgmt(void *opaque) { +#if defined(CONFIG_BLKZONED) + RawPosixAIOData *aiocb = opaque; + int fd = aiocb->aio_fildes; + int64_t sector = aiocb->aio_offset; + int64_t nr_sectors = aiocb->aio_nbytes; + struct blk_zone_range range; + int ret; + + /* Execute the operation */ + range.sector = sector; + range.nr_sectors = nr_sectors; + do { + ret = ioctl(fd, aiocb->zone_mgmt.zone_op, &range); + } while (ret != 0 && errno == EINTR); + + return ret; +#else + return -ENOTSUP; +#endif +} + static int handle_aiocb_copy_range(void *opaque) { RawPosixAIOData *aiocb = opaque; @@ -3022,6 +3183,118 @@ static void raw_account_discard(BDRVRawState *s, uint64_t nbytes, int ret) } } +/* + * zone report - Get a zone block device's information in the form + * of an array of zone descriptors. + * + * @param bs: passing zone block device file descriptor + * @param zones: an array of zone descriptors to hold zone + * information on reply + * @param offset: offset can be any byte within the zone size. + * @param len: (not sure yet. + * @return 0 on success, -1 on failure + */ +static int coroutine_fn raw_co_zone_report(BlockDriverState *bs, int64_t offset, + unsigned int *nr_zones, + BlockZoneDescriptor *zones) { +#if defined(CONFIG_BLKZONED) + BDRVRawState *s = bs->opaque; + RawPosixAIOData acb; + + acb = (RawPosixAIOData) { + .bs = bs, + .aio_fildes = s->fd, + .aio_type = QEMU_AIO_ZONE_REPORT, + .aio_offset = offset, + .zone_report = { + .nr_zones = nr_zones, + .zones = zones, + }, + }; + + return raw_thread_pool_submit(bs, handle_aiocb_zone_report, &acb); +#else + return -ENOTSUP; +#endif +} + +/* + * zone management operations - Execute an operation on a zone + */ +static int coroutine_fn raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op, + int64_t offset, int64_t len) { +#if defined(CONFIG_BLKZONED) + BDRVRawState *s = bs->opaque; + RawPosixAIOData acb; + int64_t zone_sector, zone_sector_mask; + const char *ioctl_name; + unsigned long zone_op; + int ret; + + struct stat st; + if (fstat(s->fd, &st) < 0) { + ret = -errno; + return ret; + } + zone_sector = bs->bl.zone_sectors; + zone_sector_mask = zone_sector - 1; + if (offset & zone_sector_mask) { + error_report("sector offset %" PRId64 " is not aligned to zone size " + "%" PRId64 "", offset, zone_sector); + return -EINVAL; + } + + if (len & zone_sector_mask) { + error_report("number of sectors %" PRId64 " is not aligned to zone size" + " %" PRId64 "", len, zone_sector); + return -EINVAL; + } + + switch (op) { + case BLK_ZO_OPEN: + ioctl_name = "BLKOPENZONE"; + zone_op = BLKOPENZONE; + break; + case BLK_ZO_CLOSE: + ioctl_name = "BLKCLOSEZONE"; + zone_op = BLKCLOSEZONE; + break; + case BLK_ZO_FINISH: + ioctl_name = "BLKFINISHZONE"; + zone_op = BLKFINISHZONE; + break; + case BLK_ZO_RESET: + ioctl_name = "BLKRESETZONE"; + zone_op = BLKRESETZONE; + break; + default: + error_report("Invalid zone operation 0x%x", op); + return -EINVAL; + } + + acb = (RawPosixAIOData) { + .bs = bs, + .aio_fildes = s->fd, + .aio_type = QEMU_AIO_ZONE_MGMT, + .aio_offset = offset, + .aio_nbytes = len, + .zone_mgmt = { + .zone_op = zone_op, + }, + }; + + ret = raw_thread_pool_submit(bs, handle_aiocb_zone_mgmt, &acb); + if (ret != 0) { + error_report("ioctl %s failed %d", ioctl_name, errno); + return -errno; + } + + return ret; +#else + return -ENOTSUP; +#endif +} + static coroutine_fn int raw_do_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes, bool blkdev) @@ -3752,6 +4025,54 @@ static BlockDriver bdrv_host_device = { #endif }; +#if defined(CONFIG_BLKZONED) +static BlockDriver bdrv_zoned_host_device = { + .format_name = "zoned_host_device", + .protocol_name = "zoned_host_device", + .instance_size = sizeof(BDRVRawState), + .bdrv_needs_filename = true, + .bdrv_probe_device = hdev_probe_device, + .bdrv_file_open = hdev_open, + .bdrv_close = raw_close, + .bdrv_reopen_prepare = raw_reopen_prepare, + .bdrv_reopen_commit = raw_reopen_commit, + .bdrv_reopen_abort = raw_reopen_abort, + .bdrv_co_create_opts = bdrv_co_create_opts_simple, + .create_opts = &bdrv_create_opts_simple, + .mutable_opts = mutable_opts, + .bdrv_co_invalidate_cache = raw_co_invalidate_cache, + .bdrv_co_pwrite_zeroes = hdev_co_pwrite_zeroes, + + .bdrv_co_preadv = raw_co_preadv, + .bdrv_co_pwritev = raw_co_pwritev, + .bdrv_co_flush_to_disk = raw_co_flush_to_disk, + .bdrv_co_pdiscard = hdev_co_pdiscard, + .bdrv_co_copy_range_from = raw_co_copy_range_from, + .bdrv_co_copy_range_to = raw_co_copy_range_to, + .bdrv_refresh_limits = raw_refresh_limits, + .bdrv_io_plug = raw_aio_plug, + .bdrv_io_unplug = raw_aio_unplug, + .bdrv_attach_aio_context = raw_aio_attach_aio_context, + + .bdrv_co_truncate = raw_co_truncate, + .bdrv_getlength = raw_getlength, + .bdrv_get_info = raw_get_info, + .bdrv_get_allocated_file_size + = raw_get_allocated_file_size, + .bdrv_get_specific_stats = hdev_get_specific_stats, + .bdrv_check_perm = raw_check_perm, + .bdrv_set_perm = raw_set_perm, + .bdrv_abort_perm_update = raw_abort_perm_update, + .bdrv_probe_blocksizes = hdev_probe_blocksizes, + .bdrv_probe_geometry = hdev_probe_geometry, + .bdrv_co_ioctl = hdev_co_ioctl, + + /* zone management operations */ + .bdrv_co_zone_report = raw_co_zone_report, + .bdrv_co_zone_mgmt = raw_co_zone_mgmt, +}; +#endif + #if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) static void cdrom_parse_filename(const char *filename, QDict *options, Error **errp) @@ -4012,6 +4333,9 @@ static void bdrv_file_init(void) bdrv_register(&bdrv_file); #if defined(HAVE_HOST_BLOCK_DEVICE) bdrv_register(&bdrv_host_device); +#if defined(CONFIG_BLKZONED) + bdrv_register(&bdrv_zoned_host_device); +#endif #ifdef __linux__ bdrv_register(&bdrv_host_cdrom); #endif diff --git a/block/io.c b/block/io.c index 0a8cbefe86..de9ec1d740 100644 --- a/block/io.c +++ b/block/io.c @@ -3198,6 +3198,47 @@ out: return co.ret; } +int bdrv_co_zone_report(BlockDriverState *bs, int64_t offset, + unsigned int *nr_zones, + BlockZoneDescriptor *zones) +{ + BlockDriver *drv = bs->drv; + CoroutineIOCompletion co = { + .coroutine = qemu_coroutine_self(), + }; + IO_CODE(); + + bdrv_inc_in_flight(bs); + if (!drv || !drv->bdrv_co_zone_report) { + co.ret = -ENOTSUP; + goto out; + } + co.ret = drv->bdrv_co_zone_report(bs, offset, nr_zones, zones); +out: + bdrv_dec_in_flight(bs); + return co.ret; +} + +int bdrv_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op, + int64_t offset, int64_t len) +{ + BlockDriver *drv = bs->drv; + CoroutineIOCompletion co = { + .coroutine = qemu_coroutine_self(), + }; + IO_CODE(); + + bdrv_inc_in_flight(bs); + if (!drv || !drv->bdrv_co_zone_mgmt) { + co.ret = -ENOTSUP; + goto out; + } + co.ret = drv->bdrv_co_zone_mgmt(bs, op, offset, len); +out: + bdrv_dec_in_flight(bs); + return co.ret; +} + void *qemu_blockalign(BlockDriverState *bs, size_t size) { IO_CODE(); diff --git a/include/block/block-io.h b/include/block/block-io.h index fd25ffa9be..65463b88d9 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -88,6 +88,13 @@ int bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf); /* Ensure contents are flushed to disk. */ int coroutine_fn bdrv_co_flush(BlockDriverState *bs); +/* Report zone information of zone block device. */ +int coroutine_fn bdrv_co_zone_report(BlockDriverState *bs, int64_t offset, + unsigned int *nr_zones, + BlockZoneDescriptor *zones); +int coroutine_fn bdrv_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op, + int64_t offset, int64_t len); + int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes); bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs); int bdrv_block_status(BlockDriverState *bs, int64_t offset, diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 7f7863cc9e..8541f36123 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -691,6 +691,12 @@ struct BlockDriver { QEMUIOVector *qiov, int64_t pos); + int coroutine_fn (*bdrv_co_zone_report)(BlockDriverState *bs, + int64_t offset, unsigned int *nr_zones, + BlockZoneDescriptor *zones); + int coroutine_fn (*bdrv_co_zone_mgmt)(BlockDriverState *bs, BlockZoneOp op, + int64_t offset, int64_t len); + /* removable device specific */ bool (*bdrv_is_inserted)(BlockDriverState *bs); void (*bdrv_eject)(BlockDriverState *bs, bool eject_flag); @@ -828,6 +834,21 @@ typedef struct BlockLimits { /* device zone model */ BlockZoneModel zoned; + + /* zone size expressed in 512-byte sectors */ + uint32_t zone_sectors; + + /* total number of zones */ + unsigned int nr_zones; + + /* maximum size in bytes of a zone append write operation */ + int64_t zone_append_max_bytes; + + /* maximum number of open zones */ + int64_t max_open_zones; + + /* maximum number of active zones */ + int64_t max_active_zones; } BlockLimits; typedef struct BdrvOpBlocker BdrvOpBlocker; diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h index 21fc10c4c9..3d26929cdd 100644 --- a/include/block/raw-aio.h +++ b/include/block/raw-aio.h @@ -29,6 +29,8 @@ #define QEMU_AIO_WRITE_ZEROES 0x0020 #define QEMU_AIO_COPY_RANGE 0x0040 #define QEMU_AIO_TRUNCATE 0x0080 +#define QEMU_AIO_ZONE_REPORT 0x0100 +#define QEMU_AIO_ZONE_MGMT 0x0200 #define QEMU_AIO_TYPE_MASK \ (QEMU_AIO_READ | \ QEMU_AIO_WRITE | \ @@ -37,7 +39,9 @@ QEMU_AIO_DISCARD | \ QEMU_AIO_WRITE_ZEROES | \ QEMU_AIO_COPY_RANGE | \ - QEMU_AIO_TRUNCATE) + QEMU_AIO_TRUNCATE | \ + QEMU_AIO_ZONE_REPORT | \ + QEMU_AIO_ZONE_MGMT) /* AIO flags */ #define QEMU_AIO_MISALIGNED 0x1000 diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h index 50f5aa2e07..6835525582 100644 --- a/include/sysemu/block-backend-io.h +++ b/include/sysemu/block-backend-io.h @@ -45,6 +45,12 @@ BlockAIOCB *blk_aio_pwritev(BlockBackend *blk, int64_t offset, BlockCompletionFunc *cb, void *opaque); BlockAIOCB *blk_aio_flush(BlockBackend *blk, BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *blk_aio_zone_report(BlockBackend *blk, int64_t offset, + unsigned int *nr_zones, BlockZoneDescriptor *zones, + BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *blk_aio_zone_mgmt(BlockBackend *blk, BlockZoneOp op, + int64_t offset, int64_t len, + BlockCompletionFunc *cb, void *opaque); BlockAIOCB *blk_aio_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes, BlockCompletionFunc *cb, void *opaque); void blk_aio_cancel_async(BlockAIOCB *acb); @@ -156,6 +162,17 @@ int generated_co_wrapper blk_pwrite_zeroes(BlockBackend *blk, int64_t offset, int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset, int64_t bytes, BdrvRequestFlags flags); +int coroutine_fn blk_co_zone_report(BlockBackend *blk, int64_t offset, + unsigned int *nr_zones, + BlockZoneDescriptor *zones); +int generated_co_wrapper blk_zone_report(BlockBackend *blk, int64_t offset, + unsigned int *nr_zones, + BlockZoneDescriptor *zones); +int coroutine_fn blk_co_zone_mgmt(BlockBackend *blk, BlockZoneOp op, + int64_t offset, int64_t len); +int generated_co_wrapper blk_zone_mgmt(BlockBackend *blk, BlockZoneOp op, + int64_t offset, int64_t len); + int generated_co_wrapper blk_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes); int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset, diff --git a/meson.build b/meson.build index 20fddbd707..2f436bb355 100644 --- a/meson.build +++ b/meson.build @@ -1883,6 +1883,7 @@ config_host_data.set('CONFIG_REPLICATION', get_option('live_block_migration').al # has_header config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h')) config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h')) +config_host_data.set('CONFIG_BLKZONED', cc.has_header('linux/blkzoned.h')) config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h')) config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h')) config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h')) diff --git a/qapi/block-core.json b/qapi/block-core.json index 2173e7734a..c6bbb7a037 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2942,6 +2942,7 @@ # @compress: Since 5.0 # @copy-before-write: Since 6.2 # @snapshot-access: Since 7.0 +# @zoned_host_device: Since 7.2 # # Since: 2.9 ## @@ -2955,7 +2956,8 @@ 'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'preallocate', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd', { 'name': 'replication', 'if': 'CONFIG_REPLICATION' }, - 'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] } + 'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', + { 'name': 'zoned_host_device', 'if': 'CONFIG_BLKZONED' } ] } ## # @BlockdevOptionsFile: @@ -4329,7 +4331,9 @@ 'vhdx': 'BlockdevOptionsGenericFormat', 'vmdk': 'BlockdevOptionsGenericCOWFormat', 'vpc': 'BlockdevOptionsGenericFormat', - 'vvfat': 'BlockdevOptionsVVFAT' + 'vvfat': 'BlockdevOptionsVVFAT', + 'zoned_host_device': { 'type': 'BlockdevOptionsFile', + 'if': 'CONFIG_BLKZONED' } } } ## diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 952dc940f1..446a059603 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -1712,6 +1712,144 @@ static const cmdinfo_t flush_cmd = { .oneline = "flush all in-core file state to disk", }; +static int zone_report_f(BlockBackend *blk, int argc, char **argv) +{ + int ret; + int64_t offset; + unsigned int nr_zones; + + ++optind; + offset = cvtnum(argv[optind]); + ++optind; + nr_zones = cvtnum(argv[optind]); + + g_autofree BlockZoneDescriptor *zones = NULL; + zones = g_new(BlockZoneDescriptor, nr_zones); + ret = blk_zone_report(blk, offset, &nr_zones, zones); + if (ret < 0) { + printf("zone report failed: %s\n", strerror(-ret)); + } else { + for (int i = 0; i < nr_zones; ++i) { + printf("start: 0x%" PRIx64 ", len 0x%" PRIx64 ", " + "cap"" 0x%" PRIx64 ", wptr 0x%" PRIx64 ", " + "zcond:%u, [type: %u]\n", + zones[i].start, zones[i].length, zones[i].cap, zones[i].wp, + zones[i].cond, zones[i].type); + } + } + return ret; +} + +static const cmdinfo_t zone_report_cmd = { + .name = "zone_report", + .altname = "zrp", + .cfunc = zone_report_f, + .argmin = 2, + .argmax = 2, + .args = "offset number", + .oneline = "report zone information", +}; + +static int zone_open_f(BlockBackend *blk, int argc, char **argv) +{ + int ret; + int64_t offset, len; + ++optind; + offset = cvtnum(argv[optind]); + ++optind; + len = cvtnum(argv[optind]); + ret = blk_zone_mgmt(blk, BLK_ZO_OPEN, offset, len); + if (ret < 0) { + printf("zone open failed: %s\n", strerror(-ret)); + } + return ret; +} + +static const cmdinfo_t zone_open_cmd = { + .name = "zone_open", + .altname = "zo", + .cfunc = zone_open_f, + .argmin = 2, + .argmax = 2, + .args = "offset len", + .oneline = "explicit open a range of zones in zone block device", +}; + +static int zone_close_f(BlockBackend *blk, int argc, char **argv) +{ + int ret; + int64_t offset, len; + ++optind; + offset = cvtnum(argv[optind]); + ++optind; + len = cvtnum(argv[optind]); + ret = blk_zone_mgmt(blk, BLK_ZO_CLOSE, offset, len); + if (ret < 0) { + printf("zone close failed: %s\n", strerror(-ret)); + } + return ret; +} + +static const cmdinfo_t zone_close_cmd = { + .name = "zone_close", + .altname = "zc", + .cfunc = zone_close_f, + .argmin = 2, + .argmax = 2, + .args = "offset len", + .oneline = "close a range of zones in zone block device", +}; + +static int zone_finish_f(BlockBackend *blk, int argc, char **argv) +{ + int ret; + int64_t offset, len; + ++optind; + offset = cvtnum(argv[optind]); + ++optind; + len = cvtnum(argv[optind]); + ret = blk_zone_mgmt(blk, BLK_ZO_FINISH, offset, len); + if (ret < 0) { + printf("zone finish failed: %s\n", strerror(-ret)); + } + return ret; +} + +static const cmdinfo_t zone_finish_cmd = { + .name = "zone_finish", + .altname = "zf", + .cfunc = zone_finish_f, + .argmin = 2, + .argmax = 2, + .args = "offset len", + .oneline = "finish a range of zones in zone block device", +}; + +static int zone_reset_f(BlockBackend *blk, int argc, char **argv) +{ + int ret; + int64_t offset, len; + ++optind; + offset = cvtnum(argv[optind]); + ++optind; + len = cvtnum(argv[optind]); + ret = blk_zone_mgmt(blk, BLK_ZO_RESET, offset, len); + if (ret < 0) { + printf("zone reset failed: %s\n", strerror(-ret)); + } + return ret; +} + +static const cmdinfo_t zone_reset_cmd = { + .name = "zone_reset", + .altname = "zrs", + .cfunc = zone_reset_f, + .argmin = 2, + .argmax = 2, + .args = "offset len", + .oneline = "reset a zone write pointer in zone block device", +}; + static int truncate_f(BlockBackend *blk, int argc, char **argv); static const cmdinfo_t truncate_cmd = { .name = "truncate", @@ -2504,6 +2642,11 @@ static void __attribute((constructor)) init_qemuio_commands(void) qemuio_add_command(&aio_write_cmd); qemuio_add_command(&aio_flush_cmd); qemuio_add_command(&flush_cmd); + qemuio_add_command(&zone_report_cmd); + qemuio_add_command(&zone_open_cmd); + qemuio_add_command(&zone_close_cmd); + qemuio_add_command(&zone_finish_cmd); + qemuio_add_command(&zone_reset_cmd); qemuio_add_command(&truncate_cmd); qemuio_add_command(&length_cmd); qemuio_add_command(&info_cmd); From patchwork Fri Aug 26 16:17:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Li X-Patchwork-Id: 12956276 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 2BD9CECAAA3 for ; Fri, 26 Aug 2022 16:32:47 +0000 (UTC) Received: from localhost ([::1]:47458 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oRcGE-0000QO-4L for qemu-devel@archiver.kernel.org; Fri, 26 Aug 2022 12:32:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:48986) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oRc3D-0000F3-6S; Fri, 26 Aug 2022 12:19:26 -0400 Received: from mail-pf1-x42a.google.com ([2607:f8b0:4864:20::42a]:41905) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oRc38-0007xS-Tp; Fri, 26 Aug 2022 12:19:18 -0400 Received: by mail-pf1-x42a.google.com with SMTP id x26so1986410pfo.8; Fri, 26 Aug 2022 09:19:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc; bh=XbkJfo+HAgd8F3iop4vyXnpjWO69R+8zjmI9OzzoGao=; b=cs0CwpvqcC750IP/T1KFRH4VjiWRFjvguesvMAj0bualDr/xW7gvl6Fu6vHp6Bvl4W iyBjJCWsJtbJUIkHYBnsbOkqJb44AYYwqzUW3U4/s0oZNQA7Vwbh5863HLNZ0f14Jt1n iupOT+23NdvQ6kOdA9YpFSVzX6rd7YgojWgdA3X10eGy8PtywmJ51FVNCpjnngw7JLQ7 FB3RsFgA6xk2P0hGex65Sc2POFGUcsqPwQUZ/cG29afCfymjmF1PrtMV89dv6pY4iJun DWkL65kLqUyHq3uPzXao708r76Idr7sD8thhtA8VvLEnAM74oOu1t2GX5OO3iyYRXHvt 5T0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc; bh=XbkJfo+HAgd8F3iop4vyXnpjWO69R+8zjmI9OzzoGao=; b=tDPmiiuIDpzMYTCxnicvStjiNX+rKRHM8gdsFGhU2Y6FgqwvxpG78NZE8YgjdjthIA UOo8ftWlnpOphHDanna8kE+MrMr1kvgnS57+eqhdmtr+KfU3fejRt/ZGcriKc10uLaNT lh5ayC42IF7PxcZng41pIkVPSqSr8X8wulDSCLpfIwBp15PotE39S+/vfDOr0IPDM+gF KnLBElA5ZM9DPHPkhRncOx6jNeaqKXjAR3fHvptAOK9uWsocJYoev3URLgRzuXLFCHyp 7ShMSpGFUawfYgE7Xi7MqtN9UmPBoDOBYkxfk6bPCIiZ4CX6aKhjyQ1z196mEUkgXWkf a6Xg== X-Gm-Message-State: ACgBeo1wXTCjK0SeZ4f1OHInNlSHVcs/bYluhSMnC+mm292A/1nUm1Vz NsRRCqEWd2E2r4dLJ0ysulfkKaDFhLLwaA== X-Google-Smtp-Source: AA6agR7tZGX6OuReeRMdeU9+fxBzFfgmVHYH5AZbB0J/JN/9hdINyGLpFEd9U10YkvMMlNa3uE27tw== X-Received: by 2002:a05:6a00:1784:b0:537:d623:e1cd with SMTP id s4-20020a056a00178400b00537d623e1cdmr1883616pfg.12.1661530751689; Fri, 26 Aug 2022 09:19:11 -0700 (PDT) Received: from roots.. ([106.84.135.2]) by smtp.gmail.com with ESMTPSA id a16-20020a170902ecd000b0016b90620910sm1809047plh.71.2022.08.26.09.19.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 26 Aug 2022 09:19:11 -0700 (PDT) From: Sam Li To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, damien.lemoal@opensource.wdc.com, Dmitry.Fomichev@wdc.com, hare@suse.de, qemu-block@nongnu.org, hreitz@redhat.com, eblake@redhat.com, armbru@redhat.com, fam@euphon.net, kwolf@redhat.com, Sam Li Subject: [PATCH v8 4/7] raw-format: add zone operations to pass through requests Date: Sat, 27 Aug 2022 00:17:59 +0800 Message-Id: <20220826161759.8118-1-faithilikerun@gmail.com> X-Mailer: git-send-email 2.37.2 MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::42a; envelope-from=faithilikerun@gmail.com; helo=mail-pf1-x42a.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" raw-format driver usually sits on top of file-posix driver. It needs to pass through requests of zone commands. Signed-off-by: Sam Li Reviewed-by: Stefan Hajnoczi --- block/raw-format.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/block/raw-format.c b/block/raw-format.c index 69fd650eaf..6b20bd22ef 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -314,6 +314,17 @@ static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs, return bdrv_co_pdiscard(bs->file, offset, bytes); } +static int coroutine_fn raw_co_zone_report(BlockDriverState *bs, int64_t offset, + unsigned int *nr_zones, + BlockZoneDescriptor *zones) { + return bdrv_co_zone_report(bs->file->bs, offset, nr_zones, zones); +} + +static int coroutine_fn raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op, + int64_t offset, int64_t len) { + return bdrv_co_zone_mgmt(bs->file->bs, op, offset, len); +} + static int64_t raw_getlength(BlockDriverState *bs) { int64_t len; @@ -614,6 +625,8 @@ BlockDriver bdrv_raw = { .bdrv_co_pwritev = &raw_co_pwritev, .bdrv_co_pwrite_zeroes = &raw_co_pwrite_zeroes, .bdrv_co_pdiscard = &raw_co_pdiscard, + .bdrv_co_zone_report = &raw_co_zone_report, + .bdrv_co_zone_mgmt = &raw_co_zone_mgmt, .bdrv_co_block_status = &raw_co_block_status, .bdrv_co_copy_range_from = &raw_co_copy_range_from, .bdrv_co_copy_range_to = &raw_co_copy_range_to, From patchwork Fri Aug 26 16:21:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Li X-Patchwork-Id: 12956275 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 CC421ECAAA3 for ; Fri, 26 Aug 2022 16:31:28 +0000 (UTC) Received: from localhost ([::1]:45420 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oRcEx-0006jg-Pr for qemu-devel@archiver.kernel.org; Fri, 26 Aug 2022 12:31:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55206) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oRc5d-0002M1-9I; Fri, 26 Aug 2022 12:21:49 -0400 Received: from mail-pf1-x42e.google.com ([2607:f8b0:4864:20::42e]:40899) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oRc5b-0000Ce-7s; Fri, 26 Aug 2022 12:21:48 -0400 Received: by mail-pf1-x42e.google.com with SMTP id y141so1999859pfb.7; Fri, 26 Aug 2022 09:21:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc; bh=FsaE+f5nrXOlpnlLcCe9659ufc9d3HLDaje6m9c0cck=; b=WXak7efIMiyjW4TkLbN59gDYvZiWJDt7Aj+oGfBODvAd2uu2qZKx8kvOmg2+FgKTvR aWrEA6PZ2Okg6Skjouf2qy3XrwKuJJDd+/wfUWW8yXRrNOLAy6W6AOydK5eJWLGw+Je1 srohs046YfBQsMr4fJxYwHMbQDGn2I76Y7QkHOIQb19jtHYdDr654NFXvcZG0vMKALSw uz59t6IE8Af232PY3q5Ca1zHbnrtNT9pGuPzSUaP11IYBdtE2FyLsS0tfhpN534bQQlK jTpd775BVsKHAWYDce3qO8UeYhIx8Wh5lrjmngdiVwhvcu/oFJjXHITR7xaahjbnZ1kn 1V4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc; bh=FsaE+f5nrXOlpnlLcCe9659ufc9d3HLDaje6m9c0cck=; b=wXkCGmcUL5sDYTlCABOlyIA/JMI7Eol5dJGiiYJoPBIHYaGgPOp7IUsKzXHwsjM8dB glCOGwvFyyHPw908k98yA1+JM/3iL8pQY2LpT/aYGMxdHvJ/f9Mr+7tOFBnMcXQvjMjJ ztbUNPd/JJnwHkw3UiNzdDT/F72uXb7VR86k+/anK4ivCfy10R1GY+vydyPOgigz8S6e wbZf6cgOE7TrDjAtvp/T+9GbsxzxiuaA8+/BXjaP7epA/Sgt45PDHTlpxB0TUHxElQFE crSboF03c6BWxjR3TKZvA6dUtHQDvDavf/ADtJL6s3XVHmmqLp3dHaxpzydQK8kXhyy7 CT+g== X-Gm-Message-State: ACgBeo0lzBdQ08RouO5U1lRb/np1Cz/drKx+hd5F3pTdpRvrrr9P3epY LD+4d5nUuFO2+MD0ju70zpu04sekCX7Y8Q== X-Google-Smtp-Source: AA6agR6tn/piWGsX5FEYpVlracQoLzGjkDWJ6zj9PD2QM42sJWuIRStWsW4fPKUmaNYQHWr+qyWseA== X-Received: by 2002:a05:6a00:ac6:b0:530:3197:48b6 with SMTP id c6-20020a056a000ac600b00530319748b6mr4642577pfl.80.1661530904175; Fri, 26 Aug 2022 09:21:44 -0700 (PDT) Received: from roots.. ([106.84.135.2]) by smtp.gmail.com with ESMTPSA id t4-20020a17090ae50400b001fb350026f1sm1860374pjy.4.2022.08.26.09.21.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 26 Aug 2022 09:21:43 -0700 (PDT) From: Sam Li To: qemu-devel@nongnu.org Cc: stefanha@redhat.com, damien.lemoal@opensource.wdc.com, Dmitry.Fomichev@wdc.com, hare@suse.de, qemu-block@nongnu.org, hreitz@redhat.com, eblake@redhat.com, armbru@redhat.com, fam@euphon.net, kwolf@redhat.com, Sam Li Subject: [PATCH v8 5/7] config: add check to block layer Date: Sat, 27 Aug 2022 00:21:31 +0800 Message-Id: <20220826162131.8352-1-faithilikerun@gmail.com> X-Mailer: git-send-email 2.37.2 MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::42e; envelope-from=faithilikerun@gmail.com; helo=mail-pf1-x42e.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" Putting zoned/non-zoned BlockDrivers on top of each other is not allowed. Signed-off-by: Sam Li Reviewed-by: Stefan Hajnoczi --- block.c | 14 ++++++++++++++ block/file-posix.c | 13 +++++++++++++ block/raw-format.c | 1 + include/block/block_int-common.h | 5 +++++ 4 files changed, 33 insertions(+) diff --git a/block.c b/block.c index bc85f46eed..dad2ed3959 100644 --- a/block.c +++ b/block.c @@ -7947,6 +7947,20 @@ void bdrv_add_child(BlockDriverState *parent_bs, BlockDriverState *child_bs, return; } + /* + * Non-zoned block drivers do not follow zoned storage constraints + * (i.e. sequential writes to zones). Refuse mixing zoned and non-zoned + * drivers in a graph. + */ + if (!parent_bs->drv->supports_zoned_children && + child_bs->bl.zoned == BLK_Z_HM) { + error_setg(errp, "Cannot add a %s child to a %s parent", + child_bs->bl.zoned == BLK_Z_HM ? "zoned" : "non-zoned", + parent_bs->drv->supports_zoned_children ? + "support zoned children" : "not support zoned children"); + return; + } + if (!QLIST_EMPTY(&child_bs->parents)) { error_setg(errp, "The node %s already has a parent", child_bs->node_name); diff --git a/block/file-posix.c b/block/file-posix.c index e3efba6db7..ec8672d33c 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -777,6 +777,19 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, goto fail; } } +#ifdef CONFIG_BLKZONED + /* + * The kernel page chache does not reliably work for writes to SWR zones + * of zoned block device because it can not guarantee the order of writes. + */ + + if (!(s->open_flags & O_DIRECT)) { + error_setg(errp, "driver=zoned_host_device was specified, but it " + "requires cache.direct=on, which was not specified."); + ret = -EINVAL; + return ret; /* No host kernel page cache */ + } +#endif if (S_ISBLK(st.st_mode)) { #ifdef BLKDISCARDZEROES diff --git a/block/raw-format.c b/block/raw-format.c index 6b20bd22ef..9441536819 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -614,6 +614,7 @@ static void raw_child_perm(BlockDriverState *bs, BdrvChild *c, BlockDriver bdrv_raw = { .format_name = "raw", .instance_size = sizeof(BDRVRawState), + .supports_zoned_children = true, .bdrv_probe = &raw_probe, .bdrv_reopen_prepare = &raw_reopen_prepare, .bdrv_reopen_commit = &raw_reopen_commit, diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 8541f36123..1bb5caa3be 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -127,6 +127,11 @@ struct BlockDriver { */ bool is_format; + /* + * Set to true if the BlockDriver supports zoned children. + */ + bool supports_zoned_children; + /* * Drivers not implementing bdrv_parse_filename nor bdrv_open should have * this field set to true, except ones that are defined only by their