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

Submitted by Paolo Bonzini on Dec. 12, 2012, 1:46 p.m.

Details

Message ID 1355319999-30627-19-git-send-email-pbonzini@redhat.com
State New
Headers show

Commit Message

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(+)

Comments

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 hide | download patch | download mbox

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