diff options
Diffstat (limited to 'fs/aio.c')
-rw-r--r-- | fs/aio.c | 86 |
1 files changed, 30 insertions, 56 deletions
@@ -192,7 +192,6 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) | |||
192 | } | 192 | } |
193 | 193 | ||
194 | file->f_flags = O_RDWR; | 194 | file->f_flags = O_RDWR; |
195 | file->private_data = ctx; | ||
196 | return file; | 195 | return file; |
197 | } | 196 | } |
198 | 197 | ||
@@ -202,7 +201,7 @@ static struct dentry *aio_mount(struct file_system_type *fs_type, | |||
202 | static const struct dentry_operations ops = { | 201 | static const struct dentry_operations ops = { |
203 | .d_dname = simple_dname, | 202 | .d_dname = simple_dname, |
204 | }; | 203 | }; |
205 | return mount_pseudo(fs_type, "aio:", NULL, &ops, 0xa10a10a1); | 204 | return mount_pseudo(fs_type, "aio:", NULL, &ops, AIO_RING_MAGIC); |
206 | } | 205 | } |
207 | 206 | ||
208 | /* aio_setup | 207 | /* aio_setup |
@@ -556,8 +555,7 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) | |||
556 | struct aio_ring *ring; | 555 | struct aio_ring *ring; |
557 | 556 | ||
558 | spin_lock(&mm->ioctx_lock); | 557 | spin_lock(&mm->ioctx_lock); |
559 | rcu_read_lock(); | 558 | table = rcu_dereference_raw(mm->ioctx_table); |
560 | table = rcu_dereference(mm->ioctx_table); | ||
561 | 559 | ||
562 | while (1) { | 560 | while (1) { |
563 | if (table) | 561 | if (table) |
@@ -565,7 +563,6 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) | |||
565 | if (!table->table[i]) { | 563 | if (!table->table[i]) { |
566 | ctx->id = i; | 564 | ctx->id = i; |
567 | table->table[i] = ctx; | 565 | table->table[i] = ctx; |
568 | rcu_read_unlock(); | ||
569 | spin_unlock(&mm->ioctx_lock); | 566 | spin_unlock(&mm->ioctx_lock); |
570 | 567 | ||
571 | /* While kioctx setup is in progress, | 568 | /* While kioctx setup is in progress, |
@@ -579,8 +576,6 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) | |||
579 | } | 576 | } |
580 | 577 | ||
581 | new_nr = (table ? table->nr : 1) * 4; | 578 | new_nr = (table ? table->nr : 1) * 4; |
582 | |||
583 | rcu_read_unlock(); | ||
584 | spin_unlock(&mm->ioctx_lock); | 579 | spin_unlock(&mm->ioctx_lock); |
585 | 580 | ||
586 | table = kzalloc(sizeof(*table) + sizeof(struct kioctx *) * | 581 | table = kzalloc(sizeof(*table) + sizeof(struct kioctx *) * |
@@ -591,8 +586,7 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) | |||
591 | table->nr = new_nr; | 586 | table->nr = new_nr; |
592 | 587 | ||
593 | spin_lock(&mm->ioctx_lock); | 588 | spin_lock(&mm->ioctx_lock); |
594 | rcu_read_lock(); | 589 | old = rcu_dereference_raw(mm->ioctx_table); |
595 | old = rcu_dereference(mm->ioctx_table); | ||
596 | 590 | ||
597 | if (!old) { | 591 | if (!old) { |
598 | rcu_assign_pointer(mm->ioctx_table, table); | 592 | rcu_assign_pointer(mm->ioctx_table, table); |
@@ -739,12 +733,9 @@ static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx, | |||
739 | 733 | ||
740 | 734 | ||
741 | spin_lock(&mm->ioctx_lock); | 735 | spin_lock(&mm->ioctx_lock); |
742 | rcu_read_lock(); | 736 | table = rcu_dereference_raw(mm->ioctx_table); |
743 | table = rcu_dereference(mm->ioctx_table); | ||
744 | |||
745 | WARN_ON(ctx != table->table[ctx->id]); | 737 | WARN_ON(ctx != table->table[ctx->id]); |
746 | table->table[ctx->id] = NULL; | 738 | table->table[ctx->id] = NULL; |
747 | rcu_read_unlock(); | ||
748 | spin_unlock(&mm->ioctx_lock); | 739 | spin_unlock(&mm->ioctx_lock); |
749 | 740 | ||
750 | /* percpu_ref_kill() will do the necessary call_rcu() */ | 741 | /* percpu_ref_kill() will do the necessary call_rcu() */ |
@@ -793,40 +784,30 @@ EXPORT_SYMBOL(wait_on_sync_kiocb); | |||
793 | */ | 784 | */ |
794 | void exit_aio(struct mm_struct *mm) | 785 | void exit_aio(struct mm_struct *mm) |
795 | { | 786 | { |
796 | struct kioctx_table *table; | 787 | struct kioctx_table *table = rcu_dereference_raw(mm->ioctx_table); |
797 | struct kioctx *ctx; | 788 | int i; |
798 | unsigned i = 0; | ||
799 | |||
800 | while (1) { | ||
801 | rcu_read_lock(); | ||
802 | table = rcu_dereference(mm->ioctx_table); | ||
803 | |||
804 | do { | ||
805 | if (!table || i >= table->nr) { | ||
806 | rcu_read_unlock(); | ||
807 | rcu_assign_pointer(mm->ioctx_table, NULL); | ||
808 | if (table) | ||
809 | kfree(table); | ||
810 | return; | ||
811 | } | ||
812 | 789 | ||
813 | ctx = table->table[i++]; | 790 | if (!table) |
814 | } while (!ctx); | 791 | return; |
815 | 792 | ||
816 | rcu_read_unlock(); | 793 | for (i = 0; i < table->nr; ++i) { |
794 | struct kioctx *ctx = table->table[i]; | ||
817 | 795 | ||
796 | if (!ctx) | ||
797 | continue; | ||
818 | /* | 798 | /* |
819 | * We don't need to bother with munmap() here - | 799 | * We don't need to bother with munmap() here - exit_mmap(mm) |
820 | * exit_mmap(mm) is coming and it'll unmap everything. | 800 | * is coming and it'll unmap everything. And we simply can't, |
821 | * Since aio_free_ring() uses non-zero ->mmap_size | 801 | * this is not necessarily our ->mm. |
822 | * as indicator that it needs to unmap the area, | 802 | * Since kill_ioctx() uses non-zero ->mmap_size as indicator |
823 | * just set it to 0; aio_free_ring() is the only | 803 | * that it needs to unmap the area, just set it to 0. |
824 | * place that uses ->mmap_size, so it's safe. | ||
825 | */ | 804 | */ |
826 | ctx->mmap_size = 0; | 805 | ctx->mmap_size = 0; |
827 | |||
828 | kill_ioctx(mm, ctx, NULL); | 806 | kill_ioctx(mm, ctx, NULL); |
829 | } | 807 | } |
808 | |||
809 | RCU_INIT_POINTER(mm->ioctx_table, NULL); | ||
810 | kfree(table); | ||
830 | } | 811 | } |
831 | 812 | ||
832 | static void put_reqs_available(struct kioctx *ctx, unsigned nr) | 813 | static void put_reqs_available(struct kioctx *ctx, unsigned nr) |
@@ -834,10 +815,8 @@ static void put_reqs_available(struct kioctx *ctx, unsigned nr) | |||
834 | struct kioctx_cpu *kcpu; | 815 | struct kioctx_cpu *kcpu; |
835 | unsigned long flags; | 816 | unsigned long flags; |
836 | 817 | ||
837 | preempt_disable(); | ||
838 | kcpu = this_cpu_ptr(ctx->cpu); | ||
839 | |||
840 | local_irq_save(flags); | 818 | local_irq_save(flags); |
819 | kcpu = this_cpu_ptr(ctx->cpu); | ||
841 | kcpu->reqs_available += nr; | 820 | kcpu->reqs_available += nr; |
842 | 821 | ||
843 | while (kcpu->reqs_available >= ctx->req_batch * 2) { | 822 | while (kcpu->reqs_available >= ctx->req_batch * 2) { |
@@ -846,7 +825,6 @@ static void put_reqs_available(struct kioctx *ctx, unsigned nr) | |||
846 | } | 825 | } |
847 | 826 | ||
848 | local_irq_restore(flags); | 827 | local_irq_restore(flags); |
849 | preempt_enable(); | ||
850 | } | 828 | } |
851 | 829 | ||
852 | static bool get_reqs_available(struct kioctx *ctx) | 830 | static bool get_reqs_available(struct kioctx *ctx) |
@@ -855,10 +833,8 @@ static bool get_reqs_available(struct kioctx *ctx) | |||
855 | bool ret = false; | 833 | bool ret = false; |
856 | unsigned long flags; | 834 | unsigned long flags; |
857 | 835 | ||
858 | preempt_disable(); | ||
859 | kcpu = this_cpu_ptr(ctx->cpu); | ||
860 | |||
861 | local_irq_save(flags); | 836 | local_irq_save(flags); |
837 | kcpu = this_cpu_ptr(ctx->cpu); | ||
862 | if (!kcpu->reqs_available) { | 838 | if (!kcpu->reqs_available) { |
863 | int old, avail = atomic_read(&ctx->reqs_available); | 839 | int old, avail = atomic_read(&ctx->reqs_available); |
864 | 840 | ||
@@ -878,7 +854,6 @@ static bool get_reqs_available(struct kioctx *ctx) | |||
878 | kcpu->reqs_available--; | 854 | kcpu->reqs_available--; |
879 | out: | 855 | out: |
880 | local_irq_restore(flags); | 856 | local_irq_restore(flags); |
881 | preempt_enable(); | ||
882 | return ret; | 857 | return ret; |
883 | } | 858 | } |
884 | 859 | ||
@@ -1047,7 +1022,7 @@ void aio_complete(struct kiocb *iocb, long res, long res2) | |||
1047 | } | 1022 | } |
1048 | EXPORT_SYMBOL(aio_complete); | 1023 | EXPORT_SYMBOL(aio_complete); |
1049 | 1024 | ||
1050 | /* aio_read_events | 1025 | /* aio_read_events_ring |
1051 | * Pull an event off of the ioctx's event ring. Returns the number of | 1026 | * Pull an event off of the ioctx's event ring. Returns the number of |
1052 | * events fetched | 1027 | * events fetched |
1053 | */ | 1028 | */ |
@@ -1270,12 +1245,12 @@ static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb, | |||
1270 | if (compat) | 1245 | if (compat) |
1271 | ret = compat_rw_copy_check_uvector(rw, | 1246 | ret = compat_rw_copy_check_uvector(rw, |
1272 | (struct compat_iovec __user *)buf, | 1247 | (struct compat_iovec __user *)buf, |
1273 | *nr_segs, 1, *iovec, iovec); | 1248 | *nr_segs, UIO_FASTIOV, *iovec, iovec); |
1274 | else | 1249 | else |
1275 | #endif | 1250 | #endif |
1276 | ret = rw_copy_check_uvector(rw, | 1251 | ret = rw_copy_check_uvector(rw, |
1277 | (struct iovec __user *)buf, | 1252 | (struct iovec __user *)buf, |
1278 | *nr_segs, 1, *iovec, iovec); | 1253 | *nr_segs, UIO_FASTIOV, *iovec, iovec); |
1279 | if (ret < 0) | 1254 | if (ret < 0) |
1280 | return ret; | 1255 | return ret; |
1281 | 1256 | ||
@@ -1299,9 +1274,8 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb, | |||
1299 | } | 1274 | } |
1300 | 1275 | ||
1301 | /* | 1276 | /* |
1302 | * aio_setup_iocb: | 1277 | * aio_run_iocb: |
1303 | * Performs the initial checks and aio retry method | 1278 | * Performs the initial checks and io submission. |
1304 | * setup for the kiocb at the time of io submission. | ||
1305 | */ | 1279 | */ |
1306 | static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, | 1280 | static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, |
1307 | char __user *buf, bool compat) | 1281 | char __user *buf, bool compat) |
@@ -1313,7 +1287,7 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, | |||
1313 | fmode_t mode; | 1287 | fmode_t mode; |
1314 | aio_rw_op *rw_op; | 1288 | aio_rw_op *rw_op; |
1315 | rw_iter_op *iter_op; | 1289 | rw_iter_op *iter_op; |
1316 | struct iovec inline_vec, *iovec = &inline_vec; | 1290 | struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; |
1317 | struct iov_iter iter; | 1291 | struct iov_iter iter; |
1318 | 1292 | ||
1319 | switch (opcode) { | 1293 | switch (opcode) { |
@@ -1348,7 +1322,7 @@ rw_common: | |||
1348 | if (!ret) | 1322 | if (!ret) |
1349 | ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes); | 1323 | ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes); |
1350 | if (ret < 0) { | 1324 | if (ret < 0) { |
1351 | if (iovec != &inline_vec) | 1325 | if (iovec != inline_vecs) |
1352 | kfree(iovec); | 1326 | kfree(iovec); |
1353 | return ret; | 1327 | return ret; |
1354 | } | 1328 | } |
@@ -1395,7 +1369,7 @@ rw_common: | |||
1395 | return -EINVAL; | 1369 | return -EINVAL; |
1396 | } | 1370 | } |
1397 | 1371 | ||
1398 | if (iovec != &inline_vec) | 1372 | if (iovec != inline_vecs) |
1399 | kfree(iovec); | 1373 | kfree(iovec); |
1400 | 1374 | ||
1401 | if (ret != -EIOCBQUEUED) { | 1375 | if (ret != -EIOCBQUEUED) { |