OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

virtio-dev message

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]


Subject: Re: [virtio-dev] [PATCH v2 2/2] virtio-blk: add support for zoned block devices


On Sun, 2022-10-16 at 18:23 -0400, Stefan Hajnoczi wrote:
> On Sat, Oct 15, 2022 at 11:41:27PM -0400, Dmitry Fomichev wrote:
> > This patch adds support for Zoned Block Devices (ZBDs) to the kernel
> > virtio-blk driver.
> > 
> > The patch accompanies the virtio-blk ZBD support draft that is now
> > being proposed for standardization. The latest version of the draft is
> > linked at
> > 
> > https://github.com/oasis-tcs/virtio-spec/issues/143Â;.
> > 
> > The QEMU zoned device code that implements these protocol extensions
> > has been developed by Sam Li and it is currently in review at the QEMU
> > mailing list.
> > 
> > A number of virtblk request structure changes has been introduced to
> > accommodate the functionality that is specific to zoned block devices
> > and, most importantly, make room for carrying the Zoned Append sector
> > value from the device back to the driver along with the request status.
> > 
> > The zone-specific code in the patch is heavily influenced by NVMe ZNS
> > code in drivers/nvme/host/zns.c, but it is simpler because the proposed
> > virtio ZBD draft only covers the zoned device features that are
> > relevant to the zoned functionality provided by Linux block layer.
> > 
> > Co-developed-by: Stefan Hajnoczi <stefanha@gmail.com>
> > Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
> > Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
> > ---
> > Âdrivers/block/virtio_blk.cÂÂÂÂÂ | 377 ++++++++++++++++++++++++++++++--
> > Âinclude/uapi/linux/virtio_blk.h | 105 +++++++++
> > Â2 files changed, 464 insertions(+), 18 deletions(-)
> > 
> > diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
> > index 3efe3da5f8c2..c9ad590816f8 100644
> > --- a/drivers/block/virtio_blk.c
> > +++ b/drivers/block/virtio_blk.c
> > @@ -80,22 +80,51 @@ struct virtio_blk {
> > ÂÂÂÂÂÂÂÂint num_vqs;
> > ÂÂÂÂÂÂÂÂint io_queues[HCTX_MAX_TYPES];
> > ÂÂÂÂÂÂÂÂstruct virtio_blk_vq *vqs;
> > +
> > +ÂÂÂÂÂÂÂ/* For zoned device */
> > +ÂÂÂÂÂÂÂunsigned int zone_sectors;
> > Â};
> > Â
> > Âstruct virtblk_req {
> > +ÂÂÂÂÂÂÂ/* Out header */
> > ÂÂÂÂÂÂÂÂstruct virtio_blk_outhdr out_hdr;
> > -ÂÂÂÂÂÂÂu8 status;
> > +
> > +ÂÂÂÂÂÂÂ/* In header */
> > +ÂÂÂÂÂÂÂunion {
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂu8 status;
> > +
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ/*
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ * The zone append command has an extended in header.
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ * The status field in zone_append_in_hdr must have
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ * the same offset in virtblk_req as the non-zoned
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ * status field above.
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ */
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂstruct {
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂu8 status;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂu8 reserved[7];
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂu64 append_sector;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ} zone_append_in_hdr;
> > +ÂÂÂÂÂÂÂ};
> 
> This layout is not finalized yet. In the last revision of the spec patch
> I suggested making the status byte the last byte so that devices that
> don't know about zone append can still complete the request with
> status=VIRTIO_BLK_S_UNSUPP at the correct offset.

Right, as stated in the changelog, the ZA layout is not updated yet.
I am going to make this change in the next version of the patchset.

> 
> > +
> > +ÂÂÂÂÂÂÂsize_t in_hdr_len;
> > +
> > ÂÂÂÂÂÂÂÂstruct sg_table sg_table;
> > ÂÂÂÂÂÂÂÂstruct scatterlist sg[];
> > Â};
> > Â
> > -static inline blk_status_t virtblk_result(struct virtblk_req *vbr)
> > +static inline blk_status_t virtblk_result(u8 status)
> > Â{
> > -ÂÂÂÂÂÂÂswitch (vbr->status) {
> > +ÂÂÂÂÂÂÂswitch (status) {
> > ÂÂÂÂÂÂÂÂcase VIRTIO_BLK_S_OK:
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn BLK_STS_OK;
> > ÂÂÂÂÂÂÂÂcase VIRTIO_BLK_S_UNSUPP:
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn BLK_STS_NOTSUPP;
> > +ÂÂÂÂÂÂÂcase VIRTIO_BLK_S_ZONE_OPEN_RESOURCE:
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn BLK_STS_ZONE_OPEN_RESOURCE;
> > +ÂÂÂÂÂÂÂcase VIRTIO_BLK_S_ZONE_ACTIVE_RESOURCE:
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn BLK_STS_ZONE_ACTIVE_RESOURCE;
> > +ÂÂÂÂÂÂÂcase VIRTIO_BLK_S_IOERR:
> > +ÂÂÂÂÂÂÂcase VIRTIO_BLK_S_ZONE_UNALIGNED_WP:
> > ÂÂÂÂÂÂÂÂdefault:
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn BLK_STS_IOERR;
> > ÂÂÂÂÂÂÂÂ}
> > @@ -111,11 +140,11 @@ static inline struct virtio_blk_vq
> > *get_virtio_blk_vq(struct blk_mq_hw_ctx *hctx
> > Â
> > Âstatic int virtblk_add_req(struct virtqueue *vq, struct virtblk_req *vbr)
> > Â{
> > -ÂÂÂÂÂÂÂstruct scatterlist hdr, status, *sgs[3];
> > +ÂÂÂÂÂÂÂstruct scatterlist out_hdr, in_hdr, *sgs[3];
> > ÂÂÂÂÂÂÂÂunsigned int num_out = 0, num_in = 0;
> > Â
> > -ÂÂÂÂÂÂÂsg_init_one(&hdr, &vbr->out_hdr, sizeof(vbr->out_hdr));
> > -ÂÂÂÂÂÂÂsgs[num_out++] = &hdr;
> > +ÂÂÂÂÂÂÂsg_init_one(&out_hdr, &vbr->out_hdr, sizeof(vbr->out_hdr));
> > +ÂÂÂÂÂÂÂsgs[num_out++] = &out_hdr;
> > Â
> > ÂÂÂÂÂÂÂÂif (vbr->sg_table.nents) {
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂif (vbr->out_hdr.type & cpu_to_virtio32(vq->vdev,
> > VIRTIO_BLK_T_OUT))
> > @@ -124,8 +153,8 @@ static int virtblk_add_req(struct virtqueue *vq, struct
> > virtblk_req *vbr)
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂsgs[num_out + num_in++] = vbr->sg_table.sgl;
> > ÂÂÂÂÂÂÂÂ}
> > Â
> > -ÂÂÂÂÂÂÂsg_init_one(&status, &vbr->status, sizeof(vbr->status));
> > -ÂÂÂÂÂÂÂsgs[num_out + num_in++] = &status;
> > +ÂÂÂÂÂÂÂsg_init_one(&in_hdr, &vbr->status, vbr->in_hdr_len);
> > +ÂÂÂÂÂÂÂsgs[num_out + num_in++] = &in_hdr;
> > Â
> > ÂÂÂÂÂÂÂÂreturn virtqueue_add_sgs(vq, sgs, num_out, num_in, vbr, GFP_ATOMIC);
> > Â}
> > @@ -214,21 +243,22 @@ static blk_status_t virtblk_setup_cmd(struct
> > virtio_device *vdev,
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct request *req,
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct virtblk_req *vbr)
> > Â{
> > +ÂÂÂÂÂÂÂsize_t in_hdr_len = sizeof(vbr->status);
> > ÂÂÂÂÂÂÂÂbool unmap = false;
> > ÂÂÂÂÂÂÂÂu32 type;
> > +ÂÂÂÂÂÂÂu64 sector = 0;
> > Â
> > -ÂÂÂÂÂÂÂvbr->out_hdr.sector = 0;
> > +ÂÂÂÂÂÂÂ/* Set fields for all request types */
> > +ÂÂÂÂÂÂÂvbr->out_hdr.ioprio = cpu_to_virtio32(vdev, req_get_ioprio(req));
> > Â
> > ÂÂÂÂÂÂÂÂswitch (req_op(req)) {
> > ÂÂÂÂÂÂÂÂcase REQ_OP_READ:
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂtype = VIRTIO_BLK_T_IN;
> > -ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂvbr->out_hdr.sector = cpu_to_virtio64(vdev,
> > -ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ blk_rq_pos(req));
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂsector = blk_rq_pos(req);
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > ÂÂÂÂÂÂÂÂcase REQ_OP_WRITE:
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂtype = VIRTIO_BLK_T_OUT;
> > -ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂvbr->out_hdr.sector = cpu_to_virtio64(vdev,
> > -ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ blk_rq_pos(req));
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂsector = blk_rq_pos(req);
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > ÂÂÂÂÂÂÂÂcase REQ_OP_FLUSH:
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂtype = VIRTIO_BLK_T_FLUSH;
> > @@ -243,16 +273,42 @@ static blk_status_t virtblk_setup_cmd(struct
> > virtio_device *vdev,
> > ÂÂÂÂÂÂÂÂcase REQ_OP_SECURE_ERASE:
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂtype = VIRTIO_BLK_T_SECURE_ERASE;
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > -ÂÂÂÂÂÂÂcase REQ_OP_DRV_IN:
> > -ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂtype = VIRTIO_BLK_T_GET_ID;
> > +ÂÂÂÂÂÂÂcase REQ_OP_ZONE_OPEN:
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂtype = VIRTIO_BLK_T_ZONE_OPEN;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂsector = blk_rq_pos(req);
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > +ÂÂÂÂÂÂÂcase REQ_OP_ZONE_CLOSE:
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂtype = VIRTIO_BLK_T_ZONE_CLOSE;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂsector = blk_rq_pos(req);
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > +ÂÂÂÂÂÂÂcase REQ_OP_ZONE_FINISH:
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂtype = VIRTIO_BLK_T_ZONE_FINISH;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂsector = blk_rq_pos(req);
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > +ÂÂÂÂÂÂÂcase REQ_OP_ZONE_APPEND:
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂtype = VIRTIO_BLK_T_ZONE_APPEND;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂsector = blk_rq_pos(req);
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂin_hdr_len = sizeof(vbr->zone_append_in_hdr);
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > +ÂÂÂÂÂÂÂcase REQ_OP_ZONE_RESET:
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂtype = VIRTIO_BLK_T_ZONE_RESET;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂsector = blk_rq_pos(req);
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > +ÂÂÂÂÂÂÂcase REQ_OP_ZONE_RESET_ALL:
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂtype = VIRTIO_BLK_T_ZONE_RESET_ALL;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > +ÂÂÂÂÂÂÂcase REQ_OP_DRV_IN:
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ/* Out header already filled in, nothing to do */
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn 0;
> > ÂÂÂÂÂÂÂÂdefault:
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂWARN_ON_ONCE(1);
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn BLK_STS_IOERR;
> > ÂÂÂÂÂÂÂÂ}
> > Â
> > +ÂÂÂÂÂÂÂ/* Set fields for non-REQ_OP_DRV_IN request types */
> > +ÂÂÂÂÂÂÂvbr->in_hdr_len = in_hdr_len;
> > ÂÂÂÂÂÂÂÂvbr->out_hdr.type = cpu_to_virtio32(vdev, type);
> > -ÂÂÂÂÂÂÂvbr->out_hdr.ioprio = cpu_to_virtio32(vdev, req_get_ioprio(req));
> > +ÂÂÂÂÂÂÂvbr->out_hdr.sector = cpu_to_virtio64(vdev, sector);
> > Â
> > ÂÂÂÂÂÂÂÂif (type == VIRTIO_BLK_T_DISCARD || type == VIRTIO_BLK_T_WRITE_ZEROES
> > ||
> > ÂÂÂÂÂÂÂÂÂÂÂ type == VIRTIO_BLK_T_SECURE_ERASE) {
> > @@ -266,10 +322,15 @@ static blk_status_t virtblk_setup_cmd(struct
> > virtio_device *vdev,
> > Âstatic inline void virtblk_request_done(struct request *req)
> > Â{
> > ÂÂÂÂÂÂÂÂstruct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
> > +ÂÂÂÂÂÂÂint status = virtblk_result(vbr->status);
> > Â
> > ÂÂÂÂÂÂÂÂvirtblk_unmap_data(req, vbr);
> > ÂÂÂÂÂÂÂÂvirtblk_cleanup_cmd(req);
> > -ÂÂÂÂÂÂÂblk_mq_end_request(req, virtblk_result(vbr));
> > +
> > +ÂÂÂÂÂÂÂif (req_op(req) == REQ_OP_ZONE_APPEND)
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreq->__sector = le64_to_cpu(vbr-
> > >zone_append_in_hdr.append_sector);
> 
> Not sure if it's correct to set __sector upon error, maybe if (... &&
> status == BLK_STS_OK)? A quick look at the nvme driver shows no check
> was performed there either.

I recall the same discussion to happen while adding the similar __sector
assignment to the nvme driver. Back then, it was decided that it is safe enough
to omit the status check. In ZNS spec (and virtio_blk ZBD spec extension), the
returned value is undefined if the request status is not zero. By always setting
theÂ__sector, we are not really changing this behavior. The only way for the
caller to handle ZA errors properly is not to touch the append sector value if
the request returns an error.

DF

> 
> > +
> > +ÂÂÂÂÂÂÂblk_mq_end_request(req, status);
> > Â}
> > Â
> > Âstatic void virtblk_done(struct virtqueue *vq)
> > @@ -455,6 +516,266 @@ static void virtio_queue_rqs(struct request **rqlist)
> > ÂÂÂÂÂÂÂÂ*rqlist = requeue_list;
> > Â}
> > Â
> > +#ifdef CONFIG_BLK_DEV_ZONED
> > +static void *virtblk_alloc_report_buffer(struct virtio_blk *vblk,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ unsigned int nr_zones,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ unsigned int zone_sectors,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ size_t *buflen)
> > +{
> > +ÂÂÂÂÂÂÂstruct request_queue *q = vblk->disk->queue;
> > +ÂÂÂÂÂÂÂsize_t bufsize;
> > +ÂÂÂÂÂÂÂvoid *buf;
> > +
> > +ÂÂÂÂÂÂÂnr_zones = min_t(unsigned int, nr_zones,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ get_capacity(vblk->disk) >> ilog2(zone_sectors));
> > +
> > +ÂÂÂÂÂÂÂbufsize = sizeof(struct virtio_blk_zone_report) +
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂnr_zones * sizeof(struct virtio_blk_zone_descriptor);
> > +ÂÂÂÂÂÂÂbufsize = min_t(size_t, bufsize,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂqueue_max_hw_sectors(q) << SECTOR_SHIFT);
> > +ÂÂÂÂÂÂÂbufsize = min_t(size_t, bufsize, queue_max_segments(q) <<
> > PAGE_SHIFT);
> > +
> > +ÂÂÂÂÂÂÂwhile (bufsize >= sizeof(struct virtio_blk_zone_report)) {
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂbuf = __vmalloc(bufsize, GFP_KERNEL | __GFP_NORETRY);
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂif (buf) {
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ*buflen = bufsize;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn buf;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ}
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂbufsize >>= 1;
> > +ÂÂÂÂÂÂÂ}
> > +
> > +ÂÂÂÂÂÂÂreturn NULL;
> > +}
> > +
> > +static int virtblk_submit_zone_report(struct virtio_blk *vblk,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ char *report_buf, size_t report_len,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ sector_t sector)
> > +{
> > +ÂÂÂÂÂÂÂ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->in_hdr_len = sizeof(vbr->status);
> > +ÂÂÂÂÂÂÂvbr->out_hdr.type = cpu_to_virtio32(vblk->vdev,
> > VIRTIO_BLK_T_ZONE_REPORT);
> > +ÂÂÂÂÂÂÂvbr->out_hdr.sector = cpu_to_virtio64(vblk->vdev, sector);
> > +
> > +ÂÂÂÂÂÂÂerr = blk_rq_map_kern(q, req, report_buf, report_len, GFP_KERNEL);
> > +ÂÂÂÂÂÂÂif (err)
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂgoto out;
> > +
> > +ÂÂÂÂÂÂÂblk_execute_rq(req, false);
> > +ÂÂÂÂÂÂÂerr = blk_status_to_errno(virtblk_result(vbr->status));
> > +out:
> > +ÂÂÂÂÂÂÂblk_mq_free_request(req);
> > +ÂÂÂÂÂÂÂreturn err;
> > +}
> > +
> > +static int virtblk_parse_zone(struct virtio_blk *vblk,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct virtio_blk_zone_descriptor *entry,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ unsigned int idx, unsigned int zone_sectors,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ report_zones_cb cb, void *data)
> > +{
> > +ÂÂÂÂÂÂÂstruct blk_zone zone = { };
> > +
> > +ÂÂÂÂÂÂÂif (entry->z_type != VIRTIO_BLK_ZT_SWR &&
> > +ÂÂÂÂÂÂÂÂÂÂ entry->z_type != VIRTIO_BLK_ZT_SWP &&
> > +ÂÂÂÂÂÂÂÂÂÂ entry->z_type != VIRTIO_BLK_ZT_CONV) {
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(&vblk->vdev->dev, "invalid zone type %#x\n",
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂentry->z_type);
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -EINVAL;
> > +ÂÂÂÂÂÂÂ}
> > +
> > +ÂÂÂÂÂÂÂzone.type = entry->z_type;
> > +ÂÂÂÂÂÂÂzone.cond = entry->z_state;
> > +ÂÂÂÂÂÂÂzone.len = zone_sectors;
> > +ÂÂÂÂÂÂÂzone.capacity = le64_to_cpu(entry->z_cap);
> > +ÂÂÂÂÂÂÂzone.start = le64_to_cpu(entry->z_start);
> > +ÂÂÂÂÂÂÂif (zone.cond == BLK_ZONE_COND_FULL)
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂzone.wp = zone.start + zone.len;
> > +ÂÂÂÂÂÂÂelse
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂzone.wp = le64_to_cpu(entry->z_wp);
> > +
> > +ÂÂÂÂÂÂÂreturn cb(&zone, idx, data);
> > +}
> > +
> > +static int virtblk_report_zones(struct gendisk *disk, sector_t sector,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ unsigned int nr_zones, report_zones_cb cb,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ void *data)
> > +{
> > +ÂÂÂÂÂÂÂstruct virtio_blk *vblk = disk->private_data;
> > +ÂÂÂÂÂÂÂstruct virtio_blk_zone_report *report;
> > +ÂÂÂÂÂÂÂunsigned int zone_sectors = vblk->zone_sectors;
> > +ÂÂÂÂÂÂÂunsigned int nz, i;
> > +ÂÂÂÂÂÂÂint ret, zone_idx = 0;
> > +ÂÂÂÂÂÂÂsize_t buflen;
> > +
> > +ÂÂÂÂÂÂÂif (WARN_ON_ONCE(!vblk->zone_sectors))
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -EOPNOTSUPP;
> > +
> > +ÂÂÂÂÂÂÂreport = virtblk_alloc_report_buffer(vblk, nr_zones,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ zone_sectors, &buflen);
> > +ÂÂÂÂÂÂÂif (!report)
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -ENOMEM;
> > +
> > +ÂÂÂÂÂÂÂwhile (zone_idx < nr_zones && sector < get_capacity(vblk->disk)) {
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂmemset(report, 0, buflen);
> > +
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂret = virtblk_submit_zone_report(vblk, (char *)report,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ buflen, sector);
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂif (ret) {
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂif (ret > 0)
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂret = -EIO;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂgoto out_free;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ}
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂnz = min((unsigned int)le64_to_cpu(report->nr_zones),
> > nr_zones);
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂif (!nz)
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > +
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂfor (i = 0; i < nz && zone_idx < nr_zones; i++) {
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂret = virtblk_parse_zone(vblk, &report->zones[i],
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ zone_idx, zone_sectors, cb,
> > data);
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂif (ret)
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂgoto out_free;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂsector = le64_to_cpu(report->zones[i].z_start) +
> > zone_sectors;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂzone_idx++;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ}
> > +ÂÂÂÂÂÂÂ}
> > +
> > +ÂÂÂÂÂÂÂif (zone_idx > 0)
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂret = zone_idx;
> > +ÂÂÂÂÂÂÂelse
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂret = -EINVAL;
> > +out_free:
> > +ÂÂÂÂÂÂÂkvfree(report);
> > +ÂÂÂÂÂÂÂreturn ret;
> > +}
> > +
> > +static void virtblk_revalidate_zones(struct virtio_blk *vblk)
> > +{
> > +ÂÂÂÂÂÂÂu8 model;
> > +
> > +ÂÂÂÂÂÂÂif (!vblk->zone_sectors)
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn;
> > +
> > +ÂÂÂÂÂÂÂvirtio_cread(vblk->vdev, struct virtio_blk_config,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ zoned.model, &model);
> > +ÂÂÂÂÂÂÂif (!blk_revalidate_disk_zones(vblk->disk, NULL))
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂset_capacity_and_notify(vblk->disk, 0);
> > +}
> > +
> > +static int virtblk_probe_zoned_device(struct virtio_device *vdev,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct virtio_blk *vblk,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct request_queue *q)
> > +{
> > +ÂÂÂÂÂÂÂu32 v;
> > +ÂÂÂÂÂÂÂu8 model;
> > +ÂÂÂÂÂÂÂint ret;
> > +
> > +ÂÂÂÂÂÂÂvirtio_cread(vdev, struct virtio_blk_config,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ zoned.model, &model);
> > +
> > +ÂÂÂÂÂÂÂswitch (model) {
> > +ÂÂÂÂÂÂÂcase VIRTIO_BLK_Z_NONE:
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn 0;
> > +ÂÂÂÂÂÂÂcase VIRTIO_BLK_Z_HM:
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂbreak;
> > +ÂÂÂÂÂÂÂcase VIRTIO_BLK_Z_HA:
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ/*
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ * Present the host-aware device as a regular drive.
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ * TODO It is possible to add an option to make it appear
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ * in the system as a zoned drive.
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ */
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn 0;
> > +ÂÂÂÂÂÂÂdefault:
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(&vdev->dev, "unsupported zone model %d\n", model);
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -EINVAL;
> > +ÂÂÂÂÂÂÂ}
> > +
> > +ÂÂÂÂÂÂÂdev_dbg(&vdev->dev, "probing host-managed zoned device\n");
> > +
> > +ÂÂÂÂÂÂÂdisk_set_zoned(vblk->disk, BLK_ZONED_HM);
> > +ÂÂÂÂÂÂÂblk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q);
> > +
> > +ÂÂÂÂÂÂÂvirtio_cread(vdev, struct virtio_blk_config,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ zoned.max_open_zones, &v);
> > +ÂÂÂÂÂÂÂdisk_set_max_open_zones(vblk->disk, le32_to_cpu(v));
> > +
> > +ÂÂÂÂÂÂÂdev_dbg(&vdev->dev, "max open zones = %u\n", le32_to_cpu(v));
> > +
> > +ÂÂÂÂÂÂÂvirtio_cread(vdev, struct virtio_blk_config,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ zoned.max_active_zones, &v);
> > +ÂÂÂÂÂÂÂdisk_set_max_active_zones(vblk->disk, le32_to_cpu(v));
> > +ÂÂÂÂÂÂÂdev_dbg(&vdev->dev, "max active zones = %u\n", le32_to_cpu(v));
> > +
> > +ÂÂÂÂÂÂÂvirtio_cread(vdev, struct virtio_blk_config,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ zoned.write_granularity, &v);
> > +ÂÂÂÂÂÂÂif (!v) {
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂdev_warn(&vdev->dev, "zero write granularity reported\n");
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -ENODEV;
> > +ÂÂÂÂÂÂÂ}
> > +ÂÂÂÂÂÂÂblk_queue_physical_block_size(q, le32_to_cpu(v));
> > +ÂÂÂÂÂÂÂblk_queue_io_min(q, le32_to_cpu(v));
> > +
> > +ÂÂÂÂÂÂÂdev_dbg(&vdev->dev, "write granularity = %u\n", le32_to_cpu(v));
> > +
> > +ÂÂÂÂÂÂÂ/*
> > +ÂÂÂÂÂÂÂ * virtio ZBD specification doesn't require zones to be a power of
> > +ÂÂÂÂÂÂÂ * two sectors in size, but the code in this driver expects that.
> > +ÂÂÂÂÂÂÂ */
> > +ÂÂÂÂÂÂÂvirtio_cread(vdev, struct virtio_blk_config, zoned.zone_sectors, &v);
> > +ÂÂÂÂÂÂÂvblk->zone_sectors = le32_to_cpu(v);
> > +ÂÂÂÂÂÂÂif (vblk->zone_sectors == 0 || !is_power_of_2(vblk->zone_sectors)) {
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂdev_err(&vdev->dev,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ"zoned device with non power of two zone size %u\n",
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂvblk->zone_sectors);
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -ENODEV;
> > +ÂÂÂÂÂÂÂ}
> > +ÂÂÂÂÂÂÂdev_dbg(&vdev->dev, "zone sectors = %u\n", vblk->zone_sectors);
> > +
> > +ÂÂÂÂÂÂÂif (virtio_has_feature(vdev, VIRTIO_BLK_F_DISCARD)) {
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂdev_warn(&vblk->vdev->dev,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ "ignoring negotiated F_DISCARD for zoned device\n");
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂblk_queue_max_discard_sectors(q, 0);
> > +ÂÂÂÂÂÂÂ}
> > +
> > +ÂÂÂÂÂÂÂret = blk_revalidate_disk_zones(vblk->disk, NULL);
> > +ÂÂÂÂÂÂÂif (!ret) {
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂvirtio_cread(vdev, struct virtio_blk_config,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ zoned.max_append_sectors, &v);
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂif (!v) {
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂdev_warn(&vdev->dev, "zero max_append_sectors
> > reported\n");
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂreturn -ENODEV;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ}
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂblk_queue_max_zone_append_sectors(q, le32_to_cpu(v));
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂdev_dbg(&vdev->dev, "max append sectors = %u\n",
> > le32_to_cpu(v));
> > +ÂÂÂÂÂÂÂ}
> > +
> > +ÂÂÂÂÂÂÂreturn ret;
> > +}
> > +
> > +#else
> > +
> > +/*
> > + * Zoned block device support is not configured in this kernel.
> > + * We only need to define a few symbols to avoid compilation errors.
> > + */
> > +#define virtblk_report_zonesÂÂÂÂÂÂ NULL
> > +static inline void virtblk_revalidate_zones(struct virtio_blk *vblk)
> > +{
> > +}
> > +static inline int virtblk_probe_zoned_device(struct virtio_device *vdev,
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂstruct virtio_blk *vblk, struct request_queue *q)
> > +{
> > +ÂÂÂÂÂÂÂreturn -EOPNOTSUPP;
> > +}
> > +#endif /* CONFIG_BLK_DEV_ZONED */
> > +
> > Â/* return id (s/n) string for *disk to *id_str
> > Â */
> > Âstatic int virtblk_get_id(struct gendisk *disk, char *id_str)
> > @@ -462,18 +783,24 @@ 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->in_hdr_len = sizeof(vbr->status);
> > +ÂÂÂÂÂÂÂvbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_GET_ID);
> > +ÂÂÂÂÂÂÂvbr->out_hdr.sector = 0;
> > +
> > ÂÂÂÂÂÂÂÂerr = blk_rq_map_kern(q, req, id_str, VIRTIO_BLK_ID_BYTES,
> > GFP_KERNEL);
> > ÂÂÂÂÂÂÂÂif (err)
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂgoto out;
> > Â
> > ÂÂÂÂÂÂÂÂblk_execute_rq(req, false);
> > -ÂÂÂÂÂÂÂerr = blk_status_to_errno(virtblk_result(blk_mq_rq_to_pdu(req)));
> > +ÂÂÂÂÂÂÂerr = blk_status_to_errno(virtblk_result(vbr->status));
> > Âout:
> > ÂÂÂÂÂÂÂÂblk_mq_free_request(req);
> > ÂÂÂÂÂÂÂÂreturn err;
> > @@ -524,6 +851,7 @@ static const struct block_device_operations virtblk_fops
> > = {
> > ÂÂÂÂÂÂÂÂ.ownerÂÂÂÂÂÂÂÂÂÂ= THIS_MODULE,
> > ÂÂÂÂÂÂÂÂ.getgeoÂÂÂÂÂÂÂÂÂ= virtblk_getgeo,
> > ÂÂÂÂÂÂÂÂ.free_diskÂÂÂÂÂÂ= virtblk_free_disk,
> > +ÂÂÂÂÂÂÂ.report_zonesÂÂÂ= virtblk_report_zones,
> > Â};
> > Â
> > Âstatic int index_to_minor(int index)
> > @@ -594,6 +922,7 @@ static void virtblk_config_changed_work(struct
> > work_struct *work)
> > ÂÂÂÂÂÂÂÂstruct virtio_blk *vblk =
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂcontainer_of(work, struct virtio_blk, config_work);
> > Â
> > +ÂÂÂÂÂÂÂvirtblk_revalidate_zones(vblk);
> > ÂÂÂÂÂÂÂÂvirtblk_update_capacity(vblk, true);
> > Â}
> > Â
> > @@ -1150,6 +1479,15 @@ static int virtblk_probe(struct virtio_device *vdev)
> > ÂÂÂÂÂÂÂÂvirtblk_update_capacity(vblk, false);
> > ÂÂÂÂÂÂÂÂvirtio_device_ready(vdev);
> > Â
> > +ÂÂÂÂÂÂÂif (virtio_has_feature(vdev, VIRTIO_BLK_F_ZONED)) {
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂerr = virtblk_probe_zoned_device(vdev, vblk, q);
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂif (err)
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂgoto out_cleanup_disk;
> > +ÂÂÂÂÂÂÂ}
> > +
> > +ÂÂÂÂÂÂÂdev_info(&vdev->dev, "blk config size: %zu\n",
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂsizeof(struct virtio_blk_config));
> > +
> > ÂÂÂÂÂÂÂÂerr = device_add_disk(&vdev->dev, vblk->disk, virtblk_attr_groups);
> > ÂÂÂÂÂÂÂÂif (err)
> > ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂgoto out_cleanup_disk;
> > @@ -1251,6 +1589,9 @@ static unsigned int features[] = {
> > ÂÂÂÂÂÂÂÂ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,
> > +#ifdef CONFIG_BLK_DEV_ZONED
> > +ÂÂÂÂÂÂÂVIRTIO_BLK_F_ZONED,
> > +#endif /* CONFIG_BLK_DEV_ZONED */
> > Â};
> > Â
> > Âstatic struct virtio_driver virtio_blk = {
> > diff --git a/include/uapi/linux/virtio_blk.h
> > b/include/uapi/linux/virtio_blk.h
> > index 58e70b24b504..3744e4da1b2a 100644
> > --- a/include/uapi/linux/virtio_blk.h
> > +++ b/include/uapi/linux/virtio_blk.h
> > @@ -41,6 +41,7 @@
> > Â#define VIRTIO_BLK_F_DISCARDÂÂÂ13ÂÂÂÂÂÂ/* DISCARD is supported */
> > Â#define VIRTIO_BLK_F_WRITE_ZEROESÂÂÂÂÂÂ14ÂÂÂÂÂÂ/* WRITE ZEROES is supported
> > */
> > Â#define VIRTIO_BLK_F_SECURE_ERASEÂÂÂÂÂÂ16 /* Secure Erase is supported */
> > +#define VIRTIO_BLK_F_ZONEDÂÂÂÂÂÂÂÂÂÂÂÂÂ17ÂÂÂÂÂÂ/* Zoned block device */
> > Â
> > Â/* Legacy feature bits */
> > Â#ifndef VIRTIO_BLK_NO_LEGACY
> > @@ -137,6 +138,16 @@ struct virtio_blk_config {
> > ÂÂÂÂÂÂÂÂ/* Secure erase commands must be aligned to this number of sectors.
> > */
> > ÂÂÂÂÂÂÂÂ__virtio32 secure_erase_sector_alignment;
> > Â
> > +ÂÂÂÂÂÂÂ/* 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;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ__u8 model;
> > +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ__u8 unused2[3];
> > +ÂÂÂÂÂÂÂ} zoned;
> > Â} __attribute__((packed));
> > Â
> > Â/*
> > @@ -174,6 +185,27 @@ struct virtio_blk_config {
> > Â/* Secure erase command */
> > Â#define VIRTIO_BLK_T_SECURE_ERASEÂÂÂÂÂÂ14
> > Â
> > +/* 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
> > @@ -193,6 +225,72 @@ struct virtio_blk_outhdr {
> > ÂÂÂÂÂÂÂÂ__virtio64 sector;
> > Â};
> > Â
> > +/*
> > + * 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 */
> > +ÂÂÂÂÂÂÂ__u8 z_type;
> > +ÂÂÂÂÂÂÂ/* Zone state */
> > +ÂÂÂÂÂÂÂ__u8 z_state;
> > +ÂÂÂÂÂÂÂ__u8 reserved[38];
> > +};
> > +
> > +struct virtio_blk_zone_report {
> > +ÂÂÂÂÂÂÂ__virtio64 nr_zones;
> > +ÂÂÂÂÂÂÂ__u8 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
> > Â
> > @@ -219,4 +317,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 */
> > -- 
> > 2.34.1
> > 
> > 
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: virtio-dev-unsubscribe@lists.oasis-open.org
> > For additional commands, e-mail: virtio-dev-help@lists.oasis-open.org
> > 



[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]