On 7/23/25 21:29, Denis V. Lunev wrote:
 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";
ping

Reply via email to