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
| @@ -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; |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 46e0d4e857c7..ba1790e52ff2 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -2394,7 +2394,6 @@ relock: | |||
| 2394 | /* | 2394 | /* |
| 2395 | * for completing the rest of the request. | 2395 | * for completing the rest of the request. |
| 2396 | */ | 2396 | */ |
| 2397 | *ppos += written; | ||
| 2398 | count -= written; | 2397 | count -= written; |
| 2399 | written_buffered = generic_perform_write(file, from, *ppos); | 2398 | written_buffered = generic_perform_write(file, from, *ppos); |
| 2400 | /* | 2399 | /* |
| @@ -2409,7 +2408,6 @@ relock: | |||
| 2409 | goto out_dio; | 2408 | goto out_dio; |
| 2410 | } | 2409 | } |
| 2411 | 2410 | ||
| 2412 | iocb->ki_pos = *ppos + written_buffered; | ||
| 2413 | /* We need to ensure that the page cache pages are written to | 2411 | /* We need to ensure that the page cache pages are written to |
| 2414 | * disk and invalidated to preserve the expected O_DIRECT | 2412 | * disk and invalidated to preserve the expected O_DIRECT |
| 2415 | * semantics. | 2413 | * semantics. |
| @@ -2418,6 +2416,7 @@ relock: | |||
| 2418 | ret = filemap_write_and_wait_range(file->f_mapping, *ppos, | 2416 | ret = filemap_write_and_wait_range(file->f_mapping, *ppos, |
| 2419 | endbyte); | 2417 | endbyte); |
| 2420 | if (ret == 0) { | 2418 | if (ret == 0) { |
| 2419 | iocb->ki_pos = *ppos + written_buffered; | ||
| 2421 | written += written_buffered; | 2420 | written += written_buffered; |
| 2422 | invalidate_mapping_pages(mapping, | 2421 | invalidate_mapping_pages(mapping, |
| 2423 | *ppos >> PAGE_CACHE_SHIFT, | 2422 | *ppos >> PAGE_CACHE_SHIFT, |
| @@ -2440,10 +2439,14 @@ out_dio: | |||
| 2440 | /* buffered aio wouldn't have proper lock coverage today */ | 2439 | /* buffered aio wouldn't have proper lock coverage today */ |
| 2441 | BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); | 2440 | BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); |
| 2442 | 2441 | ||
| 2442 | if (unlikely(written <= 0)) | ||
| 2443 | goto no_sync; | ||
| 2444 | |||
| 2443 | if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) || | 2445 | if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) || |
| 2444 | ((file->f_flags & O_DIRECT) && !direct_io)) { | 2446 | ((file->f_flags & O_DIRECT) && !direct_io)) { |
| 2445 | ret = filemap_fdatawrite_range(file->f_mapping, *ppos, | 2447 | ret = filemap_fdatawrite_range(file->f_mapping, |
| 2446 | *ppos + count - 1); | 2448 | iocb->ki_pos - written, |
| 2449 | iocb->ki_pos - 1); | ||
| 2447 | if (ret < 0) | 2450 | if (ret < 0) |
| 2448 | written = ret; | 2451 | written = ret; |
| 2449 | 2452 | ||
| @@ -2454,10 +2457,12 @@ out_dio: | |||
| 2454 | } | 2457 | } |
| 2455 | 2458 | ||
| 2456 | if (!ret) | 2459 | if (!ret) |
| 2457 | ret = filemap_fdatawait_range(file->f_mapping, *ppos, | 2460 | ret = filemap_fdatawait_range(file->f_mapping, |
| 2458 | *ppos + count - 1); | 2461 | iocb->ki_pos - written, |
| 2462 | iocb->ki_pos - 1); | ||
| 2459 | } | 2463 | } |
| 2460 | 2464 | ||
| 2465 | no_sync: | ||
| 2461 | /* | 2466 | /* |
| 2462 | * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io | 2467 | * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io |
| 2463 | * function pointer which is called when o_direct io completes so that | 2468 | * 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 f4131e8ead74..52cc4492cb3a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -1549,7 +1549,7 @@ struct file_operations { | |||
| 1549 | long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); | 1549 | long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); |
| 1550 | long (*compat_ioctl) (struct file *, unsigned int, unsigned long); | 1550 | long (*compat_ioctl) (struct file *, unsigned int, unsigned long); |
| 1551 | int (*mmap) (struct file *, struct vm_area_struct *); | 1551 | int (*mmap) (struct file *, struct vm_area_struct *); |
| 1552 | void (*mremap)(struct file *, struct vm_area_struct *); | 1552 | int (*mremap)(struct file *, struct vm_area_struct *); |
| 1553 | int (*open) (struct inode *, struct file *); | 1553 | int (*open) (struct inode *, struct file *); |
| 1554 | int (*flush) (struct file *, fl_owner_t id); | 1554 | int (*flush) (struct file *, fl_owner_t id); |
| 1555 | int (*release) (struct inode *, struct file *); | 1555 | 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) { |
