Skip to content

Commit

Permalink
nbd/server: use bdrv_dirty_bitmap_next_dirty_area
Browse files Browse the repository at this point in the history
Use bdrv_dirty_bitmap_next_dirty_area for bitmap_to_extents. Since
bdrv_dirty_bitmap_next_dirty_area is very accurate in its interface,
we'll never exceed requested region with last chunk. So, we don't need
dont_fragment, and bitmap_to_extents() interface becomes clean enough
to not require any comment.

Signed-off-by: Vladimir Sementsov-Ogievskiy <[email protected]>
Reviewed-by: Eric Blake <[email protected]>
Message-id: [email protected]
Signed-off-by: John Snow <[email protected]>
  • Loading branch information
Vladimir Sementsov-Ogievskiy authored and jnsnow committed Mar 18, 2020
1 parent 89cbc7e commit dacbb6e
Showing 1 changed file with 19 additions and 40 deletions.
59 changes: 19 additions & 40 deletions nbd/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -2068,57 +2068,36 @@ static int nbd_co_send_block_status(NBDClient *client, uint64_t handle,
return nbd_co_send_extents(client, handle, ea, last, context_id, errp);
}

/*
* Populate @ea from a dirty bitmap. Unless @dont_fragment, the
* final extent may exceed the original @length.
*/
/* Populate @ea from a dirty bitmap. */
static void bitmap_to_extents(BdrvDirtyBitmap *bitmap,
uint64_t offset, uint64_t length,
NBDExtentArray *ea, bool dont_fragment)
NBDExtentArray *es)
{
uint64_t begin = offset, end = offset;
uint64_t overall_end = offset + length;
BdrvDirtyBitmapIter *it;
bool dirty;
int64_t start, dirty_start, dirty_count;
int64_t end = offset + length;
bool full = false;

bdrv_dirty_bitmap_lock(bitmap);

it = bdrv_dirty_iter_new(bitmap);
dirty = bdrv_dirty_bitmap_get_locked(bitmap, offset);

while (begin < overall_end) {
bool next_dirty = !dirty;

if (dirty) {
end = bdrv_dirty_bitmap_next_zero(bitmap, begin, INT64_MAX);
} else {
bdrv_set_dirty_iter(it, begin);
end = bdrv_dirty_iter_next(it);
}
if (end == -1 || end - begin > UINT32_MAX) {
/* Cap to an aligned value < 4G beyond begin. */
end = MIN(bdrv_dirty_bitmap_size(bitmap),
begin + UINT32_MAX + 1 -
bdrv_dirty_bitmap_granularity(bitmap));
next_dirty = dirty;
}
if (dont_fragment && end > overall_end) {
end = overall_end;
}

if (nbd_extent_array_add(ea, end - begin,
dirty ? NBD_STATE_DIRTY : 0) < 0) {
for (start = offset;
bdrv_dirty_bitmap_next_dirty_area(bitmap, start, end, INT32_MAX,
&dirty_start, &dirty_count);
start = dirty_start + dirty_count)
{
if ((nbd_extent_array_add(es, dirty_start - start, 0) < 0) ||
(nbd_extent_array_add(es, dirty_count, NBD_STATE_DIRTY) < 0))
{
full = true;
break;
}
begin = end;
dirty = next_dirty;
}

bdrv_dirty_iter_free(it);
if (!full) {
/* last non dirty extent */
nbd_extent_array_add(es, end - start, 0);
}

bdrv_dirty_bitmap_unlock(bitmap);

assert(offset < end);
}

static int nbd_co_send_bitmap(NBDClient *client, uint64_t handle,
Expand All @@ -2129,7 +2108,7 @@ static int nbd_co_send_bitmap(NBDClient *client, uint64_t handle,
unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BLOCK_STATUS_EXTENTS;
g_autoptr(NBDExtentArray) ea = nbd_extent_array_new(nb_extents);

bitmap_to_extents(bitmap, offset, length, ea, dont_fragment);
bitmap_to_extents(bitmap, offset, length, ea);

return nbd_co_send_extents(client, handle, ea, last, context_id, errp);
}
Expand Down

0 comments on commit dacbb6e

Please sign in to comment.