diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-12 13:56:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-12 13:56:12 -0400 |
commit | 6a23b45f1d4b9961e9bf38bc9fb64dc154272abf (patch) | |
tree | fc4ae9cc3a3306743137fea42c463c01090b0e4c /fs/aio.c | |
parent | 54d8ccc30270586f869bfb46ff8a8ca330c8aa23 (diff) | |
parent | 64b4e2526d1cf6e6a4db6213d6e2b6e6ab59479a (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs and fs fixes from Al Viro:
"Several AIO and OCFS2 fixes"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
ocfs2: _really_ sync the right range
ocfs2_file_write_iter: keep return value and current position update in sync
[regression] ocfs2: do *not* increment ->ki_pos twice
ioctx_alloc(): fix vma (and file) leak on failure
fix mremap() vs. ioctx_kill() race
Diffstat (limited to 'fs/aio.c')
-rw-r--r-- | fs/aio.c | 20 |
1 files changed, 14 insertions, 6 deletions
@@ -278,11 +278,11 @@ static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma) | |||
278 | return 0; | 278 | return 0; |
279 | } | 279 | } |
280 | 280 | ||
281 | static void aio_ring_remap(struct file *file, struct vm_area_struct *vma) | 281 | static int aio_ring_remap(struct file *file, struct vm_area_struct *vma) |
282 | { | 282 | { |
283 | struct mm_struct *mm = vma->vm_mm; | 283 | struct mm_struct *mm = vma->vm_mm; |
284 | struct kioctx_table *table; | 284 | struct kioctx_table *table; |
285 | int i; | 285 | int i, res = -EINVAL; |
286 | 286 | ||
287 | spin_lock(&mm->ioctx_lock); | 287 | spin_lock(&mm->ioctx_lock); |
288 | rcu_read_lock(); | 288 | rcu_read_lock(); |
@@ -292,13 +292,17 @@ static void aio_ring_remap(struct file *file, struct vm_area_struct *vma) | |||
292 | 292 | ||
293 | ctx = table->table[i]; | 293 | ctx = table->table[i]; |
294 | if (ctx && ctx->aio_ring_file == file) { | 294 | if (ctx && ctx->aio_ring_file == file) { |
295 | ctx->user_id = ctx->mmap_base = vma->vm_start; | 295 | if (!atomic_read(&ctx->dead)) { |
296 | ctx->user_id = ctx->mmap_base = vma->vm_start; | ||
297 | res = 0; | ||
298 | } | ||
296 | break; | 299 | break; |
297 | } | 300 | } |
298 | } | 301 | } |
299 | 302 | ||
300 | rcu_read_unlock(); | 303 | rcu_read_unlock(); |
301 | spin_unlock(&mm->ioctx_lock); | 304 | spin_unlock(&mm->ioctx_lock); |
305 | return res; | ||
302 | } | 306 | } |
303 | 307 | ||
304 | static const struct file_operations aio_ring_fops = { | 308 | static const struct file_operations aio_ring_fops = { |
@@ -727,6 +731,9 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) | |||
727 | err_cleanup: | 731 | err_cleanup: |
728 | aio_nr_sub(ctx->max_reqs); | 732 | aio_nr_sub(ctx->max_reqs); |
729 | err_ctx: | 733 | err_ctx: |
734 | atomic_set(&ctx->dead, 1); | ||
735 | if (ctx->mmap_size) | ||
736 | vm_munmap(ctx->mmap_base, ctx->mmap_size); | ||
730 | aio_free_ring(ctx); | 737 | aio_free_ring(ctx); |
731 | err: | 738 | err: |
732 | mutex_unlock(&ctx->ring_lock); | 739 | mutex_unlock(&ctx->ring_lock); |
@@ -748,11 +755,12 @@ static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx, | |||
748 | { | 755 | { |
749 | struct kioctx_table *table; | 756 | struct kioctx_table *table; |
750 | 757 | ||
751 | if (atomic_xchg(&ctx->dead, 1)) | 758 | spin_lock(&mm->ioctx_lock); |
759 | if (atomic_xchg(&ctx->dead, 1)) { | ||
760 | spin_unlock(&mm->ioctx_lock); | ||
752 | return -EINVAL; | 761 | return -EINVAL; |
762 | } | ||
753 | 763 | ||
754 | |||
755 | spin_lock(&mm->ioctx_lock); | ||
756 | table = rcu_dereference_raw(mm->ioctx_table); | 764 | table = rcu_dereference_raw(mm->ioctx_table); |
757 | WARN_ON(ctx != table->table[ctx->id]); | 765 | WARN_ON(ctx != table->table[ctx->id]); |
758 | table->table[ctx->id] = NULL; | 766 | table->table[ctx->id] = NULL; |