|
@@ -114,8 +114,13 @@ void uuid_unparse(const uuid_t uu, char *out);
|
|
|
*/
|
|
|
#define VDI_TEXT "<<< QEMU VM Virtual Disk Image >>>\n"
|
|
|
|
|
|
-/* Unallocated blocks use this index (no need to convert endianness). */
|
|
|
-#define VDI_UNALLOCATED UINT32_MAX
|
|
|
+/* A never-allocated block; semantically arbitrary content. */
|
|
|
+#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)
|
|
|
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. */
|
|
|
for (block = 0; block < s->header.blocks_in_image; 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) {
|
|
|
blocks_allocated++;
|
|
|
- if (bmap[bmap_entry] == VDI_UNALLOCATED) {
|
|
|
+ if (!VDI_IS_ALLOCATED(bmap[bmap_entry])) {
|
|
|
bmap[bmap_entry] = bmap_entry;
|
|
|
} else {
|
|
|
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;
|
|
|
}
|
|
|
*pnum = n_sectors;
|
|
|
- return bmap_entry != VDI_UNALLOCATED;
|
|
|
+ return VDI_IS_ALLOCATED(bmap_entry);
|
|
|
}
|
|
|
|
|
|
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 */
|
|
|
acb->n_sectors = n_sectors;
|
|
|
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. */
|
|
|
memset(acb->buf, 0, n_sectors * SECTOR_SIZE);
|
|
|
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) {
|
|
|
VdiHeader *header = acb->block_buffer;
|
|
|
logout("now writing modified header\n");
|
|
|
- assert(acb->bmap_first != VDI_UNALLOCATED);
|
|
|
+ assert(VDI_IS_ALLOCATED(acb->bmap_first));
|
|
|
*header = s->header;
|
|
|
vdi_header_to_le(header);
|
|
|
acb->header_modified = 0;
|
|
@@ -699,7 +704,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
|
|
|
goto done;
|
|
|
}
|
|
|
return;
|
|
|
- } else if (acb->bmap_first != VDI_UNALLOCATED) {
|
|
|
+ } else if (VDI_IS_ALLOCATED(acb->bmap_first)) {
|
|
|
/* One or more new blocks were allocated. */
|
|
|
uint64_t offset;
|
|
|
uint32_t bmap_first;
|
|
@@ -749,7 +754,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
|
|
|
/* prepare next AIO request */
|
|
|
acb->n_sectors = n_sectors;
|
|
|
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. */
|
|
|
uint64_t offset;
|
|
|
uint8_t *block;
|