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:
		
				
					committed by
					
						
						Kevin Wolf
					
				
			
			
				
	
			
			
			
						parent
						
							2b148f392b
						
					
				
				
					commit
					2fd6163884
				
			
							
								
								
									
										43
									
								
								block.c
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -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");
 | 
			
		||||
@@ -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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -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    = ¶llels_create_opts,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
@@ -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)
 | 
			
		||||
{
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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 = {
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -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;
 | 
			
		||||
    }
 | 
			
		||||
@@ -67,7 +63,7 @@ out:
 | 
			
		||||
 * @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)
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -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);
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -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)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								block/qed.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								block/qed.c
									
									
									
									
									
								
							@@ -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 = {
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -1944,8 +1944,9 @@ exit:
 | 
			
		||||
 * 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;
 | 
			
		||||
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user