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 99 if (!name || name[0] == '\0') { 100 error_setg(errp, "Bitmap name cannot be empty"); 101 return; 102 } 103 104 bs = bdrv_lookup_bs(node, node, errp); 105 if (!bs) { 106 return; 107 } 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 return; 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 return; 132 } 133 134 bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp); 135 if (bitmap == NULL) { 136 return; 137 } 138 139 if (disabled) { 140 bdrv_disable_dirty_bitmap(bitmap); 141 } 142 143 bdrv_dirty_bitmap_set_persistence(bitmap, persistent); 144 } 145 146 BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name, 147 bool release, 148 BlockDriverState **bitmap_bs, 149 Error **errp) 150 { 151 BlockDriverState *bs; 152 BdrvDirtyBitmap *bitmap; 153 154 GLOBAL_STATE_CODE(); 155 156 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); 157 if (!bitmap || !bs) { 158 return NULL; 159 } 160 161 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO, 162 errp)) { 163 return NULL; 164 } 165 166 if (bdrv_dirty_bitmap_get_persistence(bitmap) && 167 bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0) 168 { 169 return NULL; 170 } 171 172 if (release) { 173 bdrv_release_dirty_bitmap(bitmap); 174 } 175 176 if (bitmap_bs) { 177 *bitmap_bs = bs; 178 } 179 180 return release ? NULL : bitmap; 181 } 182 183 void qmp_block_dirty_bitmap_remove(const char *node, const char *name, 184 Error **errp) 185 { 186 block_dirty_bitmap_remove(node, name, true, NULL, errp); 187 } 188 189 /** 190 * Completely clear a bitmap, for the purposes of synchronizing a bitmap 191 * immediately after a full backup operation. 192 */ 193 void qmp_block_dirty_bitmap_clear(const char *node, const char *name, 194 Error **errp) 195 { 196 BdrvDirtyBitmap *bitmap; 197 BlockDriverState *bs; 198 199 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); 200 if (!bitmap || !bs) { 201 return; 202 } 203 204 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) { 205 return; 206 } 207 208 bdrv_clear_dirty_bitmap(bitmap, NULL); 209 } 210 211 void qmp_block_dirty_bitmap_enable(const char *node, const char *name, 212 Error **errp) 213 { 214 BlockDriverState *bs; 215 BdrvDirtyBitmap *bitmap; 216 217 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); 218 if (!bitmap) { 219 return; 220 } 221 222 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { 223 return; 224 } 225 226 bdrv_enable_dirty_bitmap(bitmap); 227 } 228 229 void qmp_block_dirty_bitmap_disable(const char *node, const char *name, 230 Error **errp) 231 { 232 BlockDriverState *bs; 233 BdrvDirtyBitmap *bitmap; 234 235 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); 236 if (!bitmap) { 237 return; 238 } 239 240 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) { 241 return; 242 } 243 244 bdrv_disable_dirty_bitmap(bitmap); 245 } 246 247 BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *dst_node, 248 const char *dst_bitmap, 249 BlockDirtyBitmapOrStrList *bms, 250 HBitmap **backup, Error **errp) 251 { 252 BlockDriverState *bs; 253 BdrvDirtyBitmap *dst, *src; 254 BlockDirtyBitmapOrStrList *lst; 255 const char *src_node, *src_bitmap; 256 HBitmap *local_backup = NULL; 257 258 GLOBAL_STATE_CODE(); 259 260 dst = block_dirty_bitmap_lookup(dst_node, dst_bitmap, &bs, errp); 261 if (!dst) { 262 return NULL; 263 } 264 265 for (lst = bms; lst; lst = lst->next) { 266 switch (lst->value->type) { 267 case QTYPE_QSTRING: 268 src_bitmap = lst->value->u.local; 269 src = bdrv_find_dirty_bitmap(bs, src_bitmap); 270 if (!src) { 271 error_setg(errp, "Dirty bitmap '%s' not found", src_bitmap); 272 goto fail; 273 } 274 break; 275 case QTYPE_QDICT: 276 src_node = lst->value->u.external.node; 277 src_bitmap = lst->value->u.external.name; 278 src = block_dirty_bitmap_lookup(src_node, src_bitmap, NULL, errp); 279 if (!src) { 280 goto fail; 281 } 282 break; 283 default: 284 abort(); 285 } 286 287 /* We do backup only for first merge operation */ 288 if (!bdrv_merge_dirty_bitmap(dst, src, 289 local_backup ? NULL : &local_backup, 290 errp)) 291 { 292 goto fail; 293 } 294 } 295 296 if (backup) { 297 *backup = local_backup; 298 } else { 299 hbitmap_free(local_backup); 300 } 301 302 return dst; 303 304 fail: 305 if (local_backup) { 306 bdrv_restore_dirty_bitmap(dst, local_backup); 307 } 308 309 return NULL; 310 } 311 312 void qmp_block_dirty_bitmap_merge(const char *node, const char *target, 313 BlockDirtyBitmapOrStrList *bitmaps, 314 Error **errp) 315 { 316 block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp); 317 } 318