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>
---
docs/tools/qemu-img.rst | 4 +++-
qemu-img.c | 43 ++++++++++++++++++++++++++++++++++-------
2 files changed, 39 insertions(+), 8 deletions(-)
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index 3653adb963..a08fd6019f 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 e75707180d..920ede2a6a 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 {
@@ -191,7 +192,7 @@ void help(void)
"Parameters to bitmap subcommand:\n"
" 'bitmap' is the name of the bitmap to manipulate, through one or
more\n"
" actions from '--add', '--remove', '--clear', '--enable',
'--disable',\n"
- " or '--merge source'\n"
+ " '--remove-all' or '--merge source'\n"
" '-g granularity' sets the granularity for '--add' actions\n"
" '-b source' and '-F src_fmt' tell '--merge' actions to find the
source\n"
" bitmaps from an alternative file\n"
@@ -4770,6 +4771,7 @@ enum ImgBitmapAct {
BITMAP_ENABLE,
BITMAP_DISABLE,
BITMAP_MERGE,
+ BITMAP_REMOVE_ALL,
};
typedef struct ImgBitmapAction {
enum ImgBitmapAct act;
@@ -4788,7 +4790,7 @@ static int img_bitmap(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;
@@ -4803,6 +4805,7 @@ static int img_bitmap(int argc, char **argv)
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{"add", no_argument, 0, OPTION_ADD},
{"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},
@@ -4846,34 +4849,44 @@ static int img_bitmap(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 OPTION_REMOVE:
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 OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
@@ -4885,8 +4898,8 @@ static int img_bitmap(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;
}
@@ -4904,10 +4917,14 @@ static int img_bitmap(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];
@@ -4945,6 +4962,18 @@ static int img_bitmap(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";