aboutsummaryrefslogtreecommitdiff
path: root/block.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2018-03-01 17:36:19 +0100
committerKevin Wolf <kwolf@redhat.com>2018-03-09 15:17:47 +0100
commit2fd6163884d74e74dd1ef54ab229d15c61d0b4cb (patch)
tree42dd511fe872ce7489ac3768ffc9522d7759191c /block.c
parent2b148f392b2bfeba76d3e6d9607c3bd072350e8c (diff)
block: convert bdrv_check callback to coroutine_fn
Suggested-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-Id: <1516279431-30424-8-git-send-email-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'block.c')
-rw-r--r--block.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/block.c b/block.c
index 603befb325..8f1c43d037 100644
--- a/block.c
+++ b/block.c
@@ -3455,17 +3455,54 @@ static void bdrv_delete(BlockDriverState *bs)
* free of errors) or -errno when an internal error occurred. The results of the
* check are stored in res.
*/
-int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix)
+static int coroutine_fn bdrv_co_check(BlockDriverState *bs,
+ BdrvCheckResult *res, BdrvCheckMode fix)
{
if (bs->drv == NULL) {
return -ENOMEDIUM;
}
- if (bs->drv->bdrv_check == NULL) {
+ if (bs->drv->bdrv_co_check == NULL) {
return -ENOTSUP;
}
memset(res, 0, sizeof(*res));
- return bs->drv->bdrv_check(bs, res, fix);
+ return bs->drv->bdrv_co_check(bs, res, fix);
+}
+
+typedef struct CheckCo {
+ BlockDriverState *bs;
+ BdrvCheckResult *res;
+ BdrvCheckMode fix;
+ int ret;
+} CheckCo;
+
+static void bdrv_check_co_entry(void *opaque)
+{
+ CheckCo *cco = opaque;
+ cco->ret = bdrv_co_check(cco->bs, cco->res, cco->fix);
+}
+
+int bdrv_check(BlockDriverState *bs,
+ BdrvCheckResult *res, BdrvCheckMode fix)
+{
+ Coroutine *co;
+ CheckCo cco = {
+ .bs = bs,
+ .res = res,
+ .ret = -EINPROGRESS,
+ .fix = fix,
+ };
+
+ if (qemu_in_coroutine()) {
+ /* Fast-path if already in coroutine context */
+ bdrv_check_co_entry(&cco);
+ } else {
+ co = qemu_coroutine_create(bdrv_check_co_entry, &cco);
+ qemu_coroutine_enter(co);
+ BDRV_POLL_WHILE(bs, cco.ret == -EINPROGRESS);
+ }
+
+ return cco.ret;
}
/*