From: Dong Xu Wang <[email protected]> Add fragmentation statistics for qed file format.
Signed-off-by: Dong Xu Wang <[email protected]> --- block/qed.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 41 insertions(+), 0 deletions(-) diff --git a/block/qed.c b/block/qed.c index a041d31..eb4dd90 100644 --- a/block/qed.c +++ b/block/qed.c @@ -1444,6 +1444,46 @@ static int bdrv_qed_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) return 0; } +static int bdrv_qed_get_fragment(BlockDriverState *bs, BlockFragInfo *bfi) +{ + BDRVQEDState *s = bs->opaque; + uint32_t cluster_size = s->header.cluster_size; + uint64_t table_noffsets = s->header.table_size * cluster_size / sizeof(uint64_t); + uint64_t i, j; + uint64_t l2_offset; + int ret = 0; + uint64_t last_offset = 0; + uint64_t size = s->header.table_size * cluster_size; + uint64_t *table = qemu_blockalign(s->bs, size); + + for (i = 0; i < table_noffsets; i++) { + l2_offset = s->l1_table->offsets[i]; + if (l2_offset == 0) { + continue; + } + ret = bdrv_pread(bs->file, l2_offset, table, size); + if (ret < 0) { + qemu_vfree(table); + return ret; + } + for (j = 0; j < size/sizeof(uint64_t); j++) { + uint64_t *offset = (uint64_t *)(table + j); + if (*offset < cluster_size) { + continue; + } + bfi->allocated_clusters++; + if (last_offset && (last_offset + cluster_size) != *offset) { + bfi->fragmented_clusters++; + } + last_offset = *offset; + } + } + bfi->total_clusters = (s->header.image_size + s->header.cluster_size - 1) / + s->header.cluster_size; + qemu_vfree(table); + return ret; +} + static int bdrv_qed_change_backing_file(BlockDriverState *bs, const char *backing_file, const char *backing_fmt) @@ -1569,6 +1609,7 @@ static BlockDriver bdrv_qed = { .bdrv_get_info = bdrv_qed_get_info, .bdrv_change_backing_file = bdrv_qed_change_backing_file, .bdrv_check = bdrv_qed_check, + .bdrv_get_fragment = bdrv_qed_get_fragment, }; static void bdrv_qed_init(void) -- 1.7.5.4
