From patchwork Tue Jul 12 17:51:27 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roman Pen X-Patchwork-Id: 9225855 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 7499E6086B for ; Tue, 12 Jul 2016 17:51:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 64C092756B for ; Tue, 12 Jul 2016 17:51:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 563DA27D85; Tue, 12 Jul 2016 17:51:59 +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 8E2CF2756B for ; Tue, 12 Jul 2016 17:51:56 +0000 (UTC) Received: from localhost ([::1]:42471 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bN1qd-0001wX-ER for patchwork-qemu-devel@patchwork.kernel.org; Tue, 12 Jul 2016 13:51:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41541) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bN1qN-0001wF-C5 for qemu-devel@nongnu.org; Tue, 12 Jul 2016 13:51:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bN1qI-00065a-CH for qemu-devel@nongnu.org; Tue, 12 Jul 2016 13:51:38 -0400 Received: from mail-wm0-x229.google.com ([2a00:1450:400c:c09::229]:34882) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bN1qI-00065U-1B for qemu-devel@nongnu.org; Tue, 12 Jul 2016 13:51:34 -0400 Received: by mail-wm0-x229.google.com with SMTP id f65so108664606wmi.0 for ; Tue, 12 Jul 2016 10:51:33 -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=Z4My5ZZkQ+oj/0+h5ZLZ83brkEGUqDykTa4j/M6m87E=; b=e1EJ1nbNXxWhT78V2apPOABBaapK107r41te3juQfZK/0osUw80JWkprbdpWMjM4i2 Z/e/3iw7fl5tM2xwbL3qjvjRDtIeBC+cZCHejKswggTPFcZehllA5mv5qrVzoT2aYuGz z1zHq8F9tDjB9e43vb1YWqwcuEWEOJx2f+nKXP4elc1Ptgeps1H2+QuGeALYiS8u45XV EiU0RKmacQiBiWnwYYK8rZ9KvCTOhlRmBY4YEacDViRAbbGSeERA6vjXHtOXBFIvvzGr ha/L55hVl66Pc5MzksK0cnCBq3d1D+bkb8yodFJWxXmAAfQSXGKgeGiF6VpkHCSspO9n J2LQ== 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=Z4My5ZZkQ+oj/0+h5ZLZ83brkEGUqDykTa4j/M6m87E=; b=eXnhSJtJm32i6zsizL1JddCwSwryO+bL0FNH5n9UeBvDHD5xh3UGH8YBHOTO2O+NI7 HmHR2XVwH/KLfM9KX9G1kAj676wEB5JFV5wiln8M1hm7dugydZWht/goOuMCyLbiFZ2E t3x35ogyOeMoBZ+qS9YHdxbvcDX/yA6J+oEPPK95/UQc7a26KfVVD1CKBkFLaldpQuJ5 oLKmMhpw9eTCynJATsCfXhB8jU1EniRn83L0vlZBdCIU9sKkijD4O+Is1+YTf5KLhWYD hLvzvGzNxTa18arUP/HI89kiUKQ7jVyf1TtATmoa+sMCUn6JYS4G8UUf+laRZdtrZfta W87g== X-Gm-Message-State: ALyK8tLd+5f+Icus6h56jHuY5mmO+MogBQr95U4MBWGbHbivTEArm8LYFyXgjEUqIzCw37xl X-Received: by 10.28.153.70 with SMTP id b67mr15225216wme.84.1468345893225; Tue, 12 Jul 2016 10:51:33 -0700 (PDT) Received: from pb.pb.local ([62.217.45.26]) by smtp.gmail.com with ESMTPSA id r127sm30755654wmf.21.2016.07.12.10.51.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 12 Jul 2016 10:51:32 -0700 (PDT) From: Roman Pen To: Date: Tue, 12 Jul 2016 19:51:27 +0200 Message-Id: <1468345887-22077-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::229 Subject: [Qemu-devel] [PATCH 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 , 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 following 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 limited to MAX_EVENTS. Signed-off-by: Roman Pen Cc: Stefan Hajnoczi Cc: Paolo Bonzini Cc: qemu-devel@nongnu.org Reviewed-by: Fam Zheng --- block/linux-aio.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/block/linux-aio.c b/block/linux-aio.c index e468960..4a430a1 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,16 @@ 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 { len = 0; + if (s->io_q.in_flight >= MAX_EVENTS) + break; 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 +221,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 +267,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); }