A block driver that emulates zones (e.g. qcow2 with the zoned format feature) rejects requests that violate the zone protocol, and the device model has to report each of these to the guest with the matching zone error (ZAC/ZBC sense data, virtio-blk zone status codes, ...). It can only do so if each condition comes with an errno of its own, rather than a generic one such as EIO.
Define one for each condition: BLK_ZE_UNALIGNED_WRITE ESPIPE write not at the write pointer BLK_ZE_BOUNDARY ERANGE write past the zone capacity BLK_ZE_OPEN_RESOURCE ETOOMANYREFS open zone limit reached BLK_ZE_ACTIVE_RESOURCE EOVERFLOW active zone limit reached BLK_ZE_FULL EXFULL write to a full zone ETOOMANYREFS and EOVERFLOW are what Linux returns for BLK_STS_ZONE_OPEN_RESOURCE and BLK_STS_ZONE_ACTIVE_RESOURCE, so a host zoned device used through file-posix already reports the same values. For the boundary case, ERANGE is used rather than EFBIG, which the host file system can legitimately return for an image file. A write that is not at the write pointer gets ESPIPE, which file and block device I/O never return, rather than EINVAL, which a zoned driver also uses for invalid requests such as an invalid zone state transition. So a device model can map each of these errnos to its zone error without having to know which request failed. A full zone has no write pointer, and ZAC, ZBC, NVMe ZNS and virtio-blk all report a write to a full zone differently from a write that is not at the write pointer, so it gets its own errno, EXFULL. ETOOMANYREFS is not POSIX and EXFULL is Linux-specific, so provide fallbacks for hosts that lack them. Signed-off-by: Niklas Cassel <[email protected]> --- include/block/block-common.h | 17 +++++++++++++++++ include/qemu/osdep.h | 6 ++++++ 2 files changed, 23 insertions(+) diff --git a/include/block/block-common.h b/include/block/block-common.h index 3932ff8615..da0f64c5b3 100644 --- a/include/block/block-common.h +++ b/include/block/block-common.h @@ -125,6 +125,23 @@ typedef struct BlockZoneDescriptor { BlockZoneState state; } BlockZoneDescriptor; +/* + * Errors that zoned block drivers report for zone protocol violations, as + * positive errno values (drivers return them negated). Each condition has an + * errno of its own that zoned block drivers do not return for anything else, + * so that device models can report the matching zone error to the guest + * whichever request failed. In particular, EINVAL is not used, as it also + * reports invalid requests, such as an invalid zone state transition. The + * zone resource errors are the errnos Linux uses for BLK_STS_ZONE_OPEN_RESOURCE + * and BLK_STS_ZONE_ACTIVE_RESOURCE, so a host zoned device accessed through + * file-posix reports the same values. + */ +#define BLK_ZE_UNALIGNED_WRITE ESPIPE /* write not at write pointer */ +#define BLK_ZE_BOUNDARY ERANGE /* write past zone capacity */ +#define BLK_ZE_OPEN_RESOURCE ETOOMANYREFS /* open zone limit reached */ +#define BLK_ZE_ACTIVE_RESOURCE EOVERFLOW /* active zone limit reached */ +#define BLK_ZE_FULL EXFULL /* write to a full zone */ + /* * Track write pointers of a zone in bytes. */ diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 50c7ce33b6..8a264473fa 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -345,6 +345,12 @@ void QEMU_ERROR("code path is reachable") #if !defined(ESHUTDOWN) #define ESHUTDOWN 4099 #endif +#if !defined(ETOOMANYREFS) +#define ETOOMANYREFS 4100 +#endif +#if !defined(EXFULL) +#define EXFULL 4101 +#endif #define RETRY_ON_EINTR(expr) \ (__extension__ \ -- 2.56.0
