Patchwork [18/20] mirror: add support for persistent dirty bitmap

login
register
mail settings
Submitter Paolo Bonzini
Date Dec. 12, 2012, 1:46 p.m.
Message ID <1355319999-30627-19-git-send-email-pbonzini@redhat.com>
Download mbox | patch
Permalink /patch/205526/
State New
Headers show

Comments

Paolo Bonzini - Dec. 12, 2012, 1:46 p.m.
A persistent dirty bitmap lets mirroring proceed with no waste of work
after QEMU exits (either offline, or online when the VM restarts).
It is also useful in order to communicate to management whether the
switch to the destination was completed or not.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 block/mirror.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
Eric Blake - Dec. 20, 2012, 11:49 p.m.
On 12/12/2012 06:46 AM, Paolo Bonzini wrote:
> A persistent dirty bitmap lets mirroring proceed with no waste of work
> after QEMU exits (either offline, or online when the VM restarts).
> It is also useful in order to communicate to management whether the
> switch to the destination was completed or not.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  block/mirror.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)

Sure tiny for what it adds :)

Reviewed-by: Eric Blake <eblake@redhat.com>

Patch

diff --git a/block/mirror.c b/block/mirror.c
index 99c5bd1..3d37396 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -351,6 +351,18 @@  static void coroutine_fn mirror_run(void *opaque)
         }
     }
 
+    /*
+     * Ensure the set bits have reached the persistent dirty bitmap before
+     * moving on.  This covers the case where no I/O happens between the
+     * beginning of mirroring and block-job-complete, but there were indeed
+     * some dirty sectors.  In this case, the persistent dirty bitmap could end
+     * up staying all-zeroes all the time!
+     */
+    ret = bdrv_flush_dirty_tracking(bs, true);
+    if (ret < 0) {
+        goto immediate_exit;
+    }
+
     bdrv_dirty_iter_init(bs, &s->hbi);
     last_pause_ns = qemu_get_clock_ns(rt_clock);
     for (;;) {
@@ -392,6 +404,9 @@  static void coroutine_fn mirror_run(void *opaque)
                     break;
                 }
             } else {
+                ret = bdrv_flush_dirty_tracking(bs, false);
+                assert(ret >= 0);
+
                 /* We're out of the streaming phase.  From now on, if the job
                  * is cancelled we will actually complete all pending I/O and
                  * report completion.  This way, block-job-cancel will leave