Skip to content

Commit

Permalink
block: convert bdrv_check callback to coroutine_fn
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
bonzini authored and kevmw committed Mar 9, 2018
1 parent 2b148f3 commit 2fd6163
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 45 deletions.
43 changes: 40 additions & 3 deletions block.c
Expand Up @@ -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;
}

/*
Expand Down
17 changes: 11 additions & 6 deletions block/parallels.c
Expand Up @@ -378,8 +378,9 @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
}


static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
BdrvCheckMode fix)
static int coroutine_fn parallels_co_check(BlockDriverState *bs,
BdrvCheckResult *res,
BdrvCheckMode fix)
{
BDRVParallelsState *s = bs->opaque;
int64_t size, prev_off, high_off;
Expand All @@ -394,6 +395,7 @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
return size;
}

qemu_co_mutex_lock(&s->lock);
if (s->header_unclean) {
fprintf(stderr, "%s image was not closed correctly\n",
fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR");
Expand Down Expand Up @@ -442,11 +444,12 @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
prev_off = off;
}

ret = 0;
if (flush_bat) {
ret = bdrv_pwrite_sync(bs->file, 0, s->header, s->header_size);
if (ret < 0) {
res->check_errors++;
return ret;
goto out;
}
}

Expand All @@ -465,13 +468,15 @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
if (ret < 0) {
error_report_err(local_err);
res->check_errors++;
return ret;
goto out;
}
res->leaks_fixed += count;
}
}

return 0;
out:
qemu_co_mutex_unlock(&s->lock);
return ret;
}


Expand Down Expand Up @@ -799,7 +804,7 @@ static BlockDriver bdrv_parallels = {
.bdrv_co_writev = parallels_co_writev,
.supports_backing = true,
.bdrv_co_create_opts = parallels_co_create_opts,
.bdrv_check = parallels_check,
.bdrv_co_check = parallels_co_check,
.create_opts = &parallels_create_opts,
};

Expand Down
23 changes: 19 additions & 4 deletions block/qcow2.c
Expand Up @@ -541,8 +541,9 @@ int qcow2_mark_consistent(BlockDriverState *bs)
return 0;
}

static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result,
BdrvCheckMode fix)
static int coroutine_fn qcow2_co_check_locked(BlockDriverState *bs,
BdrvCheckResult *result,
BdrvCheckMode fix)
{
int ret = qcow2_check_refcounts(bs, result, fix);
if (ret < 0) {
Expand All @@ -559,6 +560,19 @@ static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result,
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,
uint64_t entries, size_t entry_len)
{
Expand Down Expand Up @@ -1506,7 +1520,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
(s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) {
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) {
ret = -EIO;
Expand Down Expand Up @@ -4413,7 +4428,7 @@ BlockDriver bdrv_qcow2 = {
.bdrv_inactivate = qcow2_inactivate,

.create_opts = &qcow2_create_opts,
.bdrv_check = qcow2_check,
.bdrv_co_check = qcow2_co_check,
.bdrv_amend_options = qcow2_amend_options,

.bdrv_detach_aio_context = qcow2_detach_aio_context,
Expand Down
1 change: 1 addition & 0 deletions block/qed-check.c
Expand Up @@ -217,6 +217,7 @@ static void qed_check_mark_clean(BDRVQEDState *s, BdrvCheckResult *result)
qed_write_header_sync(s);
}

/* Called with table_lock held. */
int qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix)
{
QEDCheck check = {
Expand Down
26 changes: 9 additions & 17 deletions block/qed-table.c
Expand Up @@ -18,7 +18,7 @@
#include "qed.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)
{
QEMUIOVector qiov;
Expand All @@ -33,13 +33,9 @@ static int qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *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);
if (qemu_in_coroutine()) {
qemu_co_mutex_lock(&s->table_lock);
}
qemu_co_mutex_lock(&s->table_lock);
if (ret < 0) {
goto out;
}
Expand Down Expand Up @@ -67,7 +63,7 @@ static int qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)
* @n: Number of elements
* @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,
unsigned int index, unsigned int n, bool flush)
Expand Down Expand Up @@ -104,13 +100,9 @@ static int qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
/* Adjust for offset into table */
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);
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);
if (ret < 0) {
goto out;
Expand All @@ -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);
}

/* 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)
{
BLKDBG_EVENT(s->bs->file, BLKDBG_L1_UPDATE);
Expand All @@ -148,7 +140,7 @@ int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
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 ret;
Expand Down Expand Up @@ -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);
}

/* Called either from qed_check or with table_lock held. */
/* Called with table_lock held. */
int qed_write_l2_table(BDRVQEDState *s, QEDRequest *request,
unsigned int index, unsigned int n, bool flush)
{
Expand Down
13 changes: 9 additions & 4 deletions block/qed.c
Expand Up @@ -1544,12 +1544,17 @@ static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs,
}
}

static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result,
BdrvCheckMode fix)
static int bdrv_qed_co_check(BlockDriverState *bs, BdrvCheckResult *result,
BdrvCheckMode fix)
{
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 = {
Expand Down Expand Up @@ -1609,7 +1614,7 @@ static BlockDriver bdrv_qed = {
.bdrv_refresh_limits = bdrv_qed_refresh_limits,
.bdrv_change_backing_file = bdrv_qed_change_backing_file,
.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_attach_aio_context = bdrv_qed_attach_aio_context,
.bdrv_co_drain_begin = bdrv_qed_co_drain_begin,
Expand Down
6 changes: 3 additions & 3 deletions block/vdi.c
Expand Up @@ -263,8 +263,8 @@ static void vdi_header_print(VdiHeader *header)
}
#endif

static int vdi_check(BlockDriverState *bs, BdrvCheckResult *res,
BdrvCheckMode fix)
static int coroutine_fn vdi_co_check(BlockDriverState *bs, BdrvCheckResult *res,
BdrvCheckMode fix)
{
/* TODO: additional checks possible. */
BDRVVdiState *s = (BDRVVdiState *)bs->opaque;
Expand Down Expand Up @@ -908,7 +908,7 @@ static BlockDriver bdrv_vdi = {
.bdrv_get_info = vdi_get_info,

.create_opts = &vdi_create_opts,
.bdrv_check = vdi_check,
.bdrv_co_check = vdi_co_check,
};

static void bdrv_vdi_init(void)
Expand Down
7 changes: 4 additions & 3 deletions block/vhdx.c
Expand Up @@ -1944,8 +1944,9 @@ static int coroutine_fn vhdx_co_create_opts(const char *filename, QemuOpts *opts
* r/w and any log has already been replayed, so there is nothing (currently)
* for us to do here
*/
static int vhdx_check(BlockDriverState *bs, BdrvCheckResult *result,
BdrvCheckMode fix)
static int coroutine_fn vhdx_co_check(BlockDriverState *bs,
BdrvCheckResult *result,
BdrvCheckMode fix)
{
BDRVVHDXState *s = bs->opaque;

Expand Down Expand Up @@ -2006,7 +2007,7 @@ static BlockDriver bdrv_vhdx = {
.bdrv_co_writev = vhdx_co_writev,
.bdrv_co_create_opts = vhdx_co_create_opts,
.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,

.create_opts = &vhdx_create_opts,
Expand Down
7 changes: 4 additions & 3 deletions block/vmdk.c
Expand Up @@ -2221,8 +2221,9 @@ static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent)
return info;
}

static int vmdk_check(BlockDriverState *bs, BdrvCheckResult *result,
BdrvCheckMode fix)
static int coroutine_fn vmdk_co_check(BlockDriverState *bs,
BdrvCheckResult *result,
BdrvCheckMode fix)
{
BDRVVmdkState *s = bs->opaque;
VmdkExtent *extent = NULL;
Expand Down Expand Up @@ -2391,7 +2392,7 @@ static BlockDriver bdrv_vmdk = {
.instance_size = sizeof(BDRVVmdkState),
.bdrv_probe = vmdk_probe,
.bdrv_open = vmdk_open,
.bdrv_check = vmdk_check,
.bdrv_co_check = vmdk_co_check,
.bdrv_reopen_prepare = vmdk_reopen_prepare,
.bdrv_child_perm = bdrv_format_default_perms,
.bdrv_co_preadv = vmdk_co_preadv,
Expand Down
5 changes: 3 additions & 2 deletions include/block/block_int.h
Expand Up @@ -307,8 +307,9 @@ struct BlockDriver {
* Returns 0 for completed check, -errno for internal errors.
* The check results are stored in result.
*/
int (*bdrv_check)(BlockDriverState *bs, BdrvCheckResult *result,
BdrvCheckMode fix);
int coroutine_fn (*bdrv_co_check)(BlockDriverState *bs,
BdrvCheckResult *result,
BdrvCheckMode fix);

int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts,
BlockDriverAmendStatusCB *status_cb,
Expand Down

0 comments on commit 2fd6163

Please sign in to comment.