From patchwork Thu Mar 1 16:36:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 879942 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="BiwqmJds"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zsdbV0TdZz9s3C for ; Fri, 2 Mar 2018 03:45:42 +1100 (AEDT) Received: from localhost ([::1]:58040 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erRKt-000590-Qi for incoming@patchwork.ozlabs.org; Thu, 01 Mar 2018 11:45:39 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46106) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1erRCS-0006rR-0m for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:36:58 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1erRCN-00032j-LX for qemu-devel@nongnu.org; Thu, 01 Mar 2018 11:36:56 -0500 Received: from mail-wm0-x241.google.com ([2a00:1450:400c:c09::241]:54683) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1erRCN-00031V-C0; Thu, 01 Mar 2018 11:36:51 -0500 Received: by mail-wm0-x241.google.com with SMTP id z81so13260457wmb.4; Thu, 01 Mar 2018 08:36:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=ziziMAg5KPz5FQ1EfHC2hdDYRxcOleLtt5QgzFMkt0c=; b=BiwqmJdsCQkUNHyMhRPuibYkmkGL6ld7Ek96SRk82ZoBRUDi6QhjY0nqsGCmLKFKOW oKZWYExt9nvwwkNFIVMnaXs07533YN23ZuR91gNAVNcr7N7l6q0A17d22lOleOPDdu2h vRgPsL9N2HgaLfXmJQzb6UMALSSFTvXTB2FSdn+Siou6isvexNzhCT4a4Fg9k+Kl9u49 yuxWq8R4lVvTeDxPQdBQJrw3Wc+W69XSpkiUDhqwaWslXaH9lomwQtgu3dnJUcYAgiOe cj0XfPkpV5E8DsDYT6ZZw+hkjoqDfz2Kpllg2Jw4ELIHzHtTCvpcmrZyDzEvpMPlyGX2 hD5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=ziziMAg5KPz5FQ1EfHC2hdDYRxcOleLtt5QgzFMkt0c=; b=rfg31CXAmynBv2ZKq+oDfWnpYolOu0twjKgri6bPLB8a2ixT1y/jyF+CeNKMlk/0Wi PL24JZ0J/8YoxgOVlCNt0sRuLzkS0+F0KBUkShdPQbzy03jCSuRkDRSOyBkxSoi3l7Or 7NM2MCIAyRyHa8KFYb6alPd1gpTojK0hy+kBHcRnIilR2v7UbbcNIYhZx2MhbvpC2QrC tLA1rZhTb+HBNM5JnRB5ZwrXEHLaJyPPN7bewEJyQ8E3/c02dc5thdExieyhx1ejRGHC a441xhGcEjU/4GN0zLnbwBzVuJ/DQ+NuVTxqi+oGeqn+Ie4lK1rGCf3Vl2E9oWFLlQ0T oMGQ== X-Gm-Message-State: APf1xPB9ta9/0M/a+2UQN4QCCD8IYuyzkKk5JU5mhfXO41YWkCrxw874 O1imZS7KXVmS2DgcrO6647HIivvv X-Google-Smtp-Source: AG47ELv7xQcjZc5fH8uRwqKS6tM32PP0eJatJJ5WNWXE3mKnuHUGX+vFaW9YSGHQIeQtCGLF8BruEQ== X-Received: by 10.28.225.66 with SMTP id y63mr2206451wmg.148.1519922209598; Thu, 01 Mar 2018 08:36:49 -0800 (PST) Received: from donizetti.lan (94-36-191-219.adsl-ull.clienti.tiscali.it. [94.36.191.219]) by smtp.gmail.com with ESMTPSA id a14sm4187152wrf.22.2018.03.01.08.36.48 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 01 Mar 2018 08:36:48 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 1 Mar 2018 17:36:19 +0100 Message-Id: <20180301163619.21072-9-pbonzini@redhat.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180301163619.21072-1-pbonzini@redhat.com> References: <20180301163619.21072-1-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c09::241 Subject: [Qemu-devel] [PATCH 8/8] block: convert bdrv_check callback to coroutine_fn X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Suggested-by: Kevin Wolf Signed-off-by: Paolo Bonzini Message-Id: <1516279431-30424-8-git-send-email-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- block.c | 43 ++++++++++++++++++++++++++++++++++++++++--- block/parallels.c | 17 +++++++++++------ block/qcow2.c | 23 +++++++++++++++++++---- block/qed-check.c | 1 + block/qed-table.c | 26 +++++++++----------------- block/qed.c | 13 +++++++++---- block/vdi.c | 6 +++--- block/vhdx.c | 7 ++++--- block/vmdk.c | 7 ++++--- include/block/block_int.h | 5 +++-- 10 files changed, 103 insertions(+), 45 deletions(-) diff --git a/block.c b/block.c index b72ed976fd..944423f7f7 100644 --- a/block.c +++ b/block.c @@ -3457,17 +3457,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; } /* diff --git a/block/parallels.c b/block/parallels.c index c3095bd9c0..390216c25d 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -370,8 +370,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; @@ -386,6 +387,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"); @@ -434,11 +436,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; } } @@ -457,13 +460,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; } @@ -792,7 +797,7 @@ static BlockDriver bdrv_parallels = { .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, }; diff --git a/block/qcow2.c b/block/qcow2.c index 33e260a381..39a3415c99 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -543,8 +543,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) { @@ -561,6 +562,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) { @@ -1485,7 +1499,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; @@ -4390,7 +4405,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, diff --git a/block/qed-check.c b/block/qed-check.c index dcd4f036b8..0edac03159 100644 --- a/block/qed-check.c +++ b/block/qed-check.c @@ -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 = { diff --git a/block/qed-table.c b/block/qed-table.c index eead8b0fc7..7df5680adb 100644 --- a/block/qed-table.c +++ b/block/qed-table.c @@ -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) { diff --git a/block/qed.c b/block/qed.c index 7da553035e..c655f139a2 100644 --- a/block/qed.c +++ b/block/qed.c @@ -1572,12 +1572,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 = { @@ -1637,7 +1642,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, diff --git a/block/vdi.c b/block/vdi.c index 0fa98d5ffe..a7fa62fa3c 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -259,8 +259,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; @@ -909,7 +909,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) diff --git a/block/vhdx.c b/block/vhdx.c index 3fbff5048b..d82350d07c 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -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, diff --git a/block/vmdk.c b/block/vmdk.c index a3f7610082..264d855ec1 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -2231,8 +2231,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; @@ -2401,7 +2402,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, diff --git a/include/block/block_int.h b/include/block/block_int.h index 10064d2a2f..c8d208620e 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -299,8 +299,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,