[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
- Re: [Qemu-block] [PATCH 04/18] nbd/client: refactor nbd_receive_starttls, (continued)
[Qemu-block] [PATCH 11/18] nbd: BLOCK_STATUS for bitmap export: server part, Vladimir Sementsov-Ogievskiy, 2017/02/03
[Qemu-block] [PATCH 07/18] nbd: Minimal structured read for client, Vladimir Sementsov-Ogievskiy, 2017/02/03
[Qemu-block] [PATCH 09/18] block/dirty-bitmap: add bdrv_dirty_bitmap_next(), Vladimir Sementsov-Ogievskiy, 2017/02/03
[Qemu-block] [PATCH 17/18] nbd: BLOCK_STATUS for standard get_block_status function: server part,
Vladimir Sementsov-Ogievskiy <=
[Qemu-block] [PATCH 14/18] qmp: add x-debug-block-dirty-bitmap-sha256, Vladimir Sementsov-Ogievskiy, 2017/02/03
[Qemu-block] [PATCH 03/18] nbd: Minimal structured read for server, Vladimir Sementsov-Ogievskiy, 2017/02/03
[Qemu-block] [PATCH 12/18] nbd: BLOCK_STATUS for bitmap export: client part, Vladimir Sementsov-Ogievskiy, 2017/02/03
[Qemu-block] [PATCH 08/18] hbitmap: add next_zero function, Vladimir Sementsov-Ogievskiy, 2017/02/03