mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-24 03:59:52 +00:00
Teach block/vdi about "discarded" (no longer allocated) blocks
An entry in the VDI block map will hold an offset to the actual block if the block is allocated, or one of two specially-interpreted values if not allocated. Using VirtualBox terminology, value VDI_IMAGE_BLOCK_FREE (0xffffffff) represents a never-allocated block (semantically arbitrary content). VDI_IMAGE_BLOCK_ZERO (0xfffffffe) represents a "discarded" block (semantically zero-filled). block/vdi knows only about VDI_IMAGE_BLOCK_FREE. Teach it about VDI_IMAGE_BLOCK_ZERO. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
0f5314a2c8
commit
c794b4e0fd
23
block/vdi.c
23
block/vdi.c
@ -114,8 +114,13 @@ void uuid_unparse(const uuid_t uu, char *out);
|
|||||||
*/
|
*/
|
||||||
#define VDI_TEXT "<<< QEMU VM Virtual Disk Image >>>\n"
|
#define VDI_TEXT "<<< QEMU VM Virtual Disk Image >>>\n"
|
||||||
|
|
||||||
/* Unallocated blocks use this index (no need to convert endianness). */
|
/* A never-allocated block; semantically arbitrary content. */
|
||||||
#define VDI_UNALLOCATED UINT32_MAX
|
#define VDI_UNALLOCATED 0xffffffffU
|
||||||
|
|
||||||
|
/* A discarded (no longer allocated) block; semantically zero-filled. */
|
||||||
|
#define VDI_DISCARDED 0xfffffffeU
|
||||||
|
|
||||||
|
#define VDI_IS_ALLOCATED(X) ((X) < VDI_DISCARDED)
|
||||||
|
|
||||||
#if !defined(CONFIG_UUID)
|
#if !defined(CONFIG_UUID)
|
||||||
void uuid_generate(uuid_t out)
|
void uuid_generate(uuid_t out)
|
||||||
@ -307,10 +312,10 @@ static int vdi_check(BlockDriverState *bs, BdrvCheckResult *res)
|
|||||||
/* Check block map and value of blocks_allocated. */
|
/* Check block map and value of blocks_allocated. */
|
||||||
for (block = 0; block < s->header.blocks_in_image; block++) {
|
for (block = 0; block < s->header.blocks_in_image; block++) {
|
||||||
uint32_t bmap_entry = le32_to_cpu(s->bmap[block]);
|
uint32_t bmap_entry = le32_to_cpu(s->bmap[block]);
|
||||||
if (bmap_entry != VDI_UNALLOCATED) {
|
if (VDI_IS_ALLOCATED(bmap_entry)) {
|
||||||
if (bmap_entry < s->header.blocks_in_image) {
|
if (bmap_entry < s->header.blocks_in_image) {
|
||||||
blocks_allocated++;
|
blocks_allocated++;
|
||||||
if (bmap[bmap_entry] == VDI_UNALLOCATED) {
|
if (!VDI_IS_ALLOCATED(bmap[bmap_entry])) {
|
||||||
bmap[bmap_entry] = bmap_entry;
|
bmap[bmap_entry] = bmap_entry;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "ERROR: block index %" PRIu32
|
fprintf(stderr, "ERROR: block index %" PRIu32
|
||||||
@ -472,7 +477,7 @@ static int vdi_is_allocated(BlockDriverState *bs, int64_t sector_num,
|
|||||||
n_sectors = nb_sectors;
|
n_sectors = nb_sectors;
|
||||||
}
|
}
|
||||||
*pnum = n_sectors;
|
*pnum = n_sectors;
|
||||||
return bmap_entry != VDI_UNALLOCATED;
|
return VDI_IS_ALLOCATED(bmap_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vdi_aio_cancel(BlockDriverAIOCB *blockacb)
|
static void vdi_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||||
@ -603,7 +608,7 @@ static void vdi_aio_read_cb(void *opaque, int ret)
|
|||||||
/* prepare next AIO request */
|
/* prepare next AIO request */
|
||||||
acb->n_sectors = n_sectors;
|
acb->n_sectors = n_sectors;
|
||||||
bmap_entry = le32_to_cpu(s->bmap[block_index]);
|
bmap_entry = le32_to_cpu(s->bmap[block_index]);
|
||||||
if (bmap_entry == VDI_UNALLOCATED) {
|
if (!VDI_IS_ALLOCATED(bmap_entry)) {
|
||||||
/* Block not allocated, return zeros, no need to wait. */
|
/* Block not allocated, return zeros, no need to wait. */
|
||||||
memset(acb->buf, 0, n_sectors * SECTOR_SIZE);
|
memset(acb->buf, 0, n_sectors * SECTOR_SIZE);
|
||||||
ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
|
ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
|
||||||
@ -685,7 +690,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
|
|||||||
if (acb->header_modified) {
|
if (acb->header_modified) {
|
||||||
VdiHeader *header = acb->block_buffer;
|
VdiHeader *header = acb->block_buffer;
|
||||||
logout("now writing modified header\n");
|
logout("now writing modified header\n");
|
||||||
assert(acb->bmap_first != VDI_UNALLOCATED);
|
assert(VDI_IS_ALLOCATED(acb->bmap_first));
|
||||||
*header = s->header;
|
*header = s->header;
|
||||||
vdi_header_to_le(header);
|
vdi_header_to_le(header);
|
||||||
acb->header_modified = 0;
|
acb->header_modified = 0;
|
||||||
@ -699,7 +704,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (acb->bmap_first != VDI_UNALLOCATED) {
|
} else if (VDI_IS_ALLOCATED(acb->bmap_first)) {
|
||||||
/* One or more new blocks were allocated. */
|
/* One or more new blocks were allocated. */
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
uint32_t bmap_first;
|
uint32_t bmap_first;
|
||||||
@ -749,7 +754,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
|
|||||||
/* prepare next AIO request */
|
/* prepare next AIO request */
|
||||||
acb->n_sectors = n_sectors;
|
acb->n_sectors = n_sectors;
|
||||||
bmap_entry = le32_to_cpu(s->bmap[block_index]);
|
bmap_entry = le32_to_cpu(s->bmap[block_index]);
|
||||||
if (bmap_entry == VDI_UNALLOCATED) {
|
if (!VDI_IS_ALLOCATED(bmap_entry)) {
|
||||||
/* Allocate new block and write to it. */
|
/* Allocate new block and write to it. */
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
uint8_t *block;
|
uint8_t *block;
|
||||||
|
Loading…
Reference in New Issue
Block a user