@@ -31,6 +31,36 @@
#include "block/qcow2.h"
#include "trace.h"
+int shrink_l1_table(BlockDriverState *bs, int64_t new_l1_size)
+{
+ BDRVQcow2State *s = bs->opaque;
+ int64_t old_l1_size = s->l1_size;
+ s->l1_size = new_l1_size;
+ int ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset,
+ s->l1_size, 1);
+ if(ret < 0){
+ return ret;
+ }
+
+ s->l1_size = old_l1_size;
+ ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset,
+ s->l1_size, -1);
+ if(ret < 0){
+ return ret;
+ }
+ s->l1_size = new_l1_size;
+
+ uint32_t be_l1_size = cpu_to_be32(s->l1_size);
+ ret = bdrv_pwrite_sync(bs->file->bs, offsetof(QCowHeader, l1_size),
+ &be_l1_size, sizeof(be_l1_size));
+ if (ret < 0) {
+ return ret;
+ }
+ // realloc l1 table ?
+
+ return 0;
+}
+
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
bool exact_size)
{
@@ -2516,9 +2516,16 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
}
new_l1_size = size_to_l1(s, offset);
- ret = qcow2_grow_l1_table(bs, new_l1_size, true);
- if (ret < 0) {
- return ret;
+ if(offset < bs->total_sectors * 512){
+ ret = shrink_l1_table(bs, new_l1_size);
+ if (ret < 0) {
+ return ret;
+ }
+ } else {
+ ret = qcow2_grow_l1_table(bs, new_l1_size, true);
+ if (ret < 0) {
+ return ret;
+ }
}
/* write updated header.size */
@@ -534,6 +534,7 @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
void *cb_opaque, Error **errp);
/* qcow2-cluster.c functions */
+int shrink_l1_table(BlockDriverState *bs, int64_t new_l1_size);
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
bool exact_size);
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);