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>
This commit is contained in:
Paolo Bonzini 2018-03-01 17:36:19 +01:00 committed by Kevin Wolf
parent 2b148f392b
commit 2fd6163884
10 changed files with 103 additions and 45 deletions

43
block.c
View file

@ -3455,17 +3455,54 @@ static void bdrv_delete(BlockDriverState *bs)
* free of errors) or -errno when an internal error occurred. The results of the * free of errors) or -errno when an internal error occurred. The results of the
* check are stored in res. * 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) { if (bs->drv == NULL) {
return -ENOMEDIUM; return -ENOMEDIUM;
} }
if (bs->drv->bdrv_check == NULL) { if (bs->drv->bdrv_co_check == NULL) {
return -ENOTSUP; return -ENOTSUP;
} }
memset(res, 0, sizeof(*res)); 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;
} }
/* /*

View file

@ -378,8 +378,9 @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
} }
static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res, static int coroutine_fn parallels_co_check(BlockDriverState *bs,
BdrvCheckMode fix) BdrvCheckResult *res,
BdrvCheckMode fix)
{ {
BDRVParallelsState *s = bs->opaque; BDRVParallelsState *s = bs->opaque;
int64_t size, prev_off, high_off; int64_t size, prev_off, high_off;
@ -394,6 +395,7 @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
return size; return size;
} }
qemu_co_mutex_lock(&s->lock);
if (s->header_unclean) { if (s->header_unclean) {
fprintf(stderr, "%s image was not closed correctly\n", fprintf(stderr, "%s image was not closed correctly\n",
fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR"); fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR");
@ -442,11 +444,12 @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
prev_off = off; prev_off = off;
} }
ret = 0;
if (flush_bat) { if (flush_bat) {
ret = bdrv_pwrite_sync(bs->file, 0, s->header, s->header_size); ret = bdrv_pwrite_sync(bs->file, 0, s->header, s->header_size);
if (ret < 0) { if (ret < 0) {
res->check_errors++; res->check_errors++;
return ret; goto out;
} }
} }
@ -465,13 +468,15 @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
if (ret < 0) { if (ret < 0) {
error_report_err(local_err); error_report_err(local_err);
res->check_errors++; res->check_errors++;
return ret; goto out;
} }
res->leaks_fixed += count; res->leaks_fixed += count;
} }
} }
return 0; out:
qemu_co_mutex_unlock(&s->lock);
return ret;
} }
@ -799,7 +804,7 @@ static BlockDriver bdrv_parallels = {
.bdrv_co_writev = parallels_co_writev, .bdrv_co_writev = parallels_co_writev,
.supports_backing = true, .supports_backing = true,
.bdrv_co_create_opts = parallels_co_create_opts, .bdrv_co_create_opts = parallels_co_create_opts,
.bdrv_check = parallels_check, .bdrv_co_check = parallels_co_check,
.create_opts = &parallels_create_opts, .create_opts = &parallels_create_opts,
}; };

View file

@ -541,8 +541,9 @@ int qcow2_mark_consistent(BlockDriverState *bs)
return 0; return 0;
} }
static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result, static int coroutine_fn qcow2_co_check_locked(BlockDriverState *bs,
BdrvCheckMode fix) BdrvCheckResult *result,
BdrvCheckMode fix)
{ {
int ret = qcow2_check_refcounts(bs, result, fix); int ret = qcow2_check_refcounts(bs, result, fix);
if (ret < 0) { if (ret < 0) {
@ -559,6 +560,19 @@ static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result,
return ret; return ret;
} }
static int coroutine_fn qcow2_co_check(BlockDriverState *bs,
BdrvCheckResult *result,
BdrvCheckMode fix)
{
BDRVQcow2State *s = bs->opaque;
int ret;
qemu_co_mutex_lock(&s->lock);
ret = qcow2_co_check_locked(bs, result, fix);
qemu_co_mutex_unlock(&s->lock);
return ret;
}
static int validate_table_offset(BlockDriverState *bs, uint64_t offset, static int validate_table_offset(BlockDriverState *bs, uint64_t offset,
uint64_t entries, size_t entry_len) uint64_t entries, size_t entry_len)
{ {
@ -1506,7 +1520,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
(s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) { (s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) {
BdrvCheckResult result = {0}; BdrvCheckResult result = {0};
ret = qcow2_check(bs, &result, BDRV_FIX_ERRORS | BDRV_FIX_LEAKS); ret = qcow2_co_check_locked(bs, &result,
BDRV_FIX_ERRORS | BDRV_FIX_LEAKS);
if (ret < 0 || result.check_errors) { if (ret < 0 || result.check_errors) {
if (ret >= 0) { if (ret >= 0) {
ret = -EIO; ret = -EIO;
@ -4413,7 +4428,7 @@ BlockDriver bdrv_qcow2 = {
.bdrv_inactivate = qcow2_inactivate, .bdrv_inactivate = qcow2_inactivate,
.create_opts = &qcow2_create_opts, .create_opts = &qcow2_create_opts,
.bdrv_check = qcow2_check, .bdrv_co_check = qcow2_co_check,
.bdrv_amend_options = qcow2_amend_options, .bdrv_amend_options = qcow2_amend_options,
.bdrv_detach_aio_context = qcow2_detach_aio_context, .bdrv_detach_aio_context = qcow2_detach_aio_context,

View file

@ -217,6 +217,7 @@ static void qed_check_mark_clean(BDRVQEDState *s, BdrvCheckResult *result)
qed_write_header_sync(s); qed_write_header_sync(s);
} }
/* Called with table_lock held. */
int qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix) int qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix)
{ {
QEDCheck check = { QEDCheck check = {

View file

@ -18,7 +18,7 @@
#include "qed.h" #include "qed.h"
#include "qemu/bswap.h" #include "qemu/bswap.h"
/* Called either from qed_check or with table_lock held. */ /* Called with table_lock held. */
static int qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table) static int qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)
{ {
QEMUIOVector qiov; QEMUIOVector qiov;
@ -33,13 +33,9 @@ static int qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)
trace_qed_read_table(s, offset, table); trace_qed_read_table(s, offset, table);
if (qemu_in_coroutine()) { qemu_co_mutex_unlock(&s->table_lock);
qemu_co_mutex_unlock(&s->table_lock);
}
ret = bdrv_preadv(s->bs->file, offset, &qiov); ret = bdrv_preadv(s->bs->file, offset, &qiov);
if (qemu_in_coroutine()) { qemu_co_mutex_lock(&s->table_lock);
qemu_co_mutex_lock(&s->table_lock);
}
if (ret < 0) { if (ret < 0) {
goto out; goto out;
} }
@ -67,7 +63,7 @@ out:
* @n: Number of elements * @n: Number of elements
* @flush: Whether or not to sync to disk * @flush: Whether or not to sync to disk
* *
* Called either from qed_check or with table_lock held. * Called with table_lock held.
*/ */
static int qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table, static int qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
unsigned int index, unsigned int n, bool flush) unsigned int index, unsigned int n, bool flush)
@ -104,13 +100,9 @@ static int qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
/* Adjust for offset into table */ /* Adjust for offset into table */
offset += start * sizeof(uint64_t); offset += start * sizeof(uint64_t);
if (qemu_in_coroutine()) { qemu_co_mutex_unlock(&s->table_lock);
qemu_co_mutex_unlock(&s->table_lock);
}
ret = bdrv_pwritev(s->bs->file, offset, &qiov); ret = bdrv_pwritev(s->bs->file, offset, &qiov);
if (qemu_in_coroutine()) { qemu_co_mutex_lock(&s->table_lock);
qemu_co_mutex_lock(&s->table_lock);
}
trace_qed_write_table_cb(s, table, flush, ret); trace_qed_write_table_cb(s, table, flush, ret);
if (ret < 0) { if (ret < 0) {
goto out; goto out;
@ -134,7 +126,7 @@ int qed_read_l1_table_sync(BDRVQEDState *s)
return qed_read_table(s, s->header.l1_table_offset, s->l1_table); return qed_read_table(s, s->header.l1_table_offset, s->l1_table);
} }
/* Called either from qed_check or with table_lock held. */ /* Called with table_lock held. */
int qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n) int qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n)
{ {
BLKDBG_EVENT(s->bs->file, BLKDBG_L1_UPDATE); BLKDBG_EVENT(s->bs->file, BLKDBG_L1_UPDATE);
@ -148,7 +140,7 @@ int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
return qed_write_l1_table(s, index, n); return qed_write_l1_table(s, index, n);
} }
/* Called either from qed_check or with table_lock held. */ /* Called with table_lock held. */
int qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset) int qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset)
{ {
int ret; int ret;
@ -191,7 +183,7 @@ int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset
return qed_read_l2_table(s, request, offset); return qed_read_l2_table(s, request, offset);
} }
/* Called either from qed_check or with table_lock held. */ /* Called with table_lock held. */
int qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, int qed_write_l2_table(BDRVQEDState *s, QEDRequest *request,
unsigned int index, unsigned int n, bool flush) unsigned int index, unsigned int n, bool flush)
{ {

View file

@ -1544,12 +1544,17 @@ static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs,
} }
} }
static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result, static int bdrv_qed_co_check(BlockDriverState *bs, BdrvCheckResult *result,
BdrvCheckMode fix) BdrvCheckMode fix)
{ {
BDRVQEDState *s = bs->opaque; BDRVQEDState *s = bs->opaque;
int ret;
return qed_check(s, result, !!fix); qemu_co_mutex_lock(&s->table_lock);
ret = qed_check(s, result, !!fix);
qemu_co_mutex_unlock(&s->table_lock);
return ret;
} }
static QemuOptsList qed_create_opts = { static QemuOptsList qed_create_opts = {
@ -1609,7 +1614,7 @@ static BlockDriver bdrv_qed = {
.bdrv_refresh_limits = bdrv_qed_refresh_limits, .bdrv_refresh_limits = bdrv_qed_refresh_limits,
.bdrv_change_backing_file = bdrv_qed_change_backing_file, .bdrv_change_backing_file = bdrv_qed_change_backing_file,
.bdrv_co_invalidate_cache = bdrv_qed_co_invalidate_cache, .bdrv_co_invalidate_cache = bdrv_qed_co_invalidate_cache,
.bdrv_check = bdrv_qed_check, .bdrv_co_check = bdrv_qed_co_check,
.bdrv_detach_aio_context = bdrv_qed_detach_aio_context, .bdrv_detach_aio_context = bdrv_qed_detach_aio_context,
.bdrv_attach_aio_context = bdrv_qed_attach_aio_context, .bdrv_attach_aio_context = bdrv_qed_attach_aio_context,
.bdrv_co_drain_begin = bdrv_qed_co_drain_begin, .bdrv_co_drain_begin = bdrv_qed_co_drain_begin,

View file

@ -263,8 +263,8 @@ static void vdi_header_print(VdiHeader *header)
} }
#endif #endif
static int vdi_check(BlockDriverState *bs, BdrvCheckResult *res, static int coroutine_fn vdi_co_check(BlockDriverState *bs, BdrvCheckResult *res,
BdrvCheckMode fix) BdrvCheckMode fix)
{ {
/* TODO: additional checks possible. */ /* TODO: additional checks possible. */
BDRVVdiState *s = (BDRVVdiState *)bs->opaque; BDRVVdiState *s = (BDRVVdiState *)bs->opaque;
@ -908,7 +908,7 @@ static BlockDriver bdrv_vdi = {
.bdrv_get_info = vdi_get_info, .bdrv_get_info = vdi_get_info,
.create_opts = &vdi_create_opts, .create_opts = &vdi_create_opts,
.bdrv_check = vdi_check, .bdrv_co_check = vdi_co_check,
}; };
static void bdrv_vdi_init(void) static void bdrv_vdi_init(void)

View file

@ -1944,8 +1944,9 @@ exit:
* r/w and any log has already been replayed, so there is nothing (currently) * r/w and any log has already been replayed, so there is nothing (currently)
* for us to do here * for us to do here
*/ */
static int vhdx_check(BlockDriverState *bs, BdrvCheckResult *result, static int coroutine_fn vhdx_co_check(BlockDriverState *bs,
BdrvCheckMode fix) BdrvCheckResult *result,
BdrvCheckMode fix)
{ {
BDRVVHDXState *s = bs->opaque; BDRVVHDXState *s = bs->opaque;
@ -2006,7 +2007,7 @@ static BlockDriver bdrv_vhdx = {
.bdrv_co_writev = vhdx_co_writev, .bdrv_co_writev = vhdx_co_writev,
.bdrv_co_create_opts = vhdx_co_create_opts, .bdrv_co_create_opts = vhdx_co_create_opts,
.bdrv_get_info = vhdx_get_info, .bdrv_get_info = vhdx_get_info,
.bdrv_check = vhdx_check, .bdrv_co_check = vhdx_co_check,
.bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_has_zero_init = bdrv_has_zero_init_1,
.create_opts = &vhdx_create_opts, .create_opts = &vhdx_create_opts,

View file

@ -2221,8 +2221,9 @@ static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent)
return info; return info;
} }
static int vmdk_check(BlockDriverState *bs, BdrvCheckResult *result, static int coroutine_fn vmdk_co_check(BlockDriverState *bs,
BdrvCheckMode fix) BdrvCheckResult *result,
BdrvCheckMode fix)
{ {
BDRVVmdkState *s = bs->opaque; BDRVVmdkState *s = bs->opaque;
VmdkExtent *extent = NULL; VmdkExtent *extent = NULL;
@ -2391,7 +2392,7 @@ static BlockDriver bdrv_vmdk = {
.instance_size = sizeof(BDRVVmdkState), .instance_size = sizeof(BDRVVmdkState),
.bdrv_probe = vmdk_probe, .bdrv_probe = vmdk_probe,
.bdrv_open = vmdk_open, .bdrv_open = vmdk_open,
.bdrv_check = vmdk_check, .bdrv_co_check = vmdk_co_check,
.bdrv_reopen_prepare = vmdk_reopen_prepare, .bdrv_reopen_prepare = vmdk_reopen_prepare,
.bdrv_child_perm = bdrv_format_default_perms, .bdrv_child_perm = bdrv_format_default_perms,
.bdrv_co_preadv = vmdk_co_preadv, .bdrv_co_preadv = vmdk_co_preadv,

View file

@ -307,8 +307,9 @@ struct BlockDriver {
* Returns 0 for completed check, -errno for internal errors. * Returns 0 for completed check, -errno for internal errors.
* The check results are stored in result. * The check results are stored in result.
*/ */
int (*bdrv_check)(BlockDriverState *bs, BdrvCheckResult *result, int coroutine_fn (*bdrv_co_check)(BlockDriverState *bs,
BdrvCheckMode fix); BdrvCheckResult *result,
BdrvCheckMode fix);
int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts, int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts,
BlockDriverAmendStatusCB *status_cb, BlockDriverAmendStatusCB *status_cb,