From mboxrd@z Thu Jan 1 00:00:00 1970 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 smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (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 6C736C4332F for ; Mon, 21 Nov 2022 08:59:34 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id D101D60E4B; Mon, 21 Nov 2022 08:59:33 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org D101D60E4B Authentication-Results: smtp3.osuosl.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=solid-run-com.20210112.gappssmtp.com header.i=@solid-run-com.20210112.gappssmtp.com header.a=rsa-sha256 header.s=20210112 header.b=8Tfe91Pq X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id eQj68OHJFUXP; Mon, 21 Nov 2022 08:59:33 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTPS id 441CF60E42; Mon, 21 Nov 2022 08:59:32 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 441CF60E42 Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 04F3FC0033; Mon, 21 Nov 2022 08:59:32 +0000 (UTC) Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 3D695C002D for ; Mon, 21 Nov 2022 08:59:31 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 1CF5A40880 for ; Mon, 21 Nov 2022 08:59:31 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 1CF5A40880 Authentication-Results: smtp4.osuosl.org; dkim=pass (2048-bit key) header.d=solid-run-com.20210112.gappssmtp.com header.i=@solid-run-com.20210112.gappssmtp.com header.a=rsa-sha256 header.s=20210112 header.b=8Tfe91Pq X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1uW_SNOuL0ud for ; Mon, 21 Nov 2022 08:59:29 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 7C20C4087A Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by smtp4.osuosl.org (Postfix) with ESMTPS id 7C20C4087A for ; Mon, 21 Nov 2022 08:59:29 +0000 (UTC) Received: by mail-wm1-x329.google.com with SMTP id 84-20020a1c0257000000b003cfe48519a6so5966596wmc.0 for ; Mon, 21 Nov 2022 00:59:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=solid-run-com.20210112.gappssmtp.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=oK03PBdUD6+GQdmo3tY8CjwCylaJFWVZ547uTRVk1bI=; b=8Tfe91PqHJYauCusthChEERjTz1zW+9cF9V5Mm5JnVxZ47zBo/tEv6P/6Otxck5fqy dtQmYIqfkfUzBm6zSMognHqS1rh21EzM3RC0cR637NrvzmgGTed9FUloXSmXAGPBwIWU Mc+pqyo+VtcqiYRURXOjw94wFdrlTxk2pF2mWpuuptVEimhKcMpfRFMPaHfTgIkRqLQ4 8urjb8EyKIw/LT++zXIzPm6swyYsQt+87mmTQY+g9qkbRCZPIbhiYNklv1LfPdNekmRC k15nkVwfFhkIpiYZoDSKzrqUzz1DK17DfxVaErc41XKn/Bq7LrzV7O3GmAPSWHvl98ue jaEA== 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:subject:date:message-id :reply-to; bh=oK03PBdUD6+GQdmo3tY8CjwCylaJFWVZ547uTRVk1bI=; b=X9Q2IVd6ZkQ/VUm1rTPa+McJniOcIK7SzzYKrS0H+yT+3DGOUyhkDI3ptXgWQuNqU7 vs4lRZ5KdetLga3bla4pzWpyGk9X3IB1OTYztMLyiGLbzD6aZhxfAyP/R9kZFoyghQ23 NZfcz5pPRc1l8yEtASNt3RgS1tCuZnEeNBaErparyp9y1403mlraBj9TzvYzI7FmDZJ4 6sd5wz3LjIvU9LBSR5X3vRyBymLb3NQd9JLwZyIIkXC6dG2aWDOIF41jWpFuNk+BO7v8 v33f8f09XGtdA5w96wTB7ihwYqEdWKGFB0EC86TLi44pwKiUhu0wv2RfQZ8FXjGyabqj JKsg== X-Gm-Message-State: ANoB5plzzXW8vjGtV4TgUAMvF5DltlzdceQCH1iQ686tVQ+jKQB/h00R BNw5PRMWDr2qwKbcEcU6WDLGPTh/rpuNoQ== X-Google-Smtp-Source: AA0mqf7X8R7z7SKan/0uQCnkBJRNXyGqTc+AWmWfXgmhNH4HLS4wexBq5nxjE8vHUHfwvlVeT/4/jA== X-Received: by 2002:a05:600c:4e50:b0:3d0:bda:f2c with SMTP id e16-20020a05600c4e5000b003d00bda0f2cmr2835745wmq.117.1669021167152; Mon, 21 Nov 2022 00:59:27 -0800 (PST) Received: from localhost.localdomain (bzq-84-110-153-254.static-ip.bezeqint.net. [84.110.153.254]) by smtp.gmail.com with ESMTPSA id d5-20020adffbc5000000b002417e7f0685sm12675003wrs.9.2022.11.21.00.59.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Nov 2022 00:59:26 -0800 (PST) From: Alvaro Karsz To: virtualization@lists.linux-foundation.org Subject: [PATCH v2] virtio_blk: add VIRTIO_BLK_F_LIFETIME feature support Date: Mon, 21 Nov 2022 10:59:23 +0200 Message-Id: <20221121085923.2717501-1-alvaro.karsz@solid-run.com> X-Mailer: git-send-email 2.32.0 MIME-Version: 1.0 Cc: Jens Axboe , "Michael S. Tsirkin" , Stefan Hajnoczi , Paolo Bonzini X-BeenThere: virtualization@lists.linux-foundation.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux virtualization List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: virtualization-bounces@lists.linux-foundation.org Sender: "Virtualization" Implement the VIRTIO_BLK_F_LIFETIME feature for VirtIO block devices. This commit introduces a new ioctl command, VBLK_LIFETIME. VBLK_LIFETIME ioctl asks for the block device to provide lifetime information by sending a VIRTIO_BLK_T_GET_LIFETIME command to the device. lifetime information fields: - pre_eol_info: specifies the percentage of reserved blocks that are consumed. optional values following virtio spec: *) 0 - undefined. *) 1 - normal, < 80% of reserved blocks are consumed. *) 2 - warning, 80% of reserved blocks are consumed. *) 3 - urgent, 90% of reserved blocks are consumed. - device_lifetime_est_typ_a: this field refers to wear of SLC cells and is provided in increments of 10used, and so on, thru to 11 meaning estimated lifetime exceeded. All values above 11 are reserved. - device_lifetime_est_typ_b: this field refers to wear of MLC cells and is provided with the same semantics as device_lifetime_est_typ_a. The data received from the device will be sent as is to the user. No data check/decode is done by virtblk. Signed-off-by: Alvaro Karsz -- v2: - Remove (void *) casting. - Fix comments format in virtio_blk.h. - Set ioprio value for legacy devices for REQ_OP_DRV_IN operations. -- --- drivers/block/virtio_blk.c | 100 ++++++++++++++++++++++++++++++-- include/uapi/linux/virtio_blk.h | 32 ++++++++++ 2 files changed, 127 insertions(+), 5 deletions(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 19da5defd73..9aa37677b65 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -101,6 +101,18 @@ static inline blk_status_t virtblk_result(struct virtblk_req *vbr) } } +static inline int virtblk_ioctl_result(struct virtblk_req *vbr) +{ + switch (vbr->status) { + case VIRTIO_BLK_S_OK: + return 0; + case VIRTIO_BLK_S_UNSUPP: + return -ENOTTY; + default: + return -EIO; + } +} + static inline struct virtio_blk_vq *get_virtio_blk_vq(struct blk_mq_hw_ctx *hctx) { struct virtio_blk *vblk = hctx->queue->queuedata; @@ -218,6 +230,7 @@ static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev, u32 type; vbr->out_hdr.sector = 0; + vbr->out_hdr.ioprio = cpu_to_virtio32(vdev, req_get_ioprio(req)); switch (req_op(req)) { case REQ_OP_READ: @@ -244,15 +257,14 @@ static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev, type = VIRTIO_BLK_T_SECURE_ERASE; break; case REQ_OP_DRV_IN: - type = VIRTIO_BLK_T_GET_ID; - break; + /* type is set in virtblk_get_id/virtblk_ioctl_lifetime */ + return 0; default: WARN_ON_ONCE(1); return BLK_STS_IOERR; } vbr->out_hdr.type = cpu_to_virtio32(vdev, type); - vbr->out_hdr.ioprio = cpu_to_virtio32(vdev, req_get_ioprio(req)); if (type == VIRTIO_BLK_T_DISCARD || type == VIRTIO_BLK_T_WRITE_ZEROES || type == VIRTIO_BLK_T_SECURE_ERASE) { @@ -459,12 +471,16 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str) struct virtio_blk *vblk = disk->private_data; struct request_queue *q = vblk->disk->queue; struct request *req; + struct virtblk_req *vbr; int err; req = blk_mq_alloc_request(q, REQ_OP_DRV_IN, 0); if (IS_ERR(req)) return PTR_ERR(req); + vbr = blk_mq_rq_to_pdu(req); + vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_GET_ID); + err = blk_rq_map_kern(q, req, id_str, VIRTIO_BLK_ID_BYTES, GFP_KERNEL); if (err) goto out; @@ -508,6 +524,79 @@ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) return ret; } +/* Get lifetime information from device */ +static int virtblk_ioctl_lifetime(struct virtio_blk *vblk, unsigned long arg) +{ + struct request_queue *q = vblk->disk->queue; + struct request *req = NULL; + struct virtblk_req *vbr; + struct virtio_blk_lifetime lifetime; + int ret; + + /* The virtio_blk_lifetime struct fields follow virtio spec. + * There is no check/decode on values received from the device. + * The data is sent as is to the user. + */ + + /* This ioctl is allowed only if VIRTIO_BLK_F_LIFETIME + * feature is negotiated. + */ + if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_LIFETIME)) + return -ENOTTY; + + memset(&lifetime, 0, sizeof(lifetime)); + + req = blk_mq_alloc_request(q, REQ_OP_DRV_IN, 0); + if (IS_ERR(req)) + return PTR_ERR(req); + + /* Write the correct type */ + vbr = blk_mq_rq_to_pdu(req); + vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_GET_LIFETIME); + + ret = blk_rq_map_kern(q, req, &lifetime, sizeof(lifetime), GFP_KERNEL); + if (ret) + goto out; + + blk_execute_rq(req, false); + + ret = virtblk_ioctl_result(blk_mq_rq_to_pdu(req)); + if (ret) + goto out; + + /* Pass the data to the user */ + if (copy_to_user((void __user *)arg, &lifetime, sizeof(lifetime))) { + ret = -EFAULT; + goto out; + } + +out: + blk_mq_free_request(req); + return ret; +} + +static int virtblk_ioctl(struct block_device *bd, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + struct virtio_blk *vblk = bd->bd_disk->private_data; + int ret; + + mutex_lock(&vblk->vdev_mutex); + + switch (cmd) { + case VBLK_LIFETIME: + ret = virtblk_ioctl_lifetime(vblk, arg); + break; + default: + ret = -ENOTTY; + break; + } + + mutex_unlock(&vblk->vdev_mutex); + + return ret; +} + static void virtblk_free_disk(struct gendisk *disk) { struct virtio_blk *vblk = disk->private_data; @@ -520,6 +609,7 @@ static void virtblk_free_disk(struct gendisk *disk) static const struct block_device_operations virtblk_fops = { .owner = THIS_MODULE, .getgeo = virtblk_getgeo, + .ioctl = virtblk_ioctl, .free_disk = virtblk_free_disk, }; @@ -1239,7 +1329,7 @@ static unsigned int features_legacy[] = { VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE, VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_WRITE_ZEROES, - VIRTIO_BLK_F_SECURE_ERASE, + VIRTIO_BLK_F_SECURE_ERASE, VIRTIO_BLK_F_LIFETIME, } ; static unsigned int features[] = { @@ -1247,7 +1337,7 @@ static unsigned int features[] = { VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE, VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_WRITE_ZEROES, - VIRTIO_BLK_F_SECURE_ERASE, + VIRTIO_BLK_F_SECURE_ERASE, VIRTIO_BLK_F_LIFETIME, }; static struct virtio_driver virtio_blk = { diff --git a/include/uapi/linux/virtio_blk.h b/include/uapi/linux/virtio_blk.h index 58e70b24b50..c769930d269 100644 --- a/include/uapi/linux/virtio_blk.h +++ b/include/uapi/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_LIFETIME 15 /* Storage lifetime information is supported */ #define VIRTIO_BLK_F_SECURE_ERASE 16 /* Secure Erase is supported */ /* Legacy feature bits */ @@ -165,6 +166,9 @@ struct virtio_blk_config { /* Get device ID command */ #define VIRTIO_BLK_T_GET_ID 8 +/* Get lifetime information command */ +#define VIRTIO_BLK_T_GET_LIFETIME 10 + /* Discard command */ #define VIRTIO_BLK_T_DISCARD 11 @@ -206,6 +210,30 @@ struct virtio_blk_discard_write_zeroes { __le32 flags; }; +/* Get lifetime information struct for each request */ +struct virtio_blk_lifetime { + /* + * specifies the percentage of reserved blocks that are consumed. + * optional values following virtio spec: + * 0 - undefined + * 1 - normal, < 80% of reserved blocks are consumed + * 2 - warning, 80% of reserved blocks are consumed + * 3 - urgent, 90% of reserved blocks are consumed + */ + __le16 pre_eol_info; + /* + * this field refers to wear of SLC cells and is provided in increments of 10used, + * and so on, thru to 11 meaning estimated lifetime exceeded. All values above 11 + * are reserved + */ + __le16 device_lifetime_est_typ_a; + /* + * this field refers to wear of MLC cells and is provided with the same semantics as + * device_lifetime_est_typ_a + */ + __le16 device_lifetime_est_typ_b; +}; + #ifndef VIRTIO_BLK_NO_LEGACY struct virtio_scsi_inhdr { __virtio32 errors; @@ -219,4 +247,8 @@ struct virtio_scsi_inhdr { #define VIRTIO_BLK_S_OK 0 #define VIRTIO_BLK_S_IOERR 1 #define VIRTIO_BLK_S_UNSUPP 2 + +/* Virtblk ioctl commands */ +#define VBLK_LIFETIME _IOR('r', 0, struct virtio_blk_lifetime) + #endif /* _LINUX_VIRTIO_BLK_H */ -- 2.32.0 _______________________________________________ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization