Commit 9fbeb5ab authored by Michal Hocko's avatar Michal Hocko Committed by Linus Torvalds

mm: make vm_mmap killable

All the callers of vm_mmap seem to check for the failure already and
bail out in one way or another on the error which means that we can
change it to use killable version of vm_mmap_pgoff and return -EINTR if
the current task gets killed while waiting for mmap_sem.  This also
means that vm_mmap_pgoff can be killable by default and drop the
additional parameter.

This will help in the OOM conditions when the oom victim might be stuck
waiting for the mmap_sem for write which in turn can block oom_reaper
which relies on the mmap_sem for read to make a forward progress and
reclaim the address space of the victim.

Please note that load_elf_binary is ignoring vm_mmap error for
current->personality & MMAP_PAGE_ZERO case but that shouldn't be a
problem because the address is not used anywhere and we never return to
the userspace if we got killed.
Signed-off-by: default avatarMichal Hocko <mhocko@suse.com>
Acked-by: default avatarVlastimil Babka <vbabka@suse.cz>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent dc0ef0df
...@@ -2013,7 +2013,7 @@ static inline void mm_populate(unsigned long addr, unsigned long len) {} ...@@ -2013,7 +2013,7 @@ static inline void mm_populate(unsigned long addr, unsigned long len) {}
/* These take the mm semaphore themselves */ /* These take the mm semaphore themselves */
extern unsigned long vm_brk(unsigned long, unsigned long); extern unsigned long vm_brk(unsigned long, unsigned long);
extern int vm_munmap(unsigned long, size_t); extern int vm_munmap(unsigned long, size_t);
extern unsigned long vm_mmap(struct file *, unsigned long, extern unsigned long __must_check vm_mmap(struct file *, unsigned long,
unsigned long, unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long); unsigned long, unsigned long);
......
...@@ -444,8 +444,7 @@ extern u32 hwpoison_filter_enable; ...@@ -444,8 +444,7 @@ extern u32 hwpoison_filter_enable;
extern unsigned long __must_check vm_mmap_pgoff(struct file *, unsigned long, extern unsigned long __must_check vm_mmap_pgoff(struct file *, unsigned long,
unsigned long, unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long, unsigned long, unsigned long);
bool);
extern void set_pageblock_order(void); extern void set_pageblock_order(void);
unsigned long reclaim_clean_pages_from_list(struct zone *zone, unsigned long reclaim_clean_pages_from_list(struct zone *zone,
......
...@@ -1333,7 +1333,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, ...@@ -1333,7 +1333,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff, true); retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);
out_fput: out_fput:
if (file) if (file)
fput(file); fput(file);
......
...@@ -1446,7 +1446,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, ...@@ -1446,7 +1446,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff, true); retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);
if (file) if (file)
fput(file); fput(file);
......
...@@ -289,7 +289,7 @@ EXPORT_SYMBOL_GPL(get_user_pages_fast); ...@@ -289,7 +289,7 @@ EXPORT_SYMBOL_GPL(get_user_pages_fast);
unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr, unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot, unsigned long len, unsigned long prot,
unsigned long flag, unsigned long pgoff, bool killable) unsigned long flag, unsigned long pgoff)
{ {
unsigned long ret; unsigned long ret;
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
...@@ -297,12 +297,8 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr, ...@@ -297,12 +297,8 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
ret = security_mmap_file(file, prot, flag); ret = security_mmap_file(file, prot, flag);
if (!ret) { if (!ret) {
if (killable) { if (down_write_killable(&mm->mmap_sem))
if (down_write_killable(&mm->mmap_sem)) return -EINTR;
return -EINTR;
} else {
down_write(&mm->mmap_sem);
}
ret = do_mmap_pgoff(file, addr, len, prot, flag, pgoff, ret = do_mmap_pgoff(file, addr, len, prot, flag, pgoff,
&populate); &populate);
up_write(&mm->mmap_sem); up_write(&mm->mmap_sem);
...@@ -312,7 +308,6 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr, ...@@ -312,7 +308,6 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
return ret; return ret;
} }
/* XXX are all callers checking an error */
unsigned long vm_mmap(struct file *file, unsigned long addr, unsigned long vm_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot, unsigned long len, unsigned long prot,
unsigned long flag, unsigned long offset) unsigned long flag, unsigned long offset)
...@@ -322,7 +317,7 @@ unsigned long vm_mmap(struct file *file, unsigned long addr, ...@@ -322,7 +317,7 @@ unsigned long vm_mmap(struct file *file, unsigned long addr,
if (unlikely(offset_in_page(offset))) if (unlikely(offset_in_page(offset)))
return -EINVAL; return -EINVAL;
return vm_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT, false); return vm_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
} }
EXPORT_SYMBOL(vm_mmap); EXPORT_SYMBOL(vm_mmap);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment