block: Convert bdrv_get_block_status_above() to bytes

We are gradually moving away from sector-based interfaces, towards
byte-based.  In the common case, allocation is unlikely to ever use
values that are not naturally sector-aligned, but it is possible
that byte-based values will let us be more precise about allocation
at the end of an unaligned file that can do byte-based access.

Changing the name of the function from bdrv_get_block_status_above()
to bdrv_block_status_above() ensures that the compiler enforces that
all callers are updated.  Likewise, since it a byte interface allows
an offset mapping that might not be sector aligned, split the mapping
out of the return value and into a pass-by-reference parameter.  For
now, the io.c layer still assert()s that all uses are sector-aligned,
but that can be relaxed when a later patch implements byte-based
block status in the drivers.

For the most part this patch is just the addition of scaling at the
callers followed by inverse scaling at bdrv_block_status(), plus
updates for the new split return interface.  But some code,
particularly bdrv_block_status(), gets a lot simpler because it no
longer has to mess with sectors.  Likewise, mirror code no longer
computes s->granularity >> BDRV_SECTOR_BITS, and can therefore drop
an assertion about alignment because the loop no longer depends on
alignment (never mind that we don't really have a driver that
reports sub-sector alignments, so it's not really possible to test
the effect of sub-sector mirroring).  Fix a neighboring assertion to
use is_power_of_2 while there.

For ease of review, bdrv_get_block_status() was tackled separately.

Signed-off-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Eric Blake 2017-10-11 22:47:08 -05:00 committed by Kevin Wolf
parent 5b648c67e3
commit 3182664220
5 changed files with 57 additions and 103 deletions

View file

@ -2974,8 +2974,8 @@ finish:
static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
{
int nr;
int64_t res;
int64_t nr;
int res;
int64_t start;
/* TODO: Widening to sector boundaries should only be needed as
@ -2991,10 +2991,8 @@ static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
if (!bytes) {
return true;
}
res = bdrv_get_block_status_above(bs, NULL, start >> BDRV_SECTOR_BITS,
bytes >> BDRV_SECTOR_BITS, &nr, NULL);
return res >= 0 && (res & BDRV_BLOCK_ZERO) &&
nr * BDRV_SECTOR_SIZE == bytes;
res = bdrv_block_status_above(bs, NULL, start, bytes, &nr, NULL, NULL);
return res >= 0 && (res & BDRV_BLOCK_ZERO) && nr == bytes;
}
static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
@ -3700,17 +3698,14 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
required = virtual_size;
} else {
int64_t offset;
int pnum = 0;
int64_t pnum = 0;
for (offset = 0; offset < ssize;
offset += pnum * BDRV_SECTOR_SIZE) {
int nb_sectors = MIN(ssize - offset,
BDRV_REQUEST_MAX_BYTES) / BDRV_SECTOR_SIZE;
int64_t ret;
for (offset = 0; offset < ssize; offset += pnum) {
int ret;
ret = bdrv_get_block_status_above(in_bs, NULL,
offset >> BDRV_SECTOR_BITS,
nb_sectors, &pnum, NULL);
ret = bdrv_block_status_above(in_bs, NULL, offset,
ssize - offset, &pnum, NULL,
NULL);
if (ret < 0) {
error_setg_errno(&local_err, -ret,
"Unable to get block status");
@ -3722,11 +3717,10 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
} else if ((ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) ==
(BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) {
/* Extend pnum to end of cluster for next iteration */
pnum = (ROUND_UP(offset + pnum * BDRV_SECTOR_SIZE,
cluster_size) - offset) >> BDRV_SECTOR_BITS;
pnum = ROUND_UP(offset + pnum, cluster_size) - offset;
/* Count clusters we've seen */
required += offset % cluster_size + pnum * BDRV_SECTOR_SIZE;
required += offset % cluster_size + pnum;
}
}
}