From nobody Sat May 4 12:17:26 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 15185318049651006.5385117376001; Tue, 13 Feb 2018 06:23:24 -0800 (PST) Received: from localhost ([::1]:38511 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1elbUO-0002He-E0 for importer@patchew.org; Tue, 13 Feb 2018 09:23:20 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57951) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1elbST-0001BV-10 for qemu-devel@nongnu.org; Tue, 13 Feb 2018 09:21:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1elbSP-0002Ix-PQ for qemu-devel@nongnu.org; Tue, 13 Feb 2018 09:21:21 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:60604 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1elbSP-0002IQ-Kz for qemu-devel@nongnu.org; Tue, 13 Feb 2018 09:21:17 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3DA3C4023150; Tue, 13 Feb 2018 14:21:13 +0000 (UTC) Received: from localhost (ovpn-117-252.ams2.redhat.com [10.36.117.252]) by smtp.corp.redhat.com (Postfix) with ESMTP id A845CB289D; Tue, 13 Feb 2018 14:21:12 +0000 (UTC) From: Stefan Hajnoczi To: Date: Tue, 13 Feb 2018 14:20:59 +0000 Message-Id: <20180213142102.14450-2-stefanha@redhat.com> In-Reply-To: <20180213142102.14450-1-stefanha@redhat.com> References: <20180213142102.14450-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Tue, 13 Feb 2018 14:21:13 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Tue, 13 Feb 2018 14:21:13 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'stefanha@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 1/4] block: extract AIO_WAIT_WHILE() from BlockDriverState 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: Kevin Wolf , John Snow , Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" BlockDriverState has the BDRV_POLL_WHILE() macro to wait on event loop activity while a condition evaluates to true. This is used to implement synchronous operations where it acts as a condvar between the IOThread running the operation and the main loop waiting for the operation. It can also be called from the thread that owns the AioContext and in that case it's just a nested event loop. BlockBackend needs this behavior but doesn't always have a BlockDriverState it can use. This patch extracts BDRV_POLL_WHILE() into the AioWait abstraction, which can be used with AioContext and isn't tied to BlockDriverState anymore. This feature could be built directly into AioContext but then all users would kick the event loop even if they signal different conditions. Imagine an AioContext with many BlockDriverStates, each time a request completes any waiter would wake up and re-check their condition. It's nicer to keep a separate AioWait object for each condition instead. Please see "block/aio-wait.h" for details on the API. The name AIO_WAIT_WHILE() avoids the confusion between AIO_POLL_WHILE() and AioContext polling. Signed-off-by: Stefan Hajnoczi Reviewed-by: Eric Blake --- util/Makefile.objs | 2 +- include/block/aio-wait.h | 116 ++++++++++++++++++++++++++++++++++++++++++= ++++ include/block/block.h | 40 +++------------- include/block/block_int.h | 7 ++- block.c | 5 ++ block/io.c | 10 +--- util/aio-wait.c | 40 ++++++++++++++++ 7 files changed, 174 insertions(+), 46 deletions(-) create mode 100644 include/block/aio-wait.h create mode 100644 util/aio-wait.c diff --git a/util/Makefile.objs b/util/Makefile.objs index 3fb611631f..ae90b9963d 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -1,7 +1,7 @@ util-obj-y =3D osdep.o cutils.o unicode.o qemu-timer-common.o util-obj-y +=3D bufferiszero.o util-obj-y +=3D lockcnt.o -util-obj-y +=3D aiocb.o async.o thread-pool.o qemu-timer.o +util-obj-y +=3D aiocb.o async.o aio-wait.o thread-pool.o qemu-timer.o util-obj-y +=3D main-loop.o iohandler.o util-obj-$(CONFIG_POSIX) +=3D aio-posix.o util-obj-$(CONFIG_POSIX) +=3D compatfd.o diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h new file mode 100644 index 0000000000..a08e5807dc --- /dev/null +++ b/include/block/aio-wait.h @@ -0,0 +1,116 @@ +/* + * AioContext wait support + * + * Copyright (C) 2018 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#ifndef QEMU_AIO_WAIT_H +#define QEMU_AIO_WAIT_H + +#include "block/aio.h" + +/** + * AioWait: + * + * An object that facilitates synchronous waiting on a condition. The main + * loop can wait on an operation running in an IOThread as follows: + * + * AioWait *wait =3D ...; + * AioContext *ctx =3D ...; + * MyWork work =3D { .done =3D false }; + * schedule_my_work_in_iothread(ctx, &work); + * AIO_WAIT_WHILE(wait, ctx, !work.done); + * + * The IOThread must call aio_wait_kick() to notify the main loop when + * work.done changes: + * + * static void do_work(...) + * { + * ... + * work.done =3D true; + * aio_wait_kick(wait); + * } + */ +typedef struct { + /* Is the main loop waiting for a kick? Accessed with atomic ops. */ + bool need_kick; +} AioWait; + +/** + * AIO_WAIT_WHILE: + * @wait: the aio wait object + * @ctx: the aio context + * @cond: wait while this conditional expression is true + * + * Wait while a condition is true. Use this to implement synchronous + * operations that require event loop activity. + * + * The caller must be sure that something calls aio_wait_kick() when the v= alue + * of @cond might have changed. + * + * The caller's thread must be the IOThread that owns @ctx or the main loop + * thread (with @ctx acquired exactly once). This function cannot be used= to + * wait on conditions between two IOThreads since that could lead to deadl= ock, + * go via the main loop instead. + */ +#define AIO_WAIT_WHILE(wait, ctx, cond) ({ \ + bool waited_ =3D false; \ + bool busy_ =3D true; \ + AioWait *wait_ =3D (wait); \ + AioContext *ctx_ =3D (ctx); \ + if (aio_context_in_iothread(ctx_)) { \ + while ((cond) || busy_) { \ + busy_ =3D aio_poll(ctx_, (cond)); \ + waited_ |=3D !!(cond) | busy_; \ + } \ + } else { \ + assert(qemu_get_current_aio_context() =3D=3D \ + qemu_get_aio_context()); \ + assert(!wait_->need_kick); \ + /* Set wait_->need_kick before evaluating cond. */ \ + atomic_mb_set(&wait_->need_kick, true); \ + while (busy_) { \ + if ((cond)) { \ + waited_ =3D busy_ =3D true; \ + aio_context_release(ctx_); \ + aio_poll(qemu_get_aio_context(), true); \ + aio_context_acquire(ctx_); \ + } else { \ + busy_ =3D aio_poll(ctx_, false); \ + waited_ |=3D busy_; \ + } \ + } \ + atomic_set(&wait_->need_kick, false); \ + } \ + waited_; }) + +/** + * aio_wait_kick: + * @wait: the aio wait object that should re-evaluate its condition + * + * Wake up the main thread if it is waiting on AIO_WAIT_WHILE(). During + * synchronous operations performed in an IOThread, the main thread lets t= he + * IOThread's event loop run, waiting for the operation to complete. A + * aio_wait_kick() call will wake up the main thread. + */ +void aio_wait_kick(AioWait *wait); + +#endif /* QEMU_AIO_WAIT */ diff --git a/include/block/block.h b/include/block/block.h index 19b3ab9cb5..c4beda33a8 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -2,6 +2,7 @@ #define BLOCK_H =20 #include "block/aio.h" +#include "block/aio-wait.h" #include "qapi-types.h" #include "qemu/iov.h" #include "qemu/coroutine.h" @@ -367,41 +368,14 @@ void bdrv_drain_all_begin(void); void bdrv_drain_all_end(void); void bdrv_drain_all(void); =20 +/* Returns NULL when bs =3D=3D NULL */ +AioWait *bdrv_get_aio_wait(BlockDriverState *bs); + #define BDRV_POLL_WHILE(bs, cond) ({ \ - bool waited_ =3D false; \ - bool busy_ =3D true; \ BlockDriverState *bs_ =3D (bs); \ - AioContext *ctx_ =3D bdrv_get_aio_context(bs_); \ - if (aio_context_in_iothread(ctx_)) { \ - while ((cond) || busy_) { \ - busy_ =3D aio_poll(ctx_, (cond)); \ - waited_ |=3D !!(cond) | busy_; \ - } \ - } else { \ - assert(qemu_get_current_aio_context() =3D=3D \ - qemu_get_aio_context()); \ - /* Ask bdrv_dec_in_flight to wake up the main \ - * QEMU AioContext. Extra I/O threads never take \ - * other I/O threads' AioContexts (see for example \ - * block_job_defer_to_main_loop for how to do it). \ - */ \ - assert(!bs_->wakeup); \ - /* Set bs->wakeup before evaluating cond. */ \ - atomic_mb_set(&bs_->wakeup, true); \ - while (busy_) { \ - if ((cond)) { \ - waited_ =3D busy_ =3D true; \ - aio_context_release(ctx_); \ - aio_poll(qemu_get_aio_context(), true); \ - aio_context_acquire(ctx_); \ - } else { \ - busy_ =3D aio_poll(ctx_, false); \ - waited_ |=3D busy_; \ - } \ - } \ - atomic_set(&bs_->wakeup, false); \ - } \ - waited_; }) + AIO_WAIT_WHILE(bdrv_get_aio_wait(bs_), \ + bdrv_get_aio_context(bs_), \ + cond); }) =20 int bdrv_pdiscard(BlockDriverState *bs, int64_t offset, int bytes); int bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes); diff --git a/include/block/block_int.h b/include/block/block_int.h index 5ea63f8fa8..c1f6ee961a 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -26,6 +26,7 @@ =20 #include "block/accounting.h" #include "block/block.h" +#include "block/aio-wait.h" #include "qemu/queue.h" #include "qemu/coroutine.h" #include "qemu/stats64.h" @@ -709,10 +710,8 @@ struct BlockDriverState { unsigned int in_flight; unsigned int serialising_in_flight; =20 - /* Internal to BDRV_POLL_WHILE and bdrv_wakeup. Accessed with atomic - * ops. - */ - bool wakeup; + /* Kicked to signal main loop when a request completes. */ + AioWait wait; =20 /* counter for nested bdrv_io_plug. * Accessed with atomic ops. diff --git a/block.c b/block.c index 814e5a02da..9e4da81213 100644 --- a/block.c +++ b/block.c @@ -4716,6 +4716,11 @@ AioContext *bdrv_get_aio_context(BlockDriverState *b= s) return bs->aio_context; } =20 +AioWait *bdrv_get_aio_wait(BlockDriverState *bs) +{ + return bs ? &bs->wait : NULL; +} + void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co) { aio_co_enter(bdrv_get_aio_context(bs), co); diff --git a/block/io.c b/block/io.c index 89d0745e95..69170ee234 100644 --- a/block/io.c +++ b/block/io.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "trace.h" #include "sysemu/block-backend.h" +#include "block/aio-wait.h" #include "block/blockjob.h" #include "block/blockjob_int.h" #include "block/block_int.h" @@ -587,16 +588,9 @@ void bdrv_inc_in_flight(BlockDriverState *bs) atomic_inc(&bs->in_flight); } =20 -static void dummy_bh_cb(void *opaque) -{ -} - void bdrv_wakeup(BlockDriverState *bs) { - /* The barrier (or an atomic op) is in the caller. */ - if (atomic_read(&bs->wakeup)) { - aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL); - } + aio_wait_kick(bdrv_get_aio_wait(bs)); } =20 void bdrv_dec_in_flight(BlockDriverState *bs) diff --git a/util/aio-wait.c b/util/aio-wait.c new file mode 100644 index 0000000000..a487cdb852 --- /dev/null +++ b/util/aio-wait.c @@ -0,0 +1,40 @@ +/* + * AioContext wait support + * + * Copyright (C) 2018 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "block/aio-wait.h" + +static void dummy_bh_cb(void *opaque) +{ + /* The point is to make AIO_WAIT_WHILE()'s aio_poll() return */ +} + +void aio_wait_kick(AioWait *wait) +{ + /* The barrier (or an atomic op) is in the caller. */ + if (atomic_read(&wait->need_kick)) { + aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL); + } +} --=20 2.14.3 From nobody Sat May 4 12:17:26 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518531803015200.63877519713458; Tue, 13 Feb 2018 06:23:23 -0800 (PST) Received: from localhost ([::1]:38508 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1elbUJ-0002Fv-GN for importer@patchew.org; Tue, 13 Feb 2018 09:23:15 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57950) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1elbST-0001BU-0f for qemu-devel@nongnu.org; Tue, 13 Feb 2018 09:21:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1elbSP-0002J2-QA for qemu-devel@nongnu.org; Tue, 13 Feb 2018 09:21:20 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:60605 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1elbSP-0002IR-L3 for qemu-devel@nongnu.org; Tue, 13 Feb 2018 09:21:17 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EC8DA4023141; Tue, 13 Feb 2018 14:21:14 +0000 (UTC) Received: from localhost (ovpn-117-252.ams2.redhat.com [10.36.117.252]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8189E2026DFD; Tue, 13 Feb 2018 14:21:14 +0000 (UTC) From: Stefan Hajnoczi To: Date: Tue, 13 Feb 2018 14:21:00 +0000 Message-Id: <20180213142102.14450-3-stefanha@redhat.com> In-Reply-To: <20180213142102.14450-1-stefanha@redhat.com> References: <20180213142102.14450-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Tue, 13 Feb 2018 14:21:15 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Tue, 13 Feb 2018 14:21:15 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'stefanha@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 2/4] block: add BlockBackend->in_flight counter 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: Kevin Wolf , John Snow , Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" BlockBackend currently relies on BlockDriverState->in_flight to track requests for blk_drain(). There is a corner case where BlockDriverState->in_flight cannot be used though: blk->root can be NULL when there is no medium. This results in a segfault when the NULL pointer is dereferenced. Introduce a BlockBackend->in_flight counter for aio requests so it works even when blk->root =3D=3D NULL. Based on a patch by Kevin Wolf . Signed-off-by: Kevin Wolf Signed-off-by: Stefan Hajnoczi Reviewed-by: Eric Blake --- block.c | 2 +- block/block-backend.c | 60 +++++++++++++++++++++++++++++++++++++++++++++--= ---- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/block.c b/block.c index 9e4da81213..a83037c2a5 100644 --- a/block.c +++ b/block.c @@ -4713,7 +4713,7 @@ out: =20 AioContext *bdrv_get_aio_context(BlockDriverState *bs) { - return bs->aio_context; + return bs ? bs->aio_context : qemu_get_aio_context(); } =20 AioWait *bdrv_get_aio_wait(BlockDriverState *bs) diff --git a/block/block-backend.c b/block/block-backend.c index 0266ac990b..a775a3dd2f 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -73,6 +73,14 @@ struct BlockBackend { int quiesce_counter; VMChangeStateEntry *vmsh; bool force_allow_inactivate; + + /* Number of in-flight aio requests. BlockDriverState also counts + * in-flight requests but aio requests can exist even when blk->root is + * NULL, so we cannot rely on its counter for that case. + * Accessed with atomic ops. + */ + unsigned int in_flight; + AioWait wait; }; =20 typedef struct BlockBackendAIOCB { @@ -1225,11 +1233,22 @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFla= gs flags) return bdrv_make_zero(blk->root, flags); } =20 +static void blk_inc_in_flight(BlockBackend *blk) +{ + atomic_inc(&blk->in_flight); +} + +static void blk_dec_in_flight(BlockBackend *blk) +{ + atomic_dec(&blk->in_flight); + aio_wait_kick(&blk->wait); +} + static void error_callback_bh(void *opaque) { struct BlockBackendAIOCB *acb =3D opaque; =20 - bdrv_dec_in_flight(acb->common.bs); + blk_dec_in_flight(acb->blk); acb->common.cb(acb->common.opaque, acb->ret); qemu_aio_unref(acb); } @@ -1240,7 +1259,7 @@ BlockAIOCB *blk_abort_aio_request(BlockBackend *blk, { struct BlockBackendAIOCB *acb; =20 - bdrv_inc_in_flight(blk_bs(blk)); + blk_inc_in_flight(blk); acb =3D blk_aio_get(&block_backend_aiocb_info, blk, cb, opaque); acb->blk =3D blk; acb->ret =3D ret; @@ -1263,7 +1282,7 @@ static const AIOCBInfo blk_aio_em_aiocb_info =3D { static void blk_aio_complete(BlkAioEmAIOCB *acb) { if (acb->has_returned) { - bdrv_dec_in_flight(acb->common.bs); + blk_dec_in_flight(acb->rwco.blk); acb->common.cb(acb->common.opaque, acb->rwco.ret); qemu_aio_unref(acb); } @@ -1284,7 +1303,7 @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, in= t64_t offset, int bytes, BlkAioEmAIOCB *acb; Coroutine *co; =20 - bdrv_inc_in_flight(blk_bs(blk)); + blk_inc_in_flight(blk); acb =3D blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque); acb->rwco =3D (BlkRwCo) { .blk =3D blk, @@ -1521,14 +1540,41 @@ int blk_flush(BlockBackend *blk) =20 void blk_drain(BlockBackend *blk) { - if (blk_bs(blk)) { - bdrv_drain(blk_bs(blk)); + BlockDriverState *bs =3D blk_bs(blk); + + if (bs) { + bdrv_drained_begin(bs); + } + + /* We may have -ENOMEDIUM completions in flight */ + AIO_WAIT_WHILE(&blk->wait, + blk_get_aio_context(blk), + atomic_mb_read(&blk->in_flight) > 0); + + if (bs) { + bdrv_drained_end(bs); } } =20 void blk_drain_all(void) { - bdrv_drain_all(); + BlockBackend *blk =3D NULL; + + bdrv_drain_all_begin(); + + while ((blk =3D blk_all_next(blk)) !=3D NULL) { + AioContext *ctx =3D blk_get_aio_context(blk); + + aio_context_acquire(ctx); + + /* We may have -ENOMEDIUM completions in flight */ + AIO_WAIT_WHILE(&blk->wait, ctx, + atomic_mb_read(&blk->in_flight) > 0); + + aio_context_release(ctx); + } + + bdrv_drain_all_end(); } =20 void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error, --=20 2.14.3 From nobody Sat May 4 12:17:26 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518531986240853.1637065112863; Tue, 13 Feb 2018 06:26:26 -0800 (PST) Received: from localhost ([::1]:38644 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1elbXI-00052U-62 for importer@patchew.org; Tue, 13 Feb 2018 09:26:20 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57973) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1elbSU-0001CS-AM for qemu-devel@nongnu.org; Tue, 13 Feb 2018 09:21:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1elbST-0002Kb-1R for qemu-devel@nongnu.org; Tue, 13 Feb 2018 09:21:22 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:35760 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1elbSS-0002KH-Sn for qemu-devel@nongnu.org; Tue, 13 Feb 2018 09:21:20 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 805518182D37; Tue, 13 Feb 2018 14:21:20 +0000 (UTC) Received: from localhost (ovpn-117-252.ams2.redhat.com [10.36.117.252]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5BBE710073A7; Tue, 13 Feb 2018 14:21:16 +0000 (UTC) From: Stefan Hajnoczi To: Date: Tue, 13 Feb 2018 14:21:01 +0000 Message-Id: <20180213142102.14450-4-stefanha@redhat.com> In-Reply-To: <20180213142102.14450-1-stefanha@redhat.com> References: <20180213142102.14450-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Tue, 13 Feb 2018 14:21:20 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Tue, 13 Feb 2018 14:21:20 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'stefanha@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 3/4] block: test blk_aio_flush() with blk->root == NULL 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: Kevin Wolf , John Snow , Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Kevin Wolf This patch adds test cases for the scenario where blk_aio_flush() is called on a BlockBackend with no root. Calling drain afterwards should complete the requests with -ENOMEDIUM. Signed-off-by: Kevin Wolf Signed-off-by: Stefan Hajnoczi Reviewed-by: Eric Blake --- tests/Makefile.include | 2 ++ tests/test-block-backend.c | 82 ++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 84 insertions(+) create mode 100644 tests/test-block-backend.c diff --git a/tests/Makefile.include b/tests/Makefile.include index f41da235ae..1a457c29bc 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -83,6 +83,7 @@ gcov-files-test-hbitmap-y =3D blockjob.c check-unit-y +=3D tests/test-bdrv-drain$(EXESUF) check-unit-y +=3D tests/test-blockjob$(EXESUF) check-unit-y +=3D tests/test-blockjob-txn$(EXESUF) +check-unit-y +=3D tests/test-block-backend$(EXESUF) check-unit-y +=3D tests/test-x86-cpuid$(EXESUF) # all code tested by test-x86-cpuid is inside topology.h gcov-files-test-x86-cpuid-y =3D @@ -609,6 +610,7 @@ tests/test-throttle$(EXESUF): tests/test-throttle.o $(t= est-block-obj-y) tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y= ) $(test-util-obj-y) tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(= test-util-obj-y) tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-o= bj-y) $(test-util-obj-y) +tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block= -obj-y) $(test-util-obj-y) tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj= -y) tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y) tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) $(tes= t-crypto-obj-y) diff --git a/tests/test-block-backend.c b/tests/test-block-backend.c new file mode 100644 index 0000000000..fd59f02bd0 --- /dev/null +++ b/tests/test-block-backend.c @@ -0,0 +1,82 @@ +/* + * BlockBackend tests + * + * Copyright (c) 2017 Kevin Wolf + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "block/block.h" +#include "sysemu/block-backend.h" +#include "qapi/error.h" + +static void test_drain_aio_error_flush_cb(void *opaque, int ret) +{ + bool *completed =3D opaque; + + g_assert(ret =3D=3D -ENOMEDIUM); + *completed =3D true; +} + +static void test_drain_aio_error(void) +{ + BlockBackend *blk =3D blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + BlockAIOCB *acb; + bool completed =3D false; + + acb =3D blk_aio_flush(blk, test_drain_aio_error_flush_cb, &completed); + g_assert(acb !=3D NULL); + g_assert(completed =3D=3D false); + + blk_drain(blk); + g_assert(completed =3D=3D true); + + blk_unref(blk); +} + +static void test_drain_all_aio_error(void) +{ + BlockBackend *blk =3D blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + BlockAIOCB *acb; + bool completed =3D false; + + acb =3D blk_aio_flush(blk, test_drain_aio_error_flush_cb, &completed); + g_assert(acb !=3D NULL); + g_assert(completed =3D=3D false); + + blk_drain_all(); + g_assert(completed =3D=3D true); + + blk_unref(blk); +} + +int main(int argc, char **argv) +{ + bdrv_init(); + qemu_init_main_loop(&error_abort); + + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/block-backend/drain_aio_error", test_drain_aio_error= ); + g_test_add_func("/block-backend/drain_all_aio_error", + test_drain_all_aio_error); + + return g_test_run(); +} --=20 2.14.3 From nobody Sat May 4 12:17:26 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518531815316355.1266668527554; Tue, 13 Feb 2018 06:23:35 -0800 (PST) Received: from localhost ([::1]:38521 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1elbUc-0002Sm-E7 for importer@patchew.org; Tue, 13 Feb 2018 09:23:34 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58015) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1elbSb-0001Jm-Dk for qemu-devel@nongnu.org; Tue, 13 Feb 2018 09:21:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1elbSV-0002ME-Ix for qemu-devel@nongnu.org; Tue, 13 Feb 2018 09:21:29 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:51996 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1elbSV-0002Lw-FJ for qemu-devel@nongnu.org; Tue, 13 Feb 2018 09:21:23 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0E80F40FB64A; Tue, 13 Feb 2018 14:21:23 +0000 (UTC) Received: from localhost (ovpn-117-252.ams2.redhat.com [10.36.117.252]) by smtp.corp.redhat.com (Postfix) with ESMTP id B090BB2890; Tue, 13 Feb 2018 14:21:22 +0000 (UTC) From: Stefan Hajnoczi To: Date: Tue, 13 Feb 2018 14:21:02 +0000 Message-Id: <20180213142102.14450-5-stefanha@redhat.com> In-Reply-To: <20180213142102.14450-1-stefanha@redhat.com> References: <20180213142102.14450-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Tue, 13 Feb 2018 14:21:23 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Tue, 13 Feb 2018 14:21:23 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'stefanha@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 4/4] Revert "IDE: Do not flush empty CDROM drives" 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: Kevin Wolf , John Snow , Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This reverts commit 4da97120d51a4383aa96d741a2b837f8c4bbcd0b. blk_aio_flush() now handles the blk->root =3D=3D NULL case, so we no longer need this workaround. Cc: John Snow Signed-off-by: Stefan Hajnoczi Reviewed-by: Eric Blake --- hw/ide/core.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index 257b429381..139c843514 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -1087,15 +1087,7 @@ static void ide_flush_cache(IDEState *s) s->status |=3D BUSY_STAT; ide_set_retry(s); block_acct_start(blk_get_stats(s->blk), &s->acct, 0, BLOCK_ACCT_FLUSH); - - if (blk_bs(s->blk)) { - s->pio_aiocb =3D blk_aio_flush(s->blk, ide_flush_cb, s); - } else { - /* XXX blk_aio_flush() crashes when blk_bs(blk) is NULL, remove th= is - * temporary workaround when blk_aio_*() functions handle NULL blk= _bs. - */ - ide_flush_cb(s, 0); - } + s->pio_aiocb =3D blk_aio_flush(s->blk, ide_flush_cb, s); } =20 static void ide_cfata_metadata_inquiry(IDEState *s) --=20 2.14.3