87
OPTION_FORCE = 276,
88
OPTION_SKIP_BROKEN = 277,
89
OPTION_LIMITS = 278,
90
+ OPTION_REMOVE_ALL = 279,
91
};
92
93
typedef enum OutputFormat {
5019
BITMAP_ENABLE,
5020
BITMAP_DISABLE,
5021
BITMAP_MERGE,
5022
+ BITMAP_REMOVE_ALL,
5023
};
5024
typedef struct ImgBitmapAction {
5025
enum ImgBitmapAct act;
5038
BlockDriverState *bs = NULL, *src_bs = NULL;
5039
bool image_opts = false;
5040
int64_t granularity = 0;
5039
- bool add = false, merge = false;
5041
+ bool add = false, merge = false, need_bitmap_name = false;
5042
QSIMPLEQ_HEAD(, ImgBitmapAction) actions;
5043
ImgBitmapAction *act, *act_next;
5044
const char *op;
5054
{"add", no_argument, 0, OPTION_ADD},
5055
{"granularity", required_argument, 0, 'g'},
5056
{"remove", no_argument, 0, OPTION_REMOVE},
5057
+ {"remove-all", no_argument, 0, OPTION_REMOVE_ALL},
5058
{"clear", no_argument, 0, OPTION_CLEAR},
5059
{"enable", no_argument, 0, OPTION_ENABLE},
5060
{"disable", no_argument, 0, OPTION_DISABLE},
5073
switch (c) {
5074
case 'h':
5075
cmd_help(ccmd, "[-f FMT | --image-opts]\n"
5073
-" ( --add [-g SIZE] | --remove | --clear | --enable | --disable |\n"
5074
-" --merge SOURCE [-b SRC_FILE [-F SRC_FMT]] )..\n"
5075
-" [--object OBJDEF] FILE BITMAP\n"
5076
+" ( --add [-g SIZE] | --remove | --remove-all | --clear | --enable |\n"
5077
+" --disable | --merge SOURCE [-b SRC_FILE [-F SRC_FMT]] )..\n"
5078
+" [--object OBJDEF] FILE [BITMAP]\n"
5079
,
5080
" -f, --format FMT\n"
5081
" specify FILE format explicitly (default: probing is used)\n"
5089
" with optional multiplier suffix (in powers of 1024)\n"
5090
" --remove\n"
5091
" removes BITMAP from FILE\n"
5092
+" --remove-all\n"
5093
+" removes all bitmaps from FILE\n"
5094
" --clear\n"
5095
" clears BITMAP in FILE\n"
5096
" --enable, --disable\n"
5121
act->act = BITMAP_ADD;
5122
QSIMPLEQ_INSERT_TAIL(&actions, act, next);
5123
add = true;
5124
+ need_bitmap_name = true;
5125
break;
5126
case 'g':
5127
granularity = cvtnum("granularity", optarg, true);
5133
act = g_new0(ImgBitmapAction, 1);
5134
act->act = BITMAP_REMOVE;
5135
QSIMPLEQ_INSERT_TAIL(&actions, act, next);
5136
+ need_bitmap_name = true;
5137
+ break;
5138
+ case OPTION_REMOVE_ALL:
5139
+ act = g_new0(ImgBitmapAction, 1);
5140
+ act->act = BITMAP_REMOVE_ALL;
5141
+ QSIMPLEQ_INSERT_TAIL(&actions, act, next);
5142
break;
5143
case OPTION_CLEAR:
5144
act = g_new0(ImgBitmapAction, 1);
5145
act->act = BITMAP_CLEAR;
5146
QSIMPLEQ_INSERT_TAIL(&actions, act, next);
5147
+ need_bitmap_name = true;
5148
break;
5149
case OPTION_ENABLE:
5150
act = g_new0(ImgBitmapAction, 1);
5151
act->act = BITMAP_ENABLE;
5152
QSIMPLEQ_INSERT_TAIL(&actions, act, next);
5153
+ need_bitmap_name = true;
5154
break;
5155
case OPTION_DISABLE:
5156
act = g_new0(ImgBitmapAction, 1);
5157
act->act = BITMAP_DISABLE;
5158
QSIMPLEQ_INSERT_TAIL(&actions, act, next);
5159
+ need_bitmap_name = true;
5160
break;
5161
case OPTION_MERGE:
5162
act = g_new0(ImgBitmapAction, 1);
5164
act->src = optarg;
5165
QSIMPLEQ_INSERT_TAIL(&actions, act, next);
5166
merge = true;
5167
+ need_bitmap_name = true;
5168
break;
5169
case 'b':
5170
src_filename = optarg;
5181
}
5182
5183
if (QSIMPLEQ_EMPTY(&actions)) {
5168
- error_report("Need at least one of --add, --remove, --clear, "
5169
- "--enable, --disable, or --merge");
5184
+ error_report("Need at least one of --add, --remove, --remove-all, "
5185
+ "--clear, --enable, --disable, or --merge");
5186
goto out;
5187
}
5188
5200
goto out;
5201
}
5202
5187
- if (optind != argc - 2) {
5203
+ if (need_bitmap_name && optind != argc - 2) {
5204
error_report("Expecting filename and bitmap name");
5205
goto out;
5206
}
5207
5208
+ /*
5209
+ * Every action other than --remove-all sets need_bitmap_name, so
5210
+ * !need_bitmap_name means the only action(s) given were --remove-all
5211
+ * and the BITMAP positional argument must be omitted. Combinations
5212
+ * like '--remove-all --add foo' remain valid via the branch above.
5213
+ */
5214
+ if (!need_bitmap_name && optind != argc - 1) {
5215
+ error_report("Expecting filename");
5216
+ goto out;
5217
+ }
5218
+
5219
filename = argv[optind];
5220
bitmap = argv[optind + 1];
5221
5252
qmp_block_dirty_bitmap_remove(bs->node_name, bitmap, &err);
5253
op = "remove";
5254
break;
5255
+ case BITMAP_REMOVE_ALL: {
5256
+ BdrvDirtyBitmap *bm;
5257
+ while ((bm = bdrv_dirty_bitmap_first(bs))) {
5258
+ const char *name = bdrv_dirty_bitmap_name(bm);
5259
+ qmp_block_dirty_bitmap_remove(bs->node_name, name, &err);
5260
+ if (err) {
5261
+ /* Save name for proper error reporting */
5262
+ bitmap = name;
5263
+ break;
5264
+ }
5265
+ }
5266
+ op = "remove-all";
5267
+ break;
5268
+ }
5269
case BITMAP_CLEAR:
5270
qmp_block_dirty_bitmap_clear(bs->node_name, bitmap, &err);
5271
op = "clear";