qcow2: More helpers for refcount modification
Add helper functions for getting and setting refcounts in a refcount array for any possible refcount order, and choose the correct one during refcount initialization. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
7453c96b78
commit
59c0cb7830
@ -32,10 +32,49 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
|
||||
int64_t offset, int64_t length, uint64_t addend,
|
||||
bool decrease, enum qcow2_discard_type type);
|
||||
|
||||
static uint64_t get_refcount_ro0(const void *refcount_array, uint64_t index);
|
||||
static uint64_t get_refcount_ro1(const void *refcount_array, uint64_t index);
|
||||
static uint64_t get_refcount_ro2(const void *refcount_array, uint64_t index);
|
||||
static uint64_t get_refcount_ro3(const void *refcount_array, uint64_t index);
|
||||
static uint64_t get_refcount_ro4(const void *refcount_array, uint64_t index);
|
||||
static uint64_t get_refcount_ro5(const void *refcount_array, uint64_t index);
|
||||
static uint64_t get_refcount_ro6(const void *refcount_array, uint64_t index);
|
||||
|
||||
static void set_refcount_ro0(void *refcount_array, uint64_t index,
|
||||
uint64_t value);
|
||||
static void set_refcount_ro1(void *refcount_array, uint64_t index,
|
||||
uint64_t value);
|
||||
static void set_refcount_ro2(void *refcount_array, uint64_t index,
|
||||
uint64_t value);
|
||||
static void set_refcount_ro3(void *refcount_array, uint64_t index,
|
||||
uint64_t value);
|
||||
static void set_refcount_ro4(void *refcount_array, uint64_t index,
|
||||
uint64_t value);
|
||||
static void set_refcount_ro5(void *refcount_array, uint64_t index,
|
||||
uint64_t value);
|
||||
static void set_refcount_ro6(void *refcount_array, uint64_t index,
|
||||
uint64_t value);
|
||||
|
||||
|
||||
static Qcow2GetRefcountFunc *const get_refcount_funcs[] = {
|
||||
&get_refcount_ro0,
|
||||
&get_refcount_ro1,
|
||||
&get_refcount_ro2,
|
||||
&get_refcount_ro3,
|
||||
&get_refcount_ro4,
|
||||
&get_refcount_ro5,
|
||||
&get_refcount_ro6
|
||||
};
|
||||
|
||||
static Qcow2SetRefcountFunc *const set_refcount_funcs[] = {
|
||||
&set_refcount_ro0,
|
||||
&set_refcount_ro1,
|
||||
&set_refcount_ro2,
|
||||
&set_refcount_ro3,
|
||||
&set_refcount_ro4,
|
||||
&set_refcount_ro5,
|
||||
&set_refcount_ro6
|
||||
};
|
||||
|
||||
|
||||
/*********************************************************/
|
||||
@ -47,8 +86,10 @@ int qcow2_refcount_init(BlockDriverState *bs)
|
||||
unsigned int refcount_table_size2, i;
|
||||
int ret;
|
||||
|
||||
s->get_refcount = &get_refcount_ro4;
|
||||
s->set_refcount = &set_refcount_ro4;
|
||||
assert(s->refcount_order >= 0 && s->refcount_order <= 6);
|
||||
|
||||
s->get_refcount = get_refcount_funcs[s->refcount_order];
|
||||
s->set_refcount = set_refcount_funcs[s->refcount_order];
|
||||
|
||||
assert(s->refcount_table_size <= INT_MAX / sizeof(uint64_t));
|
||||
refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);
|
||||
@ -80,6 +121,59 @@ void qcow2_refcount_close(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
|
||||
static uint64_t get_refcount_ro0(const void *refcount_array, uint64_t index)
|
||||
{
|
||||
return (((const uint8_t *)refcount_array)[index / 8] >> (index % 8)) & 0x1;
|
||||
}
|
||||
|
||||
static void set_refcount_ro0(void *refcount_array, uint64_t index,
|
||||
uint64_t value)
|
||||
{
|
||||
assert(!(value >> 1));
|
||||
((uint8_t *)refcount_array)[index / 8] &= ~(0x1 << (index % 8));
|
||||
((uint8_t *)refcount_array)[index / 8] |= value << (index % 8);
|
||||
}
|
||||
|
||||
static uint64_t get_refcount_ro1(const void *refcount_array, uint64_t index)
|
||||
{
|
||||
return (((const uint8_t *)refcount_array)[index / 4] >> (2 * (index % 4)))
|
||||
& 0x3;
|
||||
}
|
||||
|
||||
static void set_refcount_ro1(void *refcount_array, uint64_t index,
|
||||
uint64_t value)
|
||||
{
|
||||
assert(!(value >> 2));
|
||||
((uint8_t *)refcount_array)[index / 4] &= ~(0x3 << (2 * (index % 4)));
|
||||
((uint8_t *)refcount_array)[index / 4] |= value << (2 * (index % 4));
|
||||
}
|
||||
|
||||
static uint64_t get_refcount_ro2(const void *refcount_array, uint64_t index)
|
||||
{
|
||||
return (((const uint8_t *)refcount_array)[index / 2] >> (4 * (index % 2)))
|
||||
& 0xf;
|
||||
}
|
||||
|
||||
static void set_refcount_ro2(void *refcount_array, uint64_t index,
|
||||
uint64_t value)
|
||||
{
|
||||
assert(!(value >> 4));
|
||||
((uint8_t *)refcount_array)[index / 2] &= ~(0xf << (4 * (index % 2)));
|
||||
((uint8_t *)refcount_array)[index / 2] |= value << (4 * (index % 2));
|
||||
}
|
||||
|
||||
static uint64_t get_refcount_ro3(const void *refcount_array, uint64_t index)
|
||||
{
|
||||
return ((const uint8_t *)refcount_array)[index];
|
||||
}
|
||||
|
||||
static void set_refcount_ro3(void *refcount_array, uint64_t index,
|
||||
uint64_t value)
|
||||
{
|
||||
assert(!(value >> 8));
|
||||
((uint8_t *)refcount_array)[index] = value;
|
||||
}
|
||||
|
||||
static uint64_t get_refcount_ro4(const void *refcount_array, uint64_t index)
|
||||
{
|
||||
return be16_to_cpu(((const uint16_t *)refcount_array)[index]);
|
||||
@ -92,6 +186,29 @@ static void set_refcount_ro4(void *refcount_array, uint64_t index,
|
||||
((uint16_t *)refcount_array)[index] = cpu_to_be16(value);
|
||||
}
|
||||
|
||||
static uint64_t get_refcount_ro5(const void *refcount_array, uint64_t index)
|
||||
{
|
||||
return be32_to_cpu(((const uint32_t *)refcount_array)[index]);
|
||||
}
|
||||
|
||||
static void set_refcount_ro5(void *refcount_array, uint64_t index,
|
||||
uint64_t value)
|
||||
{
|
||||
assert(!(value >> 32));
|
||||
((uint32_t *)refcount_array)[index] = cpu_to_be32(value);
|
||||
}
|
||||
|
||||
static uint64_t get_refcount_ro6(const void *refcount_array, uint64_t index)
|
||||
{
|
||||
return be64_to_cpu(((const uint64_t *)refcount_array)[index]);
|
||||
}
|
||||
|
||||
static void set_refcount_ro6(void *refcount_array, uint64_t index,
|
||||
uint64_t value)
|
||||
{
|
||||
((uint64_t *)refcount_array)[index] = cpu_to_be64(value);
|
||||
}
|
||||
|
||||
|
||||
static int load_refcount_block(BlockDriverState *bs,
|
||||
int64_t refcount_block_offset,
|
||||
|
Loading…
Reference in New Issue
Block a user