qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

nbd/server: use bdrv_dirty_bitmap_next_dirty_area

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 <vsementsov@virtuozzo.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-id: 20200205112041.6003-10-vsementsov@virtuozzo.com
Signed-off-by: John Snow <jsnow@redhat.com>

authored by

Vladimir Sementsov-Ogievskiy and committed by
John Snow
dacbb6eb 89cbc7e3

+19 -40
+19 -40
nbd/server.c
··· 2068 2068 return nbd_co_send_extents(client, handle, ea, last, context_id, errp); 2069 2069 } 2070 2070 2071 - /* 2072 - * Populate @ea from a dirty bitmap. Unless @dont_fragment, the 2073 - * final extent may exceed the original @length. 2074 - */ 2071 + /* Populate @ea from a dirty bitmap. */ 2075 2072 static void bitmap_to_extents(BdrvDirtyBitmap *bitmap, 2076 2073 uint64_t offset, uint64_t length, 2077 - NBDExtentArray *ea, bool dont_fragment) 2074 + NBDExtentArray *es) 2078 2075 { 2079 - uint64_t begin = offset, end = offset; 2080 - uint64_t overall_end = offset + length; 2081 - BdrvDirtyBitmapIter *it; 2082 - bool dirty; 2076 + int64_t start, dirty_start, dirty_count; 2077 + int64_t end = offset + length; 2078 + bool full = false; 2083 2079 2084 2080 bdrv_dirty_bitmap_lock(bitmap); 2085 2081 2086 - it = bdrv_dirty_iter_new(bitmap); 2087 - dirty = bdrv_dirty_bitmap_get_locked(bitmap, offset); 2088 - 2089 - while (begin < overall_end) { 2090 - bool next_dirty = !dirty; 2091 - 2092 - if (dirty) { 2093 - end = bdrv_dirty_bitmap_next_zero(bitmap, begin, INT64_MAX); 2094 - } else { 2095 - bdrv_set_dirty_iter(it, begin); 2096 - end = bdrv_dirty_iter_next(it); 2097 - } 2098 - if (end == -1 || end - begin > UINT32_MAX) { 2099 - /* Cap to an aligned value < 4G beyond begin. */ 2100 - end = MIN(bdrv_dirty_bitmap_size(bitmap), 2101 - begin + UINT32_MAX + 1 - 2102 - bdrv_dirty_bitmap_granularity(bitmap)); 2103 - next_dirty = dirty; 2104 - } 2105 - if (dont_fragment && end > overall_end) { 2106 - end = overall_end; 2107 - } 2108 - 2109 - if (nbd_extent_array_add(ea, end - begin, 2110 - dirty ? NBD_STATE_DIRTY : 0) < 0) { 2082 + for (start = offset; 2083 + bdrv_dirty_bitmap_next_dirty_area(bitmap, start, end, INT32_MAX, 2084 + &dirty_start, &dirty_count); 2085 + start = dirty_start + dirty_count) 2086 + { 2087 + if ((nbd_extent_array_add(es, dirty_start - start, 0) < 0) || 2088 + (nbd_extent_array_add(es, dirty_count, NBD_STATE_DIRTY) < 0)) 2089 + { 2090 + full = true; 2111 2091 break; 2112 2092 } 2113 - begin = end; 2114 - dirty = next_dirty; 2115 2093 } 2116 2094 2117 - bdrv_dirty_iter_free(it); 2095 + if (!full) { 2096 + /* last non dirty extent */ 2097 + nbd_extent_array_add(es, end - start, 0); 2098 + } 2118 2099 2119 2100 bdrv_dirty_bitmap_unlock(bitmap); 2120 - 2121 - assert(offset < end); 2122 2101 } 2123 2102 2124 2103 static int nbd_co_send_bitmap(NBDClient *client, uint64_t handle, ··· 2129 2108 unsigned int nb_extents = dont_fragment ? 1 : NBD_MAX_BLOCK_STATUS_EXTENTS; 2130 2109 g_autoptr(NBDExtentArray) ea = nbd_extent_array_new(nb_extents); 2131 2110 2132 - bitmap_to_extents(bitmap, offset, length, ea, dont_fragment); 2111 + bitmap_to_extents(bitmap, offset, length, ea); 2133 2112 2134 2113 return nbd_co_send_extents(client, handle, ea, last, context_id, errp); 2135 2114 }