From: Michal Hocko <mhocko@kernel.org>
To: LKML <linux-kernel@vger.kernel.org>
Cc: "Andrew Morton" <akpm@linux-foundation.org>,
linux-mm@kvack.org, "Alex Deucher" <alexander.deucher@amd.com>,
"Alex Thorlton" <athorlton@sgi.com>,
"Andrea Arcangeli" <aarcange@redhat.com>,
"Andy Lutomirski" <luto@amacapital.net>,
"Benjamin LaHaise" <bcrl@kvack.org>,
"Christian König" <christian.koenig@amd.com>,
"Daniel Vetter" <daniel.vetter@intel.com>,
"Dave Hansen" <dave.hansen@linux.intel.com>,
"David Airlie" <airlied@linux.ie>,
"Davidlohr Bueso" <dave@stgolabs.net>,
"David Rientjes" <rientjes@google.com>,
"H . Peter Anvin" <hpa@zytor.com>,
"Hugh Dickins" <hughd@google.com>,
"Ingo Molnar" <mingo@kernel.org>,
"Johannes Weiner" <hannes@cmpxchg.org>,
"Kirill A . Shutemov" <kirill.shutemov@linux.intel.com>,
"Konstantin Khlebnikov" <koct9i@gmail.com>,
linux-arch@vger.kernel.org, "Mel Gorman" <mgorman@suse.de>,
"Oleg Nesterov" <oleg@redhat.com>,
"Peter Zijlstra" <peterz@infradead.org>,
"Petr Cermak" <petrcermak@chromium.org>,
"Thomas Gleixner" <tglx@linutronix.de>,
"Michal Hocko" <mhocko@suse.com>
Subject: [PATCH 01/18] mm: Make mmap_sem for write waits killable for mm syscalls
Date: Mon, 29 Feb 2016 14:26:40 +0100 [thread overview]
Message-ID: <1456752417-9626-2-git-send-email-mhocko@kernel.org> (raw)
In-Reply-To: <1456752417-9626-1-git-send-email-mhocko@kernel.org>
From: Michal Hocko <mhocko@suse.com>
This is the first step in making mmap_sem write holders killable. It
focuses on the trivial ones which are taking the lock early after
entering the syscall and they are not changing state before.
Therefore it is very easy to change them to use down_write_killable
and immediately return with -EINTR. This will allow the waiter to
pass away without blocking the mmap_sem which might be required to
make a forward progress. E.g. the oom reaper will need the lock for
reading to dismantle the OOM victim address space.
The only tricky function in this patch is vm_mmap_pgoff which has many
call sites via vm_mmap. To reduce the risk keep vm_mmap with the
original non-killable semantic for now.
vm_munmap callers do not bother checking the return value so open code
it into the munmap syscall path for now for simplicity.
Cc: Mel Gorman <mgorman@suse.de>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Signed-off-by: Michal Hocko <mhocko@suse.com>
---
mm/internal.h | 5 +++--
mm/madvise.c | 8 +++++---
mm/mlock.c | 16 ++++++++++------
mm/mmap.c | 27 +++++++++++++++++++++++----
mm/mprotect.c | 3 ++-
mm/mremap.c | 3 ++-
mm/nommu.c | 2 +-
mm/util.c | 12 +++++++++---
8 files changed, 55 insertions(+), 21 deletions(-)
diff --git a/mm/internal.h b/mm/internal.h
index 72bbce3efc36..26576cb3247e 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -444,9 +444,10 @@ extern u64 hwpoison_filter_flags_value;
extern u64 hwpoison_filter_memcg;
extern u32 hwpoison_filter_enable;
-extern unsigned long 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,
+ bool);
extern void set_pageblock_order(void);
unsigned long reclaim_clean_pages_from_list(struct zone *zone,
diff --git a/mm/madvise.c b/mm/madvise.c
index a50ac1885d09..b1809a409a77 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -764,10 +764,12 @@ SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior)
return error;
write = madvise_need_mmap_write(behavior);
- if (write)
- down_write(¤t->mm->mmap_sem);
- else
+ if (write) {
+ if (down_write_killable(¤t->mm->mmap_sem))
+ return -EINTR;
+ } else {
down_read(¤t->mm->mmap_sem);
+ }
blk_start_plug(&plug);
diff --git a/mm/mlock.c b/mm/mlock.c
index 96f001041928..ef8dc9f395c4 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -617,7 +617,7 @@ static int apply_vma_lock_flags(unsigned long start, size_t len,
return error;
}
-static int do_mlock(unsigned long start, size_t len, vm_flags_t flags)
+static __must_check int do_mlock(unsigned long start, size_t len, vm_flags_t flags)
{
unsigned long locked;
unsigned long lock_limit;
@@ -635,7 +635,8 @@ static int do_mlock(unsigned long start, size_t len, vm_flags_t flags)
lock_limit >>= PAGE_SHIFT;
locked = len >> PAGE_SHIFT;
- down_write(¤t->mm->mmap_sem);
+ if (down_write_killable(¤t->mm->mmap_sem))
+ return -EINTR;
locked += current->mm->locked_vm;
@@ -678,7 +679,8 @@ SYSCALL_DEFINE2(munlock, unsigned long, start, size_t, len)
len = PAGE_ALIGN(len + (offset_in_page(start)));
start &= PAGE_MASK;
- down_write(¤t->mm->mmap_sem);
+ if (down_write_killable(¤t->mm->mmap_sem))
+ return -EINTR;
ret = apply_vma_lock_flags(start, len, 0);
up_write(¤t->mm->mmap_sem);
@@ -748,9 +750,10 @@ SYSCALL_DEFINE1(mlockall, int, flags)
lock_limit = rlimit(RLIMIT_MEMLOCK);
lock_limit >>= PAGE_SHIFT;
- ret = -ENOMEM;
- down_write(¤t->mm->mmap_sem);
+ if (down_write_killable(¤t->mm->mmap_sem))
+ return -EINTR;
+ ret = -ENOMEM;
if (!(flags & MCL_CURRENT) || (current->mm->total_vm <= lock_limit) ||
capable(CAP_IPC_LOCK))
ret = apply_mlockall_flags(flags);
@@ -765,7 +768,8 @@ SYSCALL_DEFINE0(munlockall)
{
int ret;
- down_write(¤t->mm->mmap_sem);
+ if (down_write_killable(¤t->mm->mmap_sem))
+ return -EINTR;
ret = apply_mlockall_flags(0);
up_write(¤t->mm->mmap_sem);
return ret;
diff --git a/mm/mmap.c b/mm/mmap.c
index b1e30132eb52..a8ea76c22bb6 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -182,7 +182,8 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
unsigned long min_brk;
bool populate;
- down_write(&mm->mmap_sem);
+ if (down_write_killable(&mm->mmap_sem))
+ return -EINTR;
#ifdef CONFIG_COMPAT_BRK
/*
@@ -1336,7 +1337,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff, true);
out_fput:
if (file)
fput(file);
@@ -2498,6 +2499,10 @@ int vm_munmap(unsigned long start, size_t len)
int ret;
struct mm_struct *mm = current->mm;
+ /*
+ * XXX convert to down_write_killable as soon as all users are able
+ * to handle the error.
+ */
down_write(&mm->mmap_sem);
ret = do_munmap(mm, start, len);
up_write(&mm->mmap_sem);
@@ -2507,8 +2512,15 @@ EXPORT_SYMBOL(vm_munmap);
SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len)
{
+ int ret;
+ struct mm_struct *mm = current->mm;
+
profile_munmap(addr);
- return vm_munmap(addr, len);
+ if (down_write_killable(&mm->mmap_sem))
+ return -EINTR;
+ ret = do_munmap(mm, addr, len);
+ up_write(&mm->mmap_sem);
+ return ret;
}
@@ -2541,7 +2553,9 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
if (pgoff + (size >> PAGE_SHIFT) < pgoff)
return ret;
- down_write(&mm->mmap_sem);
+ if (down_write_killable(&mm->mmap_sem))
+ return -EINTR;
+
vma = find_vma(mm, start);
if (!vma || !(vma->vm_flags & VM_SHARED))
@@ -2706,6 +2720,11 @@ unsigned long vm_brk(unsigned long addr, unsigned long len)
unsigned long ret;
bool populate;
+ /*
+ * XXX not all users are chcecking the return value, convert
+ * to down_write_killable after they are able to cope with
+ * error
+ */
down_write(&mm->mmap_sem);
ret = do_brk(addr, len);
populate = ((mm->def_flags & VM_LOCKED) != 0);
diff --git a/mm/mprotect.c b/mm/mprotect.c
index bf44caea638b..ccd0044f74bd 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -378,7 +378,8 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len,
reqprot = prot;
- down_write(¤t->mm->mmap_sem);
+ if (down_write_killable(¤t->mm->mmap_sem))
+ return -EINTR;
vma = find_vma(current->mm, start);
error = -ENOMEM;
diff --git a/mm/mremap.c b/mm/mremap.c
index 3fa0a467df66..b635ce0ddfb4 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -502,7 +502,8 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
if (!new_len)
return ret;
- down_write(¤t->mm->mmap_sem);
+ if (down_write_killable(¤t->mm->mmap_sem))
+ return -EINTR;
if (flags & MREMAP_FIXED) {
ret = mremap_to(addr, old_len, new_addr, new_len,
diff --git a/mm/nommu.c b/mm/nommu.c
index de8b6b6580c1..50b1d32921c2 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1448,7 +1448,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff, true);
if (file)
fput(file);
diff --git a/mm/util.c b/mm/util.c
index 3bf315fefeb6..98eeec742254 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -319,7 +319,7 @@ EXPORT_SYMBOL_GPL(get_user_pages_fast);
unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
- unsigned long flag, unsigned long pgoff)
+ unsigned long flag, unsigned long pgoff, bool killable)
{
unsigned long ret;
struct mm_struct *mm = current->mm;
@@ -327,7 +327,12 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
ret = security_mmap_file(file, prot, flag);
if (!ret) {
- down_write(&mm->mmap_sem);
+ if (killable) {
+ if (down_write_killable(&mm->mmap_sem))
+ return -EINTR;
+ } else {
+ down_write(&mm->mmap_sem);
+ }
ret = do_mmap_pgoff(file, addr, len, prot, flag, pgoff,
&populate);
up_write(&mm->mmap_sem);
@@ -337,6 +342,7 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
return ret;
}
+/* XXX are all callers checking an error */
unsigned long vm_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flag, unsigned long offset)
@@ -346,7 +352,7 @@ unsigned long vm_mmap(struct file *file, unsigned long addr,
if (unlikely(offset_in_page(offset)))
return -EINVAL;
- return vm_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
+ return vm_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT, false);
}
EXPORT_SYMBOL(vm_mmap);
--
2.7.0
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2016-02-29 13:27 UTC|newest]
Thread overview: 88+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-29 13:26 [PATCH 0/18] change mmap_sem taken for write killable Michal Hocko
2016-02-29 13:26 ` Michal Hocko [this message]
2016-02-29 13:44 ` [PATCH 01/18] mm: Make mmap_sem for write waits killable for mm syscalls kbuild test robot
2016-02-29 13:44 ` kbuild test robot
2016-03-10 15:47 ` Vlastimil Babka
2016-03-10 15:56 ` Michal Hocko
2016-02-29 13:26 ` [PATCH 02/18] mm: make vm_mmap killable Michal Hocko
2016-03-11 9:59 ` Vlastimil Babka
2016-03-11 12:12 ` Michal Hocko
2016-03-11 12:43 ` Vlastimil Babka
2016-03-11 12:55 ` Michal Hocko
2016-02-29 13:26 ` [PATCH 03/18] mm: make vm_munmap killable Michal Hocko
2016-03-11 10:06 ` Vlastimil Babka
2016-03-11 12:32 ` Michal Hocko
2016-02-29 13:26 ` [PATCH 04/18] mm, aout: handle vm_brk failures Michal Hocko
2016-03-11 10:32 ` Vlastimil Babka
2016-03-11 12:42 ` Michal Hocko
2016-02-29 13:26 ` [PATCH 05/18] mm, elf: handle vm_brk error Michal Hocko
2016-03-11 10:35 ` Vlastimil Babka
2016-02-29 13:26 ` [PATCH 06/18] mm: make vm_brk killable Michal Hocko
2016-03-11 10:44 ` Vlastimil Babka
2016-02-29 13:26 ` [PATCH 07/18] mm, proc: make clear_refs killable Michal Hocko
2016-02-29 13:47 ` kbuild test robot
2016-02-29 17:38 ` Oleg Nesterov
2016-02-29 17:53 ` Michal Hocko
2016-02-29 17:58 ` Oleg Nesterov
2016-02-29 18:02 ` Michal Hocko
2016-02-29 17:56 ` [PATCH] " Michal Hocko
2016-02-29 18:16 ` Oleg Nesterov
2016-02-29 20:25 ` kbuild test robot
2016-03-11 10:59 ` Vlastimil Babka
2016-02-29 13:26 ` [PATCH 08/18] mm, fork: make dup_mmap wait for mmap_sem for write killable Michal Hocko
2016-02-29 13:48 ` kbuild test robot
2016-02-29 17:54 ` Oleg Nesterov
2016-02-29 18:07 ` [PATCH] " Michal Hocko
2016-02-29 20:13 ` kbuild test robot
2016-03-11 11:12 ` Vlastimil Babka
2016-02-29 13:26 ` [PATCH 09/18] ipc, shm: make shmem attach/detach wait for mmap_sem killable Michal Hocko
2016-03-08 19:15 ` Davidlohr Bueso
2016-03-09 10:16 ` Michal Hocko
2016-03-09 10:19 ` [PATCH] " Michal Hocko
2016-03-09 10:46 ` kbuild test robot
2016-03-11 11:18 ` Vlastimil Babka
2016-02-29 13:26 ` [PATCH 10/18] vdso: make arch_setup_additional_pages wait for mmap_sem for write killable Michal Hocko
2016-02-29 13:45 ` kbuild test robot
2016-02-29 13:50 ` kbuild test robot
2016-02-29 13:53 ` kbuild test robot
2016-02-29 15:41 ` Andy Lutomirski
2016-03-11 11:28 ` Vlastimil Babka
2016-02-29 13:26 ` [PATCH 11/18] coredump: make coredump_wait wait for mma_sem " Michal Hocko
2016-02-29 15:57 ` Oleg Nesterov
2016-03-11 11:32 ` Vlastimil Babka
2016-03-11 11:54 ` Vlastimil Babka
2016-03-11 12:46 ` Michal Hocko
2016-02-29 13:26 ` [PATCH 12/18] aio: make aio_setup_ring killable Michal Hocko
2016-02-29 16:17 ` Jeff Moyer
2016-03-11 11:57 ` Vlastimil Babka
2016-02-29 13:26 ` [PATCH 13/18] exec: make exec path waiting for mmap_sem killable Michal Hocko
2016-02-29 17:23 ` Oleg Nesterov
2016-02-29 17:47 ` Michal Hocko
2016-02-29 18:10 ` Oleg Nesterov
2016-03-11 12:51 ` Vlastimil Babka
2016-02-29 13:26 ` [PATCH 14/18] prctl: make PR_SET_THP_DISABLE wait " Michal Hocko
2016-03-11 12:54 ` Vlastimil Babka
2016-02-29 13:26 ` [PATCH 15/18] uprobes: wait for mmap_sem for write killable Michal Hocko
2016-02-29 15:57 ` Oleg Nesterov
2016-02-29 16:28 ` Michal Hocko
2016-02-29 17:12 ` Oleg Nesterov
2016-02-29 17:42 ` [PATCH] " Michal Hocko
2016-02-29 17:52 ` kbuild test robot
2016-02-29 17:53 ` kbuild test robot
2016-02-29 18:11 ` Oleg Nesterov
2016-02-29 18:22 ` Michal Hocko
2016-02-29 18:38 ` Oleg Nesterov
2016-03-11 14:58 ` Vlastimil Babka
2016-03-11 15:32 ` Michal Hocko
2016-02-29 13:26 ` [PATCH 16/18] drm/i915: make i915_gem_mmap_ioctl wait for mmap_sem killable Michal Hocko
2016-03-11 15:23 ` Vlastimil Babka
2016-02-29 13:26 ` [PATCH 17/18] drm/radeon: make radeon_mn_get " Michal Hocko
2016-02-29 13:35 ` Christian König
2016-03-11 15:27 ` Vlastimil Babka
2016-02-29 13:26 ` [PATCH 18/18] drm/amdgpu: make amdgpu_mn_get " Michal Hocko
2016-03-11 15:29 ` Vlastimil Babka
2016-02-29 13:31 ` [PATCH 0/18] change mmap_sem taken for write killable Michal Hocko
2016-02-29 14:04 ` Kirill A. Shutemov
2016-02-29 14:16 ` Michal Hocko
2016-02-29 15:03 ` Kirill A. Shutemov
-- strict thread matches above, loose matches on Subject: below --
2016-04-26 12:56 [PATCH 0/18] change mmap_sem taken for write killable v2 Michal Hocko
2016-04-26 12:56 ` [PATCH 01/18] mm: Make mmap_sem for write waits killable for mm syscalls Michal Hocko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1456752417-9626-2-git-send-email-mhocko@kernel.org \
--to=mhocko@kernel.org \
--cc=aarcange@redhat.com \
--cc=airlied@linux.ie \
--cc=akpm@linux-foundation.org \
--cc=alexander.deucher@amd.com \
--cc=athorlton@sgi.com \
--cc=bcrl@kvack.org \
--cc=christian.koenig@amd.com \
--cc=daniel.vetter@intel.com \
--cc=dave.hansen@linux.intel.com \
--cc=dave@stgolabs.net \
--cc=hannes@cmpxchg.org \
--cc=hpa@zytor.com \
--cc=hughd@google.com \
--cc=kirill.shutemov@linux.intel.com \
--cc=koct9i@gmail.com \
--cc=linux-arch@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=luto@amacapital.net \
--cc=mgorman@suse.de \
--cc=mhocko@suse.com \
--cc=mingo@kernel.org \
--cc=oleg@redhat.com \
--cc=peterz@infradead.org \
--cc=petrcermak@chromium.org \
--cc=rientjes@google.com \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).