[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-block] [PATCH 11/31] block: Add .bdrv_co_block_status() callback
From: |
Eric Blake |
Subject: |
[Qemu-block] [PATCH 11/31] block: Add .bdrv_co_block_status() callback |
Date: |
Mon, 17 Apr 2017 20:33:36 -0500 |
We are gradually moving away from sector-based interfaces, towards
byte-based. Now that the block layer exposes byte-based allocation,
it's time to tackle the drivers. Add a new callback that operates
on as small as byte boundaries, and update the block layer to ensure
that the callback is only used with inputs aligned to the device's
request_alignment. Subsequent patches will then update individual
drivers, and then finally remove .bdrv_co_get_block_status().
Signed-off-by: Eric Blake <address@hidden>
---
include/block/block_int.h | 12 ++++++++++++
block/io.c | 47 +++++++++++++++++++++++++++++++++++------------
2 files changed, 47 insertions(+), 12 deletions(-)
diff --git a/include/block/block_int.h b/include/block/block_int.h
index bc3a28a..8f20bc3 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -163,11 +163,23 @@ struct BlockDriver {
*/
int coroutine_fn (*bdrv_co_pwrite_zeroes)(BlockDriverState *bs,
int64_t offset, int count, BdrvRequestFlags flags);
+
int coroutine_fn (*bdrv_co_pdiscard)(BlockDriverState *bs,
int64_t offset, int count);
+
+ /*
+ * Building block for bdrv_block_status[_above]. The block layer
+ * guarantees input aligned to request_alignment, as well as
+ * non-NULL pnum and file; and the result only has to worry about
+ * BDRV_BLOCK_DATA, _ZERO, _OFFSET_VALID, and _RAW, and only
+ * according to the current BDS.
+ */
int64_t coroutine_fn (*bdrv_co_get_block_status)(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, int *pnum,
BlockDriverState **file);
+ int64_t coroutine_fn (*bdrv_co_block_status)(BlockDriverState *bd,
+ int64_t offset, int64_t bytes, int64_t *pnum,
+ BlockDriverState **file);
/*
* Invalidate any cached meta-data.
diff --git a/block/io.c b/block/io.c
index 1b101cf..361eeb8 100644
--- a/block/io.c
+++ b/block/io.c
@@ -1718,7 +1718,6 @@ static int64_t coroutine_fn
bdrv_co_block_status(BlockDriverState *bs,
int64_t total_size;
int64_t n; /* bytes */
int64_t ret, ret2;
- int count; /* sectors */
BlockDriverState *tmp_file;
total_size = bdrv_getlength(bs);
@@ -1739,7 +1738,7 @@ static int64_t coroutine_fn
bdrv_co_block_status(BlockDriverState *bs,
bytes = n;
}
- if (!bs->drv->bdrv_co_get_block_status) {
+ if (!bs->drv->bdrv_co_get_block_status && !bs->drv->bdrv_co_block_status) {
*pnum = bytes;
ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED;
if (bs->drv->protocol_name) {
@@ -1753,20 +1752,44 @@ static int64_t coroutine_fn
bdrv_co_block_status(BlockDriverState *bs,
}
*file = NULL;
bdrv_inc_in_flight(bs);
- /* TODO: Rather than require aligned offsets, we could instead
- * round to the driver's request_alignment here, then touch up
- * count afterwards back to the caller's expectations. But first
- * we want to switch the driver callback to likewise be
- * byte-based. */
- assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
- ret = bs->drv->bdrv_co_get_block_status(bs, offset >> BDRV_SECTOR_BITS,
- bytes >> BDRV_SECTOR_BITS, &count,
- file);
+ if (bs->drv->bdrv_co_get_block_status) {
+ int count; /* sectors */
+
+ assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
+ ret = bs->drv->bdrv_co_get_block_status(bs, offset >> BDRV_SECTOR_BITS,
+ bytes >> BDRV_SECTOR_BITS,
+ &count, file);
+ *pnum = count * BDRV_SECTOR_SIZE;
+ } else {
+ /* Round out to request_alignment boundaries */
+ int64_t aligned_offset, aligned_bytes;
+
+ aligned_offset = QEMU_ALIGN_DOWN(offset, bs->bl.request_alignment);
+ aligned_bytes = ROUND_UP(offset + bytes,
+ bs->bl.request_alignment) - aligned_offset;
+ ret = bs->drv->bdrv_co_block_status(bs, aligned_offset, aligned_bytes,
+ &n, file);
+ /* Clamp pnum and ret to original request */
+ if (aligned_offset != offset && ret >= 0) {
+ int sectors = DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) -
+ DIV_ROUND_UP(aligned_offset, BDRV_SECTOR_SIZE);
+
+ assert(n >= offset - aligned_offset);
+ n -= offset - aligned_offset;
+ if (sectors) {
+ ret += sectors * BDRV_SECTOR_SIZE;
+ }
+ }
+ if (ret >= 0 && n > bytes) {
+ assert(aligned_bytes != bytes);
+ n = bytes;
+ }
+ *pnum = n;
+ }
if (ret < 0) {
*pnum = 0;
goto out;
}
- *pnum = count * BDRV_SECTOR_SIZE;
if (ret & BDRV_BLOCK_RAW) {
assert(ret & BDRV_BLOCK_OFFSET_VALID);
--
2.9.3
- Re: [Qemu-block] [Qemu-devel] [PATCH 02/31] block: Make bdrv_round_to_clusters() signature more useful, (continued)
- [Qemu-block] [PATCH 03/31] qcow2: Switch is_zero_sectors() to byte-based, Eric Blake, 2017/04/17
- [Qemu-block] [PATCH 05/31] qemu-img: Switch get_block_status() to byte-based, Eric Blake, 2017/04/17
- [Qemu-block] [PATCH 06/31] block: Convert bdrv_get_block_status() to bytes, Eric Blake, 2017/04/17
- [Qemu-block] [PATCH 04/31] block: Switch bdrv_make_zero() to byte-based, Eric Blake, 2017/04/17
- [Qemu-block] [PATCH 07/31] block: Switch bdrv_co_get_block_status() to byte-based, Eric Blake, 2017/04/17
- [Qemu-block] [PATCH 08/31] block: Switch BdrvCoGetBlockStatusData to byte-based, Eric Blake, 2017/04/17
- [Qemu-block] [PATCH 09/31] block: Switch bdrv_co_get_block_status_above() to byte-based, Eric Blake, 2017/04/17
- [Qemu-block] [PATCH 10/31] block: Convert bdrv_get_block_status_above() to bytes, Eric Blake, 2017/04/17
- [Qemu-block] [PATCH 11/31] block: Add .bdrv_co_block_status() callback,
Eric Blake <=
- [Qemu-block] [PATCH 12/31] commit: Switch to .bdrv_co_block_status(), Eric Blake, 2017/04/17
- [Qemu-block] [PATCH 14/31] gluster: Switch to .bdrv_co_block_status(), Eric Blake, 2017/04/17
- [Qemu-block] [PATCH 13/31] file-posix: Switch to .bdrv_co_block_status(), Eric Blake, 2017/04/17
- [Qemu-block] [PATCH 15/31] iscsi: Switch cluster_sectors to byte-based, Eric Blake, 2017/04/17
- [Qemu-block] [PATCH 16/31] iscsi: Switch iscsi_allocmap_update() to byte-based, Eric Blake, 2017/04/17
- [Qemu-block] [PATCH 17/31] iscsi: Switch to .bdrv_co_block_status(), Eric Blake, 2017/04/17