nbd patches for 2018-09-26
Fixes for external clients; add reminder to revisit naming of x- command - Vladimir Sementsov-Ogievskiy: nbd/server: send more than one extent of base:allocation context - John Snow: qapi: bitmap-merge: document name change - Vladimir Sementsov-Ogievskiy: nbd/server: fix bitmap export -----BEGIN PGP SIGNATURE----- Comment: Public key at http://people.redhat.com/eblake/eblake.gpg iQEcBAABCAAGBQJbrEMDAAoJEKeha0olJ0NqVUMIAIsPETUWAbMbulGYqO9Q4HDz VCAJDYWW8QbxIngO1pXrfno7+VGfs6jN5H2FIc8fTQNh4hFQkDYTSn0PBoGQQifH BcS9aevHADGOqgx1E/i0trBBtSagrYcig5ZbPQnm3gNO0u7c2Mwrddy550QQDGI2 LT+0ta1lbDRxiMZXkTg7HB2Q3iYjZHdweLLJdGSpalYyXN95A5H2RsyCALA6Y0oS +lrYEoNyGqSNhgqVe/kRgvz4t9CsJ3fam/Y7JVmL/s43WvkdODpaEcEDiZRosQuo NbC+kD3t5qvElkPZUS4yqMXmjVCJpzW8ijLh3H1CSBwLjB4b2tLAEi83xeNQPRo= =6Q7H -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2018-09-26' into staging nbd patches for 2018-09-26 Fixes for external clients; add reminder to revisit naming of x- command - Vladimir Sementsov-Ogievskiy: nbd/server: send more than one extent of base:allocation context - John Snow: qapi: bitmap-merge: document name change - Vladimir Sementsov-Ogievskiy: nbd/server: fix bitmap export # gpg: Signature made Thu 27 Sep 2018 03:40:03 BST # gpg: using RSA key A7A16B4A2527436A # gpg: Good signature from "Eric Blake <eblake@redhat.com>" # gpg: aka "Eric Blake (Free Software Programmer) <ebb9@byu.net>" # gpg: aka "[jpeg image of size 6874]" # Primary key fingerprint: 71C2 CC22 B1C4 6029 27D2 F3AA A7A1 6B4A 2527 436A * remotes/ericb/tags/pull-nbd-2018-09-26: nbd/server: send more than one extent of base:allocation context qapi: bitmap-merge: document name change nbd/server: fix bitmap export Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
e7f5f0b6e6
92
nbd/server.c
92
nbd/server.c
@ -1844,37 +1844,68 @@ static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int blockstatus_to_extent_be(BlockDriverState *bs, uint64_t offset,
|
/*
|
||||||
uint64_t bytes, NBDExtent *extent)
|
* Populate @extents from block status. Update @bytes to be the actual
|
||||||
|
* length encoded (which may be smaller than the original), and update
|
||||||
|
* @nb_extents to the number of extents used.
|
||||||
|
*
|
||||||
|
* Returns zero on success and -errno on bdrv_block_status_above failure.
|
||||||
|
*/
|
||||||
|
static int blockstatus_to_extents(BlockDriverState *bs, uint64_t offset,
|
||||||
|
uint64_t *bytes, NBDExtent *extents,
|
||||||
|
unsigned int *nb_extents)
|
||||||
{
|
{
|
||||||
uint64_t remaining_bytes = bytes;
|
uint64_t remaining_bytes = *bytes;
|
||||||
|
NBDExtent *extent = extents, *extents_end = extents + *nb_extents;
|
||||||
|
bool first_extent = true;
|
||||||
|
|
||||||
|
assert(*nb_extents);
|
||||||
while (remaining_bytes) {
|
while (remaining_bytes) {
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
int64_t num;
|
int64_t num;
|
||||||
int ret = bdrv_block_status_above(bs, NULL, offset, remaining_bytes,
|
int ret = bdrv_block_status_above(bs, NULL, offset, remaining_bytes,
|
||||||
&num, NULL, NULL);
|
&num, NULL, NULL);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = (ret & BDRV_BLOCK_ALLOCATED ? 0 : NBD_STATE_HOLE) |
|
flags = (ret & BDRV_BLOCK_ALLOCATED ? 0 : NBD_STATE_HOLE) |
|
||||||
(ret & BDRV_BLOCK_ZERO ? NBD_STATE_ZERO : 0);
|
(ret & BDRV_BLOCK_ZERO ? NBD_STATE_ZERO : 0);
|
||||||
|
|
||||||
if (remaining_bytes == bytes) {
|
|
||||||
extent->flags = flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags != extent->flags) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += num;
|
offset += num;
|
||||||
remaining_bytes -= num;
|
remaining_bytes -= num;
|
||||||
|
|
||||||
|
if (first_extent) {
|
||||||
|
extent->flags = flags;
|
||||||
|
extent->length = num;
|
||||||
|
first_extent = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags == extent->flags) {
|
||||||
|
/* extend current extent */
|
||||||
|
extent->length += num;
|
||||||
|
} else {
|
||||||
|
if (extent + 1 == extents_end) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* start new extent */
|
||||||
|
extent++;
|
||||||
|
extent->flags = flags;
|
||||||
|
extent->length = num;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_to_be32s(&extent->flags);
|
extents_end = extent + 1;
|
||||||
extent->length = cpu_to_be32(bytes - remaining_bytes);
|
|
||||||
|
for (extent = extents; extent < extents_end; extent++) {
|
||||||
|
cpu_to_be32s(&extent->flags);
|
||||||
|
cpu_to_be32s(&extent->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
*bytes -= remaining_bytes;
|
||||||
|
*nb_extents = extents_end - extents;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1910,21 +1941,29 @@ static int nbd_co_send_extents(NBDClient *client, uint64_t handle,
|
|||||||
/* Get block status from the exported device and send it to the client */
|
/* Get block status from the exported device and send it to the client */
|
||||||
static int nbd_co_send_block_status(NBDClient *client, uint64_t handle,
|
static int nbd_co_send_block_status(NBDClient *client, uint64_t handle,
|
||||||
BlockDriverState *bs, uint64_t offset,
|
BlockDriverState *bs, uint64_t offset,
|
||||||
uint32_t length, bool last,
|
uint32_t length, bool dont_fragment,
|
||||||
uint32_t context_id, Error **errp)
|
bool last, uint32_t context_id,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
NBDExtent extent;
|
unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BITMAP_EXTENTS;
|
||||||
|
NBDExtent *extents = g_new(NBDExtent, nb_extents);
|
||||||
|
uint64_t final_length = length;
|
||||||
|
|
||||||
ret = blockstatus_to_extent_be(bs, offset, length, &extent);
|
ret = blockstatus_to_extents(bs, offset, &final_length, extents,
|
||||||
|
&nb_extents);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
g_free(extents);
|
||||||
return nbd_co_send_structured_error(
|
return nbd_co_send_structured_error(
|
||||||
client, handle, -ret, "can't get block status", errp);
|
client, handle, -ret, "can't get block status", errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nbd_co_send_extents(client, handle, &extent, 1,
|
ret = nbd_co_send_extents(client, handle, extents, nb_extents,
|
||||||
be32_to_cpu(extent.length), last,
|
final_length, last, context_id, errp);
|
||||||
context_id, errp);
|
|
||||||
|
g_free(extents);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1951,6 +1990,8 @@ static unsigned int bitmap_to_extents(BdrvDirtyBitmap *bitmap, uint64_t offset,
|
|||||||
|
|
||||||
assert(begin < overall_end && nb_extents);
|
assert(begin < overall_end && nb_extents);
|
||||||
while (begin < overall_end && i < nb_extents) {
|
while (begin < overall_end && i < nb_extents) {
|
||||||
|
bool next_dirty = !dirty;
|
||||||
|
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
end = bdrv_dirty_bitmap_next_zero(bitmap, begin);
|
end = bdrv_dirty_bitmap_next_zero(bitmap, begin);
|
||||||
} else {
|
} else {
|
||||||
@ -1962,6 +2003,7 @@ static unsigned int bitmap_to_extents(BdrvDirtyBitmap *bitmap, uint64_t offset,
|
|||||||
end = MIN(bdrv_dirty_bitmap_size(bitmap),
|
end = MIN(bdrv_dirty_bitmap_size(bitmap),
|
||||||
begin + UINT32_MAX + 1 -
|
begin + UINT32_MAX + 1 -
|
||||||
bdrv_dirty_bitmap_granularity(bitmap));
|
bdrv_dirty_bitmap_granularity(bitmap));
|
||||||
|
next_dirty = dirty;
|
||||||
}
|
}
|
||||||
if (dont_fragment && end > overall_end) {
|
if (dont_fragment && end > overall_end) {
|
||||||
end = overall_end;
|
end = overall_end;
|
||||||
@ -1971,7 +2013,7 @@ static unsigned int bitmap_to_extents(BdrvDirtyBitmap *bitmap, uint64_t offset,
|
|||||||
extents[i].flags = cpu_to_be32(dirty ? NBD_STATE_DIRTY : 0);
|
extents[i].flags = cpu_to_be32(dirty ? NBD_STATE_DIRTY : 0);
|
||||||
i++;
|
i++;
|
||||||
begin = end;
|
begin = end;
|
||||||
dirty = !dirty;
|
dirty = next_dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_dirty_iter_free(it);
|
bdrv_dirty_iter_free(it);
|
||||||
@ -2228,10 +2270,12 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
|
|||||||
(client->export_meta.base_allocation ||
|
(client->export_meta.base_allocation ||
|
||||||
client->export_meta.bitmap))
|
client->export_meta.bitmap))
|
||||||
{
|
{
|
||||||
|
bool dont_fragment = request->flags & NBD_CMD_FLAG_REQ_ONE;
|
||||||
|
|
||||||
if (client->export_meta.base_allocation) {
|
if (client->export_meta.base_allocation) {
|
||||||
ret = nbd_co_send_block_status(client, request->handle,
|
ret = nbd_co_send_block_status(client, request->handle,
|
||||||
blk_bs(exp->blk), request->from,
|
blk_bs(exp->blk), request->from,
|
||||||
request->len,
|
request->len, dont_fragment,
|
||||||
!client->export_meta.bitmap,
|
!client->export_meta.bitmap,
|
||||||
NBD_META_ID_BASE_ALLOCATION,
|
NBD_META_ID_BASE_ALLOCATION,
|
||||||
errp);
|
errp);
|
||||||
@ -2244,7 +2288,7 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
|
|||||||
ret = nbd_co_send_bitmap(client, request->handle,
|
ret = nbd_co_send_bitmap(client, request->handle,
|
||||||
client->exp->export_bitmap,
|
client->exp->export_bitmap,
|
||||||
request->from, request->len,
|
request->from, request->len,
|
||||||
request->flags & NBD_CMD_FLAG_REQ_ONE,
|
dont_fragment,
|
||||||
true, NBD_META_ID_DIRTY_BITMAP, errp);
|
true, NBD_META_ID_DIRTY_BITMAP, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1935,6 +1935,8 @@
|
|||||||
##
|
##
|
||||||
# @x-block-dirty-bitmap-merge:
|
# @x-block-dirty-bitmap-merge:
|
||||||
#
|
#
|
||||||
|
# FIXME: Rename @src_name and @dst_name to src-name and dst-name.
|
||||||
|
#
|
||||||
# Merge @src_name dirty bitmap to @dst_name dirty bitmap. @src_name dirty
|
# Merge @src_name dirty bitmap to @dst_name dirty bitmap. @src_name dirty
|
||||||
# bitmap is unchanged. On error, @dst_name is unchanged.
|
# bitmap is unchanged. On error, @dst_name is unchanged.
|
||||||
#
|
#
|
||||||
|
Loading…
Reference in New Issue
Block a user