block: make bdrv_create adopt coroutine

The current qemu.git introduces failure with preallocation and some
sizes:

qemu-img create -f qcow2 new.img 976563K -o preallocation=metadata
qemu-img: qemu-coroutine-lock.c:111: qemu_co_mutex_unlock: Assertion
`mutex->locked == 1' failed.

And lock needs to work in coroutine context. So to fix this issue, we
need to make bdrv_create adopt coroutine at first.

Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Zhi Yong Wu 2012-05-07 16:50:42 +08:00 committed by Kevin Wolf
parent 54e6814360
commit 5b7e1542cf

46
block.c
View File

@ -341,13 +341,53 @@ BlockDriver *bdrv_find_whitelisted_format(const char *format_name)
return drv && bdrv_is_whitelisted(drv) ? drv : NULL;
}
typedef struct CreateCo {
BlockDriver *drv;
char *filename;
QEMUOptionParameter *options;
int ret;
} CreateCo;
static void coroutine_fn bdrv_create_co_entry(void *opaque)
{
CreateCo *cco = opaque;
assert(cco->drv);
cco->ret = cco->drv->bdrv_create(cco->filename, cco->options);
}
int bdrv_create(BlockDriver *drv, const char* filename,
QEMUOptionParameter *options)
{
if (!drv->bdrv_create)
return -ENOTSUP;
int ret;
return drv->bdrv_create(filename, options);
Coroutine *co;
CreateCo cco = {
.drv = drv,
.filename = g_strdup(filename),
.options = options,
.ret = NOT_DONE,
};
if (!drv->bdrv_create) {
return -ENOTSUP;
}
if (qemu_in_coroutine()) {
/* Fast-path if already in coroutine context */
bdrv_create_co_entry(&cco);
} else {
co = qemu_coroutine_create(bdrv_create_co_entry);
qemu_coroutine_enter(co, &cco);
while (cco.ret == NOT_DONE) {
qemu_aio_wait();
}
}
ret = cco.ret;
g_free(cco.filename);
return ret;
}
int bdrv_create_file(const char* filename, QEMUOptionParameter *options)