@@ -1778,6 +1778,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
int alignment = MAX(bs->bl.pwrite_zeroes_alignment,
bs->bl.request_alignment);
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer, MAX_BOUNCE_BUFFER);
+ bool auto_no_fallback = false;
assert(alignment % bs->bl.request_alignment == 0);
@@ -1785,6 +1786,16 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
return -ENOMEDIUM;
}
+ if (!(flags & BDRV_REQ_NO_FALLBACK) &&
+ (bs->supported_zero_flags & BDRV_REQ_NO_FALLBACK) &&
+ bs->bl.max_pwrite_zeroes && bs->bl.max_pwrite_zeroes < bytes &&
+ bs->bl.max_pwrite_zeroes < bs->bl.max_pwrite_zeroes_fast)
+ {
+ assert(drv->bdrv_co_pwrite_zeroes);
+ flags |= BDRV_REQ_NO_FALLBACK;
+ auto_no_fallback = true;
+ }
+
if ((flags & ~bs->supported_zero_flags) & BDRV_REQ_NO_FALLBACK) {
return -ENOTSUP;
}
@@ -1829,6 +1840,14 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
if (drv->bdrv_co_pwrite_zeroes) {
ret = drv->bdrv_co_pwrite_zeroes(bs, offset, num,
flags & bs->supported_zero_flags);
+ if (ret == -ENOTSUP && auto_no_fallback) {
+ auto_no_fallback = false;
+ flags &= ~BDRV_REQ_NO_FALLBACK;
+ max_write_zeroes =
+ QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_pwrite_zeroes,
+ INT_MAX), alignment);
+ continue;
+ }
if (ret != -ENOTSUP && (flags & BDRV_REQ_FUA) &&
!(bs->supported_zero_flags & BDRV_REQ_FUA)) {
need_flush = true;
When BDRV_REQ_NO_FALLBACK is supported, the NBD driver supports a larger request size. Add code to try large zero requests with a NO_FALLBACK request prior to having to split a request into chunks according to max_pwrite_zeroes. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> --- block/io.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)