aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/aio.c20
-rw-r--r--fs/ocfs2/file.c17
-rw-r--r--include/linux/fs.h2
-rw-r--r--mm/mremap.c10
4 files changed, 34 insertions, 15 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 8eece807abed..5785c4b58fea 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -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
313static void aio_ring_remap(struct file *file, struct vm_area_struct *vma) 313static 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
336static const struct file_operations aio_ring_fops = { 340static const struct file_operations aio_ring_fops = {
@@ -759,6 +763,9 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
759err_cleanup: 763err_cleanup:
760 aio_nr_sub(ctx->max_reqs); 764 aio_nr_sub(ctx->max_reqs);
761err_ctx: 765err_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);
763err: 770err:
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
2462no_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) {