History

virtio-blk: add support for zoned block devices

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. includes the following fixup: virtio-blk: fix probe without CONFIG_BLK_DEV_ZONED When building without CONFIG_BLK_DEV_ZONED, VIRTIO_BLK_F_ZONED is excluded from array of driver features. As a result virtio_has_feature panics in virtio_check_driver_offered_feature since that by design verifies that a feature we are checking for is listed in the feature array. To fix, replace the call to virtio_has_feature with a stub.

Dmitry Fomichev committed 4 years ago

Commit 95bfec41 parent d16c0cd2 files · +474 −18Browse files

Unified · Split

2 files
  1. drivers/block/virtio_blk.c +369 −18
  2. include/uapi/linux/virtio_blk.h +105 −0
drivers/block/virtio_blk.c+369−18
@@ -15,6 +15,7 @@ · 14 unmodified lines
1515 #include <linux/blk-mq.h>
1616 #include <linux/blk-mq-virtio.h>
1717 #include <linux/numa.h>
18+#include <linux/vmalloc.h>
1819 #include <uapi/linux/virtio_ring.h>
1920
2021 #define PART_BITS 4
@@ -80,22 +81,51 @@ struct virtio_blk { · 59 unmodified lines
8081 int num_vqs;
8182 int io_queues[HCTX_MAX_TYPES];
8283 struct virtio_blk_vq *vqs;
84+
85+ /* For zoned device */
86+ unsigned int zone_sectors;
8387 };
8488
8589 struct virtblk_req {
90+ /* Out header */
8691 struct virtio_blk_outhdr out_hdr;
87− u8 status;
92+
93+ /* In header */
94+ union {
95+ u8 status;
96+
97+ /*
98+ * The zone append command has an extended in header.
99+ * The status field in zone_append_in_hdr must have
100+ * the same offset in virtblk_req as the non-zoned
101+ * status field above.
102+ */
103+ struct {
104+ u8 status;
105+ u8 reserved[7];
106+ u64 append_sector;
107+ } zone_append_in_hdr;
108+ };
109+
110+ size_t in_hdr_len;
111+
88112 struct sg_table sg_table;
89113 struct scatterlist sg[];
90114 };
91115
92−static inline blk_status_t virtblk_result(struct virtblk_req *vbr)
116+static inline blk_status_t virtblk_result(u8 status)
93117 {
94− switch (vbr->status) {
118+ switch (status) {
95119 case VIRTIO_BLK_S_OK:
96120 return BLK_STS_OK;
97121 case VIRTIO_BLK_S_UNSUPP:
98122 return BLK_STS_NOTSUPP;
123+ case VIRTIO_BLK_S_ZONE_OPEN_RESOURCE:
124+ return BLK_STS_ZONE_OPEN_RESOURCE;
125+ case VIRTIO_BLK_S_ZONE_ACTIVE_RESOURCE:
126+ return BLK_STS_ZONE_ACTIVE_RESOURCE;
127+ case VIRTIO_BLK_S_IOERR:
128+ case VIRTIO_BLK_S_ZONE_UNALIGNED_WP:
99129 default:
100130 return BLK_STS_IOERR;
101131 }
@@ -111,11 +141,11 @@ static inline struct virtio_blk_vq *get_virtio_blk_vq(struct blk_mq_hw_ctx *hctx · 9 unmodified lines
111141
112142 static int virtblk_add_req(struct virtqueue *vq, struct virtblk_req *vbr)
113143 {
114− struct scatterlist hdr, status, *sgs[3];
144+ struct scatterlist out_hdr, in_hdr, *sgs[3];
115145 unsigned int num_out = 0, num_in = 0;
116146
117− sg_init_one(&hdr, &vbr->out_hdr, sizeof(vbr->out_hdr));
118− sgs[num_out++] = &hdr;
147+ sg_init_one(&out_hdr, &vbr->out_hdr, sizeof(vbr->out_hdr));
148+ sgs[num_out++] = &out_hdr;
119149
120150 if (vbr->sg_table.nents) {
121151 if (vbr->out_hdr.type & cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_OUT))
@@ -124,8 +154,8 @@ static int virtblk_add_req(struct virtqueue *vq, struct virtblk_req *vbr) · 2 unmodified lines
124154 sgs[num_out + num_in++] = vbr->sg_table.sgl;
125155 }
126156
127− sg_init_one(&status, &vbr->status, sizeof(vbr->status));
128− sgs[num_out + num_in++] = &status;
157+ sg_init_one(&in_hdr, &vbr->status, vbr->in_hdr_len);
158+ sgs[num_out + num_in++] = &in_hdr;
129159
130160 return virtqueue_add_sgs(vq, sgs, num_out, num_in, vbr, GFP_ATOMIC);
131161 }
@@ -214,21 +244,22 @@ static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev, · 82 unmodified lines
214244 struct request *req,
215245 struct virtblk_req *vbr)
216246 {
247+ size_t in_hdr_len = sizeof(vbr->status);
217248 bool unmap = false;
218249 u32 type;
250+ u64 sector = 0;
219251
220− vbr->out_hdr.sector = 0;
252+ /* Set fields for all request types */
253+ vbr->out_hdr.ioprio = cpu_to_virtio32(vdev, req_get_ioprio(req));
221254
222255 switch (req_op(req)) {
223256 case REQ_OP_READ:
224257 type = VIRTIO_BLK_T_IN;
225− vbr->out_hdr.sector = cpu_to_virtio64(vdev,
226− blk_rq_pos(req));
258+ sector = blk_rq_pos(req);
227259 break;
228260 case REQ_OP_WRITE:
229261 type = VIRTIO_BLK_T_OUT;
230− vbr->out_hdr.sector = cpu_to_virtio64(vdev,
231− blk_rq_pos(req));
262+ sector = blk_rq_pos(req);
232263 break;
233264 case REQ_OP_FLUSH:
234265 type = VIRTIO_BLK_T_FLUSH;
@@ -243,16 +274,42 @@ static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev, · 8 unmodified lines
243274 case REQ_OP_SECURE_ERASE:
244275 type = VIRTIO_BLK_T_SECURE_ERASE;
245276 break;
246− case REQ_OP_DRV_IN:
247− type = VIRTIO_BLK_T_GET_ID;
277+ case REQ_OP_ZONE_OPEN:
278+ type = VIRTIO_BLK_T_ZONE_OPEN;
279+ sector = blk_rq_pos(req);
280+ break;
281+ case REQ_OP_ZONE_CLOSE:
282+ type = VIRTIO_BLK_T_ZONE_CLOSE;
283+ sector = blk_rq_pos(req);
284+ break;
285+ case REQ_OP_ZONE_FINISH:
286+ type = VIRTIO_BLK_T_ZONE_FINISH;
287+ sector = blk_rq_pos(req);
288+ break;
289+ case REQ_OP_ZONE_APPEND:
290+ type = VIRTIO_BLK_T_ZONE_APPEND;
291+ sector = blk_rq_pos(req);
292+ in_hdr_len = sizeof(vbr->zone_append_in_hdr);
248293 break;
294+ case REQ_OP_ZONE_RESET:
295+ type = VIRTIO_BLK_T_ZONE_RESET;
296+ sector = blk_rq_pos(req);
297+ break;
298+ case REQ_OP_ZONE_RESET_ALL:
299+ type = VIRTIO_BLK_T_ZONE_RESET_ALL;
300+ break;
301+ case REQ_OP_DRV_IN:
302+ /* Out header already filled in, nothing to do */
303+ return 0;
249304 default:
250305 WARN_ON_ONCE(1);
251306 return BLK_STS_IOERR;
252307 }
253308
309+ /* Set fields for non-REQ_OP_DRV_IN request types */
310+ vbr->in_hdr_len = in_hdr_len;
254311 vbr->out_hdr.type = cpu_to_virtio32(vdev, type);
255− vbr->out_hdr.ioprio = cpu_to_virtio32(vdev, req_get_ioprio(req));
312+ vbr->out_hdr.sector = cpu_to_virtio64(vdev, sector);
256313
257314 if (type == VIRTIO_BLK_T_DISCARD || type == VIRTIO_BLK_T_WRITE_ZEROES ||
258315 type == VIRTIO_BLK_T_SECURE_ERASE) {
@@ -266,10 +323,15 @@ static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev, · 7 unmodified lines
266323 static inline void virtblk_request_done(struct request *req)
267324 {
268325 struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
326+ int status = virtblk_result(vbr->status);
269327
270328 virtblk_unmap_data(req, vbr);
271329 virtblk_cleanup_cmd(req);
272− blk_mq_end_request(req, virtblk_result(vbr));
330+
331+ if (req_op(req) == REQ_OP_ZONE_APPEND)
332+ req->__sector = le64_to_cpu(vbr->zone_append_in_hdr.append_sector);
333+
334+ blk_mq_end_request(req, status);
273335 }
274336
275337 static void virtblk_done(struct virtqueue *vq)
@@ -457,6 +519,275 @@ static void virtio_queue_rqs(struct request **rqlist) · 181 unmodified lines
457519 *rqlist = requeue_list;
458520 }
459521
522+#ifdef CONFIG_BLK_DEV_ZONED
523+static void *virtblk_alloc_report_buffer(struct virtio_blk *vblk,
524+ unsigned int nr_zones,
525+ unsigned int zone_sectors,
526+ size_t *buflen)
527+{
528+ struct request_queue *q = vblk->disk->queue;
529+ size_t bufsize;
530+ void *buf;
531+
532+ nr_zones = min_t(unsigned int, nr_zones,
533+ get_capacity(vblk->disk) >> ilog2(zone_sectors));
534+
535+ bufsize = sizeof(struct virtio_blk_zone_report) +
536+ nr_zones * sizeof(struct virtio_blk_zone_descriptor);
537+ bufsize = min_t(size_t, bufsize,
538+ queue_max_hw_sectors(q) << SECTOR_SHIFT);
539+ bufsize = min_t(size_t, bufsize, queue_max_segments(q) << PAGE_SHIFT);
540+
541+ while (bufsize >= sizeof(struct virtio_blk_zone_report)) {
542+ buf = __vmalloc(bufsize, GFP_KERNEL | __GFP_NORETRY);
543+ if (buf) {
544+ *buflen = bufsize;
545+ return buf;
546+ }
547+ bufsize >>= 1;
548+ }
549+
550+ return NULL;
551+}
552+
553+static int virtblk_submit_zone_report(struct virtio_blk *vblk,
554+ char *report_buf, size_t report_len,
555+ sector_t sector)
556+{
557+ struct request_queue *q = vblk->disk->queue;
558+ struct request *req;
559+ struct virtblk_req *vbr;
560+ int err;
561+
562+ req = blk_mq_alloc_request(q, REQ_OP_DRV_IN, 0);
563+ if (IS_ERR(req))
564+ return PTR_ERR(req);
565+
566+ vbr = blk_mq_rq_to_pdu(req);
567+ vbr->in_hdr_len = sizeof(vbr->status);
568+ vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_ZONE_REPORT);
569+ vbr->out_hdr.sector = cpu_to_virtio64(vblk->vdev, sector);
570+
571+ err = blk_rq_map_kern(q, req, report_buf, report_len, GFP_KERNEL);
572+ if (err)
573+ goto out;
574+
575+ blk_execute_rq(req, false);
576+ err = blk_status_to_errno(virtblk_result(vbr->status));
577+out:
578+ blk_mq_free_request(req);
579+ return err;
580+}
581+
582+static int virtblk_parse_zone(struct virtio_blk *vblk,
583+ struct virtio_blk_zone_descriptor *entry,
584+ unsigned int idx, unsigned int zone_sectors,
585+ report_zones_cb cb, void *data)
586+{
587+ struct blk_zone zone = { };
588+
589+ if (entry->z_type != VIRTIO_BLK_ZT_SWR &&
590+ entry->z_type != VIRTIO_BLK_ZT_SWP &&
591+ entry->z_type != VIRTIO_BLK_ZT_CONV) {
592+ dev_err(&vblk->vdev->dev, "invalid zone type %#x\n",
593+ entry->z_type);
594+ return -EINVAL;
595+ }
596+
597+ zone.type = entry->z_type;
598+ zone.cond = entry->z_state;
599+ zone.len = zone_sectors;
600+ zone.capacity = le64_to_cpu(entry->z_cap);
601+ zone.start = le64_to_cpu(entry->z_start);
602+ if (zone.cond == BLK_ZONE_COND_FULL)
603+ zone.wp = zone.start + zone.len;
604+ else
605+ zone.wp = le64_to_cpu(entry->z_wp);
606+
607+ return cb(&zone, idx, data);
608+}
609+
610+static int virtblk_report_zones(struct gendisk *disk, sector_t sector,
611+ unsigned int nr_zones, report_zones_cb cb,
612+ void *data)
613+{
614+ struct virtio_blk *vblk = disk->private_data;
615+ struct virtio_blk_zone_report *report;
616+ unsigned int zone_sectors = vblk->zone_sectors;
617+ unsigned int nz, i;
618+ int ret, zone_idx = 0;
619+ size_t buflen;
620+
621+ if (WARN_ON_ONCE(!vblk->zone_sectors))
622+ return -EOPNOTSUPP;
623+
624+ report = virtblk_alloc_report_buffer(vblk, nr_zones,
625+ zone_sectors, &buflen);
626+ if (!report)
627+ return -ENOMEM;
628+
629+ while (zone_idx < nr_zones && sector < get_capacity(vblk->disk)) {
630+ memset(report, 0, buflen);
631+
632+ ret = virtblk_submit_zone_report(vblk, (char *)report,
633+ buflen, sector);
634+ if (ret) {
635+ if (ret > 0)
636+ ret = -EIO;
637+ goto out_free;
638+ }
639+ nz = min((unsigned int)le64_to_cpu(report->nr_zones), nr_zones);
640+ if (!nz)
641+ break;
642+
643+ for (i = 0; i < nz && zone_idx < nr_zones; i++) {
644+ ret = virtblk_parse_zone(vblk, &report->zones[i],
645+ zone_idx, zone_sectors, cb, data);
646+ if (ret)
647+ goto out_free;
648+ sector = le64_to_cpu(report->zones[i].z_start) + zone_sectors;
649+ zone_idx++;
650+ }
651+ }
652+
653+ if (zone_idx > 0)
654+ ret = zone_idx;
655+ else
656+ ret = -EINVAL;
657+out_free:
658+ kvfree(report);
659+ return ret;
660+}
661+
662+static void virtblk_revalidate_zones(struct virtio_blk *vblk)
663+{
664+ u8 model;
665+
666+ if (!vblk->zone_sectors)
667+ return;
668+
669+ virtio_cread(vblk->vdev, struct virtio_blk_config,
670+ zoned.model, &model);
671+ if (!blk_revalidate_disk_zones(vblk->disk, NULL))
672+ set_capacity_and_notify(vblk->disk, 0);
673+}
674+
675+static int virtblk_probe_zoned_device(struct virtio_device *vdev,
676+ struct virtio_blk *vblk,
677+ struct request_queue *q)
678+{
679+ u32 v;
680+ u8 model;
681+ int ret;
682+
683+ virtio_cread(vdev, struct virtio_blk_config,
684+ zoned.model, &model);
685+
686+ switch (model) {
687+ case VIRTIO_BLK_Z_NONE:
688+ return 0;
689+ case VIRTIO_BLK_Z_HM:
690+ break;
691+ case VIRTIO_BLK_Z_HA:
692+ /*
693+ * Present the host-aware device as a regular drive.
694+ * TODO It is possible to add an option to make it appear
695+ * in the system as a zoned drive.
696+ */
697+ return 0;
698+ default:
699+ dev_err(&vdev->dev, "unsupported zone model %d\n", model);
700+ return -EINVAL;
701+ }
702+
703+ dev_dbg(&vdev->dev, "probing host-managed zoned device\n");
704+
705+ disk_set_zoned(vblk->disk, BLK_ZONED_HM);
706+ blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q);
707+
708+ virtio_cread(vdev, struct virtio_blk_config,
709+ zoned.max_open_zones, &v);
710+ disk_set_max_open_zones(vblk->disk, le32_to_cpu(v));
711+
712+ dev_dbg(&vdev->dev, "max open zones = %u\n", le32_to_cpu(v));
713+
714+ virtio_cread(vdev, struct virtio_blk_config,
715+ zoned.max_active_zones, &v);
716+ disk_set_max_active_zones(vblk->disk, le32_to_cpu(v));
717+ dev_dbg(&vdev->dev, "max active zones = %u\n", le32_to_cpu(v));
718+
719+ virtio_cread(vdev, struct virtio_blk_config,
720+ zoned.write_granularity, &v);
721+ if (!v) {
722+ dev_warn(&vdev->dev, "zero write granularity reported\n");
723+ return -ENODEV;
724+ }
725+ blk_queue_physical_block_size(q, le32_to_cpu(v));
726+ blk_queue_io_min(q, le32_to_cpu(v));
727+
728+ dev_dbg(&vdev->dev, "write granularity = %u\n", le32_to_cpu(v));
729+
730+ /*
731+ * virtio ZBD specification doesn't require zones to be a power of
732+ * two sectors in size, but the code in this driver expects that.
733+ */
734+ virtio_cread(vdev, struct virtio_blk_config, zoned.zone_sectors, &v);
735+ vblk->zone_sectors = le32_to_cpu(v);
736+ if (vblk->zone_sectors == 0 || !is_power_of_2(vblk->zone_sectors)) {
737+ dev_err(&vdev->dev,
738+ "zoned device with non power of two zone size %u\n",
739+ vblk->zone_sectors);
740+ return -ENODEV;
741+ }
742+ dev_dbg(&vdev->dev, "zone sectors = %u\n", vblk->zone_sectors);
743+
744+ if (virtio_has_feature(vdev, VIRTIO_BLK_F_DISCARD)) {
745+ dev_warn(&vblk->vdev->dev,
746+ "ignoring negotiated F_DISCARD for zoned device\n");
747+ blk_queue_max_discard_sectors(q, 0);
748+ }
749+
750+ ret = blk_revalidate_disk_zones(vblk->disk, NULL);
751+ if (!ret) {
752+ virtio_cread(vdev, struct virtio_blk_config,
753+ zoned.max_append_sectors, &v);
754+ if (!v) {
755+ dev_warn(&vdev->dev, "zero max_append_sectors reported\n");
756+ return -ENODEV;
757+ }
758+ blk_queue_max_zone_append_sectors(q, le32_to_cpu(v));
759+ dev_dbg(&vdev->dev, "max append sectors = %u\n", le32_to_cpu(v));
760+ }
761+
762+ return ret;
763+}
764+
765+static inline bool virtblk_has_zoned_feature(struct virtio_device *vdev)
766+{
767+ return virtio_has_feature(vdev, VIRTIO_BLK_F_ZONED);
768+}
769+#else
770+
771+/*
772+ * Zoned block device support is not configured in this kernel.
773+ * We only need to define a few symbols to avoid compilation errors.
774+ */
775+#define virtblk_report_zones NULL
776+static inline void virtblk_revalidate_zones(struct virtio_blk *vblk)
777+{
778+}
779+static inline int virtblk_probe_zoned_device(struct virtio_device *vdev,
780+ struct virtio_blk *vblk, struct request_queue *q)
781+{
782+ return -EOPNOTSUPP;
783+}
784+
785+static inline bool virtblk_has_zoned_feature(struct virtio_device *vdev)
786+{
787+ return false;
788+}
789+#endif /* CONFIG_BLK_DEV_ZONED */
790+
460791 /* return id (s/n) string for *disk to *id_str
461792 */
462793 static int virtblk_get_id(struct gendisk *disk, char *id_str)
@@ -464,18 +795,24 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str) · 1 unmodified line
464795 struct virtio_blk *vblk = disk->private_data;
465796 struct request_queue *q = vblk->disk->queue;
466797 struct request *req;
798+ struct virtblk_req *vbr;
467799 int err;
468800
469801 req = blk_mq_alloc_request(q, REQ_OP_DRV_IN, 0);
470802 if (IS_ERR(req))
471803 return PTR_ERR(req);
472804
805+ vbr = blk_mq_rq_to_pdu(req);
806+ vbr->in_hdr_len = sizeof(vbr->status);
807+ vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_GET_ID);
808+ vbr->out_hdr.sector = 0;
809+
473810 err = blk_rq_map_kern(q, req, id_str, VIRTIO_BLK_ID_BYTES, GFP_KERNEL);
474811 if (err)
475812 goto out;
476813
477814 blk_execute_rq(req, false);
478− err = blk_status_to_errno(virtblk_result(blk_mq_rq_to_pdu(req)));
815+ err = blk_status_to_errno(virtblk_result(vbr->status));
479816 out:
480817 blk_mq_free_request(req);
481818 return err;
@@ -526,6 +863,7 @@ static const struct block_device_operations virtblk_fops = { · 44 unmodified lines
526863 .owner = THIS_MODULE,
527864 .getgeo = virtblk_getgeo,
528865 .free_disk = virtblk_free_disk,
866+ .report_zones = virtblk_report_zones,
529867 };
530868
531869 static int index_to_minor(int index)
@@ -596,6 +934,7 @@ static void virtblk_config_changed_work(struct work_struct *work) · 64 unmodified lines
596934 struct virtio_blk *vblk =
597935 container_of(work, struct virtio_blk, config_work);
598936
937+ virtblk_revalidate_zones(vblk);
599938 virtblk_update_capacity(vblk, true);
600939 }
601940
@@ -1152,6 +1491,15 @@ static int virtblk_probe(struct virtio_device *vdev) · 550 unmodified lines
11521491 virtblk_update_capacity(vblk, false);
11531492 virtio_device_ready(vdev);
11541493
1494+ if (virtblk_has_zoned_feature(vdev)) {
1495+ err = virtblk_probe_zoned_device(vdev, vblk, q);
1496+ if (err)
1497+ goto out_cleanup_disk;
1498+ }
1499+
1500+ dev_info(&vdev->dev, "blk config size: %zu\n",
1501+ sizeof(struct virtio_blk_config));
1502+
11551503 err = device_add_disk(&vdev->dev, vblk->disk, virtblk_attr_groups);
11561504 if (err)
11571505 goto out_cleanup_disk;
@@ -1253,6 +1601,9 @@ static unsigned int features[] = { · 95 unmodified lines
12531601 VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE,
12541602 VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_WRITE_ZEROES,
12551603 VIRTIO_BLK_F_SECURE_ERASE,
1604+#ifdef CONFIG_BLK_DEV_ZONED
1605+ VIRTIO_BLK_F_ZONED,
1606+#endif /* CONFIG_BLK_DEV_ZONED */
12561607 };
12571608
12581609 static struct virtio_driver virtio_blk = {
include/uapi/linux/virtio_blk.h+105−0
@@ -41,6 +41,7 @@ · 40 unmodified lines
4141 #define VIRTIO_BLK_F_DISCARD 13 /* DISCARD is supported */
4242 #define VIRTIO_BLK_F_WRITE_ZEROES 14 /* WRITE ZEROES is supported */
4343 #define VIRTIO_BLK_F_SECURE_ERASE 16 /* Secure Erase is supported */
44+#define VIRTIO_BLK_F_ZONED 17 /* Zoned block device */
4445
4546 /* Legacy feature bits */
4647 #ifndef VIRTIO_BLK_NO_LEGACY
@@ -137,6 +138,16 @@ struct virtio_blk_config { · 90 unmodified lines
137138 /* Secure erase commands must be aligned to this number of sectors. */
138139 __virtio32 secure_erase_sector_alignment;
139140
141+ /* Zoned block device characteristics (if VIRTIO_BLK_F_ZONED) */
142+ struct virtio_blk_zoned_characteristics {
143+ __virtio32 zone_sectors;
144+ __virtio32 max_open_zones;
145+ __virtio32 max_active_zones;
146+ __virtio32 max_append_sectors;
147+ __virtio32 write_granularity;
148+ __u8 model;
149+ __u8 unused2[3];
150+ } zoned;
140151 } __attribute__((packed));
141152
142153 /*
@@ -174,6 +185,27 @@ struct virtio_blk_config { · 31 unmodified lines
174185 /* Secure erase command */
175186 #define VIRTIO_BLK_T_SECURE_ERASE 14
176187
188+/* Zone append command */
189+#define VIRTIO_BLK_T_ZONE_APPEND 15
190+
191+/* Report zones command */
192+#define VIRTIO_BLK_T_ZONE_REPORT 16
193+
194+/* Open zone command */
195+#define VIRTIO_BLK_T_ZONE_OPEN 18
196+
197+/* Close zone command */
198+#define VIRTIO_BLK_T_ZONE_CLOSE 20
199+
200+/* Finish zone command */
201+#define VIRTIO_BLK_T_ZONE_FINISH 22
202+
203+/* Reset zone command */
204+#define VIRTIO_BLK_T_ZONE_RESET 24
205+
206+/* Reset All zones command */
207+#define VIRTIO_BLK_T_ZONE_RESET_ALL 26
208+
177209 #ifndef VIRTIO_BLK_NO_LEGACY
178210 /* Barrier before this op. */
179211 #define VIRTIO_BLK_T_BARRIER 0x80000000
@@ -193,6 +225,72 @@ struct virtio_blk_outhdr { · 13 unmodified lines
193225 __virtio64 sector;
194226 };
195227
228+/*
229+ * Supported zoned device models.
230+ */
231+
232+/* Regular block device */
233+#define VIRTIO_BLK_Z_NONE 0
234+/* Host-managed zoned device */
235+#define VIRTIO_BLK_Z_HM 1
236+/* Host-aware zoned device */
237+#define VIRTIO_BLK_Z_HA 2
238+
239+/*
240+ * Zone descriptor. A part of VIRTIO_BLK_T_ZONE_REPORT command reply.
241+ */
242+struct virtio_blk_zone_descriptor {
243+ /* Zone capacity */
244+ __virtio64 z_cap;
245+ /* The starting sector of the zone */
246+ __virtio64 z_start;
247+ /* Zone write pointer position in sectors */
248+ __virtio64 z_wp;
249+ /* Zone type */
250+ __u8 z_type;
251+ /* Zone state */
252+ __u8 z_state;
253+ __u8 reserved[38];
254+};
255+
256+struct virtio_blk_zone_report {
257+ __virtio64 nr_zones;
258+ __u8 reserved[56];
259+ struct virtio_blk_zone_descriptor zones[];
260+};
261+
262+/*
263+ * Supported zone types.
264+ */
265+
266+/* Conventional zone */
267+#define VIRTIO_BLK_ZT_CONV 1
268+/* Sequential Write Required zone */
269+#define VIRTIO_BLK_ZT_SWR 2
270+/* Sequential Write Preferred zone */
271+#define VIRTIO_BLK_ZT_SWP 3
272+
273+/*
274+ * Zone states that are available for zones of all types.
275+ */
276+
277+/* Not a write pointer (conventional zones only) */
278+#define VIRTIO_BLK_ZS_NOT_WP 0
279+/* Empty */
280+#define VIRTIO_BLK_ZS_EMPTY 1
281+/* Implicitly Open */
282+#define VIRTIO_BLK_ZS_IOPEN 2
283+/* Explicitly Open */
284+#define VIRTIO_BLK_ZS_EOPEN 3
285+/* Closed */
286+#define VIRTIO_BLK_ZS_CLOSED 4
287+/* Read-Only */
288+#define VIRTIO_BLK_ZS_RDONLY 13
289+/* Full */
290+#define VIRTIO_BLK_ZS_FULL 14
291+/* Offline */
292+#define VIRTIO_BLK_ZS_OFFLINE 15
293+
196294 /* Unmap this range (only valid for write zeroes command) */
197295 #define VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP 0x00000001
198296
@@ -219,4 +317,11 @@ struct virtio_scsi_inhdr { · 20 unmodified lines
219317 #define VIRTIO_BLK_S_OK 0
220318 #define VIRTIO_BLK_S_IOERR 1
221319 #define VIRTIO_BLK_S_UNSUPP 2
320+
321+/* Error codes that are specific to zoned block devices */
322+#define VIRTIO_BLK_S_ZONE_INVALID_CMD 3
323+#define VIRTIO_BLK_S_ZONE_UNALIGNED_WP 4
324+#define VIRTIO_BLK_S_ZONE_OPEN_RESOURCE 5
325+#define VIRTIO_BLK_S_ZONE_ACTIVE_RESOURCE 6
326+
222327 #endif /* _LINUX_VIRTIO_BLK_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t