Commit 67af674e authored by Kevin Wolf's avatar Kevin Wolf Committed by Stefan Hajnoczi
Browse files

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: default avatarKevin Wolf <kwolf@redhat.com>
Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
parent 6cfcb9b8
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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;
+26 −0
Original line number Diff line number Diff line
@@ -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) {
+5 −0
Original line number Diff line number Diff line
@@ -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;