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,
|
int64_t offset, int64_t length, uint64_t addend,
|
||||||
bool decrease, enum qcow2_discard_type type);
|
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_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,
|
static void set_refcount_ro4(void *refcount_array, uint64_t index,
|
||||||
uint64_t value);
|
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;
|
unsigned int refcount_table_size2, i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
s->get_refcount = &get_refcount_ro4;
|
assert(s->refcount_order >= 0 && s->refcount_order <= 6);
|
||||||
s->set_refcount = &set_refcount_ro4;
|
|
||||||
|
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));
|
assert(s->refcount_table_size <= INT_MAX / sizeof(uint64_t));
|
||||||
refcount_table_size2 = s->refcount_table_size * 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)
|
static uint64_t get_refcount_ro4(const void *refcount_array, uint64_t index)
|
||||||
{
|
{
|
||||||
return be16_to_cpu(((const uint16_t *)refcount_array)[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);
|
((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,
|
static int load_refcount_block(BlockDriverState *bs,
|
||||||
int64_t refcount_block_offset,
|
int64_t refcount_block_offset,
|
||||||
|
Loading…
Reference in New Issue
Block a user