block: Expand block status mode from bool to flags

This patch is purely mechanical, changing bool want_zero into an
unsigned int for bitwise-or of flags.  As of this patch, all
implementations are unchanged (the old want_zero==true is now
mode==BDRV_WANT_PRECISE which is a superset of BDRV_WANT_ZERO); but
the callers in io.c that used to pass want_zero==false are now
prepared for future driver changes that can now distinguish bewteen
BDRV_WANT_ZERO vs. BDRV_WANT_ALLOCATED.  The next patch will actually
change the file-posix driver along those lines, now that we have
more-specific hints.

As for the background why this patch is useful: right now, the
file-posix driver recognizes that if allocation is being queried, the
entire image can be reported as allocated (there is no backing file to
refer to) - but this throws away information on whether the entire
image reads as zero (trivially true if lseek(SEEK_HOLE) at offset 0
returns -ENXIO, a bit more complicated to prove if the raw file was
created with 'qemu-img create' since we intentionally allocate a small
chunk of all-zero data to help with alignment probing).  Later patches
will add a generic algorithm for seeing if an entire file reads as
zeroes.

Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-ID: <20250509204341.3553601-16-eblake@redhat.com>
This commit is contained in:
Eric Blake 2025-05-09 15:40:18 -05:00
parent 8648138789
commit c33159dec7
25 changed files with 99 additions and 86 deletions

View file

@ -751,9 +751,9 @@ blkdebug_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn GRAPH_RDLOCK
blkdebug_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset, blkdebug_co_block_status(BlockDriverState *bs, unsigned int mode,
int64_t bytes, int64_t *pnum, int64_t *map, int64_t offset, int64_t bytes, int64_t *pnum,
BlockDriverState **file) int64_t *map, BlockDriverState **file)
{ {
int err; int err;

View file

@ -291,8 +291,8 @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn GRAPH_RDLOCK
cbw_co_snapshot_block_status(BlockDriverState *bs, cbw_co_snapshot_block_status(BlockDriverState *bs, unsigned int mode,
bool want_zero, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes,
int64_t *pnum, int64_t *map, int64_t *pnum, int64_t *map,
BlockDriverState **file) BlockDriverState **file)
{ {

View file

@ -47,7 +47,7 @@ int coroutine_fn GRAPH_RDLOCK
bdrv_co_common_block_status_above(BlockDriverState *bs, bdrv_co_common_block_status_above(BlockDriverState *bs,
BlockDriverState *base, BlockDriverState *base,
bool include_base, bool include_base,
bool want_zero, unsigned int mode,
int64_t offset, int64_t offset,
int64_t bytes, int64_t bytes,
int64_t *pnum, int64_t *pnum,
@ -78,7 +78,7 @@ int co_wrapper_mixed_bdrv_rdlock
bdrv_common_block_status_above(BlockDriverState *bs, bdrv_common_block_status_above(BlockDriverState *bs,
BlockDriverState *base, BlockDriverState *base,
bool include_base, bool include_base,
bool want_zero, unsigned int mode,
int64_t offset, int64_t offset,
int64_t bytes, int64_t bytes,
int64_t *pnum, int64_t *pnum,

View file

@ -3273,7 +3273,7 @@ static int find_allocation(BlockDriverState *bs, off_t start,
* well exceed it. * well exceed it.
*/ */
static int coroutine_fn raw_co_block_status(BlockDriverState *bs, static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
bool want_zero, unsigned int mode,
int64_t offset, int64_t offset,
int64_t bytes, int64_t *pnum, int64_t bytes, int64_t *pnum,
int64_t *map, int64_t *map,
@ -3289,7 +3289,7 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
return ret; return ret;
} }
if (!want_zero) { if (mode != BDRV_WANT_PRECISE) {
*pnum = bytes; *pnum = bytes;
*map = offset; *map = offset;
*file = bs; *file = bs;

View file

@ -1461,7 +1461,7 @@ exit:
* (Based on raw_co_block_status() from file-posix.c.) * (Based on raw_co_block_status() from file-posix.c.)
*/ */
static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs, static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs,
bool want_zero, unsigned int mode,
int64_t offset, int64_t offset,
int64_t bytes, int64_t bytes,
int64_t *pnum, int64_t *pnum,
@ -1478,7 +1478,7 @@ static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs,
return ret; return ret;
} }
if (!want_zero) { if (mode != BDRV_WANT_PRECISE) {
*pnum = bytes; *pnum = bytes;
*map = offset; *map = offset;
*file = bs; *file = bs;

View file

@ -2364,10 +2364,8 @@ int bdrv_flush_all(void)
* Drivers not implementing the functionality are assumed to not support * Drivers not implementing the functionality are assumed to not support
* backing files, hence all their sectors are reported as allocated. * backing files, hence all their sectors are reported as allocated.
* *
* If 'want_zero' is true, the caller is querying for mapping * 'mode' serves as a hint as to which results are favored; see the
* purposes, with a focus on valid BDRV_BLOCK_OFFSET_VALID, _DATA, and * BDRV_WANT_* macros for details.
* _ZERO where possible; otherwise, the result favors larger 'pnum',
* with a focus on accurate BDRV_BLOCK_ALLOCATED.
* *
* If 'offset' is beyond the end of the disk image the return value is * If 'offset' is beyond the end of the disk image the return value is
* BDRV_BLOCK_EOF and 'pnum' is set to 0. * BDRV_BLOCK_EOF and 'pnum' is set to 0.
@ -2387,7 +2385,7 @@ int bdrv_flush_all(void)
* set to the host mapping and BDS corresponding to the guest offset. * set to the host mapping and BDS corresponding to the guest offset.
*/ */
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn GRAPH_RDLOCK
bdrv_co_do_block_status(BlockDriverState *bs, bool want_zero, bdrv_co_do_block_status(BlockDriverState *bs, unsigned int mode,
int64_t offset, int64_t bytes, int64_t offset, int64_t bytes,
int64_t *pnum, int64_t *map, BlockDriverState **file) int64_t *pnum, int64_t *map, BlockDriverState **file)
{ {
@ -2476,7 +2474,7 @@ bdrv_co_do_block_status(BlockDriverState *bs, bool want_zero,
local_file = bs; local_file = bs;
local_map = aligned_offset; local_map = aligned_offset;
} else { } else {
ret = bs->drv->bdrv_co_block_status(bs, want_zero, aligned_offset, ret = bs->drv->bdrv_co_block_status(bs, mode, aligned_offset,
aligned_bytes, pnum, &local_map, aligned_bytes, pnum, &local_map,
&local_file); &local_file);
@ -2488,10 +2486,10 @@ bdrv_co_do_block_status(BlockDriverState *bs, bool want_zero,
* the cache requires an RCU update, so double check here to avoid * the cache requires an RCU update, so double check here to avoid
* such an update if possible. * such an update if possible.
* *
* Check want_zero, because we only want to update the cache when we * Check mode, because we only want to update the cache when we
* have accurate information about what is zero and what is data. * have accurate information about what is zero and what is data.
*/ */
if (want_zero && if (mode == BDRV_WANT_PRECISE &&
ret == (BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID) && ret == (BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID) &&
QLIST_EMPTY(&bs->children)) QLIST_EMPTY(&bs->children))
{ {
@ -2548,7 +2546,7 @@ bdrv_co_do_block_status(BlockDriverState *bs, bool want_zero,
if (ret & BDRV_BLOCK_RAW) { if (ret & BDRV_BLOCK_RAW) {
assert(ret & BDRV_BLOCK_OFFSET_VALID && local_file); assert(ret & BDRV_BLOCK_OFFSET_VALID && local_file);
ret = bdrv_co_do_block_status(local_file, want_zero, local_map, ret = bdrv_co_do_block_status(local_file, mode, local_map,
*pnum, pnum, &local_map, &local_file); *pnum, pnum, &local_map, &local_file);
goto out; goto out;
} }
@ -2560,7 +2558,7 @@ bdrv_co_do_block_status(BlockDriverState *bs, bool want_zero,
if (!cow_bs) { if (!cow_bs) {
ret |= BDRV_BLOCK_ZERO; ret |= BDRV_BLOCK_ZERO;
} else if (want_zero) { } else if (mode == BDRV_WANT_PRECISE) {
int64_t size2 = bdrv_co_getlength(cow_bs); int64_t size2 = bdrv_co_getlength(cow_bs);
if (size2 >= 0 && offset >= size2) { if (size2 >= 0 && offset >= size2) {
@ -2569,14 +2567,14 @@ bdrv_co_do_block_status(BlockDriverState *bs, bool want_zero,
} }
} }
if (want_zero && ret & BDRV_BLOCK_RECURSE && if (mode == BDRV_WANT_PRECISE && ret & BDRV_BLOCK_RECURSE &&
local_file && local_file != bs && local_file && local_file != bs &&
(ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) && (ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) &&
(ret & BDRV_BLOCK_OFFSET_VALID)) { (ret & BDRV_BLOCK_OFFSET_VALID)) {
int64_t file_pnum; int64_t file_pnum;
int ret2; int ret2;
ret2 = bdrv_co_do_block_status(local_file, want_zero, local_map, ret2 = bdrv_co_do_block_status(local_file, mode, local_map,
*pnum, &file_pnum, NULL, NULL); *pnum, &file_pnum, NULL, NULL);
if (ret2 >= 0) { if (ret2 >= 0) {
/* Ignore errors. This is just providing extra information, it /* Ignore errors. This is just providing extra information, it
@ -2627,7 +2625,7 @@ int coroutine_fn
bdrv_co_common_block_status_above(BlockDriverState *bs, bdrv_co_common_block_status_above(BlockDriverState *bs,
BlockDriverState *base, BlockDriverState *base,
bool include_base, bool include_base,
bool want_zero, unsigned int mode,
int64_t offset, int64_t offset,
int64_t bytes, int64_t bytes,
int64_t *pnum, int64_t *pnum,
@ -2654,7 +2652,7 @@ bdrv_co_common_block_status_above(BlockDriverState *bs,
return 0; return 0;
} }
ret = bdrv_co_do_block_status(bs, want_zero, offset, bytes, pnum, ret = bdrv_co_do_block_status(bs, mode, offset, bytes, pnum,
map, file); map, file);
++*depth; ++*depth;
if (ret < 0 || *pnum == 0 || ret & BDRV_BLOCK_ALLOCATED || bs == base) { if (ret < 0 || *pnum == 0 || ret & BDRV_BLOCK_ALLOCATED || bs == base) {
@ -2671,7 +2669,7 @@ bdrv_co_common_block_status_above(BlockDriverState *bs,
for (p = bdrv_filter_or_cow_bs(bs); include_base || p != base; for (p = bdrv_filter_or_cow_bs(bs); include_base || p != base;
p = bdrv_filter_or_cow_bs(p)) p = bdrv_filter_or_cow_bs(p))
{ {
ret = bdrv_co_do_block_status(p, want_zero, offset, bytes, pnum, ret = bdrv_co_do_block_status(p, mode, offset, bytes, pnum,
map, file); map, file);
++*depth; ++*depth;
if (ret < 0) { if (ret < 0) {
@ -2734,7 +2732,8 @@ int coroutine_fn bdrv_co_block_status_above(BlockDriverState *bs,
BlockDriverState **file) BlockDriverState **file)
{ {
IO_CODE(); IO_CODE();
return bdrv_co_common_block_status_above(bs, base, false, true, offset, return bdrv_co_common_block_status_above(bs, base, false,
BDRV_WANT_PRECISE, offset,
bytes, pnum, map, file, NULL); bytes, pnum, map, file, NULL);
} }
@ -2765,8 +2764,9 @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
return 1; return 1;
} }
ret = bdrv_co_common_block_status_above(bs, NULL, false, false, offset, ret = bdrv_co_common_block_status_above(bs, NULL, false, BDRV_WANT_ZERO,
bytes, &pnum, NULL, NULL, NULL); offset, bytes, &pnum, NULL, NULL,
NULL);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
@ -2782,9 +2782,9 @@ int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset,
int64_t dummy; int64_t dummy;
IO_CODE(); IO_CODE();
ret = bdrv_co_common_block_status_above(bs, bs, true, false, offset, ret = bdrv_co_common_block_status_above(bs, bs, true, BDRV_WANT_ALLOCATED,
bytes, pnum ? pnum : &dummy, NULL, offset, bytes, pnum ? pnum : &dummy,
NULL, NULL); NULL, NULL, NULL);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -2817,7 +2817,8 @@ int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *bs,
int ret; int ret;
IO_CODE(); IO_CODE();
ret = bdrv_co_common_block_status_above(bs, base, include_base, false, ret = bdrv_co_common_block_status_above(bs, base, include_base,
BDRV_WANT_ALLOCATED,
offset, bytes, pnum, NULL, NULL, offset, bytes, pnum, NULL, NULL,
&depth); &depth);
if (ret < 0) { if (ret < 0) {
@ -3698,8 +3699,8 @@ bdrv_co_preadv_snapshot(BdrvChild *child, int64_t offset, int64_t bytes,
} }
int coroutine_fn int coroutine_fn
bdrv_co_snapshot_block_status(BlockDriverState *bs, bdrv_co_snapshot_block_status(BlockDriverState *bs, unsigned int mode,
bool want_zero, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes,
int64_t *pnum, int64_t *map, int64_t *pnum, int64_t *map,
BlockDriverState **file) BlockDriverState **file)
{ {
@ -3717,7 +3718,7 @@ bdrv_co_snapshot_block_status(BlockDriverState *bs,
} }
bdrv_inc_in_flight(bs); bdrv_inc_in_flight(bs);
ret = drv->bdrv_co_snapshot_block_status(bs, want_zero, offset, bytes, ret = drv->bdrv_co_snapshot_block_status(bs, mode, offset, bytes,
pnum, map, file); pnum, map, file);
bdrv_dec_in_flight(bs); bdrv_dec_in_flight(bs);

View file

@ -694,9 +694,9 @@ out_unlock:
static int coroutine_fn iscsi_co_block_status(BlockDriverState *bs, static int coroutine_fn iscsi_co_block_status(BlockDriverState *bs,
bool want_zero, int64_t offset, unsigned int mode,
int64_t bytes, int64_t *pnum, int64_t offset, int64_t bytes,
int64_t *map, int64_t *pnum, int64_t *map,
BlockDriverState **file) BlockDriverState **file)
{ {
IscsiLun *iscsilun = bs->opaque; IscsiLun *iscsilun = bs->opaque;

View file

@ -1397,8 +1397,8 @@ nbd_client_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
} }
static int coroutine_fn GRAPH_RDLOCK nbd_client_co_block_status( static int coroutine_fn GRAPH_RDLOCK nbd_client_co_block_status(
BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes, BlockDriverState *bs, unsigned int mode, int64_t offset,
int64_t *pnum, int64_t *map, BlockDriverState **file) int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file)
{ {
int ret, request_ret; int ret, request_ret;
NBDExtent64 extent = { 0 }; NBDExtent64 extent = { 0 };

View file

@ -227,9 +227,9 @@ static int null_reopen_prepare(BDRVReopenState *reopen_state,
} }
static int coroutine_fn null_co_block_status(BlockDriverState *bs, static int coroutine_fn null_co_block_status(BlockDriverState *bs,
bool want_zero, int64_t offset, unsigned int mode,
int64_t bytes, int64_t *pnum, int64_t offset, int64_t bytes,
int64_t *map, int64_t *pnum, int64_t *map,
BlockDriverState **file) BlockDriverState **file)
{ {
BDRVNullState *s = bs->opaque; BDRVNullState *s = bs->opaque;

View file

@ -416,9 +416,9 @@ parallels_co_flush_to_os(BlockDriverState *bs)
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn GRAPH_RDLOCK
parallels_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset, parallels_co_block_status(BlockDriverState *bs, unsigned int mode,
int64_t bytes, int64_t *pnum, int64_t *map, int64_t offset, int64_t bytes, int64_t *pnum,
BlockDriverState **file) int64_t *map, BlockDriverState **file)
{ {
BDRVParallelsState *s = bs->opaque; BDRVParallelsState *s = bs->opaque;
int count; int count;

View file

@ -530,7 +530,7 @@ get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate,
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn GRAPH_RDLOCK
qcow_co_block_status(BlockDriverState *bs, bool want_zero, qcow_co_block_status(BlockDriverState *bs, unsigned int mode,
int64_t offset, int64_t bytes, int64_t *pnum, int64_t offset, int64_t bytes, int64_t *pnum,
int64_t *map, BlockDriverState **file) int64_t *map, BlockDriverState **file)
{ {

View file

@ -2141,9 +2141,9 @@ static void qcow2_join_options(QDict *options, QDict *old_options)
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn GRAPH_RDLOCK
qcow2_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset, qcow2_co_block_status(BlockDriverState *bs, unsigned int mode,
int64_t count, int64_t *pnum, int64_t *map, int64_t offset, int64_t count, int64_t *pnum,
BlockDriverState **file) int64_t *map, BlockDriverState **file)
{ {
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
uint64_t host_offset; uint64_t host_offset;

View file

@ -833,9 +833,9 @@ fail:
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn GRAPH_RDLOCK
bdrv_qed_co_block_status(BlockDriverState *bs, bool want_zero, int64_t pos, bdrv_qed_co_block_status(BlockDriverState *bs, unsigned int mode,
int64_t bytes, int64_t *pnum, int64_t *map, int64_t pos, int64_t bytes, int64_t *pnum,
BlockDriverState **file) int64_t *map, BlockDriverState **file)
{ {
BDRVQEDState *s = bs->opaque; BDRVQEDState *s = bs->opaque;
size_t len = MIN(bytes, SIZE_MAX); size_t len = MIN(bytes, SIZE_MAX);

View file

@ -1226,7 +1226,7 @@ static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c,
* region contains zeroes, and BDRV_BLOCK_DATA otherwise. * region contains zeroes, and BDRV_BLOCK_DATA otherwise.
*/ */
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn GRAPH_RDLOCK
quorum_co_block_status(BlockDriverState *bs, bool want_zero, quorum_co_block_status(BlockDriverState *bs, unsigned int mode,
int64_t offset, int64_t count, int64_t offset, int64_t count,
int64_t *pnum, int64_t *map, BlockDriverState **file) int64_t *pnum, int64_t *map, BlockDriverState **file)
{ {
@ -1238,7 +1238,7 @@ quorum_co_block_status(BlockDriverState *bs, bool want_zero,
for (i = 0; i < s->num_children; i++) { for (i = 0; i < s->num_children; i++) {
int64_t bytes; int64_t bytes;
ret = bdrv_co_common_block_status_above(s->children[i]->bs, NULL, false, ret = bdrv_co_common_block_status_above(s->children[i]->bs, NULL, false,
want_zero, offset, count, mode, offset, count,
&bytes, NULL, NULL, NULL); &bytes, NULL, NULL, NULL);
if (ret < 0) { if (ret < 0) {
quorum_report_bad(QUORUM_OP_TYPE_READ, offset, count, quorum_report_bad(QUORUM_OP_TYPE_READ, offset, count,

View file

@ -283,8 +283,8 @@ fail:
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn GRAPH_RDLOCK
raw_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset, raw_co_block_status(BlockDriverState *bs, unsigned int mode,
int64_t bytes, int64_t *pnum, int64_t *map, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map,
BlockDriverState **file) BlockDriverState **file)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;

View file

@ -1503,9 +1503,9 @@ static int qemu_rbd_diff_iterate_cb(uint64_t offs, size_t len,
} }
static int coroutine_fn qemu_rbd_co_block_status(BlockDriverState *bs, static int coroutine_fn qemu_rbd_co_block_status(BlockDriverState *bs,
bool want_zero, int64_t offset, unsigned int mode,
int64_t bytes, int64_t *pnum, int64_t offset, int64_t bytes,
int64_t *map, int64_t *pnum, int64_t *map,
BlockDriverState **file) BlockDriverState **file)
{ {
BDRVRBDState *s = bs->opaque; BDRVRBDState *s = bs->opaque;

View file

@ -41,11 +41,11 @@ snapshot_access_co_preadv_part(BlockDriverState *bs,
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn GRAPH_RDLOCK
snapshot_access_co_block_status(BlockDriverState *bs, snapshot_access_co_block_status(BlockDriverState *bs,
bool want_zero, int64_t offset, unsigned int mode, int64_t offset,
int64_t bytes, int64_t *pnum, int64_t bytes, int64_t *pnum,
int64_t *map, BlockDriverState **file) int64_t *map, BlockDriverState **file)
{ {
return bdrv_co_snapshot_block_status(bs->file->bs, want_zero, offset, return bdrv_co_snapshot_block_status(bs->file->bs, mode, offset,
bytes, pnum, map, file); bytes, pnum, map, file);
} }

View file

@ -523,8 +523,8 @@ static int vdi_reopen_prepare(BDRVReopenState *state,
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn GRAPH_RDLOCK
vdi_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset, vdi_co_block_status(BlockDriverState *bs, unsigned int mode,
int64_t bytes, int64_t *pnum, int64_t *map, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map,
BlockDriverState **file) BlockDriverState **file)
{ {
BDRVVdiState *s = (BDRVVdiState *)bs->opaque; BDRVVdiState *s = (BDRVVdiState *)bs->opaque;

View file

@ -1777,7 +1777,7 @@ static inline uint64_t vmdk_find_offset_in_cluster(VmdkExtent *extent,
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn GRAPH_RDLOCK
vmdk_co_block_status(BlockDriverState *bs, bool want_zero, vmdk_co_block_status(BlockDriverState *bs, unsigned int mode,
int64_t offset, int64_t bytes, int64_t *pnum, int64_t offset, int64_t bytes, int64_t *pnum,
int64_t *map, BlockDriverState **file) int64_t *map, BlockDriverState **file)
{ {

View file

@ -726,7 +726,7 @@ fail:
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn GRAPH_RDLOCK
vpc_co_block_status(BlockDriverState *bs, bool want_zero, vpc_co_block_status(BlockDriverState *bs, unsigned int mode,
int64_t offset, int64_t bytes, int64_t offset, int64_t bytes,
int64_t *pnum, int64_t *map, int64_t *pnum, int64_t *map,
BlockDriverState **file) BlockDriverState **file)

View file

@ -3134,9 +3134,9 @@ vvfat_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
} }
static int coroutine_fn vvfat_co_block_status(BlockDriverState *bs, static int coroutine_fn vvfat_co_block_status(BlockDriverState *bs,
bool want_zero, int64_t offset, unsigned int mode,
int64_t bytes, int64_t *n, int64_t offset, int64_t bytes,
int64_t *map, int64_t *n, int64_t *map,
BlockDriverState **file) BlockDriverState **file)
{ {
*n = bytes; *n = bytes;

View file

@ -333,6 +333,17 @@ typedef enum {
#define BDRV_BLOCK_RECURSE 0x40 #define BDRV_BLOCK_RECURSE 0x40
#define BDRV_BLOCK_COMPRESSED 0x80 #define BDRV_BLOCK_COMPRESSED 0x80
/*
* Block status hints: the bitwise-or of these flags emphasize what
* the caller hopes to learn, and some drivers may be able to give
* faster answers by doing less work when the hint permits.
*/
#define BDRV_WANT_ZERO BDRV_BLOCK_ZERO
#define BDRV_WANT_OFFSET_VALID BDRV_BLOCK_OFFSET_VALID
#define BDRV_WANT_ALLOCATED BDRV_BLOCK_ALLOCATED
#define BDRV_WANT_PRECISE (BDRV_WANT_ZERO | BDRV_WANT_OFFSET_VALID | \
BDRV_WANT_OFFSET_VALID)
typedef QTAILQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue; typedef QTAILQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue;
typedef struct BDRVReopenState { typedef struct BDRVReopenState {

View file

@ -604,15 +604,16 @@ struct BlockDriver {
* according to the current layer, and should only need to set * according to the current layer, and should only need to set
* BDRV_BLOCK_DATA, BDRV_BLOCK_ZERO, BDRV_BLOCK_OFFSET_VALID, * BDRV_BLOCK_DATA, BDRV_BLOCK_ZERO, BDRV_BLOCK_OFFSET_VALID,
* and/or BDRV_BLOCK_RAW; if the current layer defers to a backing * and/or BDRV_BLOCK_RAW; if the current layer defers to a backing
* layer, the result should be 0 (and not BDRV_BLOCK_ZERO). See * layer, the result should be 0 (and not BDRV_BLOCK_ZERO). The
* block.h for the overall meaning of the bits. As a hint, the * caller will synthesize BDRV_BLOCK_ALLOCATED based on the
* flag want_zero is true if the caller cares more about precise * non-zero results. See block.h for the overall meaning of the
* mappings (favor accurate _OFFSET_VALID/_ZERO) or false for * bits. As a hint, the flags in @mode may include a bitwise-or
* overall allocation (favor larger *pnum, perhaps by reporting * of BDRV_WANT_ALLOCATED, BDRV_WANT_OFFSET_VALID, or
* _DATA instead of _ZERO). The block layer guarantees input * BDRV_WANT_ZERO based on what the caller is looking for in the
* clamped to bdrv_getlength() and aligned to request_alignment, * results. The block layer guarantees input clamped to
* as well as non-NULL pnum, map, and file; in turn, the driver * bdrv_getlength() and aligned to request_alignment, as well as
* must return an error or set pnum to an aligned non-zero value. * non-NULL pnum, map, and file; in turn, the driver must return
* an error or set pnum to an aligned non-zero value.
* *
* Note that @bytes is just a hint on how big of a region the * Note that @bytes is just a hint on how big of a region the
* caller wants to inspect. It is not a limit on *pnum. * caller wants to inspect. It is not a limit on *pnum.
@ -624,8 +625,8 @@ struct BlockDriver {
* to clamping *pnum for return to its caller. * to clamping *pnum for return to its caller.
*/ */
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_block_status)( int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_block_status)(
BlockDriverState *bs, BlockDriverState *bs, unsigned int mode,
bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum, int64_t offset, int64_t bytes, int64_t *pnum,
int64_t *map, BlockDriverState **file); int64_t *map, BlockDriverState **file);
/* /*
@ -649,8 +650,8 @@ struct BlockDriver {
QEMUIOVector *qiov, size_t qiov_offset); QEMUIOVector *qiov, size_t qiov_offset);
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_snapshot_block_status)( int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_snapshot_block_status)(
BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes, BlockDriverState *bs, unsigned int mode, int64_t offset,
int64_t *pnum, int64_t *map, BlockDriverState **file); int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file);
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard_snapshot)( int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard_snapshot)(
BlockDriverState *bs, int64_t offset, int64_t bytes); BlockDriverState *bs, int64_t offset, int64_t bytes);

View file

@ -38,8 +38,8 @@
int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv_snapshot(BdrvChild *child, int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv_snapshot(BdrvChild *child,
int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset); int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset);
int coroutine_fn GRAPH_RDLOCK bdrv_co_snapshot_block_status( int coroutine_fn GRAPH_RDLOCK bdrv_co_snapshot_block_status(
BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes, BlockDriverState *bs, unsigned int mode, int64_t offset,
int64_t *pnum, int64_t *map, BlockDriverState **file); int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file);
int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs, int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *bs,
int64_t offset, int64_t bytes); int64_t offset, int64_t bytes);

View file

@ -63,7 +63,7 @@ bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
} }
static int coroutine_fn bdrv_test_co_block_status(BlockDriverState *bs, static int coroutine_fn bdrv_test_co_block_status(BlockDriverState *bs,
bool want_zero, unsigned int mode,
int64_t offset, int64_t count, int64_t offset, int64_t count,
int64_t *pnum, int64_t *map, int64_t *pnum, int64_t *map,
BlockDriverState **file) BlockDriverState **file)