diff options
-rw-r--r-- | block.c | 2 | ||||
-rw-r--r-- | block/dirty-bitmap.c | 15 | ||||
-rw-r--r-- | blockdev.c | 79 | ||||
-rw-r--r-- | include/block/dirty-bitmap.h | 2 | ||||
-rw-r--r-- | migration/block-dirty-bitmap.c | 2 | ||||
-rw-r--r-- | qapi/transaction.json | 2 |
6 files changed, 85 insertions, 17 deletions
@@ -5346,7 +5346,7 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, for (bm = bdrv_dirty_bitmap_next(bs, NULL); bm; bm = bdrv_dirty_bitmap_next(bs, bm)) { - bdrv_dirty_bitmap_set_migration(bm, false); + bdrv_dirty_bitmap_skip_store(bm, false); } ret = refresh_total_sectors(bs, bs->total_sectors); diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 75a5daf116..134e0c9a0c 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -48,10 +48,9 @@ struct BdrvDirtyBitmap { bool inconsistent; /* bitmap is persistent, but inconsistent. It cannot be used at all in any way, except a QMP user can remove it. */ - bool migration; /* Bitmap is selected for migration, it should - not be stored on the next inactivation - (persistent flag doesn't matter until next - invalidation).*/ + bool skip_store; /* We are either migrating or deleting this + * bitmap; it should not be stored on the next + * inactivation. */ QLIST_ENTRY(BdrvDirtyBitmap) list; }; @@ -762,16 +761,16 @@ void bdrv_dirty_bitmap_set_inconsistent(BdrvDirtyBitmap *bitmap) } /* Called with BQL taken. */ -void bdrv_dirty_bitmap_set_migration(BdrvDirtyBitmap *bitmap, bool migration) +void bdrv_dirty_bitmap_skip_store(BdrvDirtyBitmap *bitmap, bool skip) { qemu_mutex_lock(bitmap->mutex); - bitmap->migration = migration; + bitmap->skip_store = skip; qemu_mutex_unlock(bitmap->mutex); } bool bdrv_dirty_bitmap_get_persistence(BdrvDirtyBitmap *bitmap) { - return bitmap->persistent && !bitmap->migration; + return bitmap->persistent && !bitmap->skip_store; } bool bdrv_dirty_bitmap_inconsistent(const BdrvDirtyBitmap *bitmap) @@ -783,7 +782,7 @@ bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs) { BdrvDirtyBitmap *bm; QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { - if (bm->persistent && !bm->readonly && !bm->migration) { + if (bm->persistent && !bm->readonly && !bm->skip_store) { return true; } } diff --git a/blockdev.c b/blockdev.c index bcd766a1a2..210226d829 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2136,6 +2136,51 @@ static void block_dirty_bitmap_merge_prepare(BlkActionState *common, errp); } +static BdrvDirtyBitmap *do_block_dirty_bitmap_remove( + const char *node, const char *name, bool release, + BlockDriverState **bitmap_bs, Error **errp); + +static void block_dirty_bitmap_remove_prepare(BlkActionState *common, + Error **errp) +{ + BlockDirtyBitmap *action; + BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState, + common, common); + + if (action_check_completion_mode(common, errp) < 0) { + return; + } + + action = common->action->u.block_dirty_bitmap_remove.data; + + state->bitmap = do_block_dirty_bitmap_remove(action->node, action->name, + false, &state->bs, errp); + if (state->bitmap) { + bdrv_dirty_bitmap_skip_store(state->bitmap, true); + bdrv_dirty_bitmap_set_busy(state->bitmap, true); + } +} + +static void block_dirty_bitmap_remove_abort(BlkActionState *common) +{ + BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState, + common, common); + + if (state->bitmap) { + bdrv_dirty_bitmap_skip_store(state->bitmap, false); + bdrv_dirty_bitmap_set_busy(state->bitmap, false); + } +} + +static void block_dirty_bitmap_remove_commit(BlkActionState *common) +{ + BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState, + common, common); + + bdrv_dirty_bitmap_set_busy(state->bitmap, false); + bdrv_release_dirty_bitmap(state->bs, state->bitmap); +} + static void abort_prepare(BlkActionState *common, Error **errp) { error_setg(errp, "Transaction aborted using Abort action"); @@ -2213,6 +2258,12 @@ static const BlkActionOps actions[] = { .commit = block_dirty_bitmap_free_backup, .abort = block_dirty_bitmap_restore, }, + [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_REMOVE] = { + .instance_size = sizeof(BlockDirtyBitmapState), + .prepare = block_dirty_bitmap_remove_prepare, + .commit = block_dirty_bitmap_remove_commit, + .abort = block_dirty_bitmap_remove_abort, + }, /* Where are transactions for MIRROR, COMMIT and STREAM? * Although these blockjobs use transaction callbacks like the backup job, * these jobs do not necessarily adhere to transaction semantics. @@ -2871,20 +2922,21 @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name, bdrv_dirty_bitmap_set_persistence(bitmap, persistent); } -void qmp_block_dirty_bitmap_remove(const char *node, const char *name, - Error **errp) +static BdrvDirtyBitmap *do_block_dirty_bitmap_remove( + const char *node, const char *name, bool release, + BlockDriverState **bitmap_bs, Error **errp) { BlockDriverState *bs; BdrvDirtyBitmap *bitmap; bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp); if (!bitmap || !bs) { - return; + return NULL; } if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO, errp)) { - return; + return NULL; } if (bdrv_dirty_bitmap_get_persistence(bitmap)) { @@ -2894,13 +2946,28 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name, aio_context_acquire(aio_context); bdrv_remove_persistent_dirty_bitmap(bs, name, &local_err); aio_context_release(aio_context); + if (local_err != NULL) { error_propagate(errp, local_err); - return; + return NULL; } } - bdrv_release_dirty_bitmap(bs, bitmap); + if (release) { + bdrv_release_dirty_bitmap(bs, bitmap); + } + + if (bitmap_bs) { + *bitmap_bs = bs; + } + + return release ? NULL : bitmap; +} + +void qmp_block_dirty_bitmap_remove(const char *node, const char *name, + Error **errp) +{ + do_block_dirty_bitmap_remove(node, name, true, NULL, errp); } /** diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index 0120ef3f05..4b4b731b46 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -83,7 +83,7 @@ void bdrv_dirty_bitmap_set_inconsistent(BdrvDirtyBitmap *bitmap); void bdrv_dirty_bitmap_set_busy(BdrvDirtyBitmap *bitmap, bool busy); void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src, HBitmap **backup, Error **errp); -void bdrv_dirty_bitmap_set_migration(BdrvDirtyBitmap *bitmap, bool migration); +void bdrv_dirty_bitmap_skip_store(BdrvDirtyBitmap *bitmap, bool skip); bool bdrv_dirty_bitmap_get(BdrvDirtyBitmap *bitmap, int64_t offset); /* Functions that require manual locking. */ diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c index a09a893c02..dd40724b9e 100644 --- a/migration/block-dirty-bitmap.c +++ b/migration/block-dirty-bitmap.c @@ -326,7 +326,7 @@ static int init_dirty_bitmap_migration(void) /* unset migration flags here, to not roll back it */ QSIMPLEQ_FOREACH(dbms, &dirty_bitmap_mig_state.dbms_list, entry) { - bdrv_dirty_bitmap_set_migration(dbms->bitmap, true); + bdrv_dirty_bitmap_skip_store(dbms->bitmap, true); } if (QSIMPLEQ_EMPTY(&dirty_bitmap_mig_state.dbms_list)) { diff --git a/qapi/transaction.json b/qapi/transaction.json index 95edb78227..0590dbcd1a 100644 --- a/qapi/transaction.json +++ b/qapi/transaction.json @@ -45,6 +45,7 @@ # # - @abort: since 1.6 # - @block-dirty-bitmap-add: since 2.5 +# - @block-dirty-bitmap-remove: since 4.2 # - @block-dirty-bitmap-clear: since 2.5 # - @block-dirty-bitmap-enable: since 4.0 # - @block-dirty-bitmap-disable: since 4.0 @@ -61,6 +62,7 @@ 'data': { 'abort': 'Abort', 'block-dirty-bitmap-add': 'BlockDirtyBitmapAdd', + 'block-dirty-bitmap-remove': 'BlockDirtyBitmap', 'block-dirty-bitmap-clear': 'BlockDirtyBitmap', 'block-dirty-bitmap-enable': 'BlockDirtyBitmap', 'block-dirty-bitmap-disable': 'BlockDirtyBitmap', |