aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMateusz Guzik <mguzik@redhat.com>2013-12-05 05:09:02 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-12-08 10:29:27 -0500
commitf8715e7d2a096cedd1c5ef4768deae7126659dcf (patch)
treea013b91b5bd6f58d7adeea9b96bf4ce6b3ef7645
parent604ae797e7cd1eca7897eac555961a5a25a9bde5 (diff)
aio: restore locking of ioctx list on removal
Commit 36f5588905c10a8c4568a210d601fe8c3c27e0f0 "aio: refcounting cleanup" resulted in ioctx_lock not being held during ctx removal, leaving the list susceptible to corruptions. In mainline kernel the issue went away as a side effect of db446a08c23d5475e6b08c87acca79ebb20f283c "aio: convert the ioctx list to table lookup v3". Fix the problem by restoring appropriate locking. Signed-off-by: Mateusz Guzik <mguzik@redhat.com> Reported-by: Eryu Guan <eguan@redhat.com> Cc: Jeff Moyer <jmoyer@redhat.com> Cc: Kent Overstreet <kmo@daterainc.com> Acked-by: Benjamin LaHaise <bcrl@kvack.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/aio.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 2bbcacf74d0c..ebd06fd0de89 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -423,10 +423,12 @@ static void kill_ioctx_rcu(struct rcu_head *head)
423 * when the processes owning a context have all exited to encourage 423 * when the processes owning a context have all exited to encourage
424 * the rapid destruction of the kioctx. 424 * the rapid destruction of the kioctx.
425 */ 425 */
426static void kill_ioctx(struct kioctx *ctx) 426static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx)
427{ 427{
428 if (!atomic_xchg(&ctx->dead, 1)) { 428 if (!atomic_xchg(&ctx->dead, 1)) {
429 spin_lock(&mm->ioctx_lock);
429 hlist_del_rcu(&ctx->list); 430 hlist_del_rcu(&ctx->list);
431 spin_unlock(&mm->ioctx_lock);
430 432
431 /* 433 /*
432 * It'd be more correct to do this in free_ioctx(), after all 434 * It'd be more correct to do this in free_ioctx(), after all
@@ -494,7 +496,7 @@ void exit_aio(struct mm_struct *mm)
494 */ 496 */
495 ctx->mmap_size = 0; 497 ctx->mmap_size = 0;
496 498
497 kill_ioctx(ctx); 499 kill_ioctx(mm, ctx);
498 } 500 }
499} 501}
500 502
@@ -852,7 +854,7 @@ SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)
852 if (!IS_ERR(ioctx)) { 854 if (!IS_ERR(ioctx)) {
853 ret = put_user(ioctx->user_id, ctxp); 855 ret = put_user(ioctx->user_id, ctxp);
854 if (ret) 856 if (ret)
855 kill_ioctx(ioctx); 857 kill_ioctx(current->mm, ioctx);
856 put_ioctx(ioctx); 858 put_ioctx(ioctx);
857 } 859 }
858 860
@@ -870,7 +872,7 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx)
870{ 872{
871 struct kioctx *ioctx = lookup_ioctx(ctx); 873 struct kioctx *ioctx = lookup_ioctx(ctx);
872 if (likely(NULL != ioctx)) { 874 if (likely(NULL != ioctx)) {
873 kill_ioctx(ioctx); 875 kill_ioctx(current->mm, ioctx);
874 put_ioctx(ioctx); 876 put_ioctx(ioctx);
875 return 0; 877 return 0;
876 } 878 }