qmp: add block-dirty-bitmap-clear
Add bdrv_clear_dirty_bitmap and a matching QMP command, qmp_block_dirty_bitmap_clear that enables a user to reset the bitmap attached to a drive. This allows us to reset a bitmap in the event of a full drive backup. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-id: 1429314609-29776-12-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
d58d845397
commit
e74e6b78e6
8
block.c
8
block.c
@ -63,6 +63,7 @@
|
|||||||
struct BdrvDirtyBitmap {
|
struct BdrvDirtyBitmap {
|
||||||
HBitmap *bitmap;
|
HBitmap *bitmap;
|
||||||
BdrvDirtyBitmap *successor;
|
BdrvDirtyBitmap *successor;
|
||||||
|
int64_t size;
|
||||||
char *name;
|
char *name;
|
||||||
bool disabled;
|
bool disabled;
|
||||||
QLIST_ENTRY(BdrvDirtyBitmap) list;
|
QLIST_ENTRY(BdrvDirtyBitmap) list;
|
||||||
@ -5557,6 +5558,7 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
|
|||||||
}
|
}
|
||||||
bitmap = g_new0(BdrvDirtyBitmap, 1);
|
bitmap = g_new0(BdrvDirtyBitmap, 1);
|
||||||
bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(sector_granularity));
|
bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(sector_granularity));
|
||||||
|
bitmap->size = bitmap_size;
|
||||||
bitmap->name = g_strdup(name);
|
bitmap->name = g_strdup(name);
|
||||||
bitmap->disabled = false;
|
bitmap->disabled = false;
|
||||||
QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
|
QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
|
||||||
@ -5759,6 +5761,12 @@ void bdrv_reset_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
|
|||||||
hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors);
|
hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap)
|
||||||
|
{
|
||||||
|
assert(bdrv_dirty_bitmap_enabled(bitmap));
|
||||||
|
hbitmap_reset(bitmap->bitmap, 0, bitmap->size);
|
||||||
|
}
|
||||||
|
|
||||||
static void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
|
static void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
|
||||||
int nr_sectors)
|
int nr_sectors)
|
||||||
{
|
{
|
||||||
|
34
blockdev.c
34
blockdev.c
@ -2079,6 +2079,40 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
|
|||||||
aio_context_release(aio_context);
|
aio_context_release(aio_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Completely clear a bitmap, for the purposes of synchronizing a bitmap
|
||||||
|
* immediately after a full backup operation.
|
||||||
|
*/
|
||||||
|
void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
AioContext *aio_context;
|
||||||
|
BdrvDirtyBitmap *bitmap;
|
||||||
|
BlockDriverState *bs;
|
||||||
|
|
||||||
|
bitmap = block_dirty_bitmap_lookup(node, name, &bs, &aio_context, errp);
|
||||||
|
if (!bitmap || !bs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bdrv_dirty_bitmap_frozen(bitmap)) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Bitmap '%s' is currently frozen and cannot be modified",
|
||||||
|
name);
|
||||||
|
goto out;
|
||||||
|
} else if (!bdrv_dirty_bitmap_enabled(bitmap)) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Bitmap '%s' is currently disabled and cannot be cleared",
|
||||||
|
name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bdrv_clear_dirty_bitmap(bitmap);
|
||||||
|
|
||||||
|
out:
|
||||||
|
aio_context_release(aio_context);
|
||||||
|
}
|
||||||
|
|
||||||
int hmp_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
int hmp_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||||
{
|
{
|
||||||
const char *id = qdict_get_str(qdict, "id");
|
const char *id = qdict_get_str(qdict, "id");
|
||||||
|
@ -479,6 +479,7 @@ void bdrv_set_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
|
|||||||
int64_t cur_sector, int nr_sectors);
|
int64_t cur_sector, int nr_sectors);
|
||||||
void bdrv_reset_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
|
void bdrv_reset_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
|
||||||
int64_t cur_sector, int nr_sectors);
|
int64_t cur_sector, int nr_sectors);
|
||||||
|
void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap);
|
||||||
void bdrv_dirty_iter_init(BlockDriverState *bs,
|
void bdrv_dirty_iter_init(BlockDriverState *bs,
|
||||||
BdrvDirtyBitmap *bitmap, struct HBitmapIter *hbi);
|
BdrvDirtyBitmap *bitmap, struct HBitmapIter *hbi);
|
||||||
void bdrv_set_dirty_iter(struct HBitmapIter *hbi, int64_t offset);
|
void bdrv_set_dirty_iter(struct HBitmapIter *hbi, int64_t offset);
|
||||||
|
@ -1021,6 +1021,20 @@
|
|||||||
{ 'command': 'block-dirty-bitmap-remove',
|
{ 'command': 'block-dirty-bitmap-remove',
|
||||||
'data': 'BlockDirtyBitmap' }
|
'data': 'BlockDirtyBitmap' }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @block-dirty-bitmap-clear
|
||||||
|
#
|
||||||
|
# Clear (reset) a dirty bitmap on the device
|
||||||
|
#
|
||||||
|
# Returns: nothing on success
|
||||||
|
# If @node is not a valid block device, DeviceNotFound
|
||||||
|
# If @name is not found, GenericError with an explanation
|
||||||
|
#
|
||||||
|
# Since 2.4
|
||||||
|
##
|
||||||
|
{ 'command': 'block-dirty-bitmap-clear',
|
||||||
|
'data': 'BlockDirtyBitmap' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @block_set_io_throttle:
|
# @block_set_io_throttle:
|
||||||
#
|
#
|
||||||
|
@ -1361,6 +1361,35 @@ Example:
|
|||||||
"name": "bitmap0" } }
|
"name": "bitmap0" } }
|
||||||
<- { "return": {} }
|
<- { "return": {} }
|
||||||
|
|
||||||
|
EQMP
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "block-dirty-bitmap-clear",
|
||||||
|
.args_type = "node:B,name:s",
|
||||||
|
.mhandler.cmd_new = qmp_marshal_input_block_dirty_bitmap_clear,
|
||||||
|
},
|
||||||
|
|
||||||
|
SQMP
|
||||||
|
|
||||||
|
block-dirty-bitmap-clear
|
||||||
|
------------------------
|
||||||
|
Since 2.4
|
||||||
|
|
||||||
|
Reset the dirty bitmap associated with a node so that an incremental backup
|
||||||
|
from this point in time forward will only backup clusters modified after this
|
||||||
|
clear operation.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
- "node": device/node on which to remove dirty bitmap (json-string)
|
||||||
|
- "name": name of the dirty bitmap to remove (json-string)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
-> { "execute": "block-dirty-bitmap-clear", "arguments": { "node": "drive0",
|
||||||
|
"name": "bitmap0" } }
|
||||||
|
<- { "return": {} }
|
||||||
|
|
||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user