qcow2: Options to enable discard for freed clusters
Deleted snapshots are discarded in the image file by default, discard requests take their default from the -drive discard=... option and other places that free clusters must always be enabled explicitly. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
6cfcb9b8b9
commit
67af674e47
@ -488,6 +488,11 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
|
||||
s->free_cluster_index = cluster_index;
|
||||
}
|
||||
refcount_block[block_index] = cpu_to_be16(refcount);
|
||||
if (refcount == 0 && s->discard_passthrough[type]) {
|
||||
/* Try discarding, ignore errors */
|
||||
/* FIXME Doing this cluster by cluster will be painfully slow */
|
||||
bdrv_discard(bs->file, cluster_offset, 1);
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
@ -295,6 +295,22 @@ static QemuOptsList qcow2_runtime_opts = {
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "Postpone refcount updates",
|
||||
},
|
||||
{
|
||||
.name = QCOW2_OPT_DISCARD_REQUEST,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "Pass guest discard requests to the layer below",
|
||||
},
|
||||
{
|
||||
.name = QCOW2_OPT_DISCARD_SNAPSHOT,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "Generate discard requests when snapshot related space "
|
||||
"is freed",
|
||||
},
|
||||
{
|
||||
.name = QCOW2_OPT_DISCARD_OTHER,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "Generate discard requests when other clusters are freed",
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
};
|
||||
@ -532,6 +548,16 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags)
|
||||
s->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
|
||||
(s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
|
||||
|
||||
s->discard_passthrough[QCOW2_DISCARD_NEVER] = false;
|
||||
s->discard_passthrough[QCOW2_DISCARD_ALWAYS] = true;
|
||||
s->discard_passthrough[QCOW2_DISCARD_REQUEST] =
|
||||
qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_REQUEST,
|
||||
flags & BDRV_O_UNMAP);
|
||||
s->discard_passthrough[QCOW2_DISCARD_SNAPSHOT] =
|
||||
qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_SNAPSHOT, true);
|
||||
s->discard_passthrough[QCOW2_DISCARD_OTHER] =
|
||||
qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
|
||||
|
||||
qemu_opts_del(opts);
|
||||
|
||||
if (s->use_lazy_refcounts && s->qcow_version < 3) {
|
||||
|
@ -60,6 +60,9 @@
|
||||
|
||||
|
||||
#define QCOW2_OPT_LAZY_REFCOUNTS "lazy_refcounts"
|
||||
#define QCOW2_OPT_DISCARD_REQUEST "pass_discard_request"
|
||||
#define QCOW2_OPT_DISCARD_SNAPSHOT "pass_discard_snapshot"
|
||||
#define QCOW2_OPT_DISCARD_OTHER "pass_discard_other"
|
||||
|
||||
typedef struct QCowHeader {
|
||||
uint32_t magic;
|
||||
@ -187,6 +190,8 @@ typedef struct BDRVQcowState {
|
||||
int qcow_version;
|
||||
bool use_lazy_refcounts;
|
||||
|
||||
bool discard_passthrough[QCOW2_DISCARD_MAX];
|
||||
|
||||
uint64_t incompatible_features;
|
||||
uint64_t compatible_features;
|
||||
uint64_t autoclear_features;
|
||||
|
Loading…
Reference in New Issue
Block a user