On Tue, 04/01 10:06, Jun Lee wrote: > Signed-off-by: Jun Li <junm...@gmail.com> > > This patch can make sure the data still existing after shrinking. And only > discard the unused (guest) clusters. If shrinking to the size which stored > data, It will return an error and will not do any change. > As this patch can support shrinking, so changed the func name of > qcow2_grow_l1_table to qcow2_truncate_l1_table.
Signed-off-by line is missing. > --- > block/qcow2-cluster.c | 20 ++++++++++++++------ > block/qcow2-snapshot.c | 2 +- > block/qcow2.c | 8 +------- > block/qcow2.h | 2 +- > 4 files changed, 17 insertions(+), 15 deletions(-) > > diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c > index 9499df9..70e61ea 100644 > --- a/block/qcow2-cluster.c > +++ b/block/qcow2-cluster.c > @@ -29,7 +29,7 @@ > #include "block/qcow2.h" > #include "trace.h" > > -int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, > +int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size, > bool exact_size) Parameter alignment is changed. > { > BDRVQcowState *s = bs->opaque; > @@ -39,9 +39,6 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t > min_size, > int64_t new_l1_table_offset, new_l1_size; > uint8_t data[12]; > > - if (min_size <= s->l1_size) > - return 0; > - > if (exact_size) { > new_l1_size = min_size; > } else { > @@ -66,7 +63,18 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t > min_size, > > new_l1_size2 = sizeof(uint64_t) * new_l1_size; > new_l1_table = g_malloc0(align_offset(new_l1_size2, 512)); > - memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t)); > + > + /* shrinking the image */ > + if (min_size <= s->l1_size) { > + if (s->l1_table[new_l1_size] != 0) { Is this safe as advertised? Do we need to scan all the dropped l1 entries, instead of only the first one? > + error_report("Could not shrink to this size, " > + "it will destory image data"); Better to align by quote mark. > + return -ENOTSUP; > + } > + memcpy(new_l1_table, s->l1_table, new_l1_size2); > + } > + > + memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t)); Redundant (and wrong size) memcpy for shrinking case? Fam > > /* write new table (align to cluster) */ > BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ALLOC_TABLE); > @@ -559,7 +567,7 @@ static int get_cluster_table(BlockDriverState *bs, > uint64_t offset, > > l1_index = offset >> (s->l2_bits + s->cluster_bits); > if (l1_index >= s->l1_size) { > - ret = qcow2_grow_l1_table(bs, l1_index + 1, false); > + ret = qcow2_truncate_l1_table(bs, l1_index + 1, false); > if (ret < 0) { > return ret; > } > diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c > index 2fc6320..ab16c52 100644 > --- a/block/qcow2-snapshot.c > +++ b/block/qcow2-snapshot.c > @@ -491,7 +491,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char > *snapshot_id) > * L1 table of the snapshot. If the snapshot L1 table is smaller, the > * current one must be padded with zeros. > */ > - ret = qcow2_grow_l1_table(bs, sn->l1_size, true); > + ret = qcow2_truncate_l1_table(bs, sn->l1_size, true); > if (ret < 0) { > goto fail; > } > diff --git a/block/qcow2.c b/block/qcow2.c > index b9dc960..4797879 100644 > --- a/block/qcow2.c > +++ b/block/qcow2.c > @@ -1764,14 +1764,8 @@ static int qcow2_truncate(BlockDriverState *bs, > int64_t offset) > return -ENOTSUP; > } > > - /* shrinking is currently not supported */ > - if (offset < bs->total_sectors * 512) { > - error_report("qcow2 doesn't support shrinking images yet"); > - return -ENOTSUP; > - } > - > new_l1_size = size_to_l1(s, offset); > - ret = qcow2_grow_l1_table(bs, new_l1_size, true); > + ret = qcow2_truncate_l1_table(bs, new_l1_size, true); > if (ret < 0) { > return ret; > } > diff --git a/block/qcow2.h b/block/qcow2.h > index 0b0eac8..298d84e 100644 > --- a/block/qcow2.h > +++ b/block/qcow2.h > @@ -455,7 +455,7 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, > int ign, int64_t offset, > int64_t size); > > /* qcow2-cluster.c functions */ > -int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, > +int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size, > bool exact_size); > int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index); > void qcow2_l2_cache_reset(BlockDriverState *bs); > -- > 1.8.3.1 >