util: bitmap: Rewrite virBitmapShrink using new helpers

Rather than reimplement everything manually use virBitmapBuffsize to
find the current number of units, realloc the buffer and clear the tail
using virBitmapClearTail().

This fixes a corner case where the buffer would be over-allocated by one
unit when shrinking to the boundary of the unit size.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
This commit is contained in:
Peter Krempa 2024-10-17 13:55:23 +02:00
parent e506e0b3f1
commit 7cbe9e94c4

View File

@ -1187,33 +1187,13 @@ void
virBitmapShrink(virBitmap *map,
size_t b)
{
size_t toremove;
size_t nl = 0;
size_t nb = 0;
if (!map)
if (!map ||
map->nbits <= b)
return;
if (map->nbits >= b)
map->nbits = b;
nl = map->nbits / VIR_BITMAP_BITS_PER_UNIT;
nb = map->nbits % VIR_BITMAP_BITS_PER_UNIT;
/* If we're at the end of the allocation the attempt to clear 'map->nbit'
* and further would be beyond the end of the bitmap */
if (nl >= map->map_alloc)
return;
map->map[nl] &= ((1UL << nb) - 1);
toremove = map->map_alloc - (nl + 1);
if (toremove == 0)
return;
VIR_SHRINK_N(map->map, map->map_alloc, toremove);
/* length needs to be fixed as well */
map->map_len = map->map_alloc;
map->nbits = b;
map->map_len = virBitmapBuffsize(b);
map->map = g_renew(unsigned long, map->map, map->map_len);
map->map_alloc = map->map_len;
virBitmapClearTail(map);
}