qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 11/31] block: Add .bdrv_co_block_status() callback


From: Eric Blake
Subject: [Qemu-devel] [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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]