qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 17/23] qcow2: Support updating driver-specific options in reopen
Date: Fri, 11 Sep 2015 21:40:57 +0200	[thread overview]
Message-ID: <1442000463-22777-18-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1442000463-22777-1-git-send-email-kwolf@redhat.com>

For updating the cache sizes, disabling lazy refcounts and updating the
clean_cache_timer there is a bit more to do than just changing the
variables, but otherwise we're all set for changing options during
bdrv_reopen().

Just implement the missing pieces and hook the functions up in
bdrv_reopen().

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 block/qcow2.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 72 insertions(+), 9 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 64ba3cb..56ad808 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -649,7 +649,24 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
         goto fail;
     }
 
-    /* alloc L2 table/refcount block cache */
+    /* alloc new L2 table/refcount block cache, flush old one */
+    if (s->l2_table_cache) {
+        ret = qcow2_cache_flush(bs, s->l2_table_cache);
+        if (ret) {
+            error_setg_errno(errp, -ret, "Failed to flush the L2 table cache");
+            goto fail;
+        }
+    }
+
+    if (s->refcount_block_cache) {
+        ret = qcow2_cache_flush(bs, s->refcount_block_cache);
+        if (ret) {
+            error_setg_errno(errp, -ret,
+                             "Failed to flush the refcount block cache");
+            goto fail;
+        }
+    }
+
     r->l2_table_cache = qcow2_cache_create(bs, l2_cache_size);
     r->refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size);
     if (r->l2_table_cache == NULL || r->refcount_block_cache == NULL) {
@@ -660,14 +677,15 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
 
     /* New interval for cache cleanup timer */
     r->cache_clean_interval =
-        qemu_opt_get_number(opts, QCOW2_OPT_CACHE_CLEAN_INTERVAL, 0);
+        qemu_opt_get_number(opts, QCOW2_OPT_CACHE_CLEAN_INTERVAL,
+                            s->cache_clean_interval);
     if (r->cache_clean_interval > UINT_MAX) {
         error_setg(errp, "Cache clean interval too big");
         ret = -EINVAL;
         goto fail;
     }
 
-    /* Enable lazy_refcounts according to image and command line options */
+    /* lazy-refcounts; flush if going from enabled to disabled */
     r->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
         (s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
     if (r->use_lazy_refcounts && s->qcow_version < 3) {
@@ -677,6 +695,14 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
         goto fail;
     }
 
+    if (s->use_lazy_refcounts && !r->use_lazy_refcounts) {
+        ret = qcow2_mark_clean(bs);
+        if (ret < 0) {
+            error_setg_errno(errp, -ret, "Failed to disable lazy refcounts");
+            goto fail;
+        }
+    }
+
     /* Overlap check options */
     opt_overlap_check = qemu_opt_get(opts, QCOW2_OPT_OVERLAP);
     opt_overlap_check_template = qemu_opt_get(opts, QCOW2_OPT_OVERLAP_TEMPLATE);
@@ -741,6 +767,12 @@ static void qcow2_update_options_commit(BlockDriverState *bs,
     BDRVQcow2State *s = bs->opaque;
     int i;
 
+    if (s->l2_table_cache) {
+        qcow2_cache_destroy(bs, s->l2_table_cache);
+    }
+    if (s->refcount_block_cache) {
+        qcow2_cache_destroy(bs, s->refcount_block_cache);
+    }
     s->l2_table_cache = r->l2_table_cache;
     s->refcount_block_cache = r->refcount_block_cache;
 
@@ -751,8 +783,11 @@ static void qcow2_update_options_commit(BlockDriverState *bs,
         s->discard_passthrough[i] = r->discard_passthrough[i];
     }
 
-    s->cache_clean_interval = r->cache_clean_interval;
-    cache_clean_timer_init(bs, bdrv_get_aio_context(bs));
+    if (s->cache_clean_interval != r->cache_clean_interval) {
+        cache_clean_timer_del(bs);
+        s->cache_clean_interval = r->cache_clean_interval;
+        cache_clean_timer_init(bs, bdrv_get_aio_context(bs));
+    }
 }
 
 static void qcow2_update_options_abort(BlockDriverState *bs,
@@ -1199,26 +1234,52 @@ static int qcow2_set_key(BlockDriverState *bs, const char *key)
     return 0;
 }
 
-/* We have no actual commit/abort logic for qcow2, but we need to write out any
- * unwritten data if we reopen read-only. */
 static int qcow2_reopen_prepare(BDRVReopenState *state,
                                 BlockReopenQueue *queue, Error **errp)
 {
+    Qcow2ReopenState *r;
     int ret;
 
+    r = g_new0(Qcow2ReopenState, 1);
+    state->opaque = r;
+
+    ret = qcow2_update_options_prepare(state->bs, r, state->options,
+                                       state->flags, errp);
+    if (ret < 0) {
+        goto fail;
+    }
+
+    /* We need to write out any unwritten data if we reopen read-only. */
     if ((state->flags & BDRV_O_RDWR) == 0) {
         ret = bdrv_flush(state->bs);
         if (ret < 0) {
-            return ret;
+            goto fail;
         }
 
         ret = qcow2_mark_clean(state->bs);
         if (ret < 0) {
-            return ret;
+            goto fail;
         }
     }
 
     return 0;
+
+fail:
+    qcow2_update_options_abort(state->bs, r);
+    g_free(r);
+    return ret;
+}
+
+static void qcow2_reopen_commit(BDRVReopenState *state)
+{
+    qcow2_update_options_commit(state->bs, state->opaque);
+    g_free(state->opaque);
+}
+
+static void qcow2_reopen_abort(BDRVReopenState *state)
+{
+    qcow2_update_options_abort(state->bs, state->opaque);
+    g_free(state->opaque);
 }
 
 static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
@@ -3082,6 +3143,8 @@ BlockDriver bdrv_qcow2 = {
     .bdrv_open          = qcow2_open,
     .bdrv_close         = qcow2_close,
     .bdrv_reopen_prepare  = qcow2_reopen_prepare,
+    .bdrv_reopen_commit   = qcow2_reopen_commit,
+    .bdrv_reopen_abort    = qcow2_reopen_abort,
     .bdrv_create        = qcow2_create,
     .bdrv_has_zero_init = bdrv_has_zero_init_1,
     .bdrv_co_get_block_status = qcow2_co_get_block_status,
-- 
1.8.3.1

  parent reply	other threads:[~2015-09-11 19:48 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-11 19:40 [Qemu-devel] [PULL 00/23] Block layer patches Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 01/23] block: Always pass NULL as drv for bdrv_open() Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 02/23] block: Drop drv parameter from bdrv_open() Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 03/23] block: Drop drv parameter from bdrv_open_inherit() Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 04/23] block: Drop drv parameter from bdrv_fill_options() Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 05/23] block: Drop bdrv_find_whitelisted_format() Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 06/23] qcow2: Rename BDRVQcowState to BDRVQcow2State Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 07/23] block: Allow specifying driver-specific options to reopen Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 08/23] qemu-io: Remove duplicate 'open' error message Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 09/23] qemu-io: Add command 'reopen' Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 10/23] qcow2: Improve error message Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 11/23] qcow2: Factor out qcow2_update_options() Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 12/23] qcow2: Move qcow2_update_options() call up Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 13/23] qcow2: Move rest of option handling to qcow2_update_options() Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 14/23] qcow2: Leave s unchanged on qcow2_update_options() failure Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 15/23] qcow2: Fix memory leak in qcow2_update_options() error path Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 16/23] qcow2: Make qcow2_update_options() suitable for transactions Kevin Wolf
2015-09-11 19:40 ` Kevin Wolf [this message]
2015-09-11 19:40 ` [Qemu-devel] [PULL 18/23] qemu-iotests: Reopen qcow2 with lazy-refcounts change Kevin Wolf
2015-09-11 19:40 ` [Qemu-devel] [PULL 19/23] qemu-iotests: More qcow2 reopen tests Kevin Wolf
2015-09-11 19:41 ` [Qemu-devel] [PULL 20/23] qcow2: Make size_to_clusters() return uint64_t Kevin Wolf
2015-09-11 19:41 ` [Qemu-devel] [PULL 21/23] iotests: Add test for checking large image files Kevin Wolf
2015-09-11 19:41 ` [Qemu-devel] [PULL 22/23] vmdk: Fix next_cluster_sector for compressed write Kevin Wolf
2015-09-11 19:41 ` [Qemu-devel] [PULL 23/23] qcow2: Make qcow2_alloc_bytes() more explicit Kevin Wolf
2015-09-14  9:46 ` [Qemu-devel] [PULL 00/23] Block layer patches Peter Maydell
2015-09-14  9:57   ` Kevin Wolf
2015-09-14 14:36     ` Max Reitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1442000463-22777-18-git-send-email-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).