From patchwork Wed Jul 13 13:03:24 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roman Pen X-Patchwork-Id: 9227615 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2D39C60572 for ; Wed, 13 Jul 2016 13:31:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1DB762715B for ; Wed, 13 Jul 2016 13:31:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1111A27F8E; Wed, 13 Jul 2016 13:31:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 162A62715B for ; Wed, 13 Jul 2016 13:31:47 +0000 (UTC) Received: from localhost ([::1]:47509 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bNKGQ-0006Gk-4r for patchwork-qemu-devel@patchwork.kernel.org; Wed, 13 Jul 2016 09:31:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45598) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bNJpU-0006yk-A3 for qemu-devel@nongnu.org; Wed, 13 Jul 2016 09:03:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bNJpQ-0006GW-3s for qemu-devel@nongnu.org; Wed, 13 Jul 2016 09:03:55 -0400 Received: from mail-wm0-x231.google.com ([2a00:1450:400c:c09::231]:36425) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bNJpP-0006GR-Q2 for qemu-devel@nongnu.org; Wed, 13 Jul 2016 09:03:52 -0400 Received: by mail-wm0-x231.google.com with SMTP id f126so28195891wma.1 for ; Wed, 13 Jul 2016 06:03:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=profitbricks-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=UJ0CzKFNkFsyG0QQndCcjivpclbHg9SwguQlF/XJVCk=; b=UX2tyN6peEVIHHoCA9ljpA+0e9p95nxYNV7Y6Ik8IsGKN5Uex/MXpKIDc3kvPP+2eM D/45ZcG53UWJ5Zdn5NaZCKgLEkDHaWUQQR8g4eMirhPx/cDnNqz1/n1rY9iNRv3tJGyP bT9SXcdHUsNeXLoEFgv9WY947Id9I7y0d3E7jWHjaXGItQ3myR+SnaYrTyBRc6kJjz77 uo/YDIveQE05n7gkYY7pDvGhpyQzygPeJMftpFlNVmf7a2cHq0X5UlcBVSz2jSUHU6m/ mEMQa9i3i7cHrnS7LCcXyKUAFMnnFnS42Eid4wiCr7Zyz7+0NYG1H4ZlIPM6PFBn7su9 /0uQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=UJ0CzKFNkFsyG0QQndCcjivpclbHg9SwguQlF/XJVCk=; b=dC94MH0K7sm66uSmnAwppiHGN/pvO0PXZp7OdYghX7sLtOLeQdHvDCmldsPcXgT7sp ZEagO4cVmkNHfo13+hGnlk9h2M6+D1F021aubvhouFtfuzjxUG8eyMZMfVtFrwy+BF7n u7gmStRrd4vluKLugEkwdwD0bwrkFGRQyH5P5LHKPhldaEl51UMOlmeCPs4Fpy/Bnxfg cXPGTJLDP2nXqx8sK2xeRGxHBo3zmLDLwLvlvHnXWH1VJsH10UaQ1cMJWKU0bCyO0U+T ePFk0e5iBknmjkftppbcbpMG9kBCzpIahduGYyF8hQH7BJsw7DxymdWtykcm/u8YFY/f OgXA== X-Gm-Message-State: ALyK8tKTT0+sS5EXL5fkP8kqCTGRnnDe7cyPSzOrLtfYDTulod5wO4uIuyyb1VlZemBOQGmg X-Received: by 10.194.98.173 with SMTP id ej13mr838220wjb.1.1468415030992; Wed, 13 Jul 2016 06:03:50 -0700 (PDT) Received: from pb.pb.local ([62.217.45.26]) by smtp.gmail.com with ESMTPSA id lc6sm827042wjb.32.2016.07.13.06.03.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 13 Jul 2016 06:03:50 -0700 (PDT) From: Roman Pen To: Date: Wed, 13 Jul 2016 15:03:24 +0200 Message-Id: <1468415004-31755-1-git-send-email-roman.penyaev@profitbricks.com> X-Mailer: git-send-email 2.8.2 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::231 Subject: [Qemu-devel] [PATCH v3 1/1] linux-aio: prevent submitting more than MAX_EVENTS 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: Paolo Bonzini , Fam Zheng , Stefan Hajnoczi , Roman Pen , qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Invoking io_setup(MAX_EVENTS) we ask kernel to create ring buffer for us with specified number of events. But kernel ring buffer allocation logic is a bit tricky (ring buffer is page size aligned + some percpu allocation are required) so eventually more than requested events number is allocated. From a userspace side we have to follow the convention and should not try to io_submit() more or logic, which consumes completed events, should be changed accordingly. The pitfall is in the following sequence: MAX_EVENTS = 128 io_setup(MAX_EVENTS) io_submit(MAX_EVENTS) io_submit(MAX_EVENTS) /* now 256 events are in-flight */ io_getevents(MAX_EVENTS) = 128 /* we can handle only 128 events at once, to be sure * that nothing is pended the io_getevents(MAX_EVENTS) * call must be invoked once more or hang will happen. */ To prevent the hang or reiteration of io_getevents() call this patch restricts the number of in-flights, which is now limited to MAX_EVENTS. Signed-off-by: Roman Pen Reviewed-by: Fam Zheng Reviewed-by: Paolo Bonzini Cc: Stefan Hajnoczi Cc: qemu-devel@nongnu.org Reviewed-by: Stefan Hajnoczi --- v3: o comment tweaks. v2: o comment tweaks. o fix QEMU coding style. block/linux-aio.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/block/linux-aio.c b/block/linux-aio.c index e468960..78f4524 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -28,8 +28,6 @@ */ #define MAX_EVENTS 128 -#define MAX_QUEUED_IO 128 - struct qemu_laiocb { BlockAIOCB common; Coroutine *co; @@ -44,7 +42,8 @@ struct qemu_laiocb { typedef struct { int plugged; - unsigned int n; + unsigned int in_queue; + unsigned int in_flight; bool blocked; QSIMPLEQ_HEAD(, qemu_laiocb) pending; } LaioQueue; @@ -129,6 +128,7 @@ static void qemu_laio_completion_bh(void *opaque) s->event_max = 0; return; /* no more events */ } + s->io_q.in_flight -= s->event_max; } /* Reschedule so nested event loops see currently pending completions */ @@ -190,7 +190,8 @@ static void ioq_init(LaioQueue *io_q) { QSIMPLEQ_INIT(&io_q->pending); io_q->plugged = 0; - io_q->n = 0; + io_q->in_queue = 0; + io_q->in_flight = 0; io_q->blocked = false; } @@ -198,14 +199,17 @@ static void ioq_submit(LinuxAioState *s) { int ret, len; struct qemu_laiocb *aiocb; - struct iocb *iocbs[MAX_QUEUED_IO]; + struct iocb *iocbs[MAX_EVENTS]; QSIMPLEQ_HEAD(, qemu_laiocb) completed; do { + if (s->io_q.in_flight >= MAX_EVENTS) { + break; + } len = 0; QSIMPLEQ_FOREACH(aiocb, &s->io_q.pending, next) { iocbs[len++] = &aiocb->iocb; - if (len == MAX_QUEUED_IO) { + if (s->io_q.in_flight + len >= MAX_EVENTS) { break; } } @@ -218,11 +222,12 @@ static void ioq_submit(LinuxAioState *s) abort(); } - s->io_q.n -= ret; + s->io_q.in_flight += ret; + s->io_q.in_queue -= ret; aiocb = container_of(iocbs[ret - 1], struct qemu_laiocb, iocb); QSIMPLEQ_SPLIT_AFTER(&s->io_q.pending, aiocb, next, &completed); } while (ret == len && !QSIMPLEQ_EMPTY(&s->io_q.pending)); - s->io_q.blocked = (s->io_q.n > 0); + s->io_q.blocked = (s->io_q.in_queue > 0); } void laio_io_plug(BlockDriverState *bs, LinuxAioState *s) @@ -263,9 +268,10 @@ static int laio_do_submit(int fd, struct qemu_laiocb *laiocb, off_t offset, io_set_eventfd(&laiocb->iocb, event_notifier_get_fd(&s->e)); QSIMPLEQ_INSERT_TAIL(&s->io_q.pending, laiocb, next); - s->io_q.n++; + s->io_q.in_queue++; if (!s->io_q.blocked && - (!s->io_q.plugged || s->io_q.n >= MAX_QUEUED_IO)) { + (!s->io_q.plugged || + s->io_q.in_flight + s->io_q.in_queue >= MAX_EVENTS)) { ioq_submit(s); }