Actual fix for live migration with iothread
This commit is contained in:
@@ -880,6 +880,25 @@ static int vitastor_refresh_limits(BlockDriverState *bs)
|
|||||||
// return 0;
|
// return 0;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
// Move the running coroutine to the BlockDriverState's home AioContext.
|
||||||
|
//
|
||||||
|
// The block-coroutine-wrapper generator sets poll_state.ctx to
|
||||||
|
// qemu_get_current_aio_context() in the sync wrappers (bdrv_flush(),
|
||||||
|
// bdrv_pread() etc.). When bdrv_flush_all() runs under BQL from outside the
|
||||||
|
// bs's iothread (e.g. on the migration thread inside do_vm_stop()), that is
|
||||||
|
// the main AioContext, not the iothread that actually owns the bs. The
|
||||||
|
// coroutine then runs on the wrong context while completions are delivered on
|
||||||
|
// the iothread, and racing aio_co_schedule() vs. qemu_aio_coroutine_enter()
|
||||||
|
// on the same coroutine triggers "Co-routine was already scheduled in
|
||||||
|
// aio_co_schedule" and aborts the process (observed during live migration).
|
||||||
|
//
|
||||||
|
// aio_co_reschedule_self() is a no-op when we are already on the target ctx.
|
||||||
|
#if QEMU_VERSION_MAJOR > 5 || QEMU_VERSION_MAJOR == 5 && QEMU_VERSION_MINOR >= 2
|
||||||
|
#define vitastor_co_pin_to_bs_ctx(bs) aio_co_reschedule_self(bdrv_get_aio_context(bs))
|
||||||
|
#else
|
||||||
|
#define vitastor_co_pin_to_bs_ctx(bs) ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
static void vitastor_co_init_task(BlockDriverState *bs, VitastorRPC *task)
|
static void vitastor_co_init_task(BlockDriverState *bs, VitastorRPC *task)
|
||||||
{
|
{
|
||||||
*task = (VitastorRPC) {
|
*task = (VitastorRPC) {
|
||||||
@@ -938,6 +957,7 @@ static int coroutine_fn vitastor_co_preadv(BlockDriverState *bs,
|
|||||||
{
|
{
|
||||||
VitastorClient *client = bs->opaque;
|
VitastorClient *client = bs->opaque;
|
||||||
VitastorRPC task;
|
VitastorRPC task;
|
||||||
|
vitastor_co_pin_to_bs_ctx(bs);
|
||||||
vitastor_co_init_task(bs, &task);
|
vitastor_co_init_task(bs, &task);
|
||||||
task.iov = iov;
|
task.iov = iov;
|
||||||
|
|
||||||
@@ -966,6 +986,7 @@ static int coroutine_fn vitastor_co_pwritev(BlockDriverState *bs,
|
|||||||
{
|
{
|
||||||
VitastorClient *client = bs->opaque;
|
VitastorClient *client = bs->opaque;
|
||||||
VitastorRPC task;
|
VitastorRPC task;
|
||||||
|
vitastor_co_pin_to_bs_ctx(bs);
|
||||||
vitastor_co_init_task(bs, &task);
|
vitastor_co_init_task(bs, &task);
|
||||||
task.iov = iov;
|
task.iov = iov;
|
||||||
|
|
||||||
@@ -1039,6 +1060,7 @@ static int coroutine_fn vitastor_co_block_status(BlockDriverState *bs,
|
|||||||
#endif
|
#endif
|
||||||
VitastorRPC task;
|
VitastorRPC task;
|
||||||
VitastorClient *client = bs->opaque;
|
VitastorClient *client = bs->opaque;
|
||||||
|
vitastor_co_pin_to_bs_ctx(bs);
|
||||||
uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode;
|
uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode;
|
||||||
uint8_t bit = 0;
|
uint8_t bit = 0;
|
||||||
if (client->last_bitmap && client->last_bitmap_inode == inode &&
|
if (client->last_bitmap && client->last_bitmap_inode == inode &&
|
||||||
@@ -1151,6 +1173,7 @@ static int coroutine_fn vitastor_co_flush(BlockDriverState *bs)
|
|||||||
{
|
{
|
||||||
VitastorClient *client = bs->opaque;
|
VitastorClient *client = bs->opaque;
|
||||||
VitastorRPC task;
|
VitastorRPC task;
|
||||||
|
vitastor_co_pin_to_bs_ctx(bs);
|
||||||
vitastor_co_init_task(bs, &task);
|
vitastor_co_init_task(bs, &task);
|
||||||
|
|
||||||
qemu_mutex_lock(&client->mutex);
|
qemu_mutex_lock(&client->mutex);
|
||||||
@@ -1236,6 +1259,8 @@ static BlockDriver bdrv_vitastor = {
|
|||||||
#endif
|
#endif
|
||||||
.bdrv_close = vitastor_close,
|
.bdrv_close = vitastor_close,
|
||||||
|
|
||||||
|
// Re-register fd handlers when the bs is moved to a different AioContext
|
||||||
|
// (live migration, drain, iothread reassignment).
|
||||||
.bdrv_detach_aio_context = vitastor_detach_aio_context,
|
.bdrv_detach_aio_context = vitastor_detach_aio_context,
|
||||||
.bdrv_attach_aio_context = vitastor_attach_aio_context,
|
.bdrv_attach_aio_context = vitastor_attach_aio_context,
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user