>From time to time it is needed to remove all bitmaps from the image.
Before this patch the process is not very convinient. One should
perform
    qemu-img info
and parse the output to obtain all names. After that one should
sequentially call
    qemu-img bitmap --remove
for each present bitmap.

The patch adds --remove-all sub-command to 'qemu-img bitmap'.

Signed-off-by: Denis V. Lunev <d...@openvz.org>
CC: Kevin Wolf <kw...@redhat.com>
CC: Hanna Reitz <hre...@redhat.com>
CC: Michael Tokarev <m...@tls.msk.ru>
---
Changes from v1:
* rebased to latest head
* adopted bitmap help to the new layout

 docs/tools/qemu-img.rst |  4 +++-
 qemu-img.c              | 47 ++++++++++++++++++++++++++++++++++-------
 2 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index 5e7b85079d..db739ab5c8 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -301,7 +301,7 @@ Command description:
   For write tests, by default a buffer filled with zeros is written. This can 
be
   overridden with a pattern byte specified by *PATTERN*.
 
-.. option:: bitmap (--merge SOURCE | --add | --remove | --clear | --enable | 
--disable)... [-b SOURCE_FILE [-F SOURCE_FMT]] [-g GRANULARITY] [--object 
OBJECTDEF] [--image-opts | -f FMT] FILENAME BITMAP
+.. option:: bitmap (--merge SOURCE | --add | --remove | --remove-all | --clear 
| --enable | --disable)... [-b SOURCE_FILE [-F SOURCE_FMT]] [-g GRANULARITY] 
[--object OBJECTDEF] [--image-opts | -f FMT] FILENAME BITMAP
 
   Perform one or more modifications of the persistent bitmap *BITMAP*
   in the disk image *FILENAME*.  The various modifications are:
@@ -310,6 +310,8 @@ Command description:
 
   ``--remove`` to remove *BITMAP*.
 
+  ``--remove-all`` to remove all bitmaps.
+
   ``--clear`` to clear *BITMAP*.
 
   ``--enable`` to change *BITMAP* to start recording future edits.
diff --git a/qemu-img.c b/qemu-img.c
index 7a162fdc08..ddd449c1ed 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -86,6 +86,7 @@ enum {
     OPTION_BITMAPS = 275,
     OPTION_FORCE = 276,
     OPTION_SKIP_BROKEN = 277,
+    OPTION_REMOVE_ALL = 278,
 };
 
 typedef enum OutputFormat {
@@ -4992,6 +4993,7 @@ enum ImgBitmapAct {
     BITMAP_ENABLE,
     BITMAP_DISABLE,
     BITMAP_MERGE,
+    BITMAP_REMOVE_ALL,
 };
 typedef struct ImgBitmapAction {
     enum ImgBitmapAct act;
@@ -5010,7 +5012,7 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc, 
char **argv)
     BlockDriverState *bs = NULL, *src_bs = NULL;
     bool image_opts = false;
     int64_t granularity = 0;
-    bool add = false, merge = false;
+    bool add = false, merge = false, remove_all = false, any = false;
     QSIMPLEQ_HEAD(, ImgBitmapAction) actions;
     ImgBitmapAction *act, *act_next;
     const char *op;
@@ -5026,6 +5028,7 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc, 
char **argv)
             {"add", no_argument, 0, OPTION_ADD},
             {"granularity", required_argument, 0, 'g'},
             {"remove", no_argument, 0, OPTION_REMOVE},
+            {"remove-all", no_argument, 0, OPTION_REMOVE_ALL},
             {"clear", no_argument, 0, OPTION_CLEAR},
             {"enable", no_argument, 0, OPTION_ENABLE},
             {"disable", no_argument, 0, OPTION_DISABLE},
@@ -5044,8 +5047,8 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc, 
char **argv)
         switch (c) {
         case 'h':
             cmd_help(ccmd, "[-f FMT | --image-opts]\n"
-"        ( --add [-g SIZE] | --remove | --clear | --enable | --disable |\n"
-"          --merge SOURCE [-b SRC_FILE [-F SRC_FMT]] )..\n"
+"        ( --add [-g SIZE] | --remove | --remove-all | --clear | --enable |\n"
+"          --disable | --merge SOURCE [-b SRC_FILE [-F SRC_FMT]] )..\n"
 "        [--object OBJDEF] FILE BITMAP\n"
 ,
 "  -f, --format FMT\n"
@@ -5060,6 +5063,8 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc, 
char **argv)
 "     with optional multiplier suffix (in powers of 1024)\n"
 "  --remove\n"
 "     removes BITMAP from FILE\n"
+"  --remove-all\n"
+"     removes all bitmaps from FILE\n"
 "  --clear\n"
 "     clears BITMAP in FILE\n"
 "  --enable, --disable\n"
@@ -5089,7 +5094,7 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc, 
char **argv)
             act = g_new0(ImgBitmapAction, 1);
             act->act = BITMAP_ADD;
             QSIMPLEQ_INSERT_TAIL(&actions, act, next);
-            add = true;
+            add = any = true;
             break;
         case 'g':
             granularity = cvtnum("granularity", optarg, true);
@@ -5101,28 +5106,38 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc, 
char **argv)
             act = g_new0(ImgBitmapAction, 1);
             act->act = BITMAP_REMOVE;
             QSIMPLEQ_INSERT_TAIL(&actions, act, next);
+            any = true;
+            break;
+        case OPTION_REMOVE_ALL:
+            act = g_new0(ImgBitmapAction, 1);
+            act->act = BITMAP_REMOVE_ALL;
+            QSIMPLEQ_INSERT_TAIL(&actions, act, next);
+            remove_all = true;
             break;
         case OPTION_CLEAR:
             act = g_new0(ImgBitmapAction, 1);
             act->act = BITMAP_CLEAR;
             QSIMPLEQ_INSERT_TAIL(&actions, act, next);
+            any = true;
             break;
         case OPTION_ENABLE:
             act = g_new0(ImgBitmapAction, 1);
             act->act = BITMAP_ENABLE;
             QSIMPLEQ_INSERT_TAIL(&actions, act, next);
+            any = true;
             break;
         case OPTION_DISABLE:
             act = g_new0(ImgBitmapAction, 1);
             act->act = BITMAP_DISABLE;
             QSIMPLEQ_INSERT_TAIL(&actions, act, next);
+            any = true;
             break;
         case OPTION_MERGE:
             act = g_new0(ImgBitmapAction, 1);
             act->act = BITMAP_MERGE;
             act->src = optarg;
             QSIMPLEQ_INSERT_TAIL(&actions, act, next);
-            merge = true;
+            any = merge = true;
             break;
         case 'b':
             src_filename = optarg;
@@ -5139,8 +5154,8 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc, 
char **argv)
     }
 
     if (QSIMPLEQ_EMPTY(&actions)) {
-        error_report("Need at least one of --add, --remove, --clear, "
-                     "--enable, --disable, or --merge");
+        error_report("Need at least one of --add, --remove, --remove-all, "
+                     "--clear, --enable, --disable, or --merge");
         goto out;
     }
 
@@ -5158,10 +5173,14 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc, 
char **argv)
         goto out;
     }
 
-    if (optind != argc - 2) {
+    if (any && optind != argc - 2) {
         error_report("Expecting filename and bitmap name");
         goto out;
     }
+    if (!any && remove_all && optind != argc - 1) {
+        error_report("Expecting filename");
+        goto out;
+    }
 
     filename = argv[optind];
     bitmap = argv[optind + 1];
@@ -5199,6 +5218,18 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc, 
char **argv)
             qmp_block_dirty_bitmap_remove(bs->node_name, bitmap, &err);
             op = "remove";
             break;
+        case BITMAP_REMOVE_ALL: {
+            while (1) {
+                BdrvDirtyBitmap *bm = bdrv_dirty_bitmap_first(bs);
+                if (bm == NULL) {
+                    break;
+                }
+                qmp_block_dirty_bitmap_remove(bs->node_name,
+                                              bdrv_dirty_bitmap_name(bm), 
&err);
+            }
+            op = "remove-all";
+            break;
+        }
         case BITMAP_CLEAR:
             qmp_block_dirty_bitmap_clear(bs->node_name, bitmap, &err);
             op = "clear";
-- 
2.45.2


Reply via email to