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