Signed-off-by: Devin Nakamura <devin...@gmail.com> --- block/qcow2-cluster.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ block/qcow2.c | 1 + block/qcow2.h | 3 +++ 3 files changed, 53 insertions(+), 0 deletions(-)
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index ca56918..848f2ee 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -977,3 +977,52 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset, return 0; } + +int qcow2_map(BlockDriverState *bs, uint64_t guest_offset, + uint64_t host_offset, uint64_t contiguous_bytes) +{ + BDRVQcowState *s = bs->opaque; + unsigned int nelms; + + + if ((s->cluster_size - 1) & guest_offset) { + return -EINVAL; + } + + if (contiguous_bytes % s->cluster_size) { + return -EINVAL; + } + + nelms = s->l2_size / sizeof(uint64_t); + + while (contiguous_bytes > 0) { + unsigned int l1_index, l2_index; + uint64_t *l2_table; + int ret; + l1_index = guest_offset >> (s->l2_bits + s->cluster_bits); + l2_index = (guest_offset >> s->cluster_bits) & (s->l2_size - 1); + + if (!s->l1_table[l1_index]) { + ret = l2_allocate(bs, l1_index, &l2_table); + if (ret) { + return ret; + } + } else { + ret = l2_load(bs, s->l1_table[l1_index] & ~QCOW_OFLAG_COPIED, &l2_table); + if (ret) { + return ret; + } + } + qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); + + for (; l2_index < nelms && contiguous_bytes > 0; l2_index++) { + l2_table[l2_index] = cpu_to_be64(host_offset | QCOW_OFLAG_COPIED); + host_offset += s->cluster_size; + contiguous_bytes -= s->cluster_size; + } + + qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table); + + } + return 0; +} diff --git a/block/qcow2.c b/block/qcow2.c index 05ea40c..b75364d 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1445,6 +1445,7 @@ static BlockDriver bdrv_qcow2 = { .bdrv_check = qcow2_check, .bdrv_get_mapping = qcow2_get_mapping, + .bdrv_map = qcow2_map, }; static void bdrv_qcow2_init(void) diff --git a/block/qcow2.h b/block/qcow2.h index e9efb74..feea866 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -245,4 +245,7 @@ int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, void **table); int qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table); +int qcow2_map(BlockDriverState *bs, uint64_t guest_offset, uint64_t host_ofset, + uint64_t contiguous_bytes); + #endif -- 1.7.6.rc1