bitmap-qmp-cmds.c (9215B)
1/* 2 * QEMU block dirty bitmap QMP commands 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or 7 * later. See the COPYING file in the top-level directory. 8 * 9 * This file incorporates work covered by the following copyright and 10 * permission notice: 11 * 12 * Copyright (c) 2003-2008 Fabrice Bellard 13 * 14 * Permission is hereby granted, free of charge, to any person obtaining a copy 15 * of this software and associated documentation files (the "Software"), to deal 16 * in the Software without restriction, including without limitation the rights 17 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 * copies of the Software, and to permit persons to whom the Software is 19 * furnished to do so, subject to the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be included in 22 * all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 27 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 * THE SOFTWARE. 31 */ 32 33#include "qemu/osdep.h" 34 35#include "block/block_int.h" 36#include "qapi/qapi-commands-block.h" 37#include "qapi/error.h" 38 39/** 40 * block_dirty_bitmap_lookup: 41 * Return a dirty bitmap (if present), after validating 42 * the node reference and bitmap names. 43 * 44 * @node: The name of the BDS node to search for bitmaps 45 * @name: The name of the bitmap to search for 46 * @pbs: Output pointer for BDS lookup, if desired. Can be NULL. 47 * @errp: Output pointer for error information. Can be NULL. 48 * 49 * @return: A bitmap object on success, or NULL on failure. 50 */ 51BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node, 52 const char *name, 53 BlockDriverState **pbs, 54 Error **errp) 55{ 56 BlockDriverState *bs; 57 BdrvDirtyBitmap *bitmap; 58 59 if (!node) { 60 error_setg(errp, "Node cannot be NULL"); 61 return NULL; 62 } 63 if (!name) { 64 error_setg(errp, "Bitmap name cannot be NULL"); 65 return NULL; 66 } 67 bs = bdrv_lookup_bs(node, node, NULL); 68 if (!bs) { 69 error_setg(errp, "Node '%s' not found", node); 70 return NULL; 71 } 72 73 bitmap = bdrv_find_dirty_bitmap(bs, name); 74 if (!bitmap) { 75 error_setg(errp, "Dirty bitmap '%s' not found", name); 76 return NULL; 77 } 78 79 if (pbs) { 80 *pbs = bs; 81 } 82 83 return bitmap; 84} 85 86void qmp_block_dirty_bitmap_add(const char *node, const char *name, 87 bool has_granularity, uint32_t granularity, 88 bool has_persistent, bool persistent, 89 bool has_disabled, bool disabled, 90 Error **errp) 91{ 92 BlockDriverState *bs; 93 BdrvDirtyBitmap *bitmap; 94 AioContext *aio_context; 95 96 if (!name || name[0] == '\0') { 97 error_setg(errp, "Bitmap name cannot be empty"); 98 return; 99 } 100 101 bs = bdrv_lookup_bs(node, node, errp); 102 if (!bs) { 103 return; 104 } 105 106 aio_context = bdrv_get_aio_context(bs); 107 aio_context_acquire(aio_context); 108 109 if (has_granularity) { 110 if (granularity < 512 || !is_power_of_2(granularity)) { 111 error_setg(errp, "Granularity must be power of 2 " 112 "and at least 512"); 113 goto out; 114 } 115 } else { 116 /* Default to cluster size, if available: */ 117 granularity = bdrv_get_default_bitmap_granularity(bs); 118 } 119 120 if (!has_persistent) { 121 persistent = false; 122 } 123 124 if (!has_disabled) { 125 disabled = false; 126 } 127 128 if (persistent && 129 !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp)) 130 { 131 goto out; 132 } 133 134 bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp); 135 if (bitmap == NULL) { 136 goto out; 137 } 138 139 if (disabled) { 140 bdrv_disable_dirty_bitmap(bitmap); 141 } 142 143 bdrv_dirty_bitmap_set_persistence(bitmap, persistent); 144 145out: 146 aio_context_release(aio_context); 147} 148 149BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name, 150 bool release, 151 BlockDriverState **bitmap_bs, 152 Error **errp) 153{ 154 BlockDriverState *bs; 155 BdrvDirtyBitmap *bitmap; 156 AioContext *aio_context; 157 158 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); 159 if (!bitmap || !bs) { 160 return NULL; 161 } 162 163 aio_context = bdrv_get_aio_context(bs); 164 aio_context_acquire(aio_context); 165 166 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO, 167 errp)) { 168 aio_context_release(aio_context); 169 return NULL; 170 } 171 172 if (bdrv_dirty_bitmap_get_persistence(bitmap) && 173 bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0) 174 { 175 aio_context_release(aio_context); 176 return NULL; 177 } 178 179 if (release) { 180 bdrv_release_dirty_bitmap(bitmap); 181 } 182 183 if (bitmap_bs) { 184 *bitmap_bs = bs; 185 } 186 187 aio_context_release(aio_context); 188 return release ? NULL : bitmap; 189} 190 191void qmp_block_dirty_bitmap_remove(const char *node, const char *name, 192 Error **errp) 193{ 194 block_dirty_bitmap_remove(node, name, true, NULL, errp); 195} 196 197/** 198 * Completely clear a bitmap, for the purposes of synchronizing a bitmap 199 * immediately after a full backup operation. 200 */ 201void qmp_block_dirty_bitmap_clear(const char *node, const char *name, 202 Error **errp) 203{ 204 BdrvDirtyBitmap *bitmap; 205 BlockDriverState *bs; 206 207 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); 208 if (!bitmap || !bs) { 209 return; 210 } 211 212 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) { 213 return; 214 } 215 216 bdrv_clear_dirty_bitmap(bitmap, NULL); 217} 218 219void qmp_block_dirty_bitmap_enable(const char *node, const char *name, 220 Error **errp) 221{ 222 BlockDriverState *bs; 223 BdrvDirtyBitmap *bitmap; 224 225 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); 226 if (!bitmap) { 227 return; 228 } 229 230 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { 231 return; 232 } 233 234 bdrv_enable_dirty_bitmap(bitmap); 235} 236 237void qmp_block_dirty_bitmap_disable(const char *node, const char *name, 238 Error **errp) 239{ 240 BlockDriverState *bs; 241 BdrvDirtyBitmap *bitmap; 242 243 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); 244 if (!bitmap) { 245 return; 246 } 247 248 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { 249 return; 250 } 251 252 bdrv_disable_dirty_bitmap(bitmap); 253} 254 255BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target, 256 BlockDirtyBitmapMergeSourceList *bms, 257 HBitmap **backup, Error **errp) 258{ 259 BlockDriverState *bs; 260 BdrvDirtyBitmap *dst, *src, *anon; 261 BlockDirtyBitmapMergeSourceList *lst; 262 Error *local_err = NULL; 263 264 dst = block_dirty_bitmap_lookup(node, target, &bs, errp); 265 if (!dst) { 266 return NULL; 267 } 268 269 anon = bdrv_create_dirty_bitmap(bs, bdrv_dirty_bitmap_granularity(dst), 270 NULL, errp); 271 if (!anon) { 272 return NULL; 273 } 274 275 for (lst = bms; lst; lst = lst->next) { 276 switch (lst->value->type) { 277 const char *name, *node; 278 case QTYPE_QSTRING: 279 name = lst->value->u.local; 280 src = bdrv_find_dirty_bitmap(bs, name); 281 if (!src) { 282 error_setg(errp, "Dirty bitmap '%s' not found", name); 283 dst = NULL; 284 goto out; 285 } 286 break; 287 case QTYPE_QDICT: 288 node = lst->value->u.external.node; 289 name = lst->value->u.external.name; 290 src = block_dirty_bitmap_lookup(node, name, NULL, errp); 291 if (!src) { 292 dst = NULL; 293 goto out; 294 } 295 break; 296 default: 297 abort(); 298 } 299 300 bdrv_merge_dirty_bitmap(anon, src, NULL, &local_err); 301 if (local_err) { 302 error_propagate(errp, local_err); 303 dst = NULL; 304 goto out; 305 } 306 } 307 308 /* Merge into dst; dst is unchanged on failure. */ 309 bdrv_merge_dirty_bitmap(dst, anon, backup, errp); 310 311 out: 312 bdrv_release_dirty_bitmap(anon); 313 return dst; 314} 315 316void qmp_block_dirty_bitmap_merge(const char *node, const char *target, 317 BlockDirtyBitmapMergeSourceList *bitmaps, 318 Error **errp) 319{ 320 block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp); 321}