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 f8e52a1854c1..a793f7023755 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -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
281static void aio_ring_remap(struct file *file, struct vm_area_struct *vma) 281static 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
304static const struct file_operations aio_ring_fops = { 308static const struct file_operations aio_ring_fops = {
@@ -727,6 +731,9 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
727err_cleanup: 731err_cleanup:
728 aio_nr_sub(ctx->max_reqs); 732 aio_nr_sub(ctx->max_reqs);
729err_ctx: 733err_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);
731err: 738err:
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
2465no_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) {