qemu-block
[Top][All Lists]
Advanced

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

[Qemu-block] [PATCH 17/18] nbd: BLOCK_STATUS for standard get_block_stat


From: Vladimir Sementsov-Ogievskiy
Subject: [Qemu-block] [PATCH 17/18] nbd: BLOCK_STATUS for standard get_block_status function: server part
Date: Fri, 3 Feb 2017 18:47:56 +0300

Minimal realization: only one extent in server answer is supported.

Signed-off-by: Vladimir Sementsov-Ogievskiy <address@hidden>
---
 include/block/nbd.h |  3 ++
 nbd/nbd-internal.h  |  1 +
 nbd/server.c        | 80 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 77 insertions(+), 7 deletions(-)

diff --git a/include/block/nbd.h b/include/block/nbd.h
index 08d5e51f21..69aee1eda1 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -181,6 +181,9 @@ enum {
 #define NBD_REPLY_TYPE_ERROR ((1 << 15) + 1)
 #define NBD_REPLY_TYPE_ERROR_OFFSET ((1 << 15) + 2)
 
+#define NBD_STATE_HOLE 1
+#define NBD_STATE_ZERO (1 << 1)
+
 #define NBD_MAX_BITMAP_EXTENTS (0x100000 / 8) /* 1 mb of extents data */
 
 ssize_t nbd_wr_syncv(QIOChannel *ioc,
diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h
index fbbcf69925..f89baa6049 100644
--- a/nbd/nbd-internal.h
+++ b/nbd/nbd-internal.h
@@ -86,6 +86,7 @@
 #define NBD_OPT_LIST_META_CONTEXT (9)
 #define NBD_OPT_SET_META_CONTEXT  (10)
 
+#define NBD_META_NS_BASE "base"
 #define NBD_META_NS_BITMAPS "qemu-dirty-bitmap"
 
 /* NBD errors are based on errno numbers, so there is a 1:1 mapping,
diff --git a/nbd/server.c b/nbd/server.c
index c96dda4086..cb87481382 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -103,6 +103,7 @@ struct NBDClient {
 
     bool structured_reply;
     BdrvDirtyBitmap *export_bitmap;
+    bool export_block_status;
 };
 
 /* That's all folks */
@@ -506,8 +507,24 @@ static int nbd_negotiate_one_bitmap_query(QIOChannel *ioc, 
BlockDriverState *bs,
     return 0;
 }
 
+static int nbd_negotiate_one_base_query(QIOChannel *ioc, BlockDriverState *bs,
+                                        uint32_t opt, const char *query,
+                                        bool *block_status)
+{
+    if (query[0] == '\0' || strcmp(query, "allocation") == 0) {
+        if (block_status != NULL) {
+            *block_status = true;
+        }
+
+        return nbd_negotiate_send_meta_context(ioc, "base:allocation", opt);
+    }
+
+    return 0;
+}
+
 static int nbd_negotiate_one_meta_query(QIOChannel *ioc, BlockDriverState *bs,
-                                        uint32_t opt, BdrvDirtyBitmap **bitmap)
+                                        uint32_t opt, BdrvDirtyBitmap **bitmap,
+                                        bool *block_status)
 {
     int ret = 0, nb_read;
     char *query, *colon, *namespace, *subquery;
@@ -530,6 +547,9 @@ static int nbd_negotiate_one_meta_query(QIOChannel *ioc, 
BlockDriverState *bs,
 
     if (strcmp(namespace, NBD_META_NS_BITMAPS) == 0) {
         ret = nbd_negotiate_one_bitmap_query(ioc, bs, opt, subquery, bitmap);
+    } else if (strcmp(namespace, NBD_META_NS_BASE) == 0) {
+        ret = nbd_negotiate_one_base_query(ioc, bs, opt, subquery,
+                                           block_status);
     }
 
 out:
@@ -663,7 +683,8 @@ static int nbd_negotiate_list_meta_context(NBDClient 
*client, uint32_t length)
 
     for (i = 0; i < nb_queries; ++i) {
         ret = nbd_negotiate_one_meta_query(client->ioc, bs,
-                                           NBD_OPT_LIST_META_CONTEXT, NULL);
+                                           NBD_OPT_LIST_META_CONTEXT, NULL,
+                                           NULL);
         if (ret < 0) {
             return ret;
         }
@@ -712,7 +733,8 @@ static int nbd_negotiate_set_meta_context(NBDClient 
*client, uint32_t length)
 
     ret = nbd_negotiate_one_meta_query(client->ioc, bs,
                                        NBD_OPT_SET_META_CONTEXT,
-                                       &client->export_bitmap);
+                                       &client->export_bitmap,
+                                       &client->export_block_status);
     if (ret < 0) {
         return ret;
     }
@@ -1497,6 +1519,30 @@ static unsigned add_extents(NBDExtent *extents, unsigned 
nb_extents,
     return i;
 }
 
+static int blockstatus_to_extent(BlockDriverState *bs, uint64_t offset,
+                                  uint64_t length, NBDExtent *extent)
+{
+    BlockDriverState *file;
+    uint64_t start_sector = offset >> BDRV_SECTOR_BITS;
+    uint64_t last_sector = (offset + length - 1) >> BDRV_SECTOR_BITS;
+    uint64_t begin = start_sector;
+    uint64_t end = last_sector + 1;
+
+    int nb = MIN(INT_MAX, end - begin);
+    int64_t ret = bdrv_get_block_status_above(bs, NULL, begin, nb, &nb, &file);
+    if (ret < 0) {
+        return ret;
+    }
+
+    extent->flags =
+        cpu_to_be32((ret & BDRV_BLOCK_ALLOCATED ? 0 : NBD_STATE_HOLE) |
+                    (ret & BDRV_BLOCK_ZERO      ? NBD_STATE_ZERO : 0));
+    extent->length = cpu_to_be32((nb << BDRV_SECTOR_BITS) -
+                                 (offset - (start_sector << 
BDRV_SECTOR_BITS)));
+
+    return 0;
+}
+
 static unsigned bitmap_to_extents(BdrvDirtyBitmap *bitmap, uint64_t offset,
                                   uint64_t length, NBDExtent *extents,
                                   unsigned nb_extents)
@@ -1589,6 +1635,21 @@ static int nbd_co_send_bitmap(NBDClient *client, 
uint64_t handle,
     return ret;
 }
 
+static int nbd_co_send_block_status(NBDClient *client, uint64_t handle,
+                                    BlockDriverState *bs, uint64_t offset,
+                                    uint64_t length, uint32_t context_id)
+{
+    int ret;
+    NBDExtent extent;
+
+    ret = blockstatus_to_extent(bs, offset, length, &extent);
+    if (ret < 0) {
+        return nbd_co_send_structured_error(client, handle, -ret);
+    }
+
+    return nbd_co_send_extents(client, handle, &extent, 1, context_id);
+}
+
 /* Collect a client request.  Return 0 if request looks valid, -EAGAIN
  * to keep trying the collection, -EIO to drop connection right away,
  * and any other negative value to report an error to the client
@@ -1869,13 +1930,18 @@ static void nbd_trip(void *opaque)
         break;
     case NBD_CMD_BLOCK_STATUS:
         TRACE("Request type is BLOCK_STATUS");
-        if (client->export_bitmap == NULL) {
+        if (!!client->export_bitmap) {
+            ret = nbd_co_send_bitmap(req->client, request.handle,
+                                     client->export_bitmap, request.from,
+                                     request.len, 0);
+        } else if (client->export_block_status) {
+            ret = nbd_co_send_block_status(req->client, request.handle,
+                                           blk_bs(exp->blk), request.from,
+                                           request.len, 0);
+        } else {
             reply.error = EINVAL;
             goto error_reply;
         }
-        ret = nbd_co_send_bitmap(req->client, request.handle,
-                                 client->export_bitmap, request.from,
-                                 request.len, 0);
         if (ret < 0) {
             goto out;
         }
-- 
2.11.0




reply via email to

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