diff options
-rw-r--r-- | fs/aio.c | 25 | ||||
-rw-r--r-- | include/linux/fs.h | 1 | ||||
-rw-r--r-- | mm/mremap.c | 3 |
3 files changed, 28 insertions, 1 deletions
@@ -286,12 +286,37 @@ static void aio_free_ring(struct kioctx *ctx) | |||
286 | 286 | ||
287 | static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma) | 287 | static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma) |
288 | { | 288 | { |
289 | vma->vm_flags |= VM_DONTEXPAND; | ||
289 | vma->vm_ops = &generic_file_vm_ops; | 290 | vma->vm_ops = &generic_file_vm_ops; |
290 | return 0; | 291 | return 0; |
291 | } | 292 | } |
292 | 293 | ||
294 | static void aio_ring_remap(struct file *file, struct vm_area_struct *vma) | ||
295 | { | ||
296 | struct mm_struct *mm = vma->vm_mm; | ||
297 | struct kioctx_table *table; | ||
298 | int i; | ||
299 | |||
300 | spin_lock(&mm->ioctx_lock); | ||
301 | rcu_read_lock(); | ||
302 | table = rcu_dereference(mm->ioctx_table); | ||
303 | for (i = 0; i < table->nr; i++) { | ||
304 | struct kioctx *ctx; | ||
305 | |||
306 | ctx = table->table[i]; | ||
307 | if (ctx && ctx->aio_ring_file == file) { | ||
308 | ctx->user_id = ctx->mmap_base = vma->vm_start; | ||
309 | break; | ||
310 | } | ||
311 | } | ||
312 | |||
313 | rcu_read_unlock(); | ||
314 | spin_unlock(&mm->ioctx_lock); | ||
315 | } | ||
316 | |||
293 | static const struct file_operations aio_ring_fops = { | 317 | static const struct file_operations aio_ring_fops = { |
294 | .mmap = aio_ring_mmap, | 318 | .mmap = aio_ring_mmap, |
319 | .mremap = aio_ring_remap, | ||
295 | }; | 320 | }; |
296 | 321 | ||
297 | #if IS_ENABLED(CONFIG_MIGRATION) | 322 | #if IS_ENABLED(CONFIG_MIGRATION) |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 9ab779e8a63c..85f378c55c26 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1497,6 +1497,7 @@ struct file_operations { | |||
1497 | long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); | 1497 | long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); |
1498 | long (*compat_ioctl) (struct file *, unsigned int, unsigned long); | 1498 | long (*compat_ioctl) (struct file *, unsigned int, unsigned long); |
1499 | int (*mmap) (struct file *, struct vm_area_struct *); | 1499 | int (*mmap) (struct file *, struct vm_area_struct *); |
1500 | void (*mremap)(struct file *, struct vm_area_struct *); | ||
1500 | int (*open) (struct inode *, struct file *); | 1501 | int (*open) (struct inode *, struct file *); |
1501 | int (*flush) (struct file *, fl_owner_t id); | 1502 | int (*flush) (struct file *, fl_owner_t id); |
1502 | int (*release) (struct inode *, struct file *); | 1503 | int (*release) (struct inode *, struct file *); |
diff --git a/mm/mremap.c b/mm/mremap.c index b147f66f4c40..c855922497a3 100644 --- a/mm/mremap.c +++ b/mm/mremap.c | |||
@@ -288,7 +288,8 @@ static unsigned long move_vma(struct vm_area_struct *vma, | |||
288 | old_len = new_len; | 288 | old_len = new_len; |
289 | old_addr = new_addr; | 289 | old_addr = new_addr; |
290 | new_addr = -ENOMEM; | 290 | new_addr = -ENOMEM; |
291 | } | 291 | } else if (vma->vm_file && vma->vm_file->f_op->mremap) |
292 | vma->vm_file->f_op->mremap(vma->vm_file, new_vma); | ||
292 | 293 | ||
293 | /* Conceal VM_ACCOUNT so old reservation is not undone */ | 294 | /* Conceal VM_ACCOUNT so old reservation is not undone */ |
294 | if (vm_flags & VM_ACCOUNT) { | 295 | if (vm_flags & VM_ACCOUNT) { |