mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
qed: Implement .bdrv_drain
The "need_check_timer" is used to clear the "NEED_CHECK" flag in the image header after a grace period once metadata update has finished. In compliance to the bdrv_drain semantics we should make sure it remains deleted once .bdrv_drain is called. We cannot reuse qed_need_check_timer_cb because here it doesn't satisfy the assertion. Do the "plug" and "flush" calls manually. Signed-off-by: Fam Zheng <famz@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-id: 1447064214-29930-10-git-send-email-famz@redhat.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
+113
-1
@@ -1874,6 +1874,106 @@ static void blockdev_backup_clean(BlkTransactionState *common)
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct BlockDirtyBitmapState {
|
||||
BlkTransactionState common;
|
||||
BdrvDirtyBitmap *bitmap;
|
||||
BlockDriverState *bs;
|
||||
AioContext *aio_context;
|
||||
HBitmap *backup;
|
||||
bool prepared;
|
||||
} BlockDirtyBitmapState;
|
||||
|
||||
static void block_dirty_bitmap_add_prepare(BlkTransactionState *common,
|
||||
Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
BlockDirtyBitmapAdd *action;
|
||||
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
|
||||
common, common);
|
||||
|
||||
action = common->action->block_dirty_bitmap_add;
|
||||
/* AIO context taken and released within qmp_block_dirty_bitmap_add */
|
||||
qmp_block_dirty_bitmap_add(action->node, action->name,
|
||||
action->has_granularity, action->granularity,
|
||||
&local_err);
|
||||
|
||||
if (!local_err) {
|
||||
state->prepared = true;
|
||||
} else {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
}
|
||||
|
||||
static void block_dirty_bitmap_add_abort(BlkTransactionState *common)
|
||||
{
|
||||
BlockDirtyBitmapAdd *action;
|
||||
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
|
||||
common, common);
|
||||
|
||||
action = common->action->block_dirty_bitmap_add;
|
||||
/* Should not be able to fail: IF the bitmap was added via .prepare(),
|
||||
* then the node reference and bitmap name must have been valid.
|
||||
*/
|
||||
if (state->prepared) {
|
||||
qmp_block_dirty_bitmap_remove(action->node, action->name, &error_abort);
|
||||
}
|
||||
}
|
||||
|
||||
static void block_dirty_bitmap_clear_prepare(BlkTransactionState *common,
|
||||
Error **errp)
|
||||
{
|
||||
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
|
||||
common, common);
|
||||
BlockDirtyBitmap *action;
|
||||
|
||||
action = common->action->block_dirty_bitmap_clear;
|
||||
state->bitmap = block_dirty_bitmap_lookup(action->node,
|
||||
action->name,
|
||||
&state->bs,
|
||||
&state->aio_context,
|
||||
errp);
|
||||
if (!state->bitmap) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bdrv_dirty_bitmap_frozen(state->bitmap)) {
|
||||
error_setg(errp, "Cannot modify a frozen bitmap");
|
||||
return;
|
||||
} else if (!bdrv_dirty_bitmap_enabled(state->bitmap)) {
|
||||
error_setg(errp, "Cannot clear a disabled bitmap");
|
||||
return;
|
||||
}
|
||||
|
||||
bdrv_clear_dirty_bitmap(state->bitmap, &state->backup);
|
||||
/* AioContext is released in .clean() */
|
||||
}
|
||||
|
||||
static void block_dirty_bitmap_clear_abort(BlkTransactionState *common)
|
||||
{
|
||||
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
|
||||
common, common);
|
||||
|
||||
bdrv_undo_clear_dirty_bitmap(state->bitmap, state->backup);
|
||||
}
|
||||
|
||||
static void block_dirty_bitmap_clear_commit(BlkTransactionState *common)
|
||||
{
|
||||
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
|
||||
common, common);
|
||||
|
||||
hbitmap_free(state->backup);
|
||||
}
|
||||
|
||||
static void block_dirty_bitmap_clear_clean(BlkTransactionState *common)
|
||||
{
|
||||
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
|
||||
common, common);
|
||||
|
||||
if (state->aio_context) {
|
||||
aio_context_release(state->aio_context);
|
||||
}
|
||||
}
|
||||
|
||||
static void abort_prepare(BlkTransactionState *common, Error **errp)
|
||||
{
|
||||
error_setg(errp, "Transaction aborted using Abort action");
|
||||
@@ -1921,6 +2021,18 @@ static const BdrvActionOps actions[] = {
|
||||
.abort = internal_snapshot_abort,
|
||||
.clean = internal_snapshot_clean,
|
||||
},
|
||||
[TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_ADD] = {
|
||||
.instance_size = sizeof(BlockDirtyBitmapState),
|
||||
.prepare = block_dirty_bitmap_add_prepare,
|
||||
.abort = block_dirty_bitmap_add_abort,
|
||||
},
|
||||
[TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_CLEAR] = {
|
||||
.instance_size = sizeof(BlockDirtyBitmapState),
|
||||
.prepare = block_dirty_bitmap_clear_prepare,
|
||||
.commit = block_dirty_bitmap_clear_commit,
|
||||
.abort = block_dirty_bitmap_clear_abort,
|
||||
.clean = block_dirty_bitmap_clear_clean,
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2472,7 +2584,7 @@ void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
|
||||
goto out;
|
||||
}
|
||||
|
||||
bdrv_clear_dirty_bitmap(bitmap);
|
||||
bdrv_clear_dirty_bitmap(bitmap, NULL);
|
||||
|
||||
out:
|
||||
aio_context_release(aio_context);
|
||||
|
||||
Reference in New Issue
Block a user