block: distinguish between bdrv_create running in coroutine and not

Call two different functions depending on whether bdrv_create
is in coroutine or not, following the same pattern as
generated_co_wrapper functions.

This allows to also call the coroutine function directly,
without using CreateCo or relying in bdrv_create().

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Message-Id: <20221128142337.657646-8-eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Emanuele Giuseppe Esposito 2022-11-28 09:23:30 -05:00 committed by Kevin Wolf
parent a212e675cd
commit 84bdf21f97
1 changed files with 35 additions and 36 deletions

71
block.c
View File

@ -526,63 +526,62 @@ typedef struct CreateCo {
Error *err;
} CreateCo;
static int coroutine_fn bdrv_co_create(BlockDriver *drv, const char *filename,
QemuOpts *opts, Error **errp)
{
int ret;
GLOBAL_STATE_CODE();
ERRP_GUARD();
if (!drv->bdrv_co_create_opts) {
error_setg(errp, "Driver '%s' does not support image creation",
drv->format_name);
return -ENOTSUP;
}
ret = drv->bdrv_co_create_opts(drv, filename, opts, errp);
if (ret < 0 && !*errp) {
error_setg_errno(errp, -ret, "Could not create image");
}
return ret;
}
static void coroutine_fn bdrv_create_co_entry(void *opaque)
{
Error *local_err = NULL;
int ret;
CreateCo *cco = opaque;
assert(cco->drv);
GLOBAL_STATE_CODE();
ret = cco->drv->bdrv_co_create_opts(cco->drv,
cco->filename, cco->opts, &local_err);
error_propagate(&cco->err, local_err);
cco->ret = ret;
cco->ret = bdrv_co_create(cco->drv, cco->filename, cco->opts, &cco->err);
aio_wait_kick();
}
int bdrv_create(BlockDriver *drv, const char* filename,
QemuOpts *opts, Error **errp)
{
int ret;
GLOBAL_STATE_CODE();
Coroutine *co;
CreateCo cco = {
.drv = drv,
.filename = filename,
.opts = opts,
.ret = NOT_DONE,
.err = NULL,
};
if (!drv->bdrv_co_create_opts) {
error_setg(errp, "Driver '%s' does not support image creation", drv->format_name);
return -ENOTSUP;
}
if (qemu_in_coroutine()) {
/* Fast-path if already in coroutine context */
bdrv_create_co_entry(&cco);
return bdrv_co_create(drv, filename, opts, errp);
} else {
Coroutine *co;
CreateCo cco = {
.drv = drv,
.filename = filename,
.opts = opts,
.ret = NOT_DONE,
.err = NULL,
};
co = qemu_coroutine_create(bdrv_create_co_entry, &cco);
qemu_coroutine_enter(co);
while (cco.ret == NOT_DONE) {
aio_poll(qemu_get_aio_context(), true);
}
error_propagate(errp, cco.err);
return cco.ret;
}
ret = cco.ret;
if (ret < 0) {
if (cco.err) {
error_propagate(errp, cco.err);
} else {
error_setg_errno(errp, -ret, "Could not create image");
}
}
return ret;
}
/**