mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 23:33:54 -06:00
qcow2: add shrink image support
This patch add shrinking of the image file for qcow2. As a result, this allows us to reduce the virtual image size and free up space on the disk without copying the image. Image can be fragmented and shrink is done by punching holes in the image file. Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Reviewed-by: John Snow <jsnow@redhat.com> Message-id: 20170918124230.8152-4-pbutsykin@virtuozzo.com Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
parent
f71c08ea8e
commit
46b732cdf3
5 changed files with 227 additions and 12 deletions
|
@ -32,6 +32,56 @@
|
|||
#include "qemu/bswap.h"
|
||||
#include "trace.h"
|
||||
|
||||
int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t exact_size)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
int new_l1_size, i, ret;
|
||||
|
||||
if (exact_size >= s->l1_size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
new_l1_size = exact_size;
|
||||
|
||||
#ifdef DEBUG_ALLOC2
|
||||
fprintf(stderr, "shrink l1_table from %d to %d\n", s->l1_size, new_l1_size);
|
||||
#endif
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_WRITE_TABLE);
|
||||
ret = bdrv_pwrite_zeroes(bs->file, s->l1_table_offset +
|
||||
new_l1_size * sizeof(uint64_t),
|
||||
(s->l1_size - new_l1_size) * sizeof(uint64_t), 0);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_flush(bs->file->bs);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_FREE_L2_CLUSTERS);
|
||||
for (i = s->l1_size - 1; i > new_l1_size - 1; i--) {
|
||||
if ((s->l1_table[i] & L1E_OFFSET_MASK) == 0) {
|
||||
continue;
|
||||
}
|
||||
qcow2_free_clusters(bs, s->l1_table[i] & L1E_OFFSET_MASK,
|
||||
s->cluster_size, QCOW2_DISCARD_ALWAYS);
|
||||
s->l1_table[i] = 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
/*
|
||||
* If the write in the l1_table failed the image may contain a partially
|
||||
* overwritten l1_table. In this case it would be better to clear the
|
||||
* l1_table in memory to avoid possible image corruption.
|
||||
*/
|
||||
memset(s->l1_table + new_l1_size, 0,
|
||||
(s->l1_size - new_l1_size) * sizeof(uint64_t));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
||||
bool exact_size)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue