Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

aio: Don't use ctx->tail unnecessarily

aio_complete() (arguably) needs to keep its own trusted copy of the tail
pointer, but io_getevents() doesn't have to use it - it's already using
the head pointer from the ring buffer.

So convert it to use the tail from the ring buffer so it touches fewer
cachelines and doesn't contend with the cacheline aio_complete() needs.

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>
Signed-off-by: Benjamin LaHaise <bcrl@kvack.org>

authored by

Kent Overstreet and committed by
Benjamin LaHaise
5ffac122 bec68faa

+23 -19
+23 -19
fs/aio.c
··· 406 406 struct kioctx *ctx = container_of(work, struct kioctx, free_work); 407 407 struct aio_ring *ring; 408 408 struct kiocb *req; 409 - unsigned cpu, head, avail; 409 + unsigned cpu, avail; 410 + DEFINE_WAIT(wait); 410 411 411 412 spin_lock_irq(&ctx->ctx_lock); 412 413 ··· 428 427 kcpu->reqs_available = 0; 429 428 } 430 429 431 - ring = kmap_atomic(ctx->ring_pages[0]); 432 - head = ring->head; 433 - kunmap_atomic(ring); 430 + while (1) { 431 + prepare_to_wait(&ctx->wait, &wait, TASK_UNINTERRUPTIBLE); 434 432 435 - while (atomic_read(&ctx->reqs_available) < ctx->nr_events - 1) { 436 - wait_event(ctx->wait, 437 - (head != ctx->tail) || 438 - (atomic_read(&ctx->reqs_available) >= 439 - ctx->nr_events - 1)); 440 - 441 - avail = (head <= ctx->tail ? ctx->tail : ctx->nr_events) - head; 433 + ring = kmap_atomic(ctx->ring_pages[0]); 434 + avail = (ring->head <= ring->tail) 435 + ? ring->tail - ring->head 436 + : ctx->nr_events - ring->head + ring->tail; 442 437 443 438 atomic_add(avail, &ctx->reqs_available); 444 - head += avail; 445 - head %= ctx->nr_events; 439 + ring->head = ring->tail; 440 + kunmap_atomic(ring); 441 + 442 + if (atomic_read(&ctx->reqs_available) >= ctx->nr_events - 1) 443 + break; 444 + 445 + schedule(); 446 446 } 447 + finish_wait(&ctx->wait, &wait); 447 448 448 449 WARN_ON(atomic_read(&ctx->reqs_available) > ctx->nr_events - 1); 449 450 ··· 872 869 struct io_event __user *event, long nr) 873 870 { 874 871 struct aio_ring *ring; 875 - unsigned head, pos; 872 + unsigned head, tail, pos; 876 873 long ret = 0; 877 874 int copy_ret; 878 875 ··· 880 877 881 878 ring = kmap_atomic(ctx->ring_pages[0]); 882 879 head = ring->head; 880 + tail = ring->tail; 883 881 kunmap_atomic(ring); 884 882 885 - pr_debug("h%u t%u m%u\n", head, ctx->tail, ctx->nr_events); 883 + pr_debug("h%u t%u m%u\n", head, tail, ctx->nr_events); 886 884 887 - if (head == ctx->tail) 885 + if (head == tail) 888 886 goto out; 889 887 890 888 while (ret < nr) { ··· 893 889 struct io_event *ev; 894 890 struct page *page; 895 891 896 - avail = (head <= ctx->tail ? ctx->tail : ctx->nr_events) - head; 897 - if (head == ctx->tail) 892 + avail = (head <= tail ? tail : ctx->nr_events) - head; 893 + if (head == tail) 898 894 break; 899 895 900 896 avail = min(avail, nr - ret); ··· 925 921 kunmap_atomic(ring); 926 922 flush_dcache_page(ctx->ring_pages[0]); 927 923 928 - pr_debug("%li h%u t%u\n", ret, head, ctx->tail); 924 + pr_debug("%li h%u t%u\n", ret, head, tail); 929 925 930 926 put_reqs_available(ctx, ret); 931 927 out: