All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/3] qapi: block-dirty-bitmap-remove transaction action
@ 2019-07-01 20:13 John Snow
  2019-07-01 20:13 ` [Qemu-devel] [PATCH v2 1/3] blockdev: reduce aio_context locked sections in bitmap add/remove John Snow
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: John Snow @ 2019-07-01 20:13 UTC (permalink / raw)
  To: qemu-block, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, vsementsov, Juan Quintela,
	Markus Armbruster, Max Reitz, Stefan Hajnoczi, John Snow,
	Dr. David Alan Gilbert

Hi, this is a proposal based off of Vladimir's patchset:
[Qemu-devel] [PATCH 0/4] qapi: block-dirty-bitmap-remove transaction action

It replaces patches two and three with a modified patch (now patch 2)
that foregoes the need for a hide()/unhide() bitmap API. I think it's
suitable as a smaller alternative, but I'm not sure if it covers all
of the use cases of the original series.

Patches 1 and 3 (formerly 4) included as-is.

John Snow (1):
  qapi: implement block-dirty-bitmap-remove transaction action

Vladimir Sementsov-Ogievskiy (2):
  blockdev: reduce aio_context locked sections in bitmap add/remove
  iotests: test bitmap moving inside 254

 qapi/transaction.json          |   2 +
 include/block/dirty-bitmap.h   |   3 +-
 block.c                        |   2 +-
 block/dirty-bitmap.c           |  16 ++---
 blockdev.c                     | 105 ++++++++++++++++++++++++++-------
 migration/block-dirty-bitmap.c |   2 +-
 tests/qemu-iotests/254         |  30 +++++++++-
 tests/qemu-iotests/254.out     |  82 +++++++++++++++++++++++++
 8 files changed, 208 insertions(+), 34 deletions(-)

-- 
2.21.0



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH v2 1/3] blockdev: reduce aio_context locked sections in bitmap add/remove
  2019-07-01 20:13 [Qemu-devel] [PATCH v2 0/3] qapi: block-dirty-bitmap-remove transaction action John Snow
@ 2019-07-01 20:13 ` John Snow
  2019-07-01 20:13 ` [Qemu-devel] [PATCH v2 2/3] qapi: implement block-dirty-bitmap-remove transaction action John Snow
  2019-07-01 20:13 ` [Qemu-devel] [PATCH v2 3/3] iotests: test bitmap moving inside 254 John Snow
  2 siblings, 0 replies; 7+ messages in thread
From: John Snow @ 2019-07-01 20:13 UTC (permalink / raw)
  To: qemu-block, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, vsementsov, Juan Quintela,
	Markus Armbruster, Max Reitz, Stefan Hajnoczi, John Snow,
	Dr. David Alan Gilbert

From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

Commit 0a6c86d024c52 returned these locks back to add/remove
functionality, to protect from intersection of persistent bitmap
related IO with other IO. But other bitmap-related functions called
here are unrelated to the problem, and there are no needs to keep these
calls inside critical sections.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Signed-off-by: John Snow <jsnow@redhat.com>
---
 blockdev.c | 30 +++++++++++++-----------------
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 4d141e9a1f..01248252ca 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2811,7 +2811,6 @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
 {
     BlockDriverState *bs;
     BdrvDirtyBitmap *bitmap;
-    AioContext *aio_context = NULL;
 
     if (!name || name[0] == '\0') {
         error_setg(errp, "Bitmap name cannot be empty");
@@ -2847,16 +2846,20 @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
     }
 
     if (persistent) {
-        aio_context = bdrv_get_aio_context(bs);
+        AioContext *aio_context = bdrv_get_aio_context(bs);
+        bool ok;
+
         aio_context_acquire(aio_context);
-        if (!bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp)) {
-            goto out;
+        ok = bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp);
+        aio_context_release(aio_context);
+        if (!ok) {
+            return;
         }
     }
 
     bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
     if (bitmap == NULL) {
-        goto out;
+        return;
     }
 
     if (disabled) {
@@ -2864,10 +2867,6 @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
     }
 
     bdrv_dirty_bitmap_set_persistence(bitmap, persistent);
- out:
-    if (aio_context) {
-        aio_context_release(aio_context);
-    }
 }
 
 void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
@@ -2875,8 +2874,6 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
 {
     BlockDriverState *bs;
     BdrvDirtyBitmap *bitmap;
-    Error *local_err = NULL;
-    AioContext *aio_context = NULL;
 
     bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
     if (!bitmap || !bs) {
@@ -2889,20 +2886,19 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
     }
 
     if (bdrv_dirty_bitmap_get_persistence(bitmap)) {
-        aio_context = bdrv_get_aio_context(bs);
+        AioContext *aio_context = bdrv_get_aio_context(bs);
+        Error *local_err = NULL;
+
         aio_context_acquire(aio_context);
         bdrv_remove_persistent_dirty_bitmap(bs, name, &local_err);
+        aio_context_release(aio_context);
         if (local_err != NULL) {
             error_propagate(errp, local_err);
-            goto out;
+            return;
         }
     }
 
     bdrv_release_dirty_bitmap(bs, bitmap);
- out:
-    if (aio_context) {
-        aio_context_release(aio_context);
-    }
 }
 
 /**
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH v2 2/3] qapi: implement block-dirty-bitmap-remove transaction action
  2019-07-01 20:13 [Qemu-devel] [PATCH v2 0/3] qapi: block-dirty-bitmap-remove transaction action John Snow
  2019-07-01 20:13 ` [Qemu-devel] [PATCH v2 1/3] blockdev: reduce aio_context locked sections in bitmap add/remove John Snow
@ 2019-07-01 20:13 ` John Snow
  2019-07-03 19:30   ` Max Reitz
  2019-07-01 20:13 ` [Qemu-devel] [PATCH v2 3/3] iotests: test bitmap moving inside 254 John Snow
  2 siblings, 1 reply; 7+ messages in thread
From: John Snow @ 2019-07-01 20:13 UTC (permalink / raw)
  To: qemu-block, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, vsementsov, Juan Quintela,
	Markus Armbruster, Max Reitz, Stefan Hajnoczi, John Snow,
	Dr. David Alan Gilbert

It is used to do transactional movement of the bitmap (which is
possible in conjunction with merge command). Transactional bitmap
movement is needed in scenarios with external snapshot, when we don't
want to leave copy of the bitmap in the base image.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: John Snow <jsnow@redhat.com>
---
 qapi/transaction.json          |  2 +
 include/block/dirty-bitmap.h   |  3 +-
 block.c                        |  2 +-
 block/dirty-bitmap.c           | 16 +++----
 blockdev.c                     | 79 +++++++++++++++++++++++++++++++---
 migration/block-dirty-bitmap.c |  2 +-
 6 files changed, 87 insertions(+), 17 deletions(-)

diff --git a/qapi/transaction.json b/qapi/transaction.json
index 95edb78227..da95b804aa 100644
--- a/qapi/transaction.json
+++ b/qapi/transaction.json
@@ -45,6 +45,7 @@
 #
 # - @abort: since 1.6
 # - @block-dirty-bitmap-add: since 2.5
+# - @block-dirty-bitmap-remove: since 4.1
 # - @block-dirty-bitmap-clear: since 2.5
 # - @block-dirty-bitmap-enable: since 4.0
 # - @block-dirty-bitmap-disable: since 4.0
@@ -61,6 +62,7 @@
   'data': {
        'abort': 'Abort',
        'block-dirty-bitmap-add': 'BlockDirtyBitmapAdd',
+       'block-dirty-bitmap-remove': 'BlockDirtyBitmap',
        'block-dirty-bitmap-clear': 'BlockDirtyBitmap',
        'block-dirty-bitmap-enable': 'BlockDirtyBitmap',
        'block-dirty-bitmap-disable': 'BlockDirtyBitmap',
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
index 62682eb865..aa2737f41e 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -83,7 +83,8 @@ void bdrv_dirty_bitmap_set_inconsistent(BdrvDirtyBitmap *bitmap);
 void bdrv_dirty_bitmap_set_busy(BdrvDirtyBitmap *bitmap, bool busy);
 void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
                              HBitmap **backup, Error **errp);
-void bdrv_dirty_bitmap_set_migration(BdrvDirtyBitmap *bitmap, bool migration);
+void bdrv_dirty_bitmap_squelch_persistence(BdrvDirtyBitmap *bitmap,
+                                           bool squelch);
 
 /* Functions that require manual locking.  */
 void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap);
diff --git a/block.c b/block.c
index c139540f2b..b934c522eb 100644
--- a/block.c
+++ b/block.c
@@ -5316,7 +5316,7 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs,
     for (bm = bdrv_dirty_bitmap_next(bs, NULL); bm;
          bm = bdrv_dirty_bitmap_next(bs, bm))
     {
-        bdrv_dirty_bitmap_set_migration(bm, false);
+        bdrv_dirty_bitmap_squelch_persistence(bm, false);
     }
 
     ret = refresh_total_sectors(bs, bs->total_sectors);
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 95a9c2a5d8..8551f8219e 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -48,10 +48,9 @@ struct BdrvDirtyBitmap {
     bool inconsistent;          /* bitmap is persistent, but inconsistent.
                                    It cannot be used at all in any way, except
                                    a QMP user can remove it. */
-    bool migration;             /* Bitmap is selected for migration, it should
-                                   not be stored on the next inactivation
-                                   (persistent flag doesn't matter until next
-                                   invalidation).*/
+    bool squelch_persistence;   /* We are either migrating or deleting this
+                                 * bitmap; it should not be stored on the next
+                                 * inactivation. */
     QLIST_ENTRY(BdrvDirtyBitmap) list;
 };
 
@@ -757,16 +756,17 @@ void bdrv_dirty_bitmap_set_inconsistent(BdrvDirtyBitmap *bitmap)
 }
 
 /* Called with BQL taken. */
-void bdrv_dirty_bitmap_set_migration(BdrvDirtyBitmap *bitmap, bool migration)
+void bdrv_dirty_bitmap_squelch_persistence(BdrvDirtyBitmap *bitmap,
+                                           bool squelch)
 {
     qemu_mutex_lock(bitmap->mutex);
-    bitmap->migration = migration;
+    bitmap->squelch_persistence = squelch;
     qemu_mutex_unlock(bitmap->mutex);
 }
 
 bool bdrv_dirty_bitmap_get_persistence(BdrvDirtyBitmap *bitmap)
 {
-    return bitmap->persistent && !bitmap->migration;
+    return bitmap->persistent && !bitmap->squelch_persistence;
 }
 
 bool bdrv_dirty_bitmap_inconsistent(const BdrvDirtyBitmap *bitmap)
@@ -778,7 +778,7 @@ bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs)
 {
     BdrvDirtyBitmap *bm;
     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
-        if (bm->persistent && !bm->readonly && !bm->migration) {
+        if (bm->persistent && !bm->readonly && !bm->squelch_persistence) {
             return true;
         }
     }
diff --git a/blockdev.c b/blockdev.c
index 01248252ca..4143ab7bbb 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2134,6 +2134,51 @@ static void block_dirty_bitmap_merge_prepare(BlkActionState *common,
                                                 errp);
 }
 
+static BdrvDirtyBitmap *do_block_dirty_bitmap_remove(
+        const char *node, const char *name, bool release,
+        BlockDriverState **bitmap_bs, Error **errp);
+
+static void block_dirty_bitmap_remove_prepare(BlkActionState *common,
+                                              Error **errp)
+{
+    BlockDirtyBitmap *action;
+    BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
+                                             common, common);
+
+    if (action_check_completion_mode(common, errp) < 0) {
+        return;
+    }
+
+    action = common->action->u.block_dirty_bitmap_remove.data;
+
+    state->bitmap = do_block_dirty_bitmap_remove(action->node, action->name,
+                                                 false, &state->bs, errp);
+    if (state->bitmap) {
+        bdrv_dirty_bitmap_squelch_persistence(state->bitmap, true);
+        bdrv_dirty_bitmap_set_busy(state->bitmap, true);
+    }
+}
+
+static void block_dirty_bitmap_remove_abort(BlkActionState *common)
+{
+    BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
+                                             common, common);
+
+    if (state->bitmap) {
+        bdrv_dirty_bitmap_squelch_persistence(state->bitmap, false);
+        bdrv_dirty_bitmap_set_busy(state->bitmap, false);
+    }
+}
+
+static void block_dirty_bitmap_remove_commit(BlkActionState *common)
+{
+    BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
+                                             common, common);
+
+    bdrv_dirty_bitmap_set_busy(state->bitmap, false);
+    bdrv_release_dirty_bitmap(state->bs, state->bitmap);
+}
+
 static void abort_prepare(BlkActionState *common, Error **errp)
 {
     error_setg(errp, "Transaction aborted using Abort action");
@@ -2211,6 +2256,12 @@ static const BlkActionOps actions[] = {
         .commit = block_dirty_bitmap_free_backup,
         .abort = block_dirty_bitmap_restore,
     },
+    [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_REMOVE] = {
+        .instance_size = sizeof(BlockDirtyBitmapState),
+        .prepare = block_dirty_bitmap_remove_prepare,
+        .commit = block_dirty_bitmap_remove_commit,
+        .abort = block_dirty_bitmap_remove_abort,
+    },
     /* Where are transactions for MIRROR, COMMIT and STREAM?
      * Although these blockjobs use transaction callbacks like the backup job,
      * these jobs do not necessarily adhere to transaction semantics.
@@ -2869,20 +2920,21 @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
     bdrv_dirty_bitmap_set_persistence(bitmap, persistent);
 }
 
-void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
-                                   Error **errp)
+static BdrvDirtyBitmap *do_block_dirty_bitmap_remove(
+        const char *node, const char *name, bool release,
+        BlockDriverState **bitmap_bs, Error **errp)
 {
     BlockDriverState *bs;
     BdrvDirtyBitmap *bitmap;
 
     bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
     if (!bitmap || !bs) {
-        return;
+        return NULL;
     }
 
     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO,
                                 errp)) {
-        return;
+        return NULL;
     }
 
     if (bdrv_dirty_bitmap_get_persistence(bitmap)) {
@@ -2892,13 +2944,28 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
         aio_context_acquire(aio_context);
         bdrv_remove_persistent_dirty_bitmap(bs, name, &local_err);
         aio_context_release(aio_context);
+
         if (local_err != NULL) {
             error_propagate(errp, local_err);
-            return;
+            return NULL;
         }
     }
 
-    bdrv_release_dirty_bitmap(bs, bitmap);
+    if (release) {
+        bdrv_release_dirty_bitmap(bs, bitmap);
+    }
+
+    if (bitmap_bs) {
+        *bitmap_bs = bs;
+    }
+
+    return bitmap;
+}
+
+void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
+                                   Error **errp)
+{
+    do_block_dirty_bitmap_remove(node, name, true, NULL, errp);
 }
 
 /**
diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c
index 4a896a09eb..c742b706a9 100644
--- a/migration/block-dirty-bitmap.c
+++ b/migration/block-dirty-bitmap.c
@@ -326,7 +326,7 @@ static int init_dirty_bitmap_migration(void)
 
     /* unset migration flags here, to not roll back it */
     QSIMPLEQ_FOREACH(dbms, &dirty_bitmap_mig_state.dbms_list, entry) {
-        bdrv_dirty_bitmap_set_migration(dbms->bitmap, true);
+        bdrv_dirty_bitmap_squelch_persistence(dbms->bitmap, true);
     }
 
     if (QSIMPLEQ_EMPTY(&dirty_bitmap_mig_state.dbms_list)) {
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH v2 3/3] iotests: test bitmap moving inside 254
  2019-07-01 20:13 [Qemu-devel] [PATCH v2 0/3] qapi: block-dirty-bitmap-remove transaction action John Snow
  2019-07-01 20:13 ` [Qemu-devel] [PATCH v2 1/3] blockdev: reduce aio_context locked sections in bitmap add/remove John Snow
  2019-07-01 20:13 ` [Qemu-devel] [PATCH v2 2/3] qapi: implement block-dirty-bitmap-remove transaction action John Snow
@ 2019-07-01 20:13 ` John Snow
  2 siblings, 0 replies; 7+ messages in thread
From: John Snow @ 2019-07-01 20:13 UTC (permalink / raw)
  To: qemu-block, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, vsementsov, Juan Quintela,
	Markus Armbruster, Max Reitz, Stefan Hajnoczi, John Snow,
	Dr. David Alan Gilbert

From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

Test persistent bitmap copying with and without removal of original
bitmap.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: John Snow <jsnow@redhat.com>
---
 tests/qemu-iotests/254     | 30 +++++++++++++-
 tests/qemu-iotests/254.out | 82 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 110 insertions(+), 2 deletions(-)

diff --git a/tests/qemu-iotests/254 b/tests/qemu-iotests/254
index 8edba91c5d..9a57bccc26 100755
--- a/tests/qemu-iotests/254
+++ b/tests/qemu-iotests/254
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# Test external snapshot with bitmap copying.
+# Test external snapshot with bitmap copying and moving.
 #
 # Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved.
 #
@@ -32,6 +32,10 @@ vm = iotests.VM().add_drive(disk, opts='node-name=base')
 vm.launch()
 
 vm.qmp_log('block-dirty-bitmap-add', node='drive0', name='bitmap0')
+vm.qmp_log('block-dirty-bitmap-add', node='drive0', name='bitmap1',
+           persistent=True)
+vm.qmp_log('block-dirty-bitmap-add', node='drive0', name='bitmap2',
+           persistent=True)
 
 vm.hmp_qemu_io('drive0', 'write 0 512K')
 
@@ -39,16 +43,38 @@ vm.qmp_log('transaction', indent=2, actions=[
     {'type': 'blockdev-snapshot-sync',
      'data': {'device': 'drive0', 'snapshot-file': top,
               'snapshot-node-name': 'snap'}},
+
+    # copy non-persistent bitmap0
     {'type': 'block-dirty-bitmap-add',
      'data': {'node': 'snap', 'name': 'bitmap0'}},
     {'type': 'block-dirty-bitmap-merge',
      'data': {'node': 'snap', 'target': 'bitmap0',
-              'bitmaps': [{'node': 'base', 'name': 'bitmap0'}]}}
+              'bitmaps': [{'node': 'base', 'name': 'bitmap0'}]}},
+
+    # copy persistent bitmap1, original will be saved to base image
+    {'type': 'block-dirty-bitmap-add',
+     'data': {'node': 'snap', 'name': 'bitmap1', 'persistent': True}},
+    {'type': 'block-dirty-bitmap-merge',
+     'data': {'node': 'snap', 'target': 'bitmap1',
+              'bitmaps': [{'node': 'base', 'name': 'bitmap1'}]}},
+
+    # move persistent bitmap1, original will be removed and not saved
+    # to base image
+    {'type': 'block-dirty-bitmap-add',
+     'data': {'node': 'snap', 'name': 'bitmap2', 'persistent': True}},
+    {'type': 'block-dirty-bitmap-merge',
+     'data': {'node': 'snap', 'target': 'bitmap2',
+              'bitmaps': [{'node': 'base', 'name': 'bitmap2'}]}},
+    {'type': 'block-dirty-bitmap-remove',
+     'data': {'node': 'base', 'name': 'bitmap2'}}
 ], filters=[iotests.filter_qmp_testfiles])
 
 result = vm.qmp('query-block')['return'][0]
 log("query-block: device = {}, node-name = {}, dirty-bitmaps:".format(
     result['device'], result['inserted']['node-name']))
 log(result['dirty-bitmaps'], indent=2)
+log("\nbitmaps in backing image:")
+log(result['inserted']['image']['backing-image']['format-specific'] \
+    ['data']['bitmaps'], indent=2)
 
 vm.shutdown()
diff --git a/tests/qemu-iotests/254.out b/tests/qemu-iotests/254.out
index d7394cf002..d185c0532f 100644
--- a/tests/qemu-iotests/254.out
+++ b/tests/qemu-iotests/254.out
@@ -1,5 +1,9 @@
 {"execute": "block-dirty-bitmap-add", "arguments": {"name": "bitmap0", "node": "drive0"}}
 {"return": {}}
+{"execute": "block-dirty-bitmap-add", "arguments": {"name": "bitmap1", "node": "drive0", "persistent": true}}
+{"return": {}}
+{"execute": "block-dirty-bitmap-add", "arguments": {"name": "bitmap2", "node": "drive0", "persistent": true}}
+{"return": {}}
 {
   "execute": "transaction",
   "arguments": {
@@ -31,6 +35,55 @@
           "target": "bitmap0"
         },
         "type": "block-dirty-bitmap-merge"
+      },
+      {
+        "data": {
+          "name": "bitmap1",
+          "node": "snap",
+          "persistent": true
+        },
+        "type": "block-dirty-bitmap-add"
+      },
+      {
+        "data": {
+          "bitmaps": [
+            {
+              "name": "bitmap1",
+              "node": "base"
+            }
+          ],
+          "node": "snap",
+          "target": "bitmap1"
+        },
+        "type": "block-dirty-bitmap-merge"
+      },
+      {
+        "data": {
+          "name": "bitmap2",
+          "node": "snap",
+          "persistent": true
+        },
+        "type": "block-dirty-bitmap-add"
+      },
+      {
+        "data": {
+          "bitmaps": [
+            {
+              "name": "bitmap2",
+              "node": "base"
+            }
+          ],
+          "node": "snap",
+          "target": "bitmap2"
+        },
+        "type": "block-dirty-bitmap-merge"
+      },
+      {
+        "data": {
+          "name": "bitmap2",
+          "node": "base"
+        },
+        "type": "block-dirty-bitmap-remove"
       }
     ]
   }
@@ -40,6 +93,24 @@
 }
 query-block: device = drive0, node-name = snap, dirty-bitmaps:
 [
+  {
+    "busy": false,
+    "count": 524288,
+    "granularity": 65536,
+    "name": "bitmap2",
+    "persistent": true,
+    "recording": true,
+    "status": "active"
+  },
+  {
+    "busy": false,
+    "count": 524288,
+    "granularity": 65536,
+    "name": "bitmap1",
+    "persistent": true,
+    "recording": true,
+    "status": "active"
+  },
   {
     "busy": false,
     "count": 524288,
@@ -50,3 +121,14 @@ query-block: device = drive0, node-name = snap, dirty-bitmaps:
     "status": "active"
   }
 ]
+
+bitmaps in backing image:
+[
+  {
+    "flags": [
+      "auto"
+    ],
+    "granularity": 65536,
+    "name": "bitmap1"
+  }
+]
-- 
2.21.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/3] qapi: implement block-dirty-bitmap-remove transaction action
  2019-07-01 20:13 ` [Qemu-devel] [PATCH v2 2/3] qapi: implement block-dirty-bitmap-remove transaction action John Snow
@ 2019-07-03 19:30   ` Max Reitz
  2019-07-03 19:38     ` Max Reitz
  2019-07-03 19:56     ` John Snow
  0 siblings, 2 replies; 7+ messages in thread
From: Max Reitz @ 2019-07-03 19:30 UTC (permalink / raw)
  To: John Snow, qemu-block, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, vsementsov, Juan Quintela,
	Markus Armbruster, Dr. David Alan Gilbert, Stefan Hajnoczi


[-- Attachment #1.1: Type: text/plain, Size: 3475 bytes --]

On 01.07.19 22:13, John Snow wrote:
> It is used to do transactional movement of the bitmap (which is
> possible in conjunction with merge command). Transactional bitmap
> movement is needed in scenarios with external snapshot, when we don't
> want to leave copy of the bitmap in the base image.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> Signed-off-by: John Snow <jsnow@redhat.com>
> ---
>  qapi/transaction.json          |  2 +
>  include/block/dirty-bitmap.h   |  3 +-
>  block.c                        |  2 +-
>  block/dirty-bitmap.c           | 16 +++----
>  blockdev.c                     | 79 +++++++++++++++++++++++++++++++---
>  migration/block-dirty-bitmap.c |  2 +-
>  6 files changed, 87 insertions(+), 17 deletions(-)

[...]

> diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
> index 95a9c2a5d8..8551f8219e 100644
> --- a/block/dirty-bitmap.c
> +++ b/block/dirty-bitmap.c
> @@ -48,10 +48,9 @@ struct BdrvDirtyBitmap {
>      bool inconsistent;          /* bitmap is persistent, but inconsistent.
>                                     It cannot be used at all in any way, except
>                                     a QMP user can remove it. */
> -    bool migration;             /* Bitmap is selected for migration, it should
> -                                   not be stored on the next inactivation
> -                                   (persistent flag doesn't matter until next
> -                                   invalidation).*/
> +    bool squelch_persistence;   /* We are either migrating or deleting this
> +                                 * bitmap; it should not be stored on the next
> +                                 * inactivation. */

I like the English lessons you give me, but why not just dont_store?  Or
skip_storing?

>      QLIST_ENTRY(BdrvDirtyBitmap) list;
>  };
>  

[...]

> diff --git a/blockdev.c b/blockdev.c
> index 01248252ca..4143ab7bbb 100644
> --- a/blockdev.c
> +++ b/blockdev.c

[...]

> +static void block_dirty_bitmap_remove_abort(BlkActionState *common)
> +{
> +    BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
> +                                             common, common);
> +
> +    if (state->bitmap) {
> +        bdrv_dirty_bitmap_squelch_persistence(state->bitmap, false);
> +        bdrv_dirty_bitmap_set_busy(state->bitmap, false);

Don’t you need to undo the removal?  Like, re-add it to state->bs, and
re-store it?

[...]

> @@ -2892,13 +2944,28 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
>          aio_context_acquire(aio_context);
>          bdrv_remove_persistent_dirty_bitmap(bs, name, &local_err);
>          aio_context_release(aio_context);
> +
>          if (local_err != NULL) {
>              error_propagate(errp, local_err);
> -            return;
> +            return NULL;
>          }
>      }
>  
> -    bdrv_release_dirty_bitmap(bs, bitmap);
> +    if (release) {
> +        bdrv_release_dirty_bitmap(bs, bitmap);
> +    }
> +
> +    if (bitmap_bs) {
> +        *bitmap_bs = bs;
> +    }
> +
> +    return bitmap;

I’d prefer “release ? NULL : bitmap”.

Max

> +}
> +
> +void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
> +                                   Error **errp)
> +{
> +    do_block_dirty_bitmap_remove(node, name, true, NULL, errp);
>  }
>  
>  /**


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/3] qapi: implement block-dirty-bitmap-remove transaction action
  2019-07-03 19:30   ` Max Reitz
@ 2019-07-03 19:38     ` Max Reitz
  2019-07-03 19:56     ` John Snow
  1 sibling, 0 replies; 7+ messages in thread
From: Max Reitz @ 2019-07-03 19:38 UTC (permalink / raw)
  To: John Snow, qemu-block, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, vsementsov, Juan Quintela,
	Markus Armbruster, Dr. David Alan Gilbert, Stefan Hajnoczi


[-- Attachment #1.1: Type: text/plain, Size: 4063 bytes --]

On 03.07.19 21:30, Max Reitz wrote:
> On 01.07.19 22:13, John Snow wrote:
>> It is used to do transactional movement of the bitmap (which is
>> possible in conjunction with merge command). Transactional bitmap
>> movement is needed in scenarios with external snapshot, when we don't
>> want to leave copy of the bitmap in the base image.
>>
>> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
>> Signed-off-by: John Snow <jsnow@redhat.com>
>> ---
>>  qapi/transaction.json          |  2 +
>>  include/block/dirty-bitmap.h   |  3 +-
>>  block.c                        |  2 +-
>>  block/dirty-bitmap.c           | 16 +++----
>>  blockdev.c                     | 79 +++++++++++++++++++++++++++++++---
>>  migration/block-dirty-bitmap.c |  2 +-
>>  6 files changed, 87 insertions(+), 17 deletions(-)
> 
> [...]
> 
>> diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
>> index 95a9c2a5d8..8551f8219e 100644
>> --- a/block/dirty-bitmap.c
>> +++ b/block/dirty-bitmap.c
>> @@ -48,10 +48,9 @@ struct BdrvDirtyBitmap {
>>      bool inconsistent;          /* bitmap is persistent, but inconsistent.
>>                                     It cannot be used at all in any way, except
>>                                     a QMP user can remove it. */
>> -    bool migration;             /* Bitmap is selected for migration, it should
>> -                                   not be stored on the next inactivation
>> -                                   (persistent flag doesn't matter until next
>> -                                   invalidation).*/
>> +    bool squelch_persistence;   /* We are either migrating or deleting this
>> +                                 * bitmap; it should not be stored on the next
>> +                                 * inactivation. */
> 
> I like the English lessons you give me, but why not just dont_store?  Or
> skip_storing?
> 
>>      QLIST_ENTRY(BdrvDirtyBitmap) list;
>>  };
>>  
> 
> [...]
> 
>> diff --git a/blockdev.c b/blockdev.c
>> index 01248252ca..4143ab7bbb 100644
>> --- a/blockdev.c
>> +++ b/blockdev.c
> 
> [...]
> 
>> +static void block_dirty_bitmap_remove_abort(BlkActionState *common)
>> +{
>> +    BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
>> +                                             common, common);
>> +
>> +    if (state->bitmap) {
>> +        bdrv_dirty_bitmap_squelch_persistence(state->bitmap, false);
>> +        bdrv_dirty_bitmap_set_busy(state->bitmap, false);
> 
> Don’t you need to undo the removal?  Like, re-add it to state->bs, and
> re-store it?

Ah, right, no need to re-add it because without *release(), it was never
removed from state->bs.

Having removed the persistent bitmap makes without doing anything here
to re-add it to the qcow2 file makes me a bit uneasy, though...  (It
should be stored automatically when the qcow2 file is closed or
anything, but, you know.  Feel free to say “Yes, it will be stored
automatically, don’t worry.”)

Max

> [...]
> 
>> @@ -2892,13 +2944,28 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
>>          aio_context_acquire(aio_context);
>>          bdrv_remove_persistent_dirty_bitmap(bs, name, &local_err);
>>          aio_context_release(aio_context);
>> +
>>          if (local_err != NULL) {
>>              error_propagate(errp, local_err);
>> -            return;
>> +            return NULL;
>>          }
>>      }
>>  
>> -    bdrv_release_dirty_bitmap(bs, bitmap);
>> +    if (release) {
>> +        bdrv_release_dirty_bitmap(bs, bitmap);
>> +    }
>> +
>> +    if (bitmap_bs) {
>> +        *bitmap_bs = bs;
>> +    }
>> +
>> +    return bitmap;
> 
> I’d prefer “release ? NULL : bitmap”.
> 
> Max
> 
>> +}
>> +
>> +void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
>> +                                   Error **errp)
>> +{
>> +    do_block_dirty_bitmap_remove(node, name, true, NULL, errp);
>>  }
>>  
>>  /**
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH v2 2/3] qapi: implement block-dirty-bitmap-remove transaction action
  2019-07-03 19:30   ` Max Reitz
  2019-07-03 19:38     ` Max Reitz
@ 2019-07-03 19:56     ` John Snow
  1 sibling, 0 replies; 7+ messages in thread
From: John Snow @ 2019-07-03 19:56 UTC (permalink / raw)
  To: Max Reitz, qemu-block, qemu-devel
  Cc: Kevin Wolf, Fam Zheng, vsementsov, Juan Quintela,
	Markus Armbruster, Dr. David Alan Gilbert, Stefan Hajnoczi



On 7/3/19 3:30 PM, Max Reitz wrote:
> On 01.07.19 22:13, John Snow wrote:
>> It is used to do transactional movement of the bitmap (which is
>> possible in conjunction with merge command). Transactional bitmap
>> movement is needed in scenarios with external snapshot, when we don't
>> want to leave copy of the bitmap in the base image.
>>
>> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
>> Signed-off-by: John Snow <jsnow@redhat.com>
>> ---
>>  qapi/transaction.json          |  2 +
>>  include/block/dirty-bitmap.h   |  3 +-
>>  block.c                        |  2 +-
>>  block/dirty-bitmap.c           | 16 +++----
>>  blockdev.c                     | 79 +++++++++++++++++++++++++++++++---
>>  migration/block-dirty-bitmap.c |  2 +-
>>  6 files changed, 87 insertions(+), 17 deletions(-)
> 
> [...]
> 
>> diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
>> index 95a9c2a5d8..8551f8219e 100644
>> --- a/block/dirty-bitmap.c
>> +++ b/block/dirty-bitmap.c
>> @@ -48,10 +48,9 @@ struct BdrvDirtyBitmap {
>>      bool inconsistent;          /* bitmap is persistent, but inconsistent.
>>                                     It cannot be used at all in any way, except
>>                                     a QMP user can remove it. */
>> -    bool migration;             /* Bitmap is selected for migration, it should
>> -                                   not be stored on the next inactivation
>> -                                   (persistent flag doesn't matter until next
>> -                                   invalidation).*/
>> +    bool squelch_persistence;   /* We are either migrating or deleting this
>> +                                 * bitmap; it should not be stored on the next
>> +                                 * inactivation. */
> 
> I like the English lessons you give me, but why not just dont_store?  Or
> skip_storing?
> 

I have to give you something to look forward to in my patches, don't I?

I also like "suppress_persistence" but I'll settle for "skip_store".

>>      QLIST_ENTRY(BdrvDirtyBitmap) list;
>>  };
>>  
> 
> [...]
> 
>> diff --git a/blockdev.c b/blockdev.c
>> index 01248252ca..4143ab7bbb 100644
>> --- a/blockdev.c
>> +++ b/blockdev.c
> 
> [...]
> 
>> +static void block_dirty_bitmap_remove_abort(BlkActionState *common)
>> +{
>> +    BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
>> +                                             common, common);
>> +
>> +    if (state->bitmap) {
>> +        bdrv_dirty_bitmap_squelch_persistence(state->bitmap, false);
>> +        bdrv_dirty_bitmap_set_busy(state->bitmap, false);
> 
> Don’t you need to undo the removal?  Like, re-add it to state->bs, and
> re-store it?
> 
> [...]
> 

Not right away, anyway; undoing the suppression will allow it to flush
out the next time that happens.

Why not flush it RIGHT NOW? Well, we actually never flush bitmaps until
final close right now. There has been some contention about how it's
pointless to do so as we'd have to re-open the bitmap immediately
anyway, and any results you'd get from querying the bitmap outside of
QEMU would be meaningless.

It does feel risky, though, and seems to frequently violate the
principal of least surprise.

>> @@ -2892,13 +2944,28 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
>>          aio_context_acquire(aio_context);
>>          bdrv_remove_persistent_dirty_bitmap(bs, name, &local_err);
>>          aio_context_release(aio_context);
>> +
>>          if (local_err != NULL) {
>>              error_propagate(errp, local_err);
>> -            return;
>> +            return NULL;
>>          }
>>      }
>>  
>> -    bdrv_release_dirty_bitmap(bs, bitmap);
>> +    if (release) {
>> +        bdrv_release_dirty_bitmap(bs, bitmap);
>> +    }
>> +
>> +    if (bitmap_bs) {
>> +        *bitmap_bs = bs;
>> +    }
>> +
>> +    return bitmap;
> 
> I’d prefer “release ? NULL : bitmap”.
> 
> Max
> 

Sure.

>> +}
>> +
>> +void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
>> +                                   Error **errp)
>> +{
>> +    do_block_dirty_bitmap_remove(node, name, true, NULL, errp);
>>  }
>>  
>>  /**
> 



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-07-03 19:57 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-01 20:13 [Qemu-devel] [PATCH v2 0/3] qapi: block-dirty-bitmap-remove transaction action John Snow
2019-07-01 20:13 ` [Qemu-devel] [PATCH v2 1/3] blockdev: reduce aio_context locked sections in bitmap add/remove John Snow
2019-07-01 20:13 ` [Qemu-devel] [PATCH v2 2/3] qapi: implement block-dirty-bitmap-remove transaction action John Snow
2019-07-03 19:30   ` Max Reitz
2019-07-03 19:38     ` Max Reitz
2019-07-03 19:56     ` John Snow
2019-07-01 20:13 ` [Qemu-devel] [PATCH v2 3/3] iotests: test bitmap moving inside 254 John Snow

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.