[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 06/31] block: Convert bdrv_get_block_status() to byt
From: |
Eric Blake |
Subject: |
[Qemu-devel] [PATCH 06/31] block: Convert bdrv_get_block_status() to bytes |
Date: |
Mon, 17 Apr 2017 20:33:31 -0500 |
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() to
bdrv_block_status() ensures that the compiler enforces that all
callers are updated. For now, the io.c layer still assert()s that
all callers are sector-aligned, but that can be relaxed when a later
patch implements byte-based block status in the drivers.
Note that we have an inherent limitation in the BDRV_BLOCK_* return
values: BDRV_BLOCK_OFFSET_VALID can only return the start of a
sector, even if we later relax the interface to query for the status
starting at an intermediate byte; document the obvious interpretation
that valid offsets are always sector-relative.
Therefore, for the most part this patch is just the addition of scaling
at the callers followed by inverse scaling at bdrv_block_status(). But
some code, particularly bdrv_is_allocated(), gets a lot simpler because
it no longer has to mess with sectors; also, it is now possible to pass
NULL if the caller does not care how much of the image is allocated
beyond the initial offset.
For ease of review, bdrv_get_block_status_above() will be tackled
separately.
Signed-off-by: Eric Blake <address@hidden>
---
include/block/block.h | 15 +++++++++------
block/io.c | 51 ++++++++++++++++++++++++++-------------------------
block/qcow2-cluster.c | 2 +-
qemu-img.c | 19 ++++++++++---------
4 files changed, 46 insertions(+), 41 deletions(-)
diff --git a/include/block/block.h b/include/block/block.h
index eed1330..b9e7281 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -121,10 +121,10 @@ typedef struct HDGeometry {
/*
* Allocation status flags
- * BDRV_BLOCK_DATA: data is read from a file returned by bdrv_get_block_status.
+ * BDRV_BLOCK_DATA: data is read from a file returned by bdrv_block_status.
* BDRV_BLOCK_ZERO: sectors read as zero
* BDRV_BLOCK_OFFSET_VALID: sector stored as raw data in a file returned by
- * bdrv_get_block_status.
+ * bdrv_block_status.
* BDRV_BLOCK_ALLOCATED: the content of the block is determined by this
* layer (as opposed to the backing file)
* BDRV_BLOCK_RAW: used internally to indicate that the request
@@ -132,7 +132,10 @@ typedef struct HDGeometry {
* should look in bs->file directly.
*
* If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 represent the offset in
- * bs->file where sector data can be read from as raw data.
+ * bs->file that begins the sector containing the address in question,
+ * where the sector can be read from as raw data with individual bytes
+ * at the same sector-relative locations (and thus, this bit cannot be
+ * set for mappings which are not equivalent modulo 512).
*
* DATA == 0 && ZERO == 0 means that data is read from backing_hd if present.
*
@@ -414,9 +417,9 @@ int bdrv_has_zero_init_1(BlockDriverState *bs);
int bdrv_has_zero_init(BlockDriverState *bs);
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs);
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
-int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num,
- int nb_sectors, int *pnum,
- BlockDriverState **file);
+int64_t bdrv_block_status(BlockDriverState *bs, int64_t offset,
+ int64_t bytes, int64_t *pnum,
+ BlockDriverState **file);
int64_t bdrv_get_block_status_above(BlockDriverState *bs,
BlockDriverState *base,
int64_t sector_num,
diff --git a/block/io.c b/block/io.c
index 1f8ae81..5cdb1f0 100644
--- a/block/io.c
+++ b/block/io.c
@@ -669,7 +669,6 @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
int64_t target_size, ret, bytes, offset = 0;
BlockDriverState *bs = child->bs;
BlockDriverState *file;
- int n; /* sectors */
target_size = bdrv_getlength(bs);
if (target_size < 0) {
@@ -681,24 +680,23 @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags
flags)
if (bytes <= 0) {
return 0;
}
- ret = bdrv_get_block_status(bs, offset >> BDRV_SECTOR_BITS,
- bytes >> BDRV_SECTOR_BITS, &n, &file);
+ ret = bdrv_block_status(bs, offset, bytes, &bytes, &file);
if (ret < 0) {
error_report("error getting block status at offset %" PRId64 ":
%s",
offset, strerror(-ret));
return ret;
}
if (ret & BDRV_BLOCK_ZERO) {
- offset += n * BDRV_SECTOR_BITS;
+ offset += bytes;
continue;
}
- ret = bdrv_pwrite_zeroes(child, offset, n * BDRV_SECTOR_SIZE, flags);
+ ret = bdrv_pwrite_zeroes(child, offset, bytes, flags);
if (ret < 0) {
error_report("error writing zeroes at offset %" PRId64 ": %s",
offset, strerror(-ret));
return ret;
}
- offset += n * BDRV_SECTOR_SIZE;
+ offset += bytes;
}
}
@@ -1754,9 +1752,13 @@ static int64_t coroutine_fn
bdrv_co_get_block_status(BlockDriverState *bs,
}
if (ret & BDRV_BLOCK_RAW) {
+ int64_t bytes = *pnum * BDRV_SECTOR_SIZE;
+
assert(ret & BDRV_BLOCK_OFFSET_VALID);
- ret = bdrv_get_block_status(*file, ret >> BDRV_SECTOR_BITS,
- *pnum, pnum, file);
+ ret = bdrv_block_status(*file, ret & BDRV_BLOCK_OFFSET_MASK,
+ bytes, &bytes, file);
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
+ *pnum = bytes >> BDRV_SECTOR_BITS;
goto out;
}
@@ -1874,35 +1876,34 @@ int64_t bdrv_get_block_status_above(BlockDriverState
*bs,
return data.ret;
}
-int64_t bdrv_get_block_status(BlockDriverState *bs,
- int64_t sector_num,
- int nb_sectors, int *pnum,
- BlockDriverState **file)
+int64_t bdrv_block_status(BlockDriverState *bs,
+ int64_t offset, int64_t bytes, int64_t *pnum,
+ BlockDriverState **file)
{
- return bdrv_get_block_status_above(bs, backing_bs(bs),
- sector_num, nb_sectors, pnum, file);
+ int64_t ret;
+ int n;
+
+ assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
+ assert(bytes <= BDRV_REQUEST_MAX_BYTES);
+ ret = bdrv_get_block_status_above(bs, backing_bs(bs),
+ offset >> BDRV_SECTOR_BITS,
+ bytes >> BDRV_SECTOR_BITS, &n, file);
+ if (pnum) {
+ *pnum = n * BDRV_SECTOR_SIZE;
+ }
+ return ret;
}
int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
int64_t bytes, int64_t *pnum)
{
BlockDriverState *file;
- int64_t sector_num = offset >> BDRV_SECTOR_BITS;
- int nb_sectors = bytes >> BDRV_SECTOR_BITS;
int64_t ret;
- int psectors;
- assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
- assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE) &&
- bytes < INT_MAX * BDRV_SECTOR_SIZE);
- ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &psectors,
- &file);
+ ret = bdrv_block_status(bs, offset, bytes, pnum, &file);
if (ret < 0) {
return ret;
}
- if (pnum) {
- *pnum = psectors * BDRV_SECTOR_SIZE;
- }
return !!(ret & BDRV_BLOCK_ALLOCATED);
}
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index bc59cb8..e5feb89 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1465,7 +1465,7 @@ static int discard_single_l2(BlockDriverState *bs,
uint64_t offset,
* cluster is already marked as zero, or if it's unallocated and we
* don't have a backing file.
*
- * TODO We might want to use bdrv_get_block_status(bs) here, but we're
+ * TODO We might want to use bdrv_block_status(bs) here, but we're
* holding s->lock, so that doesn't work today.
*
* If full_discard is true, the sector should not read back as zeroes,
diff --git a/qemu-img.c b/qemu-img.c
index 8cb5165..7ed77d5 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1558,12 +1558,16 @@ static int convert_iteration_sectors(ImgConvertState
*s, int64_t sector_num)
if (s->sector_next_status <= sector_num) {
BlockDriverState *file;
- ret = bdrv_get_block_status(blk_bs(s->src[src_cur]),
- sector_num - src_cur_offset,
- n, &n, &file);
+ int64_t count = n * BDRV_SECTOR_SIZE;
+
+ ret = bdrv_block_status(blk_bs(s->src[src_cur]),
+ (sector_num - src_cur_offset) *
BDRV_SECTOR_SIZE,
+ count, &count, &file);
if (ret < 0) {
return ret;
}
+ assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE));
+ n = count >> BDRV_SECTOR_BITS;
if (ret & BDRV_BLOCK_ZERO) {
s->status = BLK_ZERO;
@@ -2669,9 +2673,7 @@ static int get_block_status(BlockDriverState *bs, int64_t
offset,
int depth;
BlockDriverState *file;
bool has_offset;
- int nb_sectors = bytes >> BDRV_SECTOR_BITS;
- assert(bytes < INT_MAX);
/* As an optimization, we could cache the current range of unallocated
* clusters in each file of the chain, and avoid querying the same
* range repeatedly.
@@ -2679,12 +2681,11 @@ static int get_block_status(BlockDriverState *bs,
int64_t offset,
depth = 0;
for (;;) {
- ret = bdrv_get_block_status(bs, offset >> BDRV_SECTOR_BITS, nb_sectors,
- &nb_sectors, &file);
+ ret = bdrv_block_status(bs, offset, bytes, &bytes, &file);
if (ret < 0) {
return ret;
}
- assert(nb_sectors);
+ assert(bytes);
if (ret & (BDRV_BLOCK_ZERO|BDRV_BLOCK_DATA)) {
break;
}
@@ -2701,7 +2702,7 @@ static int get_block_status(BlockDriverState *bs, int64_t
offset,
*e = (MapEntry) {
.start = offset,
- .length = nb_sectors * BDRV_SECTOR_SIZE,
+ .length = bytes,
.data = !!(ret & BDRV_BLOCK_DATA),
.zero = !!(ret & BDRV_BLOCK_ZERO),
.offset = ret & BDRV_BLOCK_OFFSET_MASK,
--
2.9.3
- [Qemu-devel] [PATCH 00/31] make bdrv_get_block_status byte-based, Eric Blake, 2017/04/17
- [Qemu-devel] [PATCH 01/31] block: Drop unused bdrv_round_sectors_to_clusters(), Eric Blake, 2017/04/17
- [Qemu-devel] [PATCH 02/31] block: Make bdrv_round_to_clusters() signature more useful, Eric Blake, 2017/04/17
- [Qemu-devel] [PATCH 03/31] qcow2: Switch is_zero_sectors() to byte-based, Eric Blake, 2017/04/17
- [Qemu-devel] [PATCH 04/31] block: Switch bdrv_make_zero() to byte-based, Eric Blake, 2017/04/17
- [Qemu-devel] [PATCH 05/31] qemu-img: Switch get_block_status() to byte-based, Eric Blake, 2017/04/17
- [Qemu-devel] [PATCH 06/31] block: Convert bdrv_get_block_status() to bytes,
Eric Blake <=
- [Qemu-devel] [PATCH 07/31] block: Switch bdrv_co_get_block_status() to byte-based, Eric Blake, 2017/04/17
- [Qemu-devel] [PATCH 08/31] block: Switch BdrvCoGetBlockStatusData to byte-based, Eric Blake, 2017/04/17
- [Qemu-devel] [PATCH 09/31] block: Switch bdrv_co_get_block_status_above() to byte-based, Eric Blake, 2017/04/17
- [Qemu-devel] [PATCH 10/31] block: Convert bdrv_get_block_status_above() to bytes, Eric Blake, 2017/04/17
- [Qemu-devel] [PATCH 12/31] commit: Switch to .bdrv_co_block_status(), Eric Blake, 2017/04/17
- [Qemu-devel] [PATCH 11/31] block: Add .bdrv_co_block_status() callback, Eric Blake, 2017/04/17
- [Qemu-devel] [PATCH 13/31] file-posix: Switch to .bdrv_co_block_status(), Eric Blake, 2017/04/17
- [Qemu-devel] [PATCH 14/31] gluster: Switch to .bdrv_co_block_status(), Eric Blake, 2017/04/17