All of lore.kernel.org
 help / color / mirror / Atom feed
From: Fam Zheng <famz@redhat.com>
To: John Snow <jsnow@redhat.com>
Cc: kwolf@redhat.com, qemu-devel@nongnu.org, armbru@redhat.com,
	mreitz@redhat.com, vsementsov@parallels.com, stefanha@redhat.com
Subject: Re: [Qemu-devel] [PATCH v11 09/13] qmp: Add support of "dirty-bitmap" sync mode for drive-backup
Date: Wed, 14 Jan 2015 14:29:54 +0800	[thread overview]
Message-ID: <20150114062954.GA10255@fam-t430.nay.redhat.com> (raw)
In-Reply-To: <54B55AFD.1050401@redhat.com>

On Tue, 01/13 12:50, John Snow wrote:
> 
> 
> On 01/13/2015 04:37 AM, Fam Zheng wrote:
> >On Mon, 01/12 11:31, John Snow wrote:
> >>For "dirty-bitmap" sync mode, the block job will iterate through the
> >>given dirty bitmap to decide if a sector needs backup (backup all the
> >>dirty clusters and skip clean ones), just as allocation conditions of
> >>"top" sync mode.
> >>
> >>Signed-off-by: Fam Zheng <famz@redhat.com>
> >>Signed-off-by: John Snow <jsnow@redhat.com>
> >>---
> >>  block.c                   |   5 ++
> >>  block/backup.c            | 120 ++++++++++++++++++++++++++++++++++++++--------
> >>  block/mirror.c            |   4 ++
> >>  blockdev.c                |  14 +++++-
> >>  hmp.c                     |   3 +-
> >>  include/block/block.h     |   1 +
> >>  include/block/block_int.h |   2 +
> >>  qapi/block-core.json      |  11 +++--
> >>  qmp-commands.hx           |   7 +--
> >>  9 files changed, 137 insertions(+), 30 deletions(-)
> >>
> >>diff --git a/block.c b/block.c
> >>index 3f33b9d..5eb6788 100644
> >>--- a/block.c
> >>+++ b/block.c
> >>@@ -5633,6 +5633,11 @@ static void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
> >>      }
> >>  }
> >>
> >>+void bdrv_set_dirty_iter(HBitmapIter *hbi, int64_t offset)
> >>+{
> >>+    hbitmap_iter_init(hbi, hbi->hb, offset);
> >
> >What's the reason for this indirection? Can caller just use hbitmap_iter_init?
> >
> 
> Essentially it is just a rename of hbitmap_iter_init to make its usage here
> clear, that we are manually advancing the pointer. How we accomplish that
> (hbitmap_iter_init) is an implementation detail.
> 
> Yes, I can just call this directly from block/backup, but at the time I was
> less sure of how I would advance the pointer, so I created a wrapper where I
> could change details as needed, if I needed to.

OK, either is fine for me.

> 
> >>+}
> >>+
> >>  int64_t bdrv_get_dirty_count(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
> >>  {
> >>      return hbitmap_count(bitmap->bitmap);
> >>diff --git a/block/backup.c b/block/backup.c
> >>index 792e655..0626a3e 100644
> >>--- a/block/backup.c
> >>+++ b/block/backup.c
> >>@@ -37,6 +37,8 @@ typedef struct CowRequest {
> >>  typedef struct BackupBlockJob {
> >>      BlockJob common;
> >>      BlockDriverState *target;
> >>+    /* bitmap for sync=dirty-bitmap */
> >>+    BdrvDirtyBitmap *sync_bitmap;
> >>      MirrorSyncMode sync_mode;
> >>      RateLimit limit;
> >>      BlockdevOnError on_source_error;
> >>@@ -242,6 +244,31 @@ static void backup_complete(BlockJob *job, void *opaque)
> >>      g_free(data);
> >>  }
> >>
> >>+static bool coroutine_fn yield_and_check(BackupBlockJob *job)
> >>+{
> >>+    if (block_job_is_cancelled(&job->common)) {
> >>+        return true;
> >>+    }
> >>+
> >>+    /* we need to yield so that qemu_aio_flush() returns.
> >>+     * (without, VM does not reboot)
> >>+     */
> >>+    if (job->common.speed) {
> >>+        uint64_t delay_ns = ratelimit_calculate_delay(&job->limit,
> >>+                                                      job->sectors_read);
> >>+        job->sectors_read = 0;
> >>+        block_job_sleep_ns(&job->common, QEMU_CLOCK_REALTIME, delay_ns);
> >>+    } else {
> >>+        block_job_sleep_ns(&job->common, QEMU_CLOCK_REALTIME, 0);
> >>+    }
> >>+
> >>+    if (block_job_is_cancelled(&job->common)) {
> >>+        return true;
> >>+    }
> >>+
> >>+    return false;
> >>+}
> >>+
> >>  static void coroutine_fn backup_run(void *opaque)
> >>  {
> >>      BackupBlockJob *job = opaque;
> >>@@ -254,13 +281,13 @@ static void coroutine_fn backup_run(void *opaque)
> >>      };
> >>      int64_t start, end;
> >>      int ret = 0;
> >>+    bool error_is_read;
> >>
> >>      QLIST_INIT(&job->inflight_reqs);
> >>      qemu_co_rwlock_init(&job->flush_rwlock);
> >>
> >>      start = 0;
> >>-    end = DIV_ROUND_UP(job->common.len / BDRV_SECTOR_SIZE,
> >>-                       BACKUP_SECTORS_PER_CLUSTER);
> >>+    end = DIV_ROUND_UP(job->common.len, BACKUP_CLUSTER_SIZE);
> >>
> >>      job->bitmap = hbitmap_alloc(end, 0);
> >>
> >>@@ -278,28 +305,45 @@ static void coroutine_fn backup_run(void *opaque)
> >>              qemu_coroutine_yield();
> >>              job->common.busy = true;
> >>          }
> >>+    } else if (job->sync_mode == MIRROR_SYNC_MODE_DIRTY_BITMAP) {
> >>+        /* Dirty Bitmap sync has a slightly different iteration method */
> >>+        HBitmapIter hbi;
> >>+        int64_t sector;
> >>+        int64_t cluster;
> >>+        bool polyrhythmic;
> >>+
> >>+        bdrv_dirty_iter_init(bs, job->sync_bitmap, &hbi);
> >>+        /* Does the granularity happen to match our backup cluster size? */
> >>+        polyrhythmic = (bdrv_dirty_bitmap_granularity(bs, job->sync_bitmap) !=
> >>+                        BACKUP_CLUSTER_SIZE);
> >>+
> >>+        /* Find the next dirty /sector/ and copy that /cluster/ */
> >>+        while ((sector = hbitmap_iter_next(&hbi)) != -1) {
> >>+            if (yield_and_check(job)) {
> >>+                goto leave;
> >>+            }
> >>+            cluster = sector / BACKUP_SECTORS_PER_CLUSTER;
> >>+
> >>+            do {
> >>+                ret = backup_do_cow(bs, cluster * BACKUP_SECTORS_PER_CLUSTER,
> >>+                                    BACKUP_SECTORS_PER_CLUSTER, &error_is_read);
> >>+                if ((ret < 0) &&
> >>+                    backup_error_action(job, error_is_read, -ret) ==
> >>+                    BLOCK_ERROR_ACTION_REPORT) {
> >>+                    goto leave;
> >>+                }
> >>+            } while (ret < 0);
> >>+
> >>+            /* Advance (or rewind) our iterator if we need to. */
> >>+            if (polyrhythmic) {
> >>+                bdrv_set_dirty_iter(&hbi,
> >>+                                    (cluster + 1) * BACKUP_SECTORS_PER_CLUSTER);
> >>+            }
> >>+        }
> >>      } else {
> >>          /* Both FULL and TOP SYNC_MODE's require copying.. */
> >>          for (; start < end; start++) {
> >>-            bool error_is_read;
> >>-
> >>-            if (block_job_is_cancelled(&job->common)) {
> >>-                break;
> >>-            }
> >>-
> >>-            /* we need to yield so that qemu_aio_flush() returns.
> >>-             * (without, VM does not reboot)
> >>-             */
> >>-            if (job->common.speed) {
> >>-                uint64_t delay_ns = ratelimit_calculate_delay(
> >>-                        &job->limit, job->sectors_read);
> >>-                job->sectors_read = 0;
> >>-                block_job_sleep_ns(&job->common, QEMU_CLOCK_REALTIME, delay_ns);
> >>-            } else {
> >>-                block_job_sleep_ns(&job->common, QEMU_CLOCK_REALTIME, 0);
> >>-            }
> >>-
> >>-            if (block_job_is_cancelled(&job->common)) {
> >>+            if (yield_and_check(job)) {
> >>                  break;
> >>              }
> >>
> >>@@ -351,12 +395,23 @@ static void coroutine_fn backup_run(void *opaque)
> >>          }
> >>      }
> >>
> >>+leave:
> >>      notifier_with_return_remove(&before_write);
> >>
> >>      /* wait until pending backup_do_cow() calls have completed */
> >>      qemu_co_rwlock_wrlock(&job->flush_rwlock);
> >>      qemu_co_rwlock_unlock(&job->flush_rwlock);
> >>
> >>+    if (job->sync_bitmap) {
> >>+        if (ret < 0) {
> >>+            /* Merge the successor back into the parent, delete nothing. */
> >>+            assert(bdrv_reclaim_dirty_bitmap(bs, job->sync_bitmap, NULL));
> >
> >Why can't reclaim fail here? If we canassert, please move the expression out
> >because it has a side effect.
> >
> 
> It shouldn't fail; if it does, something went very wrong. The only chance
> this has to fail is if the sync bitmap has no successor, but we explicitly
> installed one (and explicitly check that it succeeded) before going into the
> block backup.
> 
> I am not sure what other meaningful recovery could happen in this case,
> though we *could* just report an error and continue on, acknowledging that
> the BdrvDirtyBitmap is now compromised and of questionable validity.
> 
> Does anyone have an error handling preference here?

I don't, as long as you move it out from assert:

int r = bdrv_reclaim_dirty_bitmap(bs, job->sync_bitmap, NULL);
assert(r);

Fam

  reply	other threads:[~2015-01-14  6:30 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-12 16:30 [Qemu-devel] [PATCH v11 00/13] block: Incremental backup series John Snow
2015-01-12 16:30 ` [Qemu-devel] [PATCH v11 01/13] block: fix spoiling all dirty bitmaps by mirror and migration John Snow
2015-01-13 15:54   ` Vladimir Sementsov-Ogievskiy
2015-01-12 16:30 ` [Qemu-devel] [PATCH v11 02/13] qapi: Add optional field "name" to block dirty bitmap John Snow
2015-01-12 16:30 ` [Qemu-devel] [PATCH v11 03/13] qmp: Add block-dirty-bitmap-add and block-dirty-bitmap-remove John Snow
2015-01-16 15:36   ` Max Reitz
2015-01-16 16:48     ` John Snow
2015-01-16 16:51       ` Max Reitz
2015-01-16 16:54         ` John Snow
2015-01-19 10:08       ` Markus Armbruster
2015-01-19 21:05         ` John Snow
2015-01-20  8:26           ` Markus Armbruster
2015-01-20 16:48             ` John Snow
2015-01-21  9:34               ` Markus Armbruster
2015-01-21 15:51                 ` Eric Blake
2015-01-30 14:32                 ` Kevin Wolf
2015-01-30 17:04                   ` John Snow
2015-01-30 18:52                     ` Kevin Wolf
2015-02-02 10:10                       ` Markus Armbruster
2015-02-02 21:40                         ` John Snow
2015-01-29 13:55   ` Vladimir Sementsov-Ogievskiy
2015-01-12 16:30 ` [Qemu-devel] [PATCH v11 04/13] block: Introduce bdrv_dirty_bitmap_granularity() John Snow
2015-01-16 15:40   ` Max Reitz
2015-01-12 16:30 ` [Qemu-devel] [PATCH v11 05/13] block: Add bdrv_clear_dirty_bitmap John Snow
2015-01-16 15:56   ` Max Reitz
2015-01-12 16:30 ` [Qemu-devel] [PATCH v11 06/13] hbitmap: add hbitmap_merge John Snow
2015-01-16 16:12   ` Max Reitz
2015-01-12 16:30 ` [Qemu-devel] [PATCH v11 07/13] qmp: Add block-dirty-bitmap-enable and block-dirty-bitmap-disable John Snow
2015-01-16 16:28   ` Max Reitz
2015-01-16 17:09     ` John Snow
2015-01-12 16:31 ` [Qemu-devel] [PATCH v11 08/13] block: Add bitmap successors John Snow
2015-01-13  9:24   ` Fam Zheng
2015-01-13 17:26     ` John Snow
2015-01-16 18:22     ` John Snow
2015-01-19  1:00       ` Fam Zheng
2015-01-12 16:31 ` [Qemu-devel] [PATCH v11 09/13] qmp: Add support of "dirty-bitmap" sync mode for drive-backup John Snow
2015-01-13  9:37   ` Fam Zheng
2015-01-13 17:50     ` John Snow
2015-01-14  6:29       ` Fam Zheng [this message]
2015-01-16 17:52   ` Max Reitz
2015-01-16 17:59     ` John Snow
2015-01-12 16:31 ` [Qemu-devel] [PATCH v11 10/13] qapi: Add transaction support to block-dirty-bitmap-{add, enable, disable} John Snow
2015-01-12 16:31 ` [Qemu-devel] [PATCH v11 11/13] qmp: Add dirty bitmap status fields in query-block John Snow
2015-01-12 16:31 ` [Qemu-devel] [PATCH v11 12/13] qemu-iotests: Add tests for drive-backup sync=dirty-bitmap John Snow
2015-02-06 14:23   ` Vladimir Sementsov-Ogievskiy
2015-02-06 17:14     ` John Snow
2015-01-12 16:31 ` [Qemu-devel] [PATCH v11 13/13] block: BdrvDirtyBitmap miscellaneous fixup John Snow
2015-01-13 16:50   ` Vladimir Sementsov-Ogievskiy
2015-01-13 18:27     ` John Snow
2015-01-13  1:21 ` [Qemu-devel] [PATCH v11 00/13] block: Incremental backup series Fam Zheng
2015-01-13 19:52 ` John Snow
2015-01-29 22:38 ` John Snow
2015-01-30 10:24 ` Vladimir Sementsov-Ogievskiy
2015-01-30 18:46   ` John Snow

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=20150114062954.GA10255@fam-t430.nay.redhat.com \
    --to=famz@redhat.com \
    --cc=armbru@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    --cc=vsementsov@parallels.com \
    /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.