diff options
Diffstat (limited to 'fs/aio.c')
-rw-r--r-- | fs/aio.c | 56 |
1 files changed, 19 insertions, 37 deletions
@@ -554,8 +554,7 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) | |||
554 | struct aio_ring *ring; | 554 | struct aio_ring *ring; |
555 | 555 | ||
556 | spin_lock(&mm->ioctx_lock); | 556 | spin_lock(&mm->ioctx_lock); |
557 | rcu_read_lock(); | 557 | table = rcu_dereference_raw(mm->ioctx_table); |
558 | table = rcu_dereference(mm->ioctx_table); | ||
559 | 558 | ||
560 | while (1) { | 559 | while (1) { |
561 | if (table) | 560 | if (table) |
@@ -563,7 +562,6 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) | |||
563 | if (!table->table[i]) { | 562 | if (!table->table[i]) { |
564 | ctx->id = i; | 563 | ctx->id = i; |
565 | table->table[i] = ctx; | 564 | table->table[i] = ctx; |
566 | rcu_read_unlock(); | ||
567 | spin_unlock(&mm->ioctx_lock); | 565 | spin_unlock(&mm->ioctx_lock); |
568 | 566 | ||
569 | /* While kioctx setup is in progress, | 567 | /* While kioctx setup is in progress, |
@@ -577,8 +575,6 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) | |||
577 | } | 575 | } |
578 | 576 | ||
579 | new_nr = (table ? table->nr : 1) * 4; | 577 | new_nr = (table ? table->nr : 1) * 4; |
580 | |||
581 | rcu_read_unlock(); | ||
582 | spin_unlock(&mm->ioctx_lock); | 578 | spin_unlock(&mm->ioctx_lock); |
583 | 579 | ||
584 | table = kzalloc(sizeof(*table) + sizeof(struct kioctx *) * | 580 | table = kzalloc(sizeof(*table) + sizeof(struct kioctx *) * |
@@ -589,8 +585,7 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) | |||
589 | table->nr = new_nr; | 585 | table->nr = new_nr; |
590 | 586 | ||
591 | spin_lock(&mm->ioctx_lock); | 587 | spin_lock(&mm->ioctx_lock); |
592 | rcu_read_lock(); | 588 | old = rcu_dereference_raw(mm->ioctx_table); |
593 | old = rcu_dereference(mm->ioctx_table); | ||
594 | 589 | ||
595 | if (!old) { | 590 | if (!old) { |
596 | rcu_assign_pointer(mm->ioctx_table, table); | 591 | rcu_assign_pointer(mm->ioctx_table, table); |
@@ -737,12 +732,9 @@ static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx, | |||
737 | 732 | ||
738 | 733 | ||
739 | spin_lock(&mm->ioctx_lock); | 734 | spin_lock(&mm->ioctx_lock); |
740 | rcu_read_lock(); | 735 | table = rcu_dereference_raw(mm->ioctx_table); |
741 | table = rcu_dereference(mm->ioctx_table); | ||
742 | |||
743 | WARN_ON(ctx != table->table[ctx->id]); | 736 | WARN_ON(ctx != table->table[ctx->id]); |
744 | table->table[ctx->id] = NULL; | 737 | table->table[ctx->id] = NULL; |
745 | rcu_read_unlock(); | ||
746 | spin_unlock(&mm->ioctx_lock); | 738 | spin_unlock(&mm->ioctx_lock); |
747 | 739 | ||
748 | /* percpu_ref_kill() will do the necessary call_rcu() */ | 740 | /* percpu_ref_kill() will do the necessary call_rcu() */ |
@@ -791,40 +783,30 @@ EXPORT_SYMBOL(wait_on_sync_kiocb); | |||
791 | */ | 783 | */ |
792 | void exit_aio(struct mm_struct *mm) | 784 | void exit_aio(struct mm_struct *mm) |
793 | { | 785 | { |
794 | struct kioctx_table *table; | 786 | struct kioctx_table *table = rcu_dereference_raw(mm->ioctx_table); |
795 | struct kioctx *ctx; | 787 | int i; |
796 | unsigned i = 0; | ||
797 | |||
798 | while (1) { | ||
799 | rcu_read_lock(); | ||
800 | table = rcu_dereference(mm->ioctx_table); | ||
801 | |||
802 | do { | ||
803 | if (!table || i >= table->nr) { | ||
804 | rcu_read_unlock(); | ||
805 | rcu_assign_pointer(mm->ioctx_table, NULL); | ||
806 | if (table) | ||
807 | kfree(table); | ||
808 | return; | ||
809 | } | ||
810 | 788 | ||
811 | ctx = table->table[i++]; | 789 | if (!table) |
812 | } while (!ctx); | 790 | return; |
813 | 791 | ||
814 | rcu_read_unlock(); | 792 | for (i = 0; i < table->nr; ++i) { |
793 | struct kioctx *ctx = table->table[i]; | ||
815 | 794 | ||
795 | if (!ctx) | ||
796 | continue; | ||
816 | /* | 797 | /* |
817 | * We don't need to bother with munmap() here - | 798 | * We don't need to bother with munmap() here - exit_mmap(mm) |
818 | * exit_mmap(mm) is coming and it'll unmap everything. | 799 | * is coming and it'll unmap everything. And we simply can't, |
819 | * Since aio_free_ring() uses non-zero ->mmap_size | 800 | * this is not necessarily our ->mm. |
820 | * as indicator that it needs to unmap the area, | 801 | * Since kill_ioctx() uses non-zero ->mmap_size as indicator |
821 | * just set it to 0; aio_free_ring() is the only | 802 | * that it needs to unmap the area, just set it to 0. |
822 | * place that uses ->mmap_size, so it's safe. | ||
823 | */ | 803 | */ |
824 | ctx->mmap_size = 0; | 804 | ctx->mmap_size = 0; |
825 | |||
826 | kill_ioctx(mm, ctx, NULL); | 805 | kill_ioctx(mm, ctx, NULL); |
827 | } | 806 | } |
807 | |||
808 | RCU_INIT_POINTER(mm->ioctx_table, NULL); | ||
809 | kfree(table); | ||
828 | } | 810 | } |
829 | 811 | ||
830 | static void put_reqs_available(struct kioctx *ctx, unsigned nr) | 812 | static void put_reqs_available(struct kioctx *ctx, unsigned nr) |