Fix deadlocks possible in qemu-img after fixing iothread

Deadlock was caused by switching QEMU coroutines directly inside
vitastor_co_read_bitmap_cb() callback. The correct way is to schedule a BH
/BH is a QEMU term for setImmediate() :)/, same as in read and write callbacks.
hotfix-1.0.0
Vitaliy Filippov 2023-07-18 23:30:20 +03:00
parent a0aac7eb2a
commit ba7427020e
1 changed files with 16 additions and 16 deletions

View File

@ -266,17 +266,15 @@ static void vitastor_schedule_uring_handler(VitastorClient *client)
replay_bh_schedule_oneshot_event(client->ctx, vitastor_uring_handler, opaque); replay_bh_schedule_oneshot_event(client->ctx, vitastor_uring_handler, opaque);
#elif QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 8 #elif QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 8
aio_bh_schedule_oneshot(client->ctx, vitastor_uring_handler, opaque); aio_bh_schedule_oneshot(client->ctx, vitastor_uring_handler, opaque);
#elif QEMU_VERSION_MAJOR >= 2 #else
VitastorBH *vbh = (VitastorBH*)malloc(sizeof(VitastorBH)); VitastorBH *vbh = (VitastorBH*)malloc(sizeof(VitastorBH));
vbh->cli = client; vbh->cli = client;
#if QEMU_VERSION_MAJOR >= 2
vbh->bh = aio_bh_new(bdrv_get_aio_context(task->bs), vitastor_bh_uring_handler, vbh); vbh->bh = aio_bh_new(bdrv_get_aio_context(task->bs), vitastor_bh_uring_handler, vbh);
qemu_bh_schedule(vbh->bh);
#else #else
client->bh_uring_scheduled = 0; vbh->bh = qemu_bh_new(vitastor_bh_uring_handler, vbh);
do #endif
{ qemu_bh_schedule(vbh->bh);
vitastor_c_uring_handle_events(client->proxy);
} while (vitastor_c_uring_has_work(client->proxy));
#endif #endif
} }
} }
@ -664,7 +662,8 @@ static void vitastor_co_generic_cb(void *opaque, long retval)
task->bh = aio_bh_new(bdrv_get_aio_context(task->bs), vitastor_co_generic_bh_cb, opaque); task->bh = aio_bh_new(bdrv_get_aio_context(task->bs), vitastor_co_generic_bh_cb, opaque);
qemu_bh_schedule(task->bh); qemu_bh_schedule(task->bh);
#else #else
vitastor_co_generic_bh_cb(opaque); task->bh = qemu_bh_new(vitastor_co_generic_bh_cb, opaque);
qemu_bh_schedule(task->bh);
#endif #endif
} }
@ -741,7 +740,6 @@ static void vitastor_co_read_bitmap_cb(void *opaque, long retval, uint8_t *bitma
VitastorRPC *task = opaque; VitastorRPC *task = opaque;
VitastorClient *client = task->bs->opaque; VitastorClient *client = task->bs->opaque;
task->ret = retval; task->ret = retval;
task->complete = 1;
if (retval >= 0) if (retval >= 0)
{ {
task->bitmap = bitmap; task->bitmap = bitmap;
@ -753,15 +751,17 @@ static void vitastor_co_read_bitmap_cb(void *opaque, long retval, uint8_t *bitma
client->last_bitmap = bitmap; client->last_bitmap = bitmap;
} }
} }
if (qemu_coroutine_self() != task->co) #if QEMU_VERSION_MAJOR > 4 || QEMU_VERSION_MAJOR == 4 && QEMU_VERSION_MINOR >= 2
{ replay_bh_schedule_oneshot_event(bdrv_get_aio_context(task->bs), vitastor_co_generic_bh_cb, opaque);
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 8 #elif QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 8
aio_co_wake(task->co); aio_bh_schedule_oneshot(bdrv_get_aio_context(task->bs), vitastor_co_generic_bh_cb, opaque);
#elif QEMU_VERSION_MAJOR >= 2
task->bh = aio_bh_new(bdrv_get_aio_context(task->bs), vitastor_co_generic_bh_cb, opaque);
qemu_bh_schedule(task->bh);
#else #else
qemu_coroutine_enter(task->co, NULL); task->bh = qemu_bh_new(vitastor_co_generic_bh_cb, opaque);
qemu_aio_release(task); qemu_bh_schedule(task->bh);
#endif #endif
}
} }
static int coroutine_fn vitastor_co_block_status( static int coroutine_fn vitastor_co_block_status(