From 789d0334d894eaea6a5ca35538926bbb63a9cea3 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 9 Sep 2013 14:28:01 +0200 Subject: [PATCH 10/38] qcow2: Options to enable discard for freed clusters RH-Author: Kevin Wolf Message-id: <1378736903-18489-11-git-send-email-kwolf@redhat.com> Patchwork-id: 54195 O-Subject: [RHEL-7.0 qemu-kvm PATCH 10/32] qcow2: Options to enable discard for freed clusters Bugzilla: 1005818 RH-Acked-by: Fam Zheng RH-Acked-by: Max Reitz RH-Acked-by: Miroslav Rezanina Bugzilla: 1005818 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 Signed-off-by: Stefan Hajnoczi (cherry picked from commit 67af674e478054086f972811dd0a11289afa39a9) Signed-off-by: Kevin Wolf --- block/qcow2-refcount.c | 5 +++++ block/qcow2.c | 26 ++++++++++++++++++++++++++ block/qcow2.h | 5 +++++ 3 files changed, 36 insertions(+) Signed-off-by: Miroslav Rezanina --- block/qcow2-refcount.c | 5 +++++ block/qcow2.c | 26 ++++++++++++++++++++++++++ block/qcow2.h | 5 +++++ 3 files changed, 36 insertions(+), 0 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 6d35e49..7488988 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -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; diff --git a/block/qcow2.c b/block/qcow2.c index e28ea47..ef8a2ca 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -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) { diff --git a/block/qcow2.h b/block/qcow2.h index 64a6479..6f91b9a 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -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; -- 1.7.1