Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost

Pull virtio/vhost updates from Michael Tsirkin:
"Features, fixes, cleanups:

- discard in virtio blk

- misc fixes and cleanups"

* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost:
vhost: correct the related warning message
vhost: split structs into a separate header file
virtio: remove deprecated VIRTIO_PCI_CONFIG()
vhost/vsock: switch to a mutex for vhost_vsock_hash
virtio_blk: add discard and write zeroes support

+279 -125
+81 -2
drivers/block/virtio_blk.c
··· 18 18 19 19 #define PART_BITS 4 20 20 #define VQ_NAME_LEN 16 21 + #define MAX_DISCARD_SEGMENTS 256u 21 22 22 23 static int major; 23 24 static DEFINE_IDA(vd_index_ida); ··· 173 172 return virtqueue_add_sgs(vq, sgs, num_out, num_in, vbr, GFP_ATOMIC); 174 173 } 175 174 175 + static int virtblk_setup_discard_write_zeroes(struct request *req, bool unmap) 176 + { 177 + unsigned short segments = blk_rq_nr_discard_segments(req); 178 + unsigned short n = 0; 179 + struct virtio_blk_discard_write_zeroes *range; 180 + struct bio *bio; 181 + u32 flags = 0; 182 + 183 + if (unmap) 184 + flags |= VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP; 185 + 186 + range = kmalloc_array(segments, sizeof(*range), GFP_ATOMIC); 187 + if (!range) 188 + return -ENOMEM; 189 + 190 + __rq_for_each_bio(bio, req) { 191 + u64 sector = bio->bi_iter.bi_sector; 192 + u32 num_sectors = bio->bi_iter.bi_size >> SECTOR_SHIFT; 193 + 194 + range[n].flags = cpu_to_le32(flags); 195 + range[n].num_sectors = cpu_to_le32(num_sectors); 196 + range[n].sector = cpu_to_le64(sector); 197 + n++; 198 + } 199 + 200 + req->special_vec.bv_page = virt_to_page(range); 201 + req->special_vec.bv_offset = offset_in_page(range); 202 + req->special_vec.bv_len = sizeof(*range) * segments; 203 + req->rq_flags |= RQF_SPECIAL_PAYLOAD; 204 + 205 + return 0; 206 + } 207 + 176 208 static inline void virtblk_request_done(struct request *req) 177 209 { 178 210 struct virtblk_req *vbr = blk_mq_rq_to_pdu(req); 211 + 212 + if (req->rq_flags & RQF_SPECIAL_PAYLOAD) { 213 + kfree(page_address(req->special_vec.bv_page) + 214 + req->special_vec.bv_offset); 215 + } 179 216 180 217 switch (req_op(req)) { 181 218 case REQ_OP_SCSI_IN: ··· 278 239 int qid = hctx->queue_num; 279 240 int err; 280 241 bool notify = false; 242 + bool unmap = false; 281 243 u32 type; 282 244 283 245 BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems); ··· 290 250 break; 291 251 case REQ_OP_FLUSH: 292 252 type = VIRTIO_BLK_T_FLUSH; 253 + break; 254 + case REQ_OP_DISCARD: 255 + type = VIRTIO_BLK_T_DISCARD; 256 + break; 257 + case REQ_OP_WRITE_ZEROES: 258 + type = VIRTIO_BLK_T_WRITE_ZEROES; 259 + unmap = !(req->cmd_flags & REQ_NOUNMAP); 293 260 break; 294 261 case REQ_OP_SCSI_IN: 295 262 case REQ_OP_SCSI_OUT: ··· 316 269 vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(req)); 317 270 318 271 blk_mq_start_request(req); 272 + 273 + if (type == VIRTIO_BLK_T_DISCARD || type == VIRTIO_BLK_T_WRITE_ZEROES) { 274 + err = virtblk_setup_discard_write_zeroes(req, unmap); 275 + if (err) 276 + return BLK_STS_RESOURCE; 277 + } 319 278 320 279 num = blk_rq_map_sg(hctx->queue, req, vbr->sg); 321 280 if (num) { ··· 870 817 if (!err && opt_io_size) 871 818 blk_queue_io_opt(q, blk_size * opt_io_size); 872 819 820 + if (virtio_has_feature(vdev, VIRTIO_BLK_F_DISCARD)) { 821 + q->limits.discard_granularity = blk_size; 822 + 823 + virtio_cread(vdev, struct virtio_blk_config, 824 + discard_sector_alignment, &v); 825 + q->limits.discard_alignment = v ? v << SECTOR_SHIFT : 0; 826 + 827 + virtio_cread(vdev, struct virtio_blk_config, 828 + max_discard_sectors, &v); 829 + blk_queue_max_discard_sectors(q, v ? v : UINT_MAX); 830 + 831 + virtio_cread(vdev, struct virtio_blk_config, max_discard_seg, 832 + &v); 833 + blk_queue_max_discard_segments(q, 834 + min_not_zero(v, 835 + MAX_DISCARD_SEGMENTS)); 836 + 837 + blk_queue_flag_set(QUEUE_FLAG_DISCARD, q); 838 + } 839 + 840 + if (virtio_has_feature(vdev, VIRTIO_BLK_F_WRITE_ZEROES)) { 841 + virtio_cread(vdev, struct virtio_blk_config, 842 + max_write_zeroes_sectors, &v); 843 + blk_queue_max_write_zeroes_sectors(q, v ? v : UINT_MAX); 844 + } 845 + 873 846 virtblk_update_capacity(vblk, false); 874 847 virtio_device_ready(vdev); 875 848 ··· 989 910 VIRTIO_BLK_F_SCSI, 990 911 #endif 991 912 VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE, 992 - VIRTIO_BLK_F_MQ, 913 + VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_WRITE_ZEROES, 993 914 } 994 915 ; 995 916 static unsigned int features[] = { 996 917 VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY, 997 918 VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, 998 919 VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE, 999 - VIRTIO_BLK_F_MQ, 920 + VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_WRITE_ZEROES, 1000 921 }; 1001 922 1002 923 static struct virtio_driver virtio_blk = {
+2 -2
drivers/vhost/scsi.c
··· 884 884 885 885 if (unlikely(!copy_from_iter_full(vc->req, vc->req_size, 886 886 &vc->out_iter))) { 887 - vq_err(vq, "Faulted on copy_from_iter\n"); 887 + vq_err(vq, "Faulted on copy_from_iter_full\n"); 888 888 } else if (unlikely(*vc->lunp != 1)) { 889 889 /* virtio-scsi spec requires byte 0 of the lun to be 1 */ 890 890 vq_err(vq, "Illegal virtio-scsi lun: %u\n", *vc->lunp); ··· 1436 1436 se_tpg = &tpg->se_tpg; 1437 1437 ret = target_depend_item(&se_tpg->tpg_group.cg_item); 1438 1438 if (ret) { 1439 - pr_warn("configfs_depend_item() failed: %d\n", ret); 1439 + pr_warn("target_depend_item() failed: %d\n", ret); 1440 1440 kfree(vs_tpg); 1441 1441 mutex_unlock(&tpg->tv_tpg_mutex); 1442 1442 goto out;
+8 -8
drivers/vhost/vsock.c
··· 27 27 }; 28 28 29 29 /* Used to track all the vhost_vsock instances on the system. */ 30 - static DEFINE_SPINLOCK(vhost_vsock_lock); 30 + static DEFINE_MUTEX(vhost_vsock_mutex); 31 31 static DEFINE_READ_MOSTLY_HASHTABLE(vhost_vsock_hash, 8); 32 32 33 33 struct vhost_vsock { 34 34 struct vhost_dev dev; 35 35 struct vhost_virtqueue vqs[2]; 36 36 37 - /* Link to global vhost_vsock_hash, writes use vhost_vsock_lock */ 37 + /* Link to global vhost_vsock_hash, writes use vhost_vsock_mutex */ 38 38 struct hlist_node hash; 39 39 40 40 struct vhost_work send_pkt_work; ··· 51 51 return VHOST_VSOCK_DEFAULT_HOST_CID; 52 52 } 53 53 54 - /* Callers that dereference the return value must hold vhost_vsock_lock or the 54 + /* Callers that dereference the return value must hold vhost_vsock_mutex or the 55 55 * RCU read lock. 56 56 */ 57 57 static struct vhost_vsock *vhost_vsock_get(u32 guest_cid) ··· 584 584 { 585 585 struct vhost_vsock *vsock = file->private_data; 586 586 587 - spin_lock_bh(&vhost_vsock_lock); 587 + mutex_lock(&vhost_vsock_mutex); 588 588 if (vsock->guest_cid) 589 589 hash_del_rcu(&vsock->hash); 590 - spin_unlock_bh(&vhost_vsock_lock); 590 + mutex_unlock(&vhost_vsock_mutex); 591 591 592 592 /* Wait for other CPUs to finish using vsock */ 593 593 synchronize_rcu(); ··· 631 631 return -EINVAL; 632 632 633 633 /* Refuse if CID is already in use */ 634 - spin_lock_bh(&vhost_vsock_lock); 634 + mutex_lock(&vhost_vsock_mutex); 635 635 other = vhost_vsock_get(guest_cid); 636 636 if (other && other != vsock) { 637 - spin_unlock_bh(&vhost_vsock_lock); 637 + mutex_unlock(&vhost_vsock_mutex); 638 638 return -EADDRINUSE; 639 639 } 640 640 ··· 643 643 644 644 vsock->guest_cid = guest_cid; 645 645 hash_add_rcu(vhost_vsock_hash, &vsock->hash, guest_cid); 646 - spin_unlock_bh(&vhost_vsock_lock); 646 + mutex_unlock(&vhost_vsock_mutex); 647 647 648 648 return 0; 649 649 }
+4 -2
drivers/virtio/virtio_pci_legacy.c
··· 52 52 { 53 53 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 54 54 void __iomem *ioaddr = vp_dev->ioaddr + 55 - VIRTIO_PCI_CONFIG(vp_dev) + offset; 55 + VIRTIO_PCI_CONFIG_OFF(vp_dev->msix_enabled) + 56 + offset; 56 57 u8 *ptr = buf; 57 58 int i; 58 59 ··· 68 67 { 69 68 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 70 69 void __iomem *ioaddr = vp_dev->ioaddr + 71 - VIRTIO_PCI_CONFIG(vp_dev) + offset; 70 + VIRTIO_PCI_CONFIG_OFF(vp_dev->msix_enabled) + 71 + offset; 72 72 const u8 *ptr = buf; 73 73 int i; 74 74
+2 -111
include/uapi/linux/vhost.h
··· 11 11 * device configuration. 12 12 */ 13 13 14 + #include <linux/vhost_types.h> 14 15 #include <linux/types.h> 15 - #include <linux/compiler.h> 16 16 #include <linux/ioctl.h> 17 - #include <linux/virtio_config.h> 18 - #include <linux/virtio_ring.h> 19 - 20 - struct vhost_vring_state { 21 - unsigned int index; 22 - unsigned int num; 23 - }; 24 - 25 - struct vhost_vring_file { 26 - unsigned int index; 27 - int fd; /* Pass -1 to unbind from file. */ 28 - 29 - }; 30 - 31 - struct vhost_vring_addr { 32 - unsigned int index; 33 - /* Option flags. */ 34 - unsigned int flags; 35 - /* Flag values: */ 36 - /* Whether log address is valid. If set enables logging. */ 37 - #define VHOST_VRING_F_LOG 0 38 - 39 - /* Start of array of descriptors (virtually contiguous) */ 40 - __u64 desc_user_addr; 41 - /* Used structure address. Must be 32 bit aligned */ 42 - __u64 used_user_addr; 43 - /* Available structure address. Must be 16 bit aligned */ 44 - __u64 avail_user_addr; 45 - /* Logging support. */ 46 - /* Log writes to used structure, at offset calculated from specified 47 - * address. Address must be 32 bit aligned. */ 48 - __u64 log_guest_addr; 49 - }; 50 - 51 - /* no alignment requirement */ 52 - struct vhost_iotlb_msg { 53 - __u64 iova; 54 - __u64 size; 55 - __u64 uaddr; 56 - #define VHOST_ACCESS_RO 0x1 57 - #define VHOST_ACCESS_WO 0x2 58 - #define VHOST_ACCESS_RW 0x3 59 - __u8 perm; 60 - #define VHOST_IOTLB_MISS 1 61 - #define VHOST_IOTLB_UPDATE 2 62 - #define VHOST_IOTLB_INVALIDATE 3 63 - #define VHOST_IOTLB_ACCESS_FAIL 4 64 - __u8 type; 65 - }; 66 - 67 - #define VHOST_IOTLB_MSG 0x1 68 - #define VHOST_IOTLB_MSG_V2 0x2 69 - 70 - struct vhost_msg { 71 - int type; 72 - union { 73 - struct vhost_iotlb_msg iotlb; 74 - __u8 padding[64]; 75 - }; 76 - }; 77 - 78 - struct vhost_msg_v2 { 79 - __u32 type; 80 - __u32 reserved; 81 - union { 82 - struct vhost_iotlb_msg iotlb; 83 - __u8 padding[64]; 84 - }; 85 - }; 86 - 87 - struct vhost_memory_region { 88 - __u64 guest_phys_addr; 89 - __u64 memory_size; /* bytes */ 90 - __u64 userspace_addr; 91 - __u64 flags_padding; /* No flags are currently specified. */ 92 - }; 93 - 94 - /* All region addresses and sizes must be 4K aligned. */ 95 - #define VHOST_PAGE_SIZE 0x1000 96 - 97 - struct vhost_memory { 98 - __u32 nregions; 99 - __u32 padding; 100 - struct vhost_memory_region regions[0]; 101 - }; 102 17 103 18 /* ioctls */ 104 19 ··· 101 186 * device. This can be used to stop the ring (e.g. for migration). */ 102 187 #define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file) 103 188 104 - /* Feature bits */ 105 - /* Log all write descriptors. Can be changed while device is active. */ 106 - #define VHOST_F_LOG_ALL 26 107 - /* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */ 108 - #define VHOST_NET_F_VIRTIO_NET_HDR 27 109 - 110 - /* VHOST_SCSI specific definitions */ 111 - 112 - /* 113 - * Used by QEMU userspace to ensure a consistent vhost-scsi ABI. 114 - * 115 - * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate + 116 - * RFC-v2 vhost-scsi userspace. Add GET_ABI_VERSION ioctl usage 117 - * ABI Rev 1: January 2013. Ignore vhost_tpgt filed in struct vhost_scsi_target. 118 - * All the targets under vhost_wwpn can be seen and used by guset. 119 - */ 120 - 121 - #define VHOST_SCSI_ABI_VERSION 1 122 - 123 - struct vhost_scsi_target { 124 - int abi_version; 125 - char vhost_wwpn[224]; /* TRANSPORT_IQN_LEN */ 126 - unsigned short vhost_tpgt; 127 - unsigned short reserved; 128 - }; 189 + /* VHOST_SCSI specific defines */ 129 190 130 191 #define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target) 131 192 #define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
+128
include/uapi/linux/vhost_types.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 + #ifndef _LINUX_VHOST_TYPES_H 3 + #define _LINUX_VHOST_TYPES_H 4 + /* Userspace interface for in-kernel virtio accelerators. */ 5 + 6 + /* vhost is used to reduce the number of system calls involved in virtio. 7 + * 8 + * Existing virtio net code is used in the guest without modification. 9 + * 10 + * This header includes interface used by userspace hypervisor for 11 + * device configuration. 12 + */ 13 + 14 + #include <linux/types.h> 15 + #include <linux/compiler.h> 16 + #include <linux/virtio_config.h> 17 + #include <linux/virtio_ring.h> 18 + 19 + struct vhost_vring_state { 20 + unsigned int index; 21 + unsigned int num; 22 + }; 23 + 24 + struct vhost_vring_file { 25 + unsigned int index; 26 + int fd; /* Pass -1 to unbind from file. */ 27 + 28 + }; 29 + 30 + struct vhost_vring_addr { 31 + unsigned int index; 32 + /* Option flags. */ 33 + unsigned int flags; 34 + /* Flag values: */ 35 + /* Whether log address is valid. If set enables logging. */ 36 + #define VHOST_VRING_F_LOG 0 37 + 38 + /* Start of array of descriptors (virtually contiguous) */ 39 + __u64 desc_user_addr; 40 + /* Used structure address. Must be 32 bit aligned */ 41 + __u64 used_user_addr; 42 + /* Available structure address. Must be 16 bit aligned */ 43 + __u64 avail_user_addr; 44 + /* Logging support. */ 45 + /* Log writes to used structure, at offset calculated from specified 46 + * address. Address must be 32 bit aligned. */ 47 + __u64 log_guest_addr; 48 + }; 49 + 50 + /* no alignment requirement */ 51 + struct vhost_iotlb_msg { 52 + __u64 iova; 53 + __u64 size; 54 + __u64 uaddr; 55 + #define VHOST_ACCESS_RO 0x1 56 + #define VHOST_ACCESS_WO 0x2 57 + #define VHOST_ACCESS_RW 0x3 58 + __u8 perm; 59 + #define VHOST_IOTLB_MISS 1 60 + #define VHOST_IOTLB_UPDATE 2 61 + #define VHOST_IOTLB_INVALIDATE 3 62 + #define VHOST_IOTLB_ACCESS_FAIL 4 63 + __u8 type; 64 + }; 65 + 66 + #define VHOST_IOTLB_MSG 0x1 67 + #define VHOST_IOTLB_MSG_V2 0x2 68 + 69 + struct vhost_msg { 70 + int type; 71 + union { 72 + struct vhost_iotlb_msg iotlb; 73 + __u8 padding[64]; 74 + }; 75 + }; 76 + 77 + struct vhost_msg_v2 { 78 + __u32 type; 79 + __u32 reserved; 80 + union { 81 + struct vhost_iotlb_msg iotlb; 82 + __u8 padding[64]; 83 + }; 84 + }; 85 + 86 + struct vhost_memory_region { 87 + __u64 guest_phys_addr; 88 + __u64 memory_size; /* bytes */ 89 + __u64 userspace_addr; 90 + __u64 flags_padding; /* No flags are currently specified. */ 91 + }; 92 + 93 + /* All region addresses and sizes must be 4K aligned. */ 94 + #define VHOST_PAGE_SIZE 0x1000 95 + 96 + struct vhost_memory { 97 + __u32 nregions; 98 + __u32 padding; 99 + struct vhost_memory_region regions[0]; 100 + }; 101 + 102 + /* VHOST_SCSI specific definitions */ 103 + 104 + /* 105 + * Used by QEMU userspace to ensure a consistent vhost-scsi ABI. 106 + * 107 + * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate + 108 + * RFC-v2 vhost-scsi userspace. Add GET_ABI_VERSION ioctl usage 109 + * ABI Rev 1: January 2013. Ignore vhost_tpgt field in struct vhost_scsi_target. 110 + * All the targets under vhost_wwpn can be seen and used by guset. 111 + */ 112 + 113 + #define VHOST_SCSI_ABI_VERSION 1 114 + 115 + struct vhost_scsi_target { 116 + int abi_version; 117 + char vhost_wwpn[224]; /* TRANSPORT_IQN_LEN */ 118 + unsigned short vhost_tpgt; 119 + unsigned short reserved; 120 + }; 121 + 122 + /* Feature bits */ 123 + /* Log all write descriptors. Can be changed while device is active. */ 124 + #define VHOST_F_LOG_ALL 26 125 + /* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */ 126 + #define VHOST_NET_F_VIRTIO_NET_HDR 27 127 + 128 + #endif
+54
include/uapi/linux/virtio_blk.h
··· 38 38 #define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/ 39 39 #define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ 40 40 #define VIRTIO_BLK_F_MQ 12 /* support more than one vq */ 41 + #define VIRTIO_BLK_F_DISCARD 13 /* DISCARD is supported */ 42 + #define VIRTIO_BLK_F_WRITE_ZEROES 14 /* WRITE ZEROES is supported */ 41 43 42 44 /* Legacy feature bits */ 43 45 #ifndef VIRTIO_BLK_NO_LEGACY ··· 88 86 89 87 /* number of vqs, only available when VIRTIO_BLK_F_MQ is set */ 90 88 __u16 num_queues; 89 + 90 + /* the next 3 entries are guarded by VIRTIO_BLK_F_DISCARD */ 91 + /* 92 + * The maximum discard sectors (in 512-byte sectors) for 93 + * one segment. 94 + */ 95 + __u32 max_discard_sectors; 96 + /* 97 + * The maximum number of discard segments in a 98 + * discard command. 99 + */ 100 + __u32 max_discard_seg; 101 + /* Discard commands must be aligned to this number of sectors. */ 102 + __u32 discard_sector_alignment; 103 + 104 + /* the next 3 entries are guarded by VIRTIO_BLK_F_WRITE_ZEROES */ 105 + /* 106 + * The maximum number of write zeroes sectors (in 512-byte sectors) in 107 + * one segment. 108 + */ 109 + __u32 max_write_zeroes_sectors; 110 + /* 111 + * The maximum number of segments in a write zeroes 112 + * command. 113 + */ 114 + __u32 max_write_zeroes_seg; 115 + /* 116 + * Set if a VIRTIO_BLK_T_WRITE_ZEROES request may result in the 117 + * deallocation of one or more of the sectors. 118 + */ 119 + __u8 write_zeroes_may_unmap; 120 + 121 + __u8 unused1[3]; 91 122 } __attribute__((packed)); 92 123 93 124 /* ··· 149 114 /* Get device ID command */ 150 115 #define VIRTIO_BLK_T_GET_ID 8 151 116 117 + /* Discard command */ 118 + #define VIRTIO_BLK_T_DISCARD 11 119 + 120 + /* Write zeroes command */ 121 + #define VIRTIO_BLK_T_WRITE_ZEROES 13 122 + 152 123 #ifndef VIRTIO_BLK_NO_LEGACY 153 124 /* Barrier before this op. */ 154 125 #define VIRTIO_BLK_T_BARRIER 0x80000000 ··· 172 131 __virtio32 ioprio; 173 132 /* Sector (ie. 512 byte offset) */ 174 133 __virtio64 sector; 134 + }; 135 + 136 + /* Unmap this range (only valid for write zeroes command) */ 137 + #define VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP 0x00000001 138 + 139 + /* Discard/write zeroes range for each request. */ 140 + struct virtio_blk_discard_write_zeroes { 141 + /* discard/write zeroes start sector */ 142 + __le64 sector; 143 + /* number of discard/write zeroes sectors */ 144 + __le32 num_sectors; 145 + /* flags for this range */ 146 + __le32 flags; 175 147 }; 176 148 177 149 #ifndef VIRTIO_BLK_NO_LEGACY