mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Kent Overstreet <koverstreet@google.com>
To: linux-kernel@vger.kernel.org, linux-aio@kvack.org,
	akpm@linux-foundation.org
Cc: Kent Overstreet <koverstreet@google.com>,
	Zach Brown <zab@redhat.com>, Felipe Balbi <balbi@ti.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Mark Fasheh <mfasheh@suse.com>, Joel Becker <jlbec@evilplan.org>,
	Rusty Russell <rusty@rustcorp.com.au>,
	Jens Axboe <axboe@kernel.dk>,
	Asai Thambi S P <asamymuthupa@micron.com>,
	Selvan Mani <smani@micron.com>,
	Sam Bradshaw <sbradshaw@micron.com>,
	Jeff Moyer <jmoyer@redhat.com>, Al Viro <viro@zeniv.linux.org.uk>,
	Benjamin LaHaise <bcrl@kvack.org>,
	"Theodore Ts'o" <tytso@mit.edu>
Subject: [PATCH 17/33] aio: change reqs_active to include unreaped completions
Date: Thu, 21 Mar 2013 09:35:38 -0700	[thread overview]
Message-ID: <1363883754-27966-18-git-send-email-koverstreet@google.com> (raw)
In-Reply-To: <1363883754-27966-1-git-send-email-koverstreet@google.com>

The aio code tries really hard to avoid having to deal with the completion
ringbuffer overflowing.  To do that, it has to keep track of the number of
outstanding kiocbs, and the number of completions currently in the
ringbuffer - and it's got to check that every time we allocate a kiocb.
Ouch.

But - we can improve this quite a bit if we just change reqs_active to
mean "number of outstanding requests and unreaped completions" - that
means kiocb allocation doesn't have to look at the ringbuffer, which is a
fairly significant win.

Signed-off-by: Kent Overstreet <koverstreet@google.com>
Cc: Zach Brown <zab@redhat.com>
Cc: Felipe Balbi <balbi@ti.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Asai Thambi S P <asamymuthupa@micron.com>
Cc: Selvan Mani <smani@micron.com>
Cc: Sam Bradshaw <sbradshaw@micron.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Benjamin LaHaise <bcrl@kvack.org>
Cc: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
 fs/aio.c | 46 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 14 deletions(-)

diff --git a/fs/aio.c b/fs/aio.c
index 16050fa..6828a31 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -71,12 +71,6 @@ struct aio_ring_info {
 	struct page		*internal_pages[AIO_RING_PAGES];
 };
 
-static inline unsigned aio_ring_avail(struct aio_ring_info *info,
-					struct aio_ring *ring)
-{
-	return (ring->head + info->nr - 1 - ring->tail) % info->nr;
-}
-
 struct kioctx {
 	atomic_t		users;
 	atomic_t		dead;
@@ -92,7 +86,13 @@ struct kioctx {
 	atomic_t		reqs_active;
 	struct list_head	active_reqs;	/* used for cancellation */
 
-	/* sys_io_setup currently limits this to an unsigned int */
+	/*
+	 * This is what userspace passed to io_setup(), it's not used for
+	 * anything but counting against the global max_reqs quota.
+	 *
+	 * The real limit is ring->nr - 1, which will be larger (see
+	 * aio_setup_ring())
+	 */
 	unsigned		max_reqs;
 
 	struct aio_ring_info	ring_info;
@@ -284,8 +284,11 @@ static void free_ioctx_rcu(struct rcu_head *head)
  */
 static void free_ioctx(struct kioctx *ctx)
 {
+	struct aio_ring_info *info = &ctx->ring_info;
+	struct aio_ring *ring;
 	struct io_event res;
 	struct kiocb *req;
+	unsigned head, avail;
 
 	spin_lock_irq(&ctx->ctx_lock);
 
@@ -299,7 +302,21 @@ static void free_ioctx(struct kioctx *ctx)
 
 	spin_unlock_irq(&ctx->ctx_lock);
 
-	wait_event(ctx->wait, !atomic_read(&ctx->reqs_active));
+	ring = kmap_atomic(info->ring_pages[0]);
+	head = ring->head;
+	kunmap_atomic(ring);
+
+	while (atomic_read(&ctx->reqs_active) > 0) {
+		wait_event(ctx->wait, head != info->tail);
+
+		avail = (head <= info->tail ? info->tail : info->nr) - head;
+
+		atomic_sub(avail, &ctx->reqs_active);
+		head += avail;
+		head %= info->nr;
+	}
+
+	WARN_ON(atomic_read(&ctx->reqs_active) < 0);
 
 	aio_free_ring(ctx);
 
@@ -548,7 +565,6 @@ static int kiocb_batch_refill(struct kioctx *ctx, struct kiocb_batch *batch)
 	unsigned short allocated, to_alloc;
 	long avail;
 	struct kiocb *req, *n;
-	struct aio_ring *ring;
 
 	to_alloc = min(batch->count, KIOCB_BATCH_SIZE);
 	for (allocated = 0; allocated < to_alloc; allocated++) {
@@ -563,9 +579,8 @@ static int kiocb_batch_refill(struct kioctx *ctx, struct kiocb_batch *batch)
 		goto out;
 
 	spin_lock_irq(&ctx->ctx_lock);
-	ring = kmap_atomic(ctx->ring_info.ring_pages[0]);
 
-	avail = aio_ring_avail(&ctx->ring_info, ring) - atomic_read(&ctx->reqs_active);
+	avail = ctx->ring_info.nr - atomic_read(&ctx->reqs_active) - 1;
 	BUG_ON(avail < 0);
 	if (avail < allocated) {
 		/* Trim back the number of requests. */
@@ -580,7 +595,6 @@ static int kiocb_batch_refill(struct kioctx *ctx, struct kiocb_batch *batch)
 	batch->count -= allocated;
 	atomic_add(allocated, &ctx->reqs_active);
 
-	kunmap_atomic(ring);
 	spin_unlock_irq(&ctx->ctx_lock);
 
 out:
@@ -687,8 +701,11 @@ void aio_complete(struct kiocb *iocb, long res, long res2)
 	 * when the event got cancelled.
 	 */
 	if (unlikely(xchg(&iocb->ki_cancel,
-			  KIOCB_CANCELLED) == KIOCB_CANCELLED))
+			  KIOCB_CANCELLED) == KIOCB_CANCELLED)) {
+		atomic_dec(&ctx->reqs_active);
+		/* Still need the wake_up in case free_ioctx is waiting */
 		goto put_rq;
+	}
 
 	/*
 	 * Add a completion event to the ring buffer. Must be done holding
@@ -745,7 +762,6 @@ void aio_complete(struct kiocb *iocb, long res, long res2)
 put_rq:
 	/* everything turned out well, dispose of the aiocb. */
 	aio_put_req(iocb);
-	atomic_dec(&ctx->reqs_active);
 
 	/*
 	 * We have to order our ring_info tail store above and test
@@ -822,6 +838,8 @@ static long aio_read_events_ring(struct kioctx *ctx,
 	flush_dcache_page(info->ring_pages[0]);
 
 	pr_debug("%li  h%u t%u\n", ret, head, info->tail);
+
+	atomic_sub(ret, &ctx->reqs_active);
 out:
 	mutex_unlock(&info->ring_lock);
 
-- 
1.8.1.3


  parent reply	other threads:[~2013-03-21 16:41 UTC|newest]

Thread overview: 87+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-21 16:35 [PATCH 00/33] AIO cleanups/performance improvements Kent Overstreet
2013-03-21 16:35 ` [PATCH 01/33] mm: remove old aio use_mm() comment Kent Overstreet
2013-03-28 14:13   ` Theodore Ts'o
2013-04-12 15:42   ` Jeff Moyer
2013-03-21 16:35 ` [PATCH 02/33] aio: remove dead code from aio.h Kent Overstreet
2013-03-28 14:13   ` Theodore Ts'o
2013-04-12 15:42   ` Jeff Moyer
2013-03-21 16:35 ` [PATCH 03/33] gadget: remove only user of aio retry Kent Overstreet
2013-03-21 16:42   ` Felipe Balbi
2013-04-12 15:42   ` Jeff Moyer
2013-03-21 16:35 ` [PATCH 04/33] aio: remove retry-based AIO Kent Overstreet
2013-03-28 14:20   ` Theodore Ts'o
2013-04-12 15:43   ` Jeff Moyer
2013-03-21 16:35 ` [PATCH 05/33] char: add aio_{read,write} to /dev/{null,zero} Kent Overstreet
2013-03-28 14:20   ` Theodore Ts'o
2013-04-12 15:43   ` Jeff Moyer
2013-03-21 16:35 ` [PATCH 06/33] aio: kill return value of aio_complete() Kent Overstreet
2013-03-28 14:22   ` Theodore Ts'o
2013-04-12 15:44   ` Jeff Moyer
2013-03-21 16:35 ` [PATCH 07/33] aio: add kiocb_cancel() Kent Overstreet
2013-03-28 14:54   ` Theodore Ts'o
2013-04-12 15:58   ` Jeff Moyer
2013-03-21 16:35 ` [PATCH 08/33] aio: move private stuff out of aio.h Kent Overstreet
2013-03-29 16:07   ` Theodore Ts'o
2013-04-12 15:59   ` Jeff Moyer
2013-03-21 16:35 ` [PATCH 09/33] aio: dprintk() -> pr_debug() Kent Overstreet
2013-03-21 17:38   ` Joe Perches
2013-03-29 16:17   ` Theodore Ts'o
2013-04-12 16:01   ` Jeff Moyer
2013-03-21 16:35 ` [PATCH 10/33] aio: do fget() after aio_get_req() Kent Overstreet
2013-03-29 16:48   ` Theodore Ts'o
2013-04-12 16:51   ` Jeff Moyer
2013-03-21 16:35 ` [PATCH 11/33] aio: make aio_put_req() lockless Kent Overstreet
2013-03-29 17:14   ` Theodore Ts'o
2013-04-12 21:01   ` Jeff Moyer
2013-03-21 16:35 ` [PATCH 12/33] aio: refcounting cleanup Kent Overstreet
2013-04-02  1:32   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 13/33] wait: add wait_event_hrtimeout() Kent Overstreet
2013-04-02  1:43   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 14/33] aio: make aio_read_evt() more efficient, convert to hrtimers Kent Overstreet
2013-04-02  1:58   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 15/33] aio: use flush_dcache_page() Kent Overstreet
2013-04-02  2:12   ` Theodore Ts'o
2013-04-09 21:07     ` Kent Overstreet
2013-03-21 16:35 ` [PATCH 16/33] aio: use cancellation list lazily Kent Overstreet
2013-04-02  2:36   ` Theodore Ts'o
2013-03-21 16:35 ` Kent Overstreet [this message]
2013-04-02  2:53   ` [PATCH 17/33] aio: change reqs_active to include unreaped completions Theodore Ts'o
2013-04-02 15:47     ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 18/33] aio: kill batch allocation Kent Overstreet
2013-04-02  3:03   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 19/33] aio: kill struct aio_ring_info Kent Overstreet
2013-04-02  3:26   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 20/33] aio: give shared kioctx fields their own cachelines Kent Overstreet
2013-04-02  3:27   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 21/33] aio: reqs_active -> reqs_available Kent Overstreet
2013-04-02 15:48   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 22/33] aio: percpu reqs_available Kent Overstreet
2013-04-02 16:03   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 23/33] generic dynamic per cpu refcounting Kent Overstreet
2013-04-02 16:27   ` Theodore Ts'o
2013-04-12 19:36     ` Kent Overstreet
2013-04-16  1:41       ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 24/33] aio: percpu ioctx refcount Kent Overstreet
2013-04-02 16:28   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 25/33] aio: use xchg() instead of completion_lock Kent Overstreet
2013-04-02 16:35   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 26/33] aio: don't include aio.h in sched.h Kent Overstreet
2013-04-02 16:35   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 27/33] aio: kill ki_key Kent Overstreet
2013-04-02 16:36   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 28/33] aio: kill ki_retry Kent Overstreet
2013-04-02 18:46   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 29/33] block: Prep work for batch completion Kent Overstreet
2013-04-02 18:48   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 30/33] block, aio: batch completion for bios/kiocbs Kent Overstreet
2013-04-02 19:48   ` Theodore Ts'o
2013-04-10 21:59     ` Kent Overstreet
2013-04-02 19:53   ` Theodore Ts'o
2013-04-10 22:09     ` Kent Overstreet
2013-03-21 16:35 ` [PATCH 31/33] virtio-blk: convert to batch completion Kent Overstreet
2013-04-02 19:53   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 32/33] mtip32xx: " Kent Overstreet
2013-04-02 19:54   ` Theodore Ts'o
2013-03-21 16:35 ` [PATCH 33/33] aio: fix kioctx not being freed after cancellation at exit time Kent Overstreet
2013-04-02 21:35   ` Theodore Ts'o
2013-04-09 21:15     ` Kent Overstreet

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1363883754-27966-18-git-send-email-koverstreet@google.com \
    --to=koverstreet@google.com \
    --cc=akpm@linux-foundation.org \
    --cc=asamymuthupa@micron.com \
    --cc=axboe@kernel.dk \
    --cc=balbi@ti.com \
    --cc=bcrl@kvack.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jlbec@evilplan.org \
    --cc=jmoyer@redhat.com \
    --cc=linux-aio@kvack.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mfasheh@suse.com \
    --cc=rusty@rustcorp.com.au \
    --cc=sbradshaw@micron.com \
    --cc=smani@micron.com \
    --cc=tytso@mit.edu \
    --cc=viro@zeniv.linux.org.uk \
    --cc=zab@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome