static int vdi_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix) { /* TODO: additional checks possible. */ BDRVVdiState *s = (BDRVVdiState *)bs->opaque; uint32_t blocks_allocated = 0; uint32_t block; uint32_t *bmap; logout("\n"); if (fix) { return -ENOTSUP; } bmap = g_try_malloc(s->header.blocks_in_image * sizeof(uint32_t)); if (s->header.blocks_in_image && bmap == NULL) { res->check_errors++; return -ENOMEM; } memset(bmap, 0xff, s->header.blocks_in_image * sizeof(uint32_t)); /* 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 (VDI_IS_ALLOCATED(bmap_entry)) { if (bmap_entry < s->header.blocks_in_image) { blocks_allocated++; if (!VDI_IS_ALLOCATED(bmap[bmap_entry])) { bmap[bmap_entry] = bmap_entry; } else { fprintf(stderr, "ERROR: block index %" PRIu32 " also used by %" PRIu32 "\n", bmap[bmap_entry], bmap_entry); res->corruptions++; } } else { fprintf(stderr, "ERROR: block index %" PRIu32 " too large, is %" PRIu32 "\n", block, bmap_entry); res->corruptions++; } } } if (blocks_allocated != s->header.blocks_allocated) { fprintf(stderr, "ERROR: allocated blocks mismatch, is %" PRIu32 ", should be %" PRIu32 "\n", blocks_allocated, s->header.blocks_allocated); res->corruptions++; } g_free(bmap); return 0; }