[Libguestfs] [PATCH nbdkit v3] common: Move shared bitmap code to a common library.

Eric Blake eblake at redhat.com
Mon Dec 3 22:41:47 UTC 2018


On 12/3/18 4:13 PM, Richard W.M. Jones wrote:
> The cow and cache filters both use a bitmap mapping virtual disk
> blocks to status stored in the bitmap.  The implementation of the
> bitmaps is very similar because one was derived from the other when
> the filters were implemented.
> 
> The main difference is the cow filter uses a simple bitmap (one bit
> per block), whereas the cache filter uses two bits per block.
> 
> This commit abstracts the bitmap structure into a common library.  The
> block size and bits per block are configurable.
> 
> This commit is refactoring, except:
> 
> - it cures a memory leak (bitmap was not being freed),
> 
> - in the cache filter we now mask out existing bits when updating the
>    bitmap.
> ---
> +
> +/* This is the bitmap structure. */
> +struct bitmap {
> +  unsigned blksize;             /* Block size. */
> +  unsigned bpb;                 /* Bits per block (1, 2, 4, 8 only). */
> +  /* bpb = 1 << bitshift   ibpb = 8/bpb
> +     1          0          8
> +     2          1          4
> +     4          2          2
> +     8          3          1
> +  */
> +  unsigned bitshift, ibpb;

As written, you've consumed 16 bytes in the struct by this point.  If 
cache line pressure is a concern, you could make these three values 
unsigned char, and only consume 8 bytes (1 padding) before the next 
field member.

> +
> +  uint8_t *bitmap;              /* The bitmap. */
> +  size_t size;                  /* Size of bitmap in bytes. */
> +};

But even without that compression, a 64-bit architecture should fit the 
struct in 32 bytes, which means cache line pressure may not be a concern.

> +/* This macro calculates the byte offset in the bitmap and which
> + * bit/mask we are addressing within that byte.
> + *
> + * bpb     blk_offset         blk_bit          mask
> + * 1       blk >> 3           0,1,2,...,7      any single bit
> + * 2       blk >> 2           0, 2, 4 or 6     0x3, 0xc, 0x30 or 0xc0
> + * 4       blk >> 1           0 or 4           0xf, 0xf0
> + * 8       blk >> 0           always 0         always 0xff
> + */
> +#define BITMAP_OFFSET_BIT_MASK(bm, blk)                         \
> +  uint64_t blk_offset = (blk) >> (3 - (bm)->bitshift);          \
> +  unsigned blk_bit = (bm)->bpb * ((blk) & ((bm)->ibpb - 1));    \
> +  unsigned mask = ((1 << (bm)->bpb) - 1) << blk_bit

Nice.  Maybe not the easiest indirection when reading a given function 
in isolation (macros don't very often declare variables), but does 
reduce the duplication and chance for errors.

ACK

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




More information about the Libguestfs mailing list