Skip to content

Commit a6d23d5

Browse files
Vladimir Sementsov-OgievskiyXanClic
authored andcommitted
block/block-copy: add block_copy_cancel
Add function to cancel running async block-copy call. It will be used in backup. Signed-off-by: Vladimir Sementsov-Ogievskiy <[email protected]> Reviewed-by: Max Reitz <[email protected]> Message-Id: <[email protected]> Signed-off-by: Max Reitz <[email protected]>
1 parent 7e032df commit a6d23d5

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

block/block-copy.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ typedef struct BlockCopyCallState {
5151
int ret;
5252
bool finished;
5353
QemuCoSleepState *sleep_state;
54+
bool cancelled;
5455

5556
/* OUT parameters */
5657
bool error_is_read;
@@ -594,7 +595,7 @@ block_copy_dirty_clusters(BlockCopyCallState *call_state)
594595
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
595596
assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
596597

597-
while (bytes && aio_task_pool_status(aio) == 0) {
598+
while (bytes && aio_task_pool_status(aio) == 0 && !call_state->cancelled) {
598599
BlockCopyTask *task;
599600
int64_t status_bytes;
600601

@@ -707,7 +708,7 @@ static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
707708
do {
708709
ret = block_copy_dirty_clusters(call_state);
709710

710-
if (ret == 0) {
711+
if (ret == 0 && !call_state->cancelled) {
711712
ret = block_copy_wait_one(call_state->s, call_state->offset,
712713
call_state->bytes);
713714
}
@@ -721,7 +722,7 @@ static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
721722
* 2. We have waited for some intersecting block-copy request
722723
* It may have failed and produced new dirty bits.
723724
*/
724-
} while (ret > 0);
725+
} while (ret > 0 && !call_state->cancelled);
725726

726727
call_state->finished = true;
727728

@@ -801,12 +802,19 @@ bool block_copy_call_finished(BlockCopyCallState *call_state)
801802

802803
bool block_copy_call_succeeded(BlockCopyCallState *call_state)
803804
{
804-
return call_state->finished && call_state->ret == 0;
805+
return call_state->finished && !call_state->cancelled &&
806+
call_state->ret == 0;
805807
}
806808

807809
bool block_copy_call_failed(BlockCopyCallState *call_state)
808810
{
809-
return call_state->finished && call_state->ret < 0;
811+
return call_state->finished && !call_state->cancelled &&
812+
call_state->ret < 0;
813+
}
814+
815+
bool block_copy_call_cancelled(BlockCopyCallState *call_state)
816+
{
817+
return call_state->cancelled;
810818
}
811819

812820
int block_copy_call_status(BlockCopyCallState *call_state, bool *error_is_read)
@@ -818,6 +826,12 @@ int block_copy_call_status(BlockCopyCallState *call_state, bool *error_is_read)
818826
return call_state->ret;
819827
}
820828

829+
void block_copy_call_cancel(BlockCopyCallState *call_state)
830+
{
831+
call_state->cancelled = true;
832+
block_copy_kick(call_state);
833+
}
834+
821835
BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s)
822836
{
823837
return s->copy_bitmap;

include/block/block-copy.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,24 @@ void block_copy_call_free(BlockCopyCallState *call_state);
7474
bool block_copy_call_finished(BlockCopyCallState *call_state);
7575
bool block_copy_call_succeeded(BlockCopyCallState *call_state);
7676
bool block_copy_call_failed(BlockCopyCallState *call_state);
77+
bool block_copy_call_cancelled(BlockCopyCallState *call_state);
7778
int block_copy_call_status(BlockCopyCallState *call_state, bool *error_is_read);
7879

7980
void block_copy_set_speed(BlockCopyState *s, uint64_t speed);
8081
void block_copy_kick(BlockCopyCallState *call_state);
8182

83+
/*
84+
* Cancel running block-copy call.
85+
*
86+
* Cancel leaves block-copy state valid: dirty bits are correct and you may use
87+
* cancel + <run block_copy with same parameters> to emulate pause/resume.
88+
*
89+
* Note also, that the cancel is async: it only marks block-copy call to be
90+
* cancelled. So, the call may be cancelled (block_copy_call_cancelled() reports
91+
* true) but not yet finished (block_copy_call_finished() reports false).
92+
*/
93+
void block_copy_call_cancel(BlockCopyCallState *call_state);
94+
8295
BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s);
8396
void block_copy_set_skip_unallocated(BlockCopyState *s, bool skip);
8497

0 commit comments

Comments
 (0)