diff options
-rw-r--r-- | fs/aio.c | 20 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 17 | ||||
-rw-r--r-- | include/linux/fs.h | 2 | ||||
-rw-r--r-- | mm/mremap.c | 10 |
4 files changed, 34 insertions, 15 deletions
@@ -310,11 +310,11 @@ static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma) | |||
310 | return 0; | 310 | return 0; |
311 | } | 311 | } |
312 | 312 | ||
313 | static void aio_ring_remap(struct file *file, struct vm_area_struct *vma) | 313 | static int aio_ring_remap(struct file *file, struct vm_area_struct *vma) |
314 | { | 314 | { |
315 | struct mm_struct *mm = vma->vm_mm; | 315 | struct mm_struct *mm = vma->vm_mm; |
316 | struct kioctx_table *table; | 316 | struct kioctx_table *table; |
317 | int i; | 317 | int i, res = -EINVAL; |
318 | 318 | ||
319 | spin_lock(&mm->ioctx_lock); | 319 | spin_lock(&mm->ioctx_lock); |
320 | rcu_read_lock(); | 320 | rcu_read_lock(); |
@@ -324,13 +324,17 @@ static void aio_ring_remap(struct file *file, struct vm_area_struct *vma) | |||
324 | 324 | ||
325 | ctx = table->table[i]; | 325 | ctx = table->table[i]; |
326 | if (ctx && ctx->aio_ring_file == file) { | 326 | if (ctx && ctx->aio_ring_file == file) { |
327 | ctx->user_id = ctx->mmap_base = vma->vm_start; | 327 | if (!atomic_read(&ctx->dead)) { |
328 | ctx->user_id = ctx->mmap_base = vma->vm_start; | ||
329 | res = 0; | ||
330 | } | ||
328 | break; | 331 | break; |
329 | } | 332 | } |
330 | } | 333 | } |
331 | 334 | ||
332 | rcu_read_unlock(); | 335 | rcu_read_unlock(); |
333 | spin_unlock(&mm->ioctx_lock); | 336 | spin_unlock(&mm->ioctx_lock); |
337 | return res; | ||
334 | } | 338 | } |
335 | 339 | ||
336 | static const struct file_operations aio_ring_fops = { | 340 | static const struct file_operations aio_ring_fops = { |
@@ -759,6 +763,9 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) | |||
759 | err_cleanup: | 763 | err_cleanup: |
760 | aio_nr_sub(ctx->max_reqs); | 764 | aio_nr_sub(ctx->max_reqs); |
761 | err_ctx: | 765 | err_ctx: |
766 | atomic_set(&ctx->dead, 1); | ||
767 | if (ctx->mmap_size) | ||
768 | vm_munmap(ctx->mmap_base, ctx->mmap_size); | ||
762 | aio_free_ring(ctx); | 769 | aio_free_ring(ctx); |
763 | err: | 770 | err: |
764 | mutex_unlock(&ctx->ring_lock); | 771 | mutex_unlock(&ctx->ring_lock); |
@@ -780,11 +787,12 @@ static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx, | |||
780 | { | 787 | { |
781 | struct kioctx_table *table; | 788 | struct kioctx_table *table; |
782 | 789 | ||
783 | if (atomic_xchg(&ctx->dead, 1)) | 790 | spin_lock(&mm->ioctx_lock); |
791 | if (atomic_xchg(&ctx->dead, 1)) { | ||
792 | spin_unlock(&mm->ioctx_lock); | ||
784 | return -EINVAL; | 793 | return -EINVAL; |
794 | } | ||
785 | 795 | ||
786 | |||
787 | spin_lock(&mm->ioctx_lock); | ||
788 | table = rcu_dereference_raw(mm->ioctx_table); | 796 | table = rcu_dereference_raw(mm->ioctx_table); |
789 | WARN_ON(ctx != table->table[ctx->id]); | 797 | WARN_ON(ctx != table->table[ctx->id]); |
790 | table->table[ctx->id] = NULL; | 798 | table->table[ctx->id] = NULL; |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 1c11314946cb..8096fb6c081b 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -2391,7 +2391,6 @@ relock: | |||
2391 | /* | 2391 | /* |
2392 | * for completing the rest of the request. | 2392 | * for completing the rest of the request. |
2393 | */ | 2393 | */ |
2394 | *ppos += written; | ||
2395 | count -= written; | 2394 | count -= written; |
2396 | written_buffered = generic_perform_write(file, from, *ppos); | 2395 | written_buffered = generic_perform_write(file, from, *ppos); |
2397 | /* | 2396 | /* |
@@ -2406,7 +2405,6 @@ relock: | |||
2406 | goto out_dio; | 2405 | goto out_dio; |
2407 | } | 2406 | } |
2408 | 2407 | ||
2409 | iocb->ki_pos = *ppos + written_buffered; | ||
2410 | /* We need to ensure that the page cache pages are written to | 2408 | /* We need to ensure that the page cache pages are written to |
2411 | * disk and invalidated to preserve the expected O_DIRECT | 2409 | * disk and invalidated to preserve the expected O_DIRECT |
2412 | * semantics. | 2410 | * semantics. |
@@ -2415,6 +2413,7 @@ relock: | |||
2415 | ret = filemap_write_and_wait_range(file->f_mapping, *ppos, | 2413 | ret = filemap_write_and_wait_range(file->f_mapping, *ppos, |
2416 | endbyte); | 2414 | endbyte); |
2417 | if (ret == 0) { | 2415 | if (ret == 0) { |
2416 | iocb->ki_pos = *ppos + written_buffered; | ||
2418 | written += written_buffered; | 2417 | written += written_buffered; |
2419 | invalidate_mapping_pages(mapping, | 2418 | invalidate_mapping_pages(mapping, |
2420 | *ppos >> PAGE_CACHE_SHIFT, | 2419 | *ppos >> PAGE_CACHE_SHIFT, |
@@ -2437,10 +2436,14 @@ out_dio: | |||
2437 | /* buffered aio wouldn't have proper lock coverage today */ | 2436 | /* buffered aio wouldn't have proper lock coverage today */ |
2438 | BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); | 2437 | BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); |
2439 | 2438 | ||
2439 | if (unlikely(written <= 0)) | ||
2440 | goto no_sync; | ||
2441 | |||
2440 | if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) || | 2442 | if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) || |
2441 | ((file->f_flags & O_DIRECT) && !direct_io)) { | 2443 | ((file->f_flags & O_DIRECT) && !direct_io)) { |
2442 | ret = filemap_fdatawrite_range(file->f_mapping, *ppos, | 2444 | ret = filemap_fdatawrite_range(file->f_mapping, |
2443 | *ppos + count - 1); | 2445 | iocb->ki_pos - written, |
2446 | iocb->ki_pos - 1); | ||
2444 | if (ret < 0) | 2447 | if (ret < 0) |
2445 | written = ret; | 2448 | written = ret; |
2446 | 2449 | ||
@@ -2451,10 +2454,12 @@ out_dio: | |||
2451 | } | 2454 | } |
2452 | 2455 | ||
2453 | if (!ret) | 2456 | if (!ret) |
2454 | ret = filemap_fdatawait_range(file->f_mapping, *ppos, | 2457 | ret = filemap_fdatawait_range(file->f_mapping, |
2455 | *ppos + count - 1); | 2458 | iocb->ki_pos - written, |
2459 | iocb->ki_pos - 1); | ||
2456 | } | 2460 | } |
2457 | 2461 | ||
2462 | no_sync: | ||
2458 | /* | 2463 | /* |
2459 | * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io | 2464 | * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io |
2460 | * function pointer which is called when o_direct io completes so that | 2465 | * function pointer which is called when o_direct io completes so that |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 492948ea4c9b..c7b21db7782f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1569,7 +1569,7 @@ struct file_operations { | |||
1569 | long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); | 1569 | long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); |
1570 | long (*compat_ioctl) (struct file *, unsigned int, unsigned long); | 1570 | long (*compat_ioctl) (struct file *, unsigned int, unsigned long); |
1571 | int (*mmap) (struct file *, struct vm_area_struct *); | 1571 | int (*mmap) (struct file *, struct vm_area_struct *); |
1572 | void (*mremap)(struct file *, struct vm_area_struct *); | 1572 | int (*mremap)(struct file *, struct vm_area_struct *); |
1573 | int (*open) (struct inode *, struct file *); | 1573 | int (*open) (struct inode *, struct file *); |
1574 | int (*flush) (struct file *, fl_owner_t id); | 1574 | int (*flush) (struct file *, fl_owner_t id); |
1575 | int (*release) (struct inode *, struct file *); | 1575 | int (*release) (struct inode *, struct file *); |
diff --git a/mm/mremap.c b/mm/mremap.c index 57dadc025c64..2dc44b1cb1df 100644 --- a/mm/mremap.c +++ b/mm/mremap.c | |||
@@ -286,8 +286,14 @@ static unsigned long move_vma(struct vm_area_struct *vma, | |||
286 | old_len = new_len; | 286 | old_len = new_len; |
287 | old_addr = new_addr; | 287 | old_addr = new_addr; |
288 | new_addr = -ENOMEM; | 288 | new_addr = -ENOMEM; |
289 | } else if (vma->vm_file && vma->vm_file->f_op->mremap) | 289 | } else if (vma->vm_file && vma->vm_file->f_op->mremap) { |
290 | vma->vm_file->f_op->mremap(vma->vm_file, new_vma); | 290 | err = vma->vm_file->f_op->mremap(vma->vm_file, new_vma); |
291 | if (err < 0) { | ||
292 | move_page_tables(new_vma, new_addr, vma, old_addr, | ||
293 | moved_len, true); | ||
294 | return err; | ||
295 | } | ||
296 | } | ||
291 | 297 | ||
292 | /* Conceal VM_ACCOUNT so old reservation is not undone */ | 298 | /* Conceal VM_ACCOUNT so old reservation is not undone */ |
293 | if (vm_flags & VM_ACCOUNT) { | 299 | if (vm_flags & VM_ACCOUNT) { |