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