diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-16 21:49:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-16 21:49:16 -0400 |
commit | d82312c80860b8b83cd4473ac6eafd244e712061 (patch) | |
tree | 028b2e843e9d59d35aeb8924582864f18aa4ca36 /fs/aio.c | |
parent | 7d69cff26ceadce8638cb65191285932a3de3d4c (diff) | |
parent | 889fa31f00b218a2cef96c32a6b3f57e6d3bf918 (diff) |
Merge branch 'for-4.1/core' of git://git.kernel.dk/linux-block
Pull block layer core bits from Jens Axboe:
"This is the core pull request for 4.1. Not a lot of stuff in here for
this round, mostly little fixes or optimizations. This pull request
contains:
- An optimization that speeds up queue runs on blk-mq, especially for
the case where there's a large difference between nr_cpu_ids and
the actual mapped software queues on a hardware queue. From Chong
Yuan.
- Honor node local allocations for requests on legacy devices. From
David Rientjes.
- Cleanup of blk_mq_rq_to_pdu() from me.
- exit_aio() fixup from me, greatly speeding up exiting multiple IO
contexts off exit_group(). For my particular test case, fio exit
took ~6 seconds. A typical case of both exposing RCU grace periods
to user space, and serializing exit of them.
- Make blk_mq_queue_enter() honor the gfp mask passed in, so we only
wait if __GFP_WAIT is set. From Keith Busch.
- blk-mq exports and two added helpers from Mike Snitzer, which will
be used by the dm-mq code.
- Cleanups of blk-mq queue init from Wei Fang and Xiaoguang Wang"
* 'for-4.1/core' of git://git.kernel.dk/linux-block:
blk-mq: reduce unnecessary software queue looping
aio: fix serial draining in exit_aio()
blk-mq: cleanup blk_mq_rq_to_pdu()
blk-mq: put blk_queue_rq_timeout together in blk_mq_init_queue()
block: remove redundant check about 'set->nr_hw_queues' in blk_mq_alloc_tag_set()
block: allocate request memory local to request queue
blk-mq: don't wait in blk_mq_queue_enter() if __GFP_WAIT isn't set
blk-mq: export blk_mq_run_hw_queues
blk-mq: add blk_mq_init_allocated_queue and export blk_mq_register_disk
Diffstat (limited to 'fs/aio.c')
-rw-r--r-- | fs/aio.c | 45 |
1 files changed, 30 insertions, 15 deletions
@@ -77,6 +77,11 @@ struct kioctx_cpu { | |||
77 | unsigned reqs_available; | 77 | unsigned reqs_available; |
78 | }; | 78 | }; |
79 | 79 | ||
80 | struct ctx_rq_wait { | ||
81 | struct completion comp; | ||
82 | atomic_t count; | ||
83 | }; | ||
84 | |||
80 | struct kioctx { | 85 | struct kioctx { |
81 | struct percpu_ref users; | 86 | struct percpu_ref users; |
82 | atomic_t dead; | 87 | atomic_t dead; |
@@ -115,7 +120,7 @@ struct kioctx { | |||
115 | /* | 120 | /* |
116 | * signals when all in-flight requests are done | 121 | * signals when all in-flight requests are done |
117 | */ | 122 | */ |
118 | struct completion *requests_done; | 123 | struct ctx_rq_wait *rq_wait; |
119 | 124 | ||
120 | struct { | 125 | struct { |
121 | /* | 126 | /* |
@@ -572,8 +577,8 @@ static void free_ioctx_reqs(struct percpu_ref *ref) | |||
572 | struct kioctx *ctx = container_of(ref, struct kioctx, reqs); | 577 | struct kioctx *ctx = container_of(ref, struct kioctx, reqs); |
573 | 578 | ||
574 | /* At this point we know that there are no any in-flight requests */ | 579 | /* At this point we know that there are no any in-flight requests */ |
575 | if (ctx->requests_done) | 580 | if (ctx->rq_wait && atomic_dec_and_test(&ctx->rq_wait->count)) |
576 | complete(ctx->requests_done); | 581 | complete(&ctx->rq_wait->comp); |
577 | 582 | ||
578 | INIT_WORK(&ctx->free_work, free_ioctx); | 583 | INIT_WORK(&ctx->free_work, free_ioctx); |
579 | schedule_work(&ctx->free_work); | 584 | schedule_work(&ctx->free_work); |
@@ -783,7 +788,7 @@ err: | |||
783 | * the rapid destruction of the kioctx. | 788 | * the rapid destruction of the kioctx. |
784 | */ | 789 | */ |
785 | static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx, | 790 | static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx, |
786 | struct completion *requests_done) | 791 | struct ctx_rq_wait *wait) |
787 | { | 792 | { |
788 | struct kioctx_table *table; | 793 | struct kioctx_table *table; |
789 | 794 | ||
@@ -813,7 +818,7 @@ static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx, | |||
813 | if (ctx->mmap_size) | 818 | if (ctx->mmap_size) |
814 | vm_munmap(ctx->mmap_base, ctx->mmap_size); | 819 | vm_munmap(ctx->mmap_base, ctx->mmap_size); |
815 | 820 | ||
816 | ctx->requests_done = requests_done; | 821 | ctx->rq_wait = wait; |
817 | percpu_ref_kill(&ctx->users); | 822 | percpu_ref_kill(&ctx->users); |
818 | return 0; | 823 | return 0; |
819 | } | 824 | } |
@@ -829,18 +834,24 @@ static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx, | |||
829 | void exit_aio(struct mm_struct *mm) | 834 | void exit_aio(struct mm_struct *mm) |
830 | { | 835 | { |
831 | struct kioctx_table *table = rcu_dereference_raw(mm->ioctx_table); | 836 | struct kioctx_table *table = rcu_dereference_raw(mm->ioctx_table); |
832 | int i; | 837 | struct ctx_rq_wait wait; |
838 | int i, skipped; | ||
833 | 839 | ||
834 | if (!table) | 840 | if (!table) |
835 | return; | 841 | return; |
836 | 842 | ||
843 | atomic_set(&wait.count, table->nr); | ||
844 | init_completion(&wait.comp); | ||
845 | |||
846 | skipped = 0; | ||
837 | for (i = 0; i < table->nr; ++i) { | 847 | for (i = 0; i < table->nr; ++i) { |
838 | struct kioctx *ctx = table->table[i]; | 848 | struct kioctx *ctx = table->table[i]; |
839 | struct completion requests_done = | ||
840 | COMPLETION_INITIALIZER_ONSTACK(requests_done); | ||
841 | 849 | ||
842 | if (!ctx) | 850 | if (!ctx) { |
851 | skipped++; | ||
843 | continue; | 852 | continue; |
853 | } | ||
854 | |||
844 | /* | 855 | /* |
845 | * We don't need to bother with munmap() here - exit_mmap(mm) | 856 | * We don't need to bother with munmap() here - exit_mmap(mm) |
846 | * is coming and it'll unmap everything. And we simply can't, | 857 | * is coming and it'll unmap everything. And we simply can't, |
@@ -849,10 +860,12 @@ void exit_aio(struct mm_struct *mm) | |||
849 | * that it needs to unmap the area, just set it to 0. | 860 | * that it needs to unmap the area, just set it to 0. |
850 | */ | 861 | */ |
851 | ctx->mmap_size = 0; | 862 | ctx->mmap_size = 0; |
852 | kill_ioctx(mm, ctx, &requests_done); | 863 | kill_ioctx(mm, ctx, &wait); |
864 | } | ||
853 | 865 | ||
866 | if (!atomic_sub_and_test(skipped, &wait.count)) { | ||
854 | /* Wait until all IO for the context are done. */ | 867 | /* Wait until all IO for the context are done. */ |
855 | wait_for_completion(&requests_done); | 868 | wait_for_completion(&wait.comp); |
856 | } | 869 | } |
857 | 870 | ||
858 | RCU_INIT_POINTER(mm->ioctx_table, NULL); | 871 | RCU_INIT_POINTER(mm->ioctx_table, NULL); |
@@ -1331,15 +1344,17 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx) | |||
1331 | { | 1344 | { |
1332 | struct kioctx *ioctx = lookup_ioctx(ctx); | 1345 | struct kioctx *ioctx = lookup_ioctx(ctx); |
1333 | if (likely(NULL != ioctx)) { | 1346 | if (likely(NULL != ioctx)) { |
1334 | struct completion requests_done = | 1347 | struct ctx_rq_wait wait; |
1335 | COMPLETION_INITIALIZER_ONSTACK(requests_done); | ||
1336 | int ret; | 1348 | int ret; |
1337 | 1349 | ||
1350 | init_completion(&wait.comp); | ||
1351 | atomic_set(&wait.count, 1); | ||
1352 | |||
1338 | /* Pass requests_done to kill_ioctx() where it can be set | 1353 | /* Pass requests_done to kill_ioctx() where it can be set |
1339 | * in a thread-safe way. If we try to set it here then we have | 1354 | * in a thread-safe way. If we try to set it here then we have |
1340 | * a race condition if two io_destroy() called simultaneously. | 1355 | * a race condition if two io_destroy() called simultaneously. |
1341 | */ | 1356 | */ |
1342 | ret = kill_ioctx(current->mm, ioctx, &requests_done); | 1357 | ret = kill_ioctx(current->mm, ioctx, &wait); |
1343 | percpu_ref_put(&ioctx->users); | 1358 | percpu_ref_put(&ioctx->users); |
1344 | 1359 | ||
1345 | /* Wait until all IO for the context are done. Otherwise kernel | 1360 | /* Wait until all IO for the context are done. Otherwise kernel |
@@ -1347,7 +1362,7 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx) | |||
1347 | * is destroyed. | 1362 | * is destroyed. |
1348 | */ | 1363 | */ |
1349 | if (!ret) | 1364 | if (!ret) |
1350 | wait_for_completion(&requests_done); | 1365 | wait_for_completion(&wait.comp); |
1351 | 1366 | ||
1352 | return ret; | 1367 | return ret; |
1353 | } | 1368 | } |