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-io.h" 36 #include "block/block_int.h" 37 #include "block/dirty-bitmap.h" 38 #include "qapi/qapi-commands-block.h" 39 #include "qapi/error.h" 40 41 /** 42 * block_dirty_bitmap_lookup: 43 * Return a dirty bitmap (if present), after validating 44 * the node reference and bitmap names. 45 * 46 * @node: The name of the BDS node to search for bitmaps 47 * @name: The name of the bitmap to search for 48 * @pbs: Output pointer for BDS lookup, if desired. Can be NULL. 49 * @errp: Output pointer for error information. Can be NULL. 50 * 51 * @return: A bitmap object on success, or NULL on failure. 52 */ 53 BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node, 54 const char *name, 55 BlockDriverState **pbs, 56 Error **errp) 57 { 58 BlockDriverState *bs; 59 BdrvDirtyBitmap *bitmap; 60 61 GLOBAL_STATE_CODE(); 62 63 if (!node) { 64 error_setg(errp, "Node cannot be NULL"); 65 return NULL; 66 } 67 if (!name) { 68 error_setg(errp, "Bitmap name cannot be NULL"); 69 return NULL; 70 } 71 bs = bdrv_lookup_bs(node, node, NULL); 72 if (!bs) { 73 error_setg(errp, "Node '%s' not found", node); 74 return NULL; 75 } 76 77 bitmap = bdrv_find_dirty_bitmap(bs, name); 78 if (!bitmap) { 79 error_setg(errp, "Dirty bitmap '%s' not found", name); 80 return NULL; 81 } 82 83 if (pbs) { 84 *pbs = bs; 85 } 86 87 return bitmap; 88 } 89 90 void qmp_block_dirty_bitmap_add(const char *node, const char *name, 91 bool has_granularity, uint32_t granularity, 92 bool has_persistent, bool persistent, 93 bool has_disabled, bool disabled, 94 Error **errp) 95 { 96 BlockDriverState *bs; 97 BdrvDirtyBitmap *bitmap; 98 AioContext *aio_context; 99 100 if (!name || name[0] == '\0') { 101 error_setg(errp, "Bitmap name cannot be empty"); 102 return; 103 } 104 105 bs = bdrv_lookup_bs(node, node, errp); 106 if (!bs) { 107 return; 108 } 109 110 aio_context = bdrv_get_aio_context(bs); 111 aio_context_acquire(aio_context); 112 113 if (has_granularity) { 114 if (granularity < 512 || !is_power_of_2(granularity)) { 115 error_setg(errp, "Granularity must be power of 2 " 116 "and at least 512"); 117 goto out; 118 } 119 } else { 120 /* Default to cluster size, if available: */ 121 granularity = bdrv_get_default_bitmap_granularity(bs); 122 } 123 124 if (!has_persistent) { 125 persistent = false; 126 } 127 128 if (!has_disabled) { 129 disabled = false; 130 } 131 132 if (persistent && 133 !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp)) 134 { 135 goto out; 136 } 137 138 bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp); 139 if (bitmap == NULL) { 140 goto out; 141 } 142 143 if (disabled) { 144 bdrv_disable_dirty_bitmap(bitmap); 145 } 146 147 bdrv_dirty_bitmap_set_persistence(bitmap, persistent); 148 149 out: 150 aio_context_release(aio_context); 151 } 152 153 BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name, 154 bool release, 155 BlockDriverState **bitmap_bs, 156 Error **errp) 157 { 158 BlockDriverState *bs; 159 BdrvDirtyBitmap *bitmap; 160 AioContext *aio_context; 161 162 GLOBAL_STATE_CODE(); 163 164 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); 165 if (!bitmap || !bs) { 166 return NULL; 167 } 168 169 aio_context = bdrv_get_aio_context(bs); 170 aio_context_acquire(aio_context); 171 172 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO, 173 errp)) { 174 aio_context_release(aio_context); 175 return NULL; 176 } 177 178 if (bdrv_dirty_bitmap_get_persistence(bitmap) && 179 bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0) 180 { 181 aio_context_release(aio_context); 182 return NULL; 183 } 184 185 if (release) { 186 bdrv_release_dirty_bitmap(bitmap); 187 } 188 189 if (bitmap_bs) { 190 *bitmap_bs = bs; 191 } 192 193 aio_context_release(aio_context); 194 return release ? NULL : bitmap; 195 } 196 197 void qmp_block_dirty_bitmap_remove(const char *node, const char *name, 198 Error **errp) 199 { 200 block_dirty_bitmap_remove(node, name, true, NULL, errp); 201 } 202 203 /** 204 * Completely clear a bitmap, for the purposes of synchronizing a bitmap 205 * immediately after a full backup operation. 206 */ 207 void qmp_block_dirty_bitmap_clear(const char *node, const char *name, 208 Error **errp) 209 { 210 BdrvDirtyBitmap *bitmap; 211 BlockDriverState *bs; 212 213 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); 214 if (!bitmap || !bs) { 215 return; 216 } 217 218 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) { 219 return; 220 } 221 222 bdrv_clear_dirty_bitmap(bitmap, NULL); 223 } 224 225 void qmp_block_dirty_bitmap_enable(const char *node, const char *name, 226 Error **errp) 227 { 228 BlockDriverState *bs; 229 BdrvDirtyBitmap *bitmap; 230 231 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); 232 if (!bitmap) { 233 return; 234 } 235 236 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { 237 return; 238 } 239 240 bdrv_enable_dirty_bitmap(bitmap); 241 } 242 243 void qmp_block_dirty_bitmap_disable(const char *node, const char *name, 244 Error **errp) 245 { 246 BlockDriverState *bs; 247 BdrvDirtyBitmap *bitmap; 248 249 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); 250 if (!bitmap) { 251 return; 252 } 253 254 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { 255 return; 256 } 257 258 bdrv_disable_dirty_bitmap(bitmap); 259 } 260 261 BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target, 262 BlockDirtyBitmapOrStrList *bms, 263 HBitmap **backup, Error **errp) 264 { 265 BlockDriverState *bs; 266 BdrvDirtyBitmap *dst, *src; 267 BlockDirtyBitmapOrStrList *lst; 268 HBitmap *local_backup = NULL; 269 270 GLOBAL_STATE_CODE(); 271 272 dst = block_dirty_bitmap_lookup(node, target, &bs, errp); 273 if (!dst) { 274 return NULL; 275 } 276 277 for (lst = bms; lst; lst = lst->next) { 278 switch (lst->value->type) { 279 const char *name, *node; 280 case QTYPE_QSTRING: 281 name = lst->value->u.local; 282 src = bdrv_find_dirty_bitmap(bs, name); 283 if (!src) { 284 error_setg(errp, "Dirty bitmap '%s' not found", name); 285 goto fail; 286 } 287 break; 288 case QTYPE_QDICT: 289 node = lst->value->u.external.node; 290 name = lst->value->u.external.name; 291 src = block_dirty_bitmap_lookup(node, name, NULL, errp); 292 if (!src) { 293 goto fail; 294 } 295 break; 296 default: 297 abort(); 298 } 299 300 /* We do backup only for first merge operation */ 301 if (!bdrv_merge_dirty_bitmap(dst, src, 302 local_backup ? NULL : &local_backup, 303 errp)) 304 { 305 goto fail; 306 } 307 } 308 309 if (backup) { 310 *backup = local_backup; 311 } else { 312 hbitmap_free(local_backup); 313 } 314 315 return dst; 316 317 fail: 318 if (local_backup) { 319 bdrv_restore_dirty_bitmap(dst, local_backup); 320 } 321 322 return NULL; 323 } 324 325 void qmp_block_dirty_bitmap_merge(const char *node, const char *target, 326 BlockDirtyBitmapOrStrList *bitmaps, 327 Error **errp) 328 { 329 block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp); 330 } 331