All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.