|
@@ -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);
|
|
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,
|
|
static void bitmap_to_extents(BdrvDirtyBitmap *bitmap,
|
|
uint64_t offset, uint64_t length,
|
|
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);
|
|
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;
|
|
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);
|
|
bdrv_dirty_bitmap_unlock(bitmap);
|
|
-
|
|
|
|
- assert(offset < end);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static int nbd_co_send_bitmap(NBDClient *client, uint64_t handle,
|
|
static int nbd_co_send_bitmap(NBDClient *client, uint64_t handle,
|
|
@@ -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;
|
|
unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BLOCK_STATUS_EXTENTS;
|
|
g_autoptr(NBDExtentArray) ea = nbd_extent_array_new(nb_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);
|
|
return nbd_co_send_extents(client, handle, ea, last, context_id, errp);
|
|
}
|
|
}
|