|
@@ -682,6 +682,7 @@ static const char *const mutable_opts[] = {
|
|
QCOW2_OPT_DISCARD_REQUEST,
|
|
QCOW2_OPT_DISCARD_REQUEST,
|
|
QCOW2_OPT_DISCARD_SNAPSHOT,
|
|
QCOW2_OPT_DISCARD_SNAPSHOT,
|
|
QCOW2_OPT_DISCARD_OTHER,
|
|
QCOW2_OPT_DISCARD_OTHER,
|
|
|
|
+ QCOW2_OPT_DISCARD_NO_UNREF,
|
|
QCOW2_OPT_OVERLAP,
|
|
QCOW2_OPT_OVERLAP,
|
|
QCOW2_OPT_OVERLAP_TEMPLATE,
|
|
QCOW2_OPT_OVERLAP_TEMPLATE,
|
|
QCOW2_OPT_OVERLAP_MAIN_HEADER,
|
|
QCOW2_OPT_OVERLAP_MAIN_HEADER,
|
|
@@ -726,6 +727,11 @@ static QemuOptsList qcow2_runtime_opts = {
|
|
.type = QEMU_OPT_BOOL,
|
|
.type = QEMU_OPT_BOOL,
|
|
.help = "Generate discard requests when other clusters are freed",
|
|
.help = "Generate discard requests when other clusters are freed",
|
|
},
|
|
},
|
|
|
|
+ {
|
|
|
|
+ .name = QCOW2_OPT_DISCARD_NO_UNREF,
|
|
|
|
+ .type = QEMU_OPT_BOOL,
|
|
|
|
+ .help = "Do not unreference discarded clusters",
|
|
|
|
+ },
|
|
{
|
|
{
|
|
.name = QCOW2_OPT_OVERLAP,
|
|
.name = QCOW2_OPT_OVERLAP,
|
|
.type = QEMU_OPT_STRING,
|
|
.type = QEMU_OPT_STRING,
|
|
@@ -969,6 +975,7 @@ typedef struct Qcow2ReopenState {
|
|
bool use_lazy_refcounts;
|
|
bool use_lazy_refcounts;
|
|
int overlap_check;
|
|
int overlap_check;
|
|
bool discard_passthrough[QCOW2_DISCARD_MAX];
|
|
bool discard_passthrough[QCOW2_DISCARD_MAX];
|
|
|
|
+ bool discard_no_unref;
|
|
uint64_t cache_clean_interval;
|
|
uint64_t cache_clean_interval;
|
|
QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */
|
|
QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */
|
|
} Qcow2ReopenState;
|
|
} Qcow2ReopenState;
|
|
@@ -1140,6 +1147,15 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
|
|
r->discard_passthrough[QCOW2_DISCARD_OTHER] =
|
|
r->discard_passthrough[QCOW2_DISCARD_OTHER] =
|
|
qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
|
|
qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
|
|
|
|
|
|
|
|
+ r->discard_no_unref = qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_NO_UNREF,
|
|
|
|
+ false);
|
|
|
|
+ if (r->discard_no_unref && s->qcow_version < 3) {
|
|
|
|
+ error_setg(errp,
|
|
|
|
+ "discard-no-unref is only supported since qcow2 version 3");
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ goto fail;
|
|
|
|
+ }
|
|
|
|
+
|
|
switch (s->crypt_method_header) {
|
|
switch (s->crypt_method_header) {
|
|
case QCOW_CRYPT_NONE:
|
|
case QCOW_CRYPT_NONE:
|
|
if (encryptfmt) {
|
|
if (encryptfmt) {
|
|
@@ -1220,6 +1236,8 @@ static void qcow2_update_options_commit(BlockDriverState *bs,
|
|
s->discard_passthrough[i] = r->discard_passthrough[i];
|
|
s->discard_passthrough[i] = r->discard_passthrough[i];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ s->discard_no_unref = r->discard_no_unref;
|
|
|
|
+
|
|
if (s->cache_clean_interval != r->cache_clean_interval) {
|
|
if (s->cache_clean_interval != r->cache_clean_interval) {
|
|
cache_clean_timer_del(bs);
|
|
cache_clean_timer_del(bs);
|
|
s->cache_clean_interval = r->cache_clean_interval;
|
|
s->cache_clean_interval = r->cache_clean_interval;
|