@@ -65,9 +65,13 @@ typedef enum {
BDRV_REQ_NO_SERIALISING = 0x8,
BDRV_REQ_FUA = 0x10,
BDRV_REQ_WRITE_COMPRESSED = 0x20,
+ /* The BDRV_REQ_ALLOCATE flag is used to indicate that the driver has to
+ * efficiently allocate the space so it reads as zeroes, or return an error.
+ */
+ BDRV_REQ_ALLOCATE = 0x40,
/* Mask of valid flags */
- BDRV_REQ_MASK = 0x3f,
+ BDRV_REQ_MASK = 0x7f,
} BdrvRequestFlags;
typedef struct BlockSizes {
@@ -632,7 +632,7 @@ struct BlockDriverState {
/* Flags honored during pwrite (so far: BDRV_REQ_FUA) */
unsigned int supported_write_flags;
/* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA,
- * BDRV_REQ_MAY_UNMAP) */
+ * BDRV_REQ_MAY_UNMAP, BDRV_REQ_ALLOCATE) */
unsigned int supported_zero_flags;
/* the following member gives a name to every node on the bs graph. */
@@ -1334,7 +1334,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
assert(!bs->supported_zero_flags);
}
- if (ret == -ENOTSUP) {
+ if (ret == -ENOTSUP && !(flags & BDRV_REQ_ALLOCATE)) {
/* Fall back to bounce buffer if write zeroes is unsupported */
BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE;
@@ -1420,8 +1420,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req);
if (!ret && bs->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF &&
- !(flags & BDRV_REQ_ZERO_WRITE) && drv->bdrv_co_pwrite_zeroes &&
- qemu_iovec_is_zero(qiov)) {
+ !(flags & BDRV_REQ_ZERO_WRITE) && !(flags & BDRV_REQ_ALLOCATE) &&
+ drv->bdrv_co_pwrite_zeroes && qemu_iovec_is_zero(qiov)) {
flags |= BDRV_REQ_ZERO_WRITE;
if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) {
flags |= BDRV_REQ_MAY_UNMAP;
@@ -1499,6 +1499,9 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
assert(flags & BDRV_REQ_ZERO_WRITE);
if (head_padding_bytes || tail_padding_bytes) {
+ if (flags & BDRV_REQ_ALLOCATE) {
+ return -ENOTSUP;
+ }
buf = qemu_blockalign(bs, align);
iov = (struct iovec) {
.iov_base = buf,
@@ -1599,6 +1602,9 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
return ret;
}
+ /* allocation request with qiov provided doesn't make much sense */
+ assert(!(qiov && (flags & BDRV_REQ_ALLOCATE)));
+
bdrv_inc_in_flight(bs);
/*
* Align write if necessary by performing a read-modify-write cycle.
@@ -1728,6 +1734,14 @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
{
trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags);
+ assert(!((flags & BDRV_REQ_MAY_UNMAP) && (flags & BDRV_REQ_ALLOCATE)));
+
+ if ((flags & BDRV_REQ_ALLOCATE) &&
+ !(child->bs->supported_zero_flags & BDRV_REQ_ALLOCATE))
+ {
+ return -ENOTSUP;
+ }
+
if (!(child->bs->open_flags & BDRV_O_UNMAP)) {
flags &= ~BDRV_REQ_MAY_UNMAP;
}