Skip to contentSkip to conversation

change mmap_sem taken for write killable

PATCH In review Michal Hocko 9 participants 87 messages Feb 29, 2016 – Mar 11, 2016

Subsystems (26)
lore
Share & tools
lore
#0 lore raw

cover change mmap_sem taken for write killable

Hi,
this is a follow up work for oom_reaper [1]. As the async OOM killing depends on oom_sem for read we would really appreciate if a holder for write stood in the way. This patchset is changing many of down_write calls to be killable to help those cases when the writer is blocked and waiting for readers to release the lock and so help __oom_reap_task to process the oom victim.

Most of the patches are really trivial because the lock is help from a shallow syscall paths where we can return EINTR trivially. Others seem to be easy as well as the callers are already handling fatal errors and bail and return to userspace which should be sufficient to handle the failure gracefully. I am not familiar with all those code paths so a deeper review is really appreciated.

As this work is touching more areas which are not directly connected I have tried to keep the CC list as small as possible and people who I believed would be familiar are CCed only to the specific patches (all should have received the cover though).

This patchset is based on linux-next and it depends on down_write_killable for rw_semaphores posted recently [2].

I haven't covered all the mmap_write(mm->mmap_sem) instances here

$ git grep "down_write(.*\<mmap_sem\>)" next/master | wc -l
102
$ git grep "down_write(.*\<mmap_sem\>)" | wc -l
66

I have tried to cover those which should be relatively easy to review in this series because this alone should be a nice improvement. Other places can be changed on top.

Any feedback is highly appreciated.

---
[1] http://lkml.kernel.org/r/[email protected]
[2] http://lkml.kernel.org/r/[email protected]

#1 lore raw

PATCH 1/18 mm: Make mmap_sem for write waits killable for mm syscalls

From: Michal Hocko <[email protected]>

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 <[email protected]>
Cc "Kirill A. Shutemov" <[email protected]>
Cc Konstantin Khlebnikov <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc Andrea Arcangeli <[email protected]>
Cc David Rientjes <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Johannes Weiner <[email protected]>
---
 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(-)
mm/internal.h +3 -2
index 72bbce3efc36..26576cb3247e 100644
@@ -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,
mm/madvise.c +5 -3
index a50ac1885d09..b1809a409a77 100644
@@ -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(&current->mm->mmap_sem);
-	else
+	if (write) {
+		if (down_write_killable(&current->mm->mmap_sem))
+			return -EINTR;
+	} else {
 		down_read(&current->mm->mmap_sem);
+	}
 
 	blk_start_plug(&plug);
 
mm/mlock.c +10 -6
index 96f001041928..ef8dc9f395c4 100644
@@ -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(&current->mm->mmap_sem);
+	if (down_write_killable(&current->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(&current->mm->mmap_sem);
+	if (down_write_killable(&current->mm->mmap_sem))
+		return -EINTR;
 	ret = apply_vma_lock_flags(start, len, 0);
 	up_write(&current->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(&current->mm->mmap_sem);
+	if (down_write_killable(&current->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(&current->mm->mmap_sem);
+	if (down_write_killable(&current->mm->mmap_sem))
+		return -EINTR;
 	ret = apply_mlockall_flags(0);
 	up_write(&current->mm->mmap_sem);
 	return ret;
mm/mmap.c +23 -4
index b1e30132eb52..a8ea76c22bb6 100644
@@ -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);
mm/mprotect.c +2 -1
index bf44caea638b..ccd0044f74bd 100644
@@ -378,7 +378,8 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len,
 
 	reqprot = prot;
 
-	down_write(&current->mm->mmap_sem);
+	if (down_write_killable(&current->mm->mmap_sem))
+		return -EINTR;
 
 	vma = find_vma(current->mm, start);
 	error = -ENOMEM;
mm/mremap.c +2 -1
index 3fa0a467df66..b635ce0ddfb4 100644
@@ -502,7 +502,8 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
 	if (!new_len)
 		return ret;
 
-	down_write(&current->mm->mmap_sem);
+	if (down_write_killable(&current->mm->mmap_sem))
+		return -EINTR;
 
 	if (flags & MREMAP_FIXED) {
 		ret = mremap_to(addr, old_len, new_addr, new_len,
mm/nommu.c +1 -1
index de8b6b6580c1..50b1d32921c2 100644
@@ -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);
mm/util.c +9 -3
index 3bf315fefeb6..98eeec742254 100644
@@ -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);
 
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#2 lore raw

Re: [PATCH 01/18] mm: Make mmap_sem for write waits killable for mm syscalls

reproduce:

Hi Michal,

[auto build test ERROR on next-20160229]
[also build test ERROR on v4.5-rc6]
[cannot apply to drm/drm-next drm-intel/for-linux-next v4.5-rc6 v4.5-rc5 v4.5-rc4] [if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Michal-Hocko/change-mmap_sem-taken-for-write-killable/20160229-213258
config: i386-randconfig-x004-201609 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

mm/util.c: In function 'vm_mmap_pgoff':

>> mm/util.c:331:8: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
       if (down_write_killable(&mm->mmap_sem))
           ^
   cc1: some warnings being treated as errors
--
   mm/mlock.c: In function 'do_mlock':
>> mm/mlock.c:638:6: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
     if (down_write_killable(&current->mm->mmap_sem))
         ^
   cc1: some warnings being treated as errors
--
   mm/mmap.c: In function 'SYSC_brk':
>> mm/mmap.c:185:6: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
     if (down_write_killable(&mm->mmap_sem))
         ^
   cc1: some warnings being treated as errors
--
   mm/mprotect.c: In function 'SYSC_mprotect':
>> mm/mprotect.c:381:6: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
     if (down_write_killable(&current->mm->mmap_sem))
         ^
   cc1: some warnings being treated as errors
--
   mm/mremap.c: In function 'SYSC_mremap':
>> mm/mremap.c:505:6: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
     if (down_write_killable(&current->mm->mmap_sem))
         ^

cc1: some warnings being treated as errors

vim +/down_write_killable +331 mm/util.c

325 struct mm_struct *mm = current->mm;
326 unsigned long populate;
327
328 ret = security_mmap_file(file, prot, flag);
329 if (!ret) {
330 if (killable) {

 > 331				if (down_write_killable(&mm->mmap_sem))

332 return -EINTR;
333 } else {
334 down_write(&mm->mmap_sem);

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#3 lore raw

Re: [PATCH 01/18] mm: Make mmap_sem for write waits killable for mm syscalls

In reply to Michal Hocko
reproduce:

Hi Michal,

[auto build test WARNING on next-20160229]
[also build test WARNING on v4.5-rc6]
[cannot apply to drm/drm-next drm-intel/for-linux-next v4.5-rc6 v4.5-rc5 v4.5-rc4] [if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Michal-Hocko/change-mmap_sem-taken-for-write-killable/20160229-213258
config: i386-randconfig-x003-201609 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

In file included from include/asm-generic/bug.h:4:0,

                    from arch/x86/include/asm/bug.h:35,
                    from include/linux/bug.h:4,
                    from include/linux/mmdebug.h:4,
                    from include/linux/mm.h:8,
                    from mm/util.c:1:
   mm/util.c: In function 'vm_mmap_pgoff':
   mm/util.c:331:8: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
       if (down_write_killable(&mm->mmap_sem))
           ^
   include/linux/compiler.h:151:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^
>> mm/util.c:331:4: note: in expansion of macro 'if'
       if (down_write_killable(&mm->mmap_sem))
       ^
   cc1: some warnings being treated as errors
--
   In file included from include/uapi/linux/stddef.h:1:0,
                    from include/linux/stddef.h:4,
                    from include/uapi/linux/posix_types.h:4,
                    from include/uapi/linux/types.h:13,
                    from include/linux/types.h:5,
                    from include/uapi/linux/capability.h:16,
                    from include/linux/capability.h:15,
                    from mm/mlock.c:8:
   mm/mlock.c: In function 'do_mlock':
   mm/mlock.c:638:6: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
     if (down_write_killable(&current->mm->mmap_sem))
         ^
   include/linux/compiler.h:151:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^
>> mm/mlock.c:638:2: note: in expansion of macro 'if'
     if (down_write_killable(&current->mm->mmap_sem))
     ^
   cc1: some warnings being treated as errors
--
   In file included from include/linux/linkage.h:4:0,
                    from include/linux/kernel.h:6,
                    from mm/mmap.c:11:
   mm/mmap.c: In function 'SYSC_brk':
   mm/mmap.c:185:6: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
     if (down_write_killable(&mm->mmap_sem))
         ^
   include/linux/compiler.h:151:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^
>> mm/mmap.c:185:2: note: in expansion of macro 'if'
     if (down_write_killable(&mm->mmap_sem))
     ^
   cc1: some warnings being treated as errors
--
   In file included from include/asm-generic/bug.h:4:0,
                    from arch/x86/include/asm/bug.h:35,
                    from include/linux/bug.h:4,
                    from include/linux/mmdebug.h:4,
                    from include/linux/mm.h:8,
                    from mm/mprotect.c:11:
   mm/mprotect.c: In function 'SYSC_mprotect':
   mm/mprotect.c:381:6: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
     if (down_write_killable(&current->mm->mmap_sem))
         ^
   include/linux/compiler.h:151:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^
>> mm/mprotect.c:381:2: note: in expansion of macro 'if'
     if (down_write_killable(&current->mm->mmap_sem))
     ^
   cc1: some warnings being treated as errors
--
   In file included from include/asm-generic/bug.h:4:0,
                    from arch/x86/include/asm/bug.h:35,
                    from include/linux/bug.h:4,
                    from include/linux/mmdebug.h:4,
                    from include/linux/mm.h:8,
                    from mm/mremap.c:10:
   mm/mremap.c: In function 'SYSC_mremap':
   mm/mremap.c:505:6: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
     if (down_write_killable(&current->mm->mmap_sem))
         ^
   include/linux/compiler.h:151:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^
>> mm/mremap.c:505:2: note: in expansion of macro 'if'
     if (down_write_killable(&current->mm->mmap_sem))
     ^
   cc1: some warnings being treated as errors
--
   In file included from include/asm-generic/bug.h:4:0,
                    from arch/x86/include/asm/bug.h:35,
                    from include/linux/bug.h:4,
                    from include/linux/mmdebug.h:4,
                    from include/linux/mm.h:8,
                    from include/linux/mman.h:4,
                    from mm/madvise.c:8:
   mm/madvise.c: In function 'SYSC_madvise':
   mm/madvise.c:768:7: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
      if (down_write_killable(&current->mm->mmap_sem))
          ^
   include/linux/compiler.h:151:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^
>> mm/madvise.c:768:3: note: in expansion of macro 'if'
      if (down_write_killable(&current->mm->mmap_sem))
      ^

cc1: some warnings being treated as errors

vim +/if +331 mm/util.c

315 {
316 return get_user_pages_unlocked(start, nr_pages, write, 0, pages);
317 }
318 EXPORT_SYMBOL_GPL(get_user_pages_fast);
319
320 unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
321 unsigned long len, unsigned long prot,
322 unsigned long flag, unsigned long pgoff, bool killable)
323 {
324 unsigned long ret;
325 struct mm_struct *mm = current->mm;
326 unsigned long populate;
327
328 ret = security_mmap_file(file, prot, flag);
329 if (!ret) {
330 if (killable) {

 > 331				if (down_write_killable(&mm->mmap_sem))

332 return -EINTR;
333 } else {
334 down_write(&mm->mmap_sem);
335 }
336 ret = do_mmap_pgoff(file, addr, len, prot, flag, pgoff,
337 &populate);
338 up_write(&mm->mmap_sem);
339 if (populate)

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

Acked-by on v1 1/18
#4 lore raw

Re: [PATCH 01/18] mm: Make mmap_sem for write waits killable for mm syscalls

In reply to Michal Hocko
Quoted 3 lines · Michal Hocko

From: Michal Hocko <[email protected]>

This is the first step in making mmap_sem write holders killable. It

s/holders/waiters/?

Quoted 16 lines

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.

Quoted 9 lines
Cc Mel Gorman <[email protected]>
Cc "Kirill A. Shutemov" <[email protected]>
Cc Konstantin Khlebnikov <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc Andrea Arcangeli <[email protected]>
Cc David Rientjes <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Johannes Weiner <[email protected]>
#5 lore raw

Re: [PATCH 01/18] mm: Make mmap_sem for write waits killable for mm syscalls

Quoted 6 lines · Vlastimil Babka
Quoted 3 lines · Michal Hocko

From: Michal Hocko <[email protected]>

This is the first step in making mmap_sem write holders killable. It

s/holders/waiters/?

right. Fixed

Quoted 26 lines
Quoted 16 lines

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.

Quoted 9 lines
Cc Mel Gorman <[email protected]>
Cc "Kirill A. Shutemov" <[email protected]>
Cc Konstantin Khlebnikov <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc Andrea Arcangeli <[email protected]>
Cc David Rientjes <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Johannes Weiner <[email protected]>
Quoted 1 line

Thanks!

Signature · 2 lines
Michal Hocko
SUSE Labs
#6 lore raw

PATCH 2/18 mm: make vm_mmap killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

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.

Cc "Kirill A. Shutemov" <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Oleg Nesterov <[email protected]>
Cc Andrea Arcangeli <[email protected]>
Cc Al Viro <[email protected]>
Cc Johannes Weiner <[email protected]>
---
 include/linux/mm.h |  2 +-
 mm/internal.h      |  3 +--
 mm/mmap.c          |  2 +-
 mm/nommu.c         |  2 +-
 mm/util.c          | 13 ++++---------
 5 files changed, 8 insertions(+), 14 deletions(-)
include/linux/mm.h +1 -1
index 8a84cf07da8c..4ee6a3561540 100644
@@ -2079,7 +2079,7 @@ static inline void mm_populate(unsigned long addr, unsigned long len) {}
 /* These take the mm semaphore themselves */
 extern unsigned long vm_brk(unsigned long, unsigned long);
 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);
 
mm/internal.h +1 -2
index 26576cb3247e..d8d4c32bfce4 100644
@@ -446,8 +446,7 @@ extern u32 hwpoison_filter_enable;
 
 extern unsigned long  __must_check vm_mmap_pgoff(struct file *, unsigned long,
         unsigned long, unsigned long,
-        unsigned long, unsigned long,
-        bool);
+        unsigned long, unsigned long);
 
 extern void set_pageblock_order(void);
 unsigned long reclaim_clean_pages_from_list(struct zone *zone,
mm/mmap.c +1 -1
index a8ea76c22bb6..4e1f852a52ff 100644
@@ -1337,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, true);
+	retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 out_fput:
 	if (file)
 		fput(file);
mm/nommu.c +1 -1
index 50b1d32921c2..de8b6b6580c1 100644
@@ -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, true);
+	retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 
 	if (file)
 		fput(file);
mm/util.c +4 -9
index 98eeec742254..0e383fe48145 100644
@@ -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, bool killable)
+	unsigned long flag, unsigned long pgoff)
 {
 	unsigned long ret;
 	struct mm_struct *mm = current->mm;
@@ -327,12 +327,8 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
 
 	ret = security_mmap_file(file, prot, flag);
 	if (!ret) {
-		if (killable) {
-			if (down_write_killable(&mm->mmap_sem))
-				return -EINTR;
-		} else {
-			down_write(&mm->mmap_sem);
-		}
+		if (down_write_killable(&mm->mmap_sem))
+			return -EINTR;
 		ret = do_mmap_pgoff(file, addr, len, prot, flag, pgoff,
 				    &populate);
 		up_write(&mm->mmap_sem);
@@ -342,7 +338,6 @@ 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)
@@ -352,7 +347,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, false);
+	return vm_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
 }
 EXPORT_SYMBOL(vm_mmap);
 
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#7 lore raw

Re: [PATCH 02/18] mm: make vm_mmap killable

Quoted 4 lines · Michal Hocko

From: Michal Hocko <[email protected]>

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

Hmm I'm not that sure about this one:
17 1071 fs/binfmt_elf.c <<load_elf_binary>>

Assigns result of vm_mmap() to "error" variable which is never checked. Shouldn't __must_check trigger here?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#8 lore raw

Re: [PATCH 02/18] mm: make vm_mmap killable

Quoted 10 lines · Vlastimil Babka
Quoted 4 lines · Michal Hocko

From: Michal Hocko <[email protected]>

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

Hmm I'm not that sure about this one:
17 1071 fs/binfmt_elf.c <<load_elf_binary>>

Assigns result of vm_mmap() to "error" variable which is never checked.

Yes it is not checked but not used either. If the current got killed then it wouldn't return to the userspace so my understanding is that not checking this value is not a problem. At least that is my understanding.

Quoted 1 line

Shouldn't __must_check trigger here?

well, __must_check is a misleading name. It doesn't actually enforce the value is checked. It just has to be used and an assignment is sufficient. I was discussing this without our gcc guy and he promissed to look and try to come up with a different attribute which would actually work like __must_check.

Signature · 2 lines
Michal Hocko
SUSE Labs
#9 lore raw

Re: [PATCH 02/18] mm: make vm_mmap killable

Quoted 7 lines · Michal Hocko
Quoted 6 lines · Vlastimil Babka
Quoted 4 lines · Michal Hocko

From: Michal Hocko <[email protected]>

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

Quoted 8 lines
Quoted 4 lines

Hmm I'm not that sure about this one:
17 1071 fs/binfmt_elf.c <<load_elf_binary>>

Assigns result of vm_mmap() to "error" variable which is never checked.

Yes it is not checked but not used either. If the current got killed then it wouldn't return to the userspace so my understanding is that not checking this value is not a problem. At least that is my understanding.

Hmm, that's true. So,

Quoted 7 lines
Quoted 1 line

Shouldn't __must_check trigger here?

well, __must_check is a misleading name. It doesn't actually enforce the value is checked. It just has to be used and an assignment is sufficient. I was discussing this without our gcc guy and he promissed to look and try to come up with a different attribute which would actually work like __must_check.

OK!

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#10 lore raw

Re: [PATCH 02/18] mm: make vm_mmap killable

Quoted 11 lines · Vlastimil Babka
Quoted 10 lines · Michal Hocko
Quoted 9 lines · Vlastimil Babka
Quoted 4 lines · Michal Hocko

From: Michal Hocko <[email protected]>

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

Hmm I'm not that sure about this one:
17 1071 fs/binfmt_elf.c <<load_elf_binary>>

Quoted 7 lines
Quoted 5 lines
Quoted 1 line

Assigns result of vm_mmap() to "error" variable which is never checked.

Yes it is not checked but not used either. If the current got killed then it wouldn't return to the userspace so my understanding is that not checking this value is not a problem. At least that is my understanding.

Hmm, that's true. So,

I have updated the changelog and added the following note:
"
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.
"

Quoted 1 line

Thanks!

Signature · 2 lines
Michal Hocko
SUSE Labs
#11 lore raw

PATCH 3/18 mm: make vm_munmap killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

Almost all current users of vm_munmap are ignoring the return value and so they do not handle potential error. This means that some VMAs might stay behind. This patch doesn't try to solve those potential problems. Quite contrary it adds a new failure mode by using down_write_killable in vm_munmap. This should be safer than other failure modes, though, because the process is guaranteed to die as soon as it leaves the kernel and exit_mmap will clean the whole address space.

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.

Cc Oleg Nesterov <[email protected]>
Cc "Kirill A. Shutemov" <[email protected]>
Cc Konstantin Khlebnikov <[email protected]>
Cc Andrea Arcangeli <[email protected]>
Cc Alexander Viro <[email protected]>
---
 mm/mmap.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)
mm/mmap.c +3 -5
index 4e1f852a52ff..5d33c841e3a2 100644
@@ -2499,11 +2499,9 @@ 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);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+
 	ret = do_munmap(mm, start, len);
 	up_write(&mm->mmap_sem);
 	return ret;
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#12 lore raw

Re: [PATCH 03/18] mm: make vm_munmap killable

Quoted 4 lines · Michal Hocko

From: Michal Hocko <[email protected]>

Almost all current users of vm_munmap are ignoring the return value and so they do not handle potential error. This means that some VMAs

1 7834 arch/x86/kvm/x86.c <<__x86_set_memory_region>>

             r = vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE);
             WARN_ON(r < 0);

This warning will potentially add noise to OOM output?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#13 lore raw

Re: [PATCH 03/18] mm: make vm_munmap killable

Quoted 6 lines · Vlastimil Babka
Quoted 4 lines · Michal Hocko

From: Michal Hocko <[email protected]>

Almost all current users of vm_munmap are ignoring the return value and so they do not handle potential error. This means that some VMAs

Quoted 6 lines
   1   7834  arch/x86/kvm/x86.c <<__x86_set_memory_region>>

             r = vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE);
             WARN_ON(r < 0);

This warning will potentially add noise to OOM output?

Would it be harmfull though? I mean the warning is just goofy. I can make it not warn on (r < 0 && r != -EINTR) but is it worth bothering?

Thanks!

Signature · 8 lines
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#14 lore raw

PATCH 4/18 mm, aout: handle vm_brk failures

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

vm_brk is allowed to fail but load_aout_binary simply ignores the error and happily continues. I haven't noticed any problem from that in real life but later patches will make the failure more likely because vm_brk will become killable (resp. mmap_sem for write waiting will become killable) so we should be more careful now.

The error handling should be quite straightforward because there are calls to vm_mmap which check the error properly already. The only notable exception is set_brk which is called after beyond_if label. But nothing indicates that we cannot move it above set_binfmt as the two do not depend on each other and fail before we do set_binfmt and alter reference counting.

Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Alexander Viro <[email protected]>
---
 arch/x86/ia32/ia32_aout.c | 22 +++++++++++++++-------
 fs/binfmt_aout.c          |  9 +++++++--
 2 files changed, 22 insertions(+), 9 deletions(-)
arch/x86/ia32/ia32_aout.c +15 -7
index ae6aad1d24f7..f5e737ff0022 100644
@@ -116,13 +116,13 @@ static struct linux_binfmt aout_format = {
 	.min_coredump	= PAGE_SIZE
 };
 
-static void set_brk(unsigned long start, unsigned long end)
+static unsigned long set_brk(unsigned long start, unsigned long end)
 {
 	start = PAGE_ALIGN(start);
 	end = PAGE_ALIGN(end);
 	if (end <= start)
-		return;
-	vm_brk(start, end - start);
+		return start;
+	return vm_brk(start, end - start);
 }
 
 #ifdef CONFIG_COREDUMP
@@ -349,7 +349,10 @@ static int load_aout_binary(struct linux_binprm *bprm)
 #endif
 
 		if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) {
-			vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
+			error = vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
+			if (IS_ERR_VALUE(error))
+				return error;
+
 			read_code(bprm->file, N_TXTADDR(ex), fd_offset,
 					ex.a_text+ex.a_data);
 			goto beyond_if;
@@ -372,10 +375,13 @@ static int load_aout_binary(struct linux_binprm *bprm)
 		if (error != N_DATADDR(ex))
 			return error;
 	}
+
 beyond_if:
-	set_binfmt(&aout_format);
+	error = set_brk(current->mm->start_brk, current->mm->brk);
+	if (IS_ERR_VALUE(error))
+		return error;
 
-	set_brk(current->mm->start_brk, current->mm->brk);
+	set_binfmt(&aout_format);
 
 	current->mm->start_stack =
 		(unsigned long)create_aout_tables((char __user *)bprm->p, bprm);
@@ -434,7 +440,9 @@ static int load_aout_library(struct file *file)
 			error_time = jiffies;
 		}
 #endif
-		vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+		retval = vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+		if (IS_ERR_VALUE(retval))
+			goto out;
 
 		read_code(file, start_addr, N_TXTOFF(ex),
 			  ex.a_text + ex.a_data);
fs/binfmt_aout.c +7 -2
index 4c556680fa74..5fb075f05706 100644
@@ -297,7 +297,10 @@ static int load_aout_binary(struct linux_binprm * bprm)
 		}
 
 		if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
-			vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
+			error = vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
+			if (IS_ERR_VALUE(error))
+				return error;
+
 			read_code(bprm->file, N_TXTADDR(ex), fd_offset,
 				  ex.a_text + ex.a_data);
 			goto beyond_if;
@@ -378,7 +381,9 @@ static int load_aout_library(struct file *file)
 			       "N_TXTOFF is not page aligned. Please convert library: %pD\n",
 			       file);
 		}
-		vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+		retval = vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+		if (IS_ERR_VALUE(retval))
+			goto out;
 		
 		read_code(file, start_addr, N_TXTOFF(ex),
 			  ex.a_text + ex.a_data);
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#15 lore raw

Re: [PATCH 04/18] mm, aout: handle vm_brk failures

Quoted 15 lines · Michal Hocko

From: Michal Hocko <[email protected]>

vm_brk is allowed to fail but load_aout_binary simply ignores the error and happily continues. I haven't noticed any problem from that in real life but later patches will make the failure more likely because vm_brk will become killable (resp. mmap_sem for write waiting will become killable) so we should be more careful now.

The error handling should be quite straightforward because there are calls to vm_mmap which check the error properly already. The only notable exception is set_brk which is called after beyond_if label. But nothing indicates that we cannot move it above set_binfmt as the two do not depend on each other and fail before we do set_binfmt and alter reference counting.

Quoted 5 lines
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Alexander Viro <[email protected]>

[...]

fs/binfmt_aout.c static int load_aout_library(struct file *file) · line 387

Quoted 9 lines
fs/binfmt_aout.c +3 -1
@@ -378,7 +381,9 @@ static int load_aout_library(struct file *file)
  			       "N_TXTOFF is not page aligned. Please convert library: %pD\n",
  			       file);
  		}
-		vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+		retval = vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+		if (IS_ERR_VALUE(retval))
+			goto out;
 

You could have removed the extra whitespace on the line above, which my vim so prominently highlights :)

Quoted 3 lines
(quoted diff) +0 -0
  		read_code(file, start_addr, N_TXTOFF(ex),
  			  ex.a_text + ex.a_data);
#16 lore raw

Re: [PATCH 04/18] mm, aout: handle vm_brk failures

Quoted 16 lines · Vlastimil Babka
Quoted 15 lines · Michal Hocko

From: Michal Hocko <[email protected]>

vm_brk is allowed to fail but load_aout_binary simply ignores the error and happily continues. I haven't noticed any problem from that in real life but later patches will make the failure more likely because vm_brk will become killable (resp. mmap_sem for write waiting will become killable) so we should be more careful now.

The error handling should be quite straightforward because there are calls to vm_mmap which check the error properly already. The only notable exception is set_brk which is called after beyond_if label. But nothing indicates that we cannot move it above set_binfmt as the two do not depend on each other and fail before we do set_binfmt and alter reference counting.

Quoted 7 lines
Quoted 5 lines
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Alexander Viro <[email protected]>

thanks!

Quoted 15 lines

[...]

fs/binfmt_aout.c static int load_aout_library(struct file *file) · line 387

Quoted 9 lines
fs/binfmt_aout.c +3 -1
@@ -378,7 +381,9 @@ static int load_aout_library(struct file *file)
 			       "N_TXTOFF is not page aligned. Please convert library: %pD\n",
 			       file);
 		}
-		vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+		retval = vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+		if (IS_ERR_VALUE(retval))
+			goto out;
 

You could have removed the extra whitespace on the line above, which my vim so prominently highlights :)

Fixed

Quoted 4 lines
Quoted 4 lines
(quoted diff) +0 -0
 		read_code(file, start_addr, N_TXTOFF(ex),
 			  ex.a_text + ex.a_data);
Signature · 2 lines
Michal Hocko
SUSE Labs
#17 lore raw

PATCH 5/18 mm, elf: handle vm_brk error

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

load_elf_library doesn't handle vm_brk failure although nothing really indicates it cannot do that because the function is allowed to fail due to vm_mmap failures already. This might be not a problem now but later patch will make vm_brk killable (resp. mmap_sem for write waiting will become killable) and so the failure will be more probable.

Cc Alexander Viro <[email protected]>
---
 fs/binfmt_elf.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
fs/binfmt_elf.c +5 -2
index 7d914c67a9d0..2e45ae57ea88 100644
@@ -1176,8 +1176,11 @@ static int load_elf_library(struct file *file)
 	len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr +
 			    ELF_MIN_ALIGN - 1);
 	bss = eppnt->p_memsz + eppnt->p_vaddr;
-	if (bss > len)
-		vm_brk(len, bss - len);
+	if (bss > len) {
+		error = vm_brk(len, bss - len);
+		if (BAD_ADDR(error))
+			goto out_free_ph;
+	}
 	error = 0;
 
 out_free_ph:
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Acked-by on v1 5/18
#18 lore raw

Re: [PATCH 05/18] mm, elf: handle vm_brk error

Quoted 10 lines · Michal Hocko

From: Michal Hocko <[email protected]>

load_elf_library doesn't handle vm_brk failure although nothing really indicates it cannot do that because the function is allowed to fail due to vm_mmap failures already. This might be not a problem now but later patch will make vm_brk killable (resp. mmap_sem for write waiting will become killable) and so the failure will be more probable.

Cc Alexander Viro <[email protected]>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#19 lore raw

PATCH 6/18 mm: make vm_brk killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

Now that all the callers handle vm_brk failure we can change it wait for mmap_sem killable to help oom_reaper to not get blocked just because vm_brk gets blocked behind mmap_sem readers.

Cc "Kirill A. Shutemov" <[email protected]>
Cc Oleg Nesterov <[email protected]>
Cc Andrea Arcangeli <[email protected]>
---
 include/linux/mm.h | 2 +-
 mm/mmap.c          | 9 +++------
 2 files changed, 4 insertions(+), 7 deletions(-)
include/linux/mm.h +1 -1
index 4ee6a3561540..dccaea8682f2 100644
@@ -2077,7 +2077,7 @@ static inline void mm_populate(unsigned long addr, unsigned long len) {}
 #endif
 
 /* These take the mm semaphore themselves */
-extern unsigned long vm_brk(unsigned long, unsigned long);
+extern unsigned long __must_check vm_brk(unsigned long, unsigned long);
 extern int vm_munmap(unsigned long, size_t);
 extern unsigned long __must_check vm_mmap(struct file *, unsigned long,
         unsigned long, unsigned long,
mm/mmap.c +3 -6
index 5d33c841e3a2..3f264fb14118 100644
@@ -2718,12 +2718,9 @@ 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);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+
 	ret = do_brk(addr, len);
 	populate = ((mm->def_flags & VM_LOCKED) != 0);
 	up_write(&mm->mmap_sem);
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Acked-by on v1 6/18
#20 lore raw

Re: [PATCH 06/18] mm: make vm_brk killable

Quoted 10 lines · Michal Hocko

From: Michal Hocko <[email protected]>

Now that all the callers handle vm_brk failure we can change it wait for mmap_sem killable to help oom_reaper to not get blocked just because vm_brk gets blocked behind mmap_sem readers.

Cc "Kirill A. Shutemov" <[email protected]>
Cc Oleg Nesterov <[email protected]>
Cc Andrea Arcangeli <[email protected]>
#21 lore raw

PATCH 7/18 mm, proc: make clear_refs killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

CLEAR_REFS_MM_HIWATER_RSS and CLEAR_REFS_SOFT_DIRTY are relying on mmap_sem for write. If the waiting task gets killed by the oom killer and it would operate on the current's mm it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting. This will also expedite the return to the userspace and do_exit even if the mm is remote.

---
 fs/proc/task_mmu.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
fs/proc/task_mmu.c +9 -2
index 9df431642042..fc303fa1f5c0 100644
@@ -1027,11 +1027,15 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
 		};
 
 		if (type == CLEAR_REFS_MM_HIWATER_RSS) {
+			if (down_write_killable(&mm->mmap_sem)) {
+				put_task_struct(task);
+				return -EINTR;
+			}
+
 			/*
 			 * Writing 5 to /proc/pid/clear_refs resets the peak
 			 * resident set size to this mm's current rss value.
 			 */
-			down_write(&mm->mmap_sem);
 			reset_mm_hiwater_rss(mm);
 			up_write(&mm->mmap_sem);
 			goto out_mm;
@@ -1043,7 +1047,10 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
 				if (!(vma->vm_flags & VM_SOFTDIRTY))
 					continue;
 				up_read(&mm->mmap_sem);
-				down_write(&mm->mmap_sem);
+				if (down_write_killable(&mm->mmap_sem)) {
+					put_task_struct(task);
+					return -EINTR;
+				}
 				for (vma = mm->mmap; vma; vma = vma->vm_next) {
 					vma->vm_flags &= ~VM_SOFTDIRTY;
 					vma_set_page_prot(vma);
Signature · 1 line
2.7.0
#22 lore raw

Re: [PATCH 07/18] mm, proc: make clear_refs killable

reproduce:

Hi Michal,

[auto build test WARNING on next-20160229]
[also build test WARNING on v4.5-rc6]
[cannot apply to drm/drm-next drm-intel/for-linux-next v4.5-rc6 v4.5-rc5 v4.5-rc4] [if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Michal-Hocko/change-mmap_sem-taken-for-write-killable/20160229-213258
config: i386-randconfig-x003-201609 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

In file included from include/asm-generic/bug.h:4:0,

                    from arch/x86/include/asm/bug.h:35,
                    from include/linux/bug.h:4,
                    from include/linux/mmdebug.h:4,
                    from include/linux/mm.h:8,
                    from fs/proc/task_mmu.c:1:
   fs/proc/task_mmu.c: In function 'clear_refs_write':
   fs/proc/task_mmu.c:1030:8: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
       if (down_write_killable(&mm->mmap_sem)) {
           ^
   include/linux/compiler.h:151:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^
>> fs/proc/task_mmu.c:1030:4: note: in expansion of macro 'if'
       if (down_write_killable(&mm->mmap_sem)) {
       ^

cc1: some warnings being treated as errors

vim +/if +1030 fs/proc/task_mmu.c

1014 task = get_proc_task(file_inode(file));
1015 if (!task)
1016 return -ESRCH;
1017 mm = get_task_mm(task);
1018 if (mm) {
1019 struct clear_refs_private cp = {
1020 .type = type,
1021 };
1022 struct mm_walk clear_refs_walk = {
1023 .pmd_entry = clear_refs_pte_range,
1024 .test_walk = clear_refs_test_walk,
1025 .mm = mm,
1026 .private = &cp,
1027 };
1028
1029 if (type == CLEAR_REFS_MM_HIWATER_RSS) {

> 1030				if (down_write_killable(&mm->mmap_sem)) {

1031 put_task_struct(task);
1032 return -EINTR;
1033 }
1034
1035 /*
1036 * Writing 5 to /proc/pid/clear_refs resets the peak
1037 * resident set size to this mm's current rss value.
1038 */

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

maintainer
#23 lore raw

Re: [PATCH 07/18] mm, proc: make clear_refs killable

In reply to Michal Hocko
Quoted 21 lines · Michal Hocko
fs/proc/task_mmu.c +5 -1
@@ -1027,11 +1027,15 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
 		};
 
 		if (type == CLEAR_REFS_MM_HIWATER_RSS) {
+			if (down_write_killable(&mm->mmap_sem)) {
+				put_task_struct(task);
+				return -EINTR;
+			}
+
 			/*
 			 * Writing 5 to /proc/pid/clear_refs resets the peak
 			 * resident set size to this mm's current rss value.
 			 */
-			down_write(&mm->mmap_sem);
 			reset_mm_hiwater_rss(mm);
 			up_write(&mm->mmap_sem);
 			goto out_mm;

fs/proc/task_mmu.c static ssize_t clear_refs_write(struct file *file, const char __user *buf, · line 1053

Quoted 8 lines
fs/proc/task_mmu.c +4 -1
@@ -1043,7 +1047,10 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
 				if (!(vma->vm_flags & VM_SOFTDIRTY))
 					continue;
 				up_read(&mm->mmap_sem);
-				down_write(&mm->mmap_sem);
+				if (down_write_killable(&mm->mmap_sem)) {
+					put_task_struct(task);
+					return -EINTR;
+				}

Both lack mmput() afaics. Don't you need "goto out_mm" rather then "return" ? In this case you do not need put_task_struct().

Oleg.

#24 lore raw

Re: [PATCH 07/18] mm, proc: make clear_refs killable

Quoted 24 lines · Oleg Nesterov
Quoted 23 lines · Michal Hocko
fs/proc/task_mmu.c +5 -1
@@ -1027,11 +1027,15 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
 		};
 
 		if (type == CLEAR_REFS_MM_HIWATER_RSS) {
+			if (down_write_killable(&mm->mmap_sem)) {
+				put_task_struct(task);
+				return -EINTR;
+			}
+
 			/*
 			 * Writing 5 to /proc/pid/clear_refs resets the peak
 			 * resident set size to this mm's current rss value.
 			 */
-			down_write(&mm->mmap_sem);
 			reset_mm_hiwater_rss(mm);
 			up_write(&mm->mmap_sem);
 			goto out_mm;
@@ -1043,7 +1047,10 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
 				if (!(vma->vm_flags & VM_SOFTDIRTY))
 					continue;
Quoted 8 lines

fs/proc/task_mmu.c static ssize_t clear_refs_write(struct file *file, const char __user *buf, · line 1053

Quoted 6 lines
fs/proc/task_mmu.c +4 -1
 				up_read(&mm->mmap_sem);
-				down_write(&mm->mmap_sem);
+				if (down_write_killable(&mm->mmap_sem)) {
+					put_task_struct(task);
+					return -EINTR;
+				}

Both lack mmput() afaics. Don't you need "goto out_mm" rather then "return" ?

Of course I need! Thanks for catching that.

Quoted 1 line

In this case you do not need put_task_struct().

Why not? Both are after get_proc_task which takes a reference to the task...

I will send an updated patch. Thanks!

Signature · 8 lines
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#25 lore raw

Re: [PATCH 07/18] mm, proc: make clear_refs killable

Quoted 7 lines · Michal Hocko
Quoted 1 line · Oleg Nesterov

In this case you do not need put_task_struct().

Why not? Both are after get_proc_task which takes a reference to the task...

Yes, but we already have put_task_struct(task) in the "out_mm" path, so "goto out_mm" should work just fine?

Oleg.

#26 lore raw

Re: [PATCH 07/18] mm, proc: make clear_refs killable

Quoted 11 lines · Oleg Nesterov
Quoted 7 lines · Michal Hocko
Quoted 1 line · Oleg Nesterov

In this case you do not need put_task_struct().

Why not? Both are after get_proc_task which takes a reference to the task...

Yes, but we already have put_task_struct(task) in the "out_mm" path, so "goto out_mm" should work just fine?

OK, got what you mean now. That's what I did and is on the way. I just thought you mean that put_task_struct is implicit for other reason.

Signature · 8 lines
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#27 lore raw

PATCH 1/1 mm, proc: make clear_refs killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

CLEAR_REFS_MM_HIWATER_RSS and CLEAR_REFS_SOFT_DIRTY are relying on mmap_sem for write. If the waiting task gets killed by the oom killer and it would operate on the current's mm it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting. This will also expedite the return to the userspace and do_exit even if the mm is remote.

Cc Oleg Nesterov <[email protected]>
Cc Petr Cermak <[email protected]>
---
 fs/proc/task_mmu.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
fs/proc/task_mmu.c +9 -2
index 9df431642042..bb117356a04e 100644
@@ -1027,11 +1027,15 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
 		};
 
 		if (type == CLEAR_REFS_MM_HIWATER_RSS) {
+			if (down_write_killable(&mm->mmap_sem)) {
+				count = -EINTR;
+				goto out_mm;
+			}
+
 			/*
 			 * Writing 5 to /proc/pid/clear_refs resets the peak
 			 * resident set size to this mm's current rss value.
 			 */
-			down_write(&mm->mmap_sem);
 			reset_mm_hiwater_rss(mm);
 			up_write(&mm->mmap_sem);
 			goto out_mm;
@@ -1043,7 +1047,10 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
 				if (!(vma->vm_flags & VM_SOFTDIRTY))
 					continue;
 				up_read(&mm->mmap_sem);
-				down_write(&mm->mmap_sem);
+				if (down_write_killable(&mm->mmap_sem)) {
+					count = -EINTR;
+					goto out_mm;
+				}
 				for (vma = mm->mmap; vma; vma = vma->vm_next) {
 					vma->vm_flags &= ~VM_SOFTDIRTY;
 					vma_set_page_prot(vma);
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#28 lore raw

Re: [PATCH] mm, proc: make clear_refs killable

fs/proc/task_mmu.c static ssize_t clear_refs_write(struct file *file, const char __user *buf, · line 1034

Quoted 12 lines · Michal Hocko
fs/proc/task_mmu.c +5 -0
@@ -1027,11 +1027,15 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
 		};
 
 		if (type == CLEAR_REFS_MM_HIWATER_RSS) {
+			if (down_write_killable(&mm->mmap_sem)) {
+				count = -EINTR;
+				goto out_mm;
+			}
+

We do not even need to change count, userspace won't see it anyway. But I agree it look more clean this way.

I believe the patch is fine.

Oleg.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#29 lore raw

Re: [PATCH] mm, proc: make clear_refs killable

In reply to Michal Hocko
reproduce:

Hi Michal,

[auto build test ERROR on v4.5-rc6]
[also build test ERROR on next-20160229]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Michal-Hocko/mm-proc-make-clear_refs-killable/20160301-020426
config: x86_64-lkp (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

fs/proc/task_mmu.c: In function 'clear_refs_write':

>> fs/proc/task_mmu.c:1016:4: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
       if (down_write_killable(&mm->mmap_sem)) {
       ^

cc1: some warnings being treated as errors

vim +/down_write_killable +1016 fs/proc/task_mmu.c

1010 .test_walk = clear_refs_test_walk,
1011 .mm = mm,
1012 .private = &cp,
1013 };
1014
1015 if (type == CLEAR_REFS_MM_HIWATER_RSS) {

> 1016				if (down_write_killable(&mm->mmap_sem)) {

1017 count = -EINTR;
1018 goto out_mm;
1019 }

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

Acked-by on v1 1/1
#30 lore raw

Re: [PATCH] mm, proc: make clear_refs killable

In reply to Michal Hocko
Quoted 10 lines · Michal Hocko

From: Michal Hocko <[email protected]>

CLEAR_REFS_MM_HIWATER_RSS and CLEAR_REFS_SOFT_DIRTY are relying on mmap_sem for write. If the waiting task gets killed by the oom killer and it would operate on the current's mm it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting. This will also expedite the return to the userspace and do_exit even if the mm is remote.

Quoted 3 lines
Cc Oleg Nesterov <[email protected]>
Cc Petr Cermak <[email protected]>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#31 lore raw

PATCH 8/18 mm, fork: make dup_mmap wait for mmap_sem for write killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

dup_mmap needs to lock current's mm mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Cc Ingo Molnar <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Oleg Nesterov <[email protected]>
Cc Konstantin Khlebnikov <[email protected]>
---
 kernel/fork.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
kernel/fork.c +4 -1
index d277e83ed3e0..e064bc8453dc 100644
@@ -413,7 +413,10 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
 	unsigned long charge;
 
 	uprobe_start_dup_mmap();
-	down_write(&oldmm->mmap_sem);
+	if (down_write_killable(&oldmm->mmap_sem)) {
+		uprobe_end_dup_mmap();
+		return -EINTR;
+	}
 	flush_cache_dup_mm(oldmm);
 	uprobe_dup_mmap(oldmm, mm);
 	/*
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#32 lore raw

Re: [PATCH 08/18] mm, fork: make dup_mmap wait for mmap_sem for write killable

reproduce:

Hi Michal,

[auto build test ERROR on next-20160229]
[also build test ERROR on v4.5-rc6]
[cannot apply to drm/drm-next drm-intel/for-linux-next v4.5-rc6 v4.5-rc5 v4.5-rc4] [if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Michal-Hocko/change-mmap_sem-taken-for-write-killable/20160229-213258
config: i386-randconfig-x004-201609 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

kernel/fork.c: In function 'dup_mmap':

>> kernel/fork.c:416:6: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
     if (down_write_killable(&oldmm->mmap_sem)) {
         ^

cc1: some warnings being treated as errors

vim +/down_write_killable +416 kernel/fork.c

410 struct vm_area_struct *mpnt, *tmp, *prev, **pprev;
411 struct rb_node **rb_link, *rb_parent;
412 int retval;
413 unsigned long charge;
414
415 uprobe_start_dup_mmap();

 > 416		if (down_write_killable(&oldmm->mmap_sem)) {

417 uprobe_end_dup_mmap();
418 return -EINTR;
419 }

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

maintainer
#33 lore raw

Re: [PATCH 08/18] mm, fork: make dup_mmap wait for mmap_sem for write killable

In reply to Michal Hocko

kernel/fork.c static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) · line 419

Quoted 12 lines · Michal Hocko
kernel/fork.c +4 -1
@@ -413,7 +413,10 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
 	unsigned long charge;
 
 	uprobe_start_dup_mmap();
-	down_write(&oldmm->mmap_sem);
+	if (down_write_killable(&oldmm->mmap_sem)) {
+		uprobe_end_dup_mmap();
+		return -EINTR;
+	}

This is really cosmetic and subjective, I won't insist if you prefer it this way.

But perhaps it makes sense to add another "fail" label above uprobe_end_dup_mmap() we already have... IMO it is always better to avoid duplicating when it comes to "unlock".

Oleg.

#34 lore raw

PATCH 1/1 mm, fork: make dup_mmap wait for mmap_sem for write killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

dup_mmap needs to lock current's mm mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Cc Ingo Molnar <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Oleg Nesterov <[email protected]>
Cc Konstantin Khlebnikov <[email protected]>
---
 kernel/fork.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
kernel/fork.c +5 -1
index d277e83ed3e0..139968026b76 100644
@@ -413,7 +413,10 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
 	unsigned long charge;
 
 	uprobe_start_dup_mmap();
-	down_write(&oldmm->mmap_sem);
+	if (down_write_killable(&oldmm->mmap_sem)) {
+		retval = -EINTR;
+		goto fail_uprobe_end;
+	}
 	flush_cache_dup_mm(oldmm);
 	uprobe_dup_mmap(oldmm, mm);
 	/*
@@ -525,6 +528,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
 	up_write(&mm->mmap_sem);
 	flush_tlb_mm(oldmm);
 	up_write(&oldmm->mmap_sem);
+fail_uprobe_end:
 	uprobe_end_dup_mmap();
 	return retval;
 fail_nomem_anon_vma_fork:
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#35 lore raw

Re: [PATCH] mm, fork: make dup_mmap wait for mmap_sem for write killable

reproduce:

Hi Michal,

[auto build test ERROR on v4.5-rc6]
[also build test ERROR on next-20160229]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Michal-Hocko/mm-fork-make-dup_mmap-wait-for-mmap_sem-for-write-killable/20160301-021107
config: x86_64-lkp (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

kernel/fork.c: In function 'dup_mmap':

>> kernel/fork.c:405:2: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
     if (down_write_killable(&oldmm->mmap_sem)) {
     ^

cc1: some warnings being treated as errors

vim +/down_write_killable +405 kernel/fork.c

399 struct vm_area_struct *mpnt, *tmp, *prev, **pprev;
400 struct rb_node **rb_link, *rb_parent;
401 int retval;
402 unsigned long charge;
403
404 uprobe_start_dup_mmap();

 > 405		if (down_write_killable(&oldmm->mmap_sem)) {

406 retval = -EINTR;
407 goto fail_uprobe_end;
408 }

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

Acked-by on v1 1/1
#36 lore raw

Re: [PATCH] mm, fork: make dup_mmap wait for mmap_sem for write killable

In reply to Michal Hocko
Quoted 8 lines · Michal Hocko

From: Michal Hocko <[email protected]>

dup_mmap needs to lock current's mm mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Quoted 5 lines
Cc Ingo Molnar <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Oleg Nesterov <[email protected]>
Cc Konstantin Khlebnikov <[email protected]>
Quoted 22 lines
---
  kernel/fork.c | 6 +++++-
  1 file changed, 5 insertions(+), 1 deletion(-)
kernel/fork.c +4 -1
index d277e83ed3e0..139968026b76 100644
@@ -413,7 +413,10 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
  	unsigned long charge;
 
  	uprobe_start_dup_mmap();
-	down_write(&oldmm->mmap_sem);
+	if (down_write_killable(&oldmm->mmap_sem)) {
+		retval = -EINTR;
+		goto fail_uprobe_end;
+	}
  	flush_cache_dup_mm(oldmm);
  	uprobe_dup_mmap(oldmm, mm);
  	/*

kernel/fork.c static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) · line 534

Quoted 7 lines
kernel/fork.c +1 -0
@@ -525,6 +528,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
  	up_write(&mm->mmap_sem);
  	flush_tlb_mm(oldmm);
  	up_write(&oldmm->mmap_sem);
+fail_uprobe_end:
  	uprobe_end_dup_mmap();
  	return retval;
  fail_nomem_anon_vma_fork:

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#37 lore raw

PATCH 9/18 ipc, shm: make shmem attach/detach wait for mmap_sem killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

shmat and shmdt rely on mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Cc Davidlohr Bueso <[email protected]>
Cc Hugh Dickins <[email protected]>
---
 ipc/shm.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
ipc/shm.c +7 -2
index 331fc1b0b3c7..b8cfa05940d2 100644
@@ -1200,7 +1200,11 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
 	if (err)
 		goto out_fput;
 
-	down_write(&current->mm->mmap_sem);
+	if (down_write_killable(&current->mm->mmap_sem)) {
+		err = -EINVAL;
+		goto out_fput;
+	}
+
 	if (addr && !(shmflg & SHM_REMAP)) {
 		err = -EINVAL;
 		if (addr + size < addr)
@@ -1271,7 +1275,8 @@ SYSCALL_DEFINE1(shmdt, char __user *, shmaddr)
 	if (addr & ~PAGE_MASK)
 		return retval;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 
 	/*
 	 * This function tries to be smart and unmap shm segments that
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Acked-by on v1 9/18
#38 lore raw

Re: [PATCH 09/18] ipc, shm: make shmem attach/detach wait for mmap_sem killable

Quoted 11 lines · Michal Hocko

From: Michal Hocko <[email protected]>

shmat and shmdt rely on mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Cc Davidlohr Bueso <[email protected]>
Cc Hugh Dickins <[email protected]>

I have no objection to this perse, just one comment below.

Quoted 9 lines

---
ipc/shm.c | 9 +++++++--

1 file changed, 7 insertions(+), 2 deletions(-)
ipc/shm.c +0 -0
index 331fc1b0b3c7..b8cfa05940d2 100644

ipc/shm.c long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, · line 1206

Quoted 8 lines
ipc/shm.c +4 -1
@@ -1200,7 +1200,11 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
 	if (err)
 		goto out_fput;
 
-	down_write(&current->mm->mmap_sem);
+	if (down_write_killable(&current->mm->mmap_sem)) {
+		err = -EINVAL;
+		goto out_fput;
+	}

This should be EINTR, no?

Thanks,
Davidlohr

Quoted 17 lines
ipc/shm.c +3 -1
+
 	if (addr && !(shmflg & SHM_REMAP)) {
 		err = -EINVAL;
 		if (addr + size < addr)
@@ -1271,7 +1275,8 @@ SYSCALL_DEFINE1(shmdt, char __user *, shmaddr)
 	if (addr & ~PAGE_MASK)
 		return retval;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 
 	/*
 	 * This function tries to be smart and unmap shm segments that
Signature · 1 line
2.7.0
#39 lore raw

Re: [PATCH 09/18] ipc, shm: make shmem attach/detach wait for mmap_sem killable

Quoted 10 lines · Davidlohr Bueso
Quoted 8 lines · Michal Hocko

From: Michal Hocko <[email protected]>

shmat and shmdt rely on mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Quoted 7 lines
Quoted 3 lines
Cc Davidlohr Bueso <[email protected]>
Cc Hugh Dickins <[email protected]>

I have no objection to this perse, just one comment below.

Thanks!

[...]

Quoted 7 lines

ipc/shm.c long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, · line 1206

Quoted 5 lines
ipc/shm.c +4 -1
-	down_write(&current->mm->mmap_sem);
+	if (down_write_killable(&current->mm->mmap_sem)) {
+		err = -EINVAL;
+		goto out_fput;
+	}

This should be EINTR, no?

Of course. Thanks for catching that.

Signature · 2 lines
Michal Hocko
SUSE Labs
#40 lore raw

PATCH 1/1 ipc, shm: make shmem attach/detach wait for mmap_sem killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

shmat and shmdt rely on mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

---
 ipc/shm.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
ipc/shm.c +7 -2
index 331fc1b0b3c7..13282510bc0d 100644
@@ -1200,7 +1200,11 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
 	if (err)
 		goto out_fput;
 
-	down_write(&current->mm->mmap_sem);
+	if (down_write_killable(&current->mm->mmap_sem)) {
+		err = -EINTR;
+		goto out_fput;
+	}
+
 	if (addr && !(shmflg & SHM_REMAP)) {
 		err = -EINVAL;
 		if (addr + size < addr)
@@ -1271,7 +1275,8 @@ SYSCALL_DEFINE1(shmdt, char __user *, shmaddr)
 	if (addr & ~PAGE_MASK)
 		return retval;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 
 	/*
 	 * This function tries to be smart and unmap shm segments that
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#41 lore raw

Re: [PATCH] ipc, shm: make shmem attach/detach wait for mmap_sem killable

reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree…

Hi Michal,

[auto build test ERROR on v4.5-rc7]
[also build test ERROR on next-20160309]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Michal-Hocko/ipc-shm-make-shmem-attach-detach-wait-for-mmap_sem-killable/20160309-182238
config: xtensa-allyesconfig (attached as .config)

reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=xtensa

All errors (new ones prefixed by >>):

ipc/shm.c: In function 'do_shmat':

>> ipc/shm.c:1203:2: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
     if (down_write_killable(&current->mm->mmap_sem)) {
     ^

cc1: some warnings being treated as errors

vim +/down_write_killable +1203 ipc/shm.c

1197 sfd->vm_ops = NULL;
1198
1199 err = security_mmap_file(file, prot, flags);
1200 if (err)
1201 goto out_fput;
1202

> 1203		if (down_write_killable(&current->mm->mmap_sem)) {

1204 err = -EINTR;
1205 goto out_fput;
1206 }

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

Acked-by on v1 1/1
#42 lore raw

Re: [PATCH] ipc, shm: make shmem attach/detach wait for mmap_sem killable

In reply to Michal Hocko
Quoted 11 lines · Michal Hocko

From: Michal Hocko <[email protected]>

shmat and shmdt rely on mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Quoted 23 lines
---
  ipc/shm.c | 9 +++++++--
  1 file changed, 7 insertions(+), 2 deletions(-)
ipc/shm.c +5 -1
index 331fc1b0b3c7..13282510bc0d 100644
@@ -1200,7 +1200,11 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
  	if (err)
  		goto out_fput;
 
-	down_write(&current->mm->mmap_sem);
+	if (down_write_killable(&current->mm->mmap_sem)) {
+		err = -EINTR;
+		goto out_fput;
+	}
+
  	if (addr && !(shmflg & SHM_REMAP)) {
  		err = -EINVAL;
  		if (addr + size < addr)

ipc/shm.c SYSCALL_DEFINE1(shmdt, char __user *, shmaddr) · line 1282

Quoted 9 lines
ipc/shm.c +2 -1
@@ -1271,7 +1275,8 @@ SYSCALL_DEFINE1(shmdt, char __user *, shmaddr)
  	if (addr & ~PAGE_MASK)
  		return retval;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 
  	/*
  	 * This function tries to be smart and unmap shm segments that

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#43 lore raw

PATCH 10/18 vdso: make arch_setup_additional_pages wait for mmap_sem for write killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

most architectures are relying on mmap_sem for write in their arch_setup_additional_pages. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

---
 arch/arm/kernel/process.c          | 3 ++-
 arch/arm64/kernel/vdso.c           | 6 ++++--
 arch/hexagon/kernel/vdso.c         | 3 ++-
 arch/mips/kernel/vdso.c            | 3 ++-
 arch/powerpc/kernel/vdso.c         | 3 ++-
 arch/s390/kernel/vdso.c            | 3 ++-
 arch/sh/kernel/vsyscall/vsyscall.c | 4 +++-
 arch/x86/entry/vdso/vma.c          | 3 ++-
 arch/x86/um/vdso/vma.c             | 3 ++-
 9 files changed, 21 insertions(+), 10 deletions(-)
arch/arm/kernel/process.c +2 -1
index 4adfb46e3ee9..94cccae090fa 100644
@@ -420,7 +420,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	npages = 1; /* for sigpage */
 	npages += vdso_total_pages;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 	hint = sigpage_addr(mm, npages);
 	addr = get_unmapped_area(NULL, hint, npages << PAGE_SHIFT, 0, 0);
 	if (IS_ERR_VALUE(addr)) {
arch/arm64/kernel/vdso.c +4 -2
index 97bc68f4c689..d7423dfb4a4a 100644
@@ -95,7 +95,8 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)
 	};
 	void *ret;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 	current->mm->context.vdso = (void *)addr;
 
 	/* Map vectors page at the high address. */
@@ -163,7 +164,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 	/* Be sure to map the data page */
 	vdso_mapping_len = vdso_text_len + PAGE_SIZE;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 	vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0);
 	if (IS_ERR_VALUE(vdso_base)) {
 		ret = ERR_PTR(vdso_base);
arch/hexagon/kernel/vdso.c +2 -1
index 0bf5a87e4d0a..3ea968415539 100644
@@ -65,7 +65,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	unsigned long vdso_base;
 	struct mm_struct *mm = current->mm;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 
 	/* Try to get it loaded right near ld.so/glibc. */
 	vdso_base = STACK_TOP;
arch/mips/kernel/vdso.c +2 -1
index 975e99759bab..54e1663ce639 100644
@@ -104,7 +104,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	struct resource gic_res;
 	int ret;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 
 	/*
 	 * Determine total area size. This includes the VDSO data itself, the
arch/powerpc/kernel/vdso.c +2 -1
index def1b8b5e6c1..6767605ea8da 100644
@@ -195,7 +195,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	 * and end up putting it elsewhere.
 	 * Add enough to the size so that the result can be aligned.
 	 */
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 	vdso_base = get_unmapped_area(NULL, vdso_base,
 				      (vdso_pages << PAGE_SHIFT) +
 				      ((VDSO_ALIGNMENT - 1) & PAGE_MASK),
arch/s390/kernel/vdso.c +2 -1
index 94495cac8be3..5904abf6b1ae 100644
@@ -216,7 +216,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	 * it at vdso_base which is the "natural" base for it, but we might
 	 * fail and end up putting it elsewhere.
 	 */
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 	vdso_base = get_unmapped_area(NULL, 0, vdso_pages << PAGE_SHIFT, 0, 0);
 	if (IS_ERR_VALUE(vdso_base)) {
 		rc = vdso_base;
arch/sh/kernel/vsyscall/vsyscall.c +3 -1
index ea2aa1393b87..cc0cc5b4ff18 100644
@@ -64,7 +64,9 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	unsigned long addr;
 	int ret;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+
 	addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
 	if (IS_ERR_VALUE(addr)) {
 		ret = addr;
arch/x86/entry/vdso/vma.c +2 -1
index 10f704584922..69d861f67c47 100644
@@ -174,7 +174,8 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr)
 		addr = 0;
 	}
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 
 	addr = get_unmapped_area(NULL, addr,
 				 image->size - image->sym_vvar_start, 0, 0);
arch/x86/um/vdso/vma.c +2 -1
index 237c6831e095..6be22f991b59 100644
@@ -61,7 +61,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	if (!vdso_enabled)
 		return 0;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 
 	err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
 		VM_READ|VM_EXEC|
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#44 lore raw

Re: [PATCH 10/18] vdso: make arch_setup_additional_pages wait for mmap_sem for write killable

reproduce:

Hi Michal,

[auto build test ERROR on next-20160229]
[also build test ERROR on v4.5-rc6]
[cannot apply to drm/drm-next drm-intel/for-linux-next v4.5-rc6 v4.5-rc5 v4.5-rc4] [if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Michal-Hocko/change-mmap_sem-taken-for-write-killable/20160229-213258
config: i386-randconfig-x004-201609 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

arch/x86/entry/vdso/vma.c: In function 'map_vdso':

>> arch/x86/entry/vdso/vma.c:177:6: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
     if (down_write_killable(&mm->mmap_sem))
         ^

cc1: some warnings being treated as errors

vim +/down_write_killable +177 arch/x86/entry/vdso/vma.c

171 addr = vdso_addr(current->mm->start_stack,
172 image->size - image->sym_vvar_start);
173 } else {
174 addr = 0;
175 }
176

 > 177		if (down_write_killable(&mm->mmap_sem))

178 return -EINTR;
179
180 addr = get_unmapped_area(NULL, addr,

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#45 lore raw

Re: [PATCH 10/18] vdso: make arch_setup_additional_pages wait for mmap_sem for write killable

In reply to Michal Hocko
reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree…

Hi Michal,

[auto build test ERROR on next-20160229]
[also build test ERROR on v4.5-rc6]
[cannot apply to drm/drm-next drm-intel/for-linux-next v4.5-rc6 v4.5-rc5 v4.5-rc4] [if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Michal-Hocko/change-mmap_sem-taken-for-write-killable/20160229-213258
config: mips-allyesconfig (attached as .config)

reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=mips

All errors (new ones prefixed by >>):

arch/mips/kernel/vdso.c: In function 'arch_setup_additional_pages':

>> arch/mips/kernel/vdso.c:107:6: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
     if (down_write_killable(&mm->mmap_sem))
         ^

cc1: some warnings being treated as errors

vim +/down_write_killable +107 arch/mips/kernel/vdso.c

101 struct mm_struct *mm = current->mm;
102 unsigned long gic_size, vvar_size, size, base, data_addr, vdso_addr;
103 struct vm_area_struct *vma;
104 struct resource gic_res;
105 int ret;
106

 > 107		if (down_write_killable(&mm->mmap_sem))

108 return -EINTR;
109
110 /*

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#46 lore raw

Re: [PATCH 10/18] vdso: make arch_setup_additional_pages wait for mmap_sem for write killable

In reply to Michal Hocko
reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree…

Hi Michal,

[auto build test ERROR on next-20160229]
[also build test ERROR on v4.5-rc6]
[cannot apply to drm/drm-next drm-intel/for-linux-next v4.5-rc6 v4.5-rc5 v4.5-rc4] [if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Michal-Hocko/change-mmap_sem-taken-for-write-killable/20160229-213258
config: s390-allyesconfig (attached as .config)

reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=s390

All errors (new ones prefixed by >>):

arch/s390/kernel/vdso.c: In function 'arch_setup_additional_pages':

>> arch/s390/kernel/vdso.c:219:2: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]
     if (down_write_killable(&mm->mmap_sem))
     ^

cc1: some warnings being treated as errors

vim +/down_write_killable +219 arch/s390/kernel/vdso.c

213
214 /*
215 * pick a base address for the vDSO in process space. We try to put
216 * it at vdso_base which is the "natural" base for it, but we might
217 * fail and end up putting it elsewhere.
218 */

 > 219		if (down_write_killable(&mm->mmap_sem))

220 return -EINTR;
221 vdso_base = get_unmapped_area(NULL, 0, vdso_pages << PAGE_SHIFT, 0, 0);
222 if (IS_ERR_VALUE(vdso_base)) {

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

Acked-by on v1 10/18
#47 lore raw

Re: [PATCH 10/18] vdso: make arch_setup_additional_pages wait for mmap_sem for write killable

In reply to Michal Hocko
Quoted 8 lines · Michal Hocko

From: Michal Hocko <[email protected]>

most architectures are relying on mmap_sem for write in their arch_setup_additional_pages. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

Acked-by on v1 10/18
#48 lore raw

Re: [PATCH 10/18] vdso: make arch_setup_additional_pages wait for mmap_sem for write killable

In reply to Michal Hocko
Quoted 9 lines · Michal Hocko

From: Michal Hocko <[email protected]>

most architectures are relying on mmap_sem for write in their arch_setup_additional_pages. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Quoted 3 lines

I don't have much arch-specific insight, but looks OK.

#49 lore raw

PATCH 11/18 coredump: make coredump_wait wait for mma_sem for write killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

coredump_wait waits for mmap_sem for write currently which can prevent oom_reaper to reclaim the oom victims address space asynchronously because that requires mmap_sem for read. This might happen if the oom victim is multi threaded and some thread(s) is holding mmap_sem for read (e.g. page fault) and it is stuck in the page allocator while other thread(s) reached coredump_wait already.

This patch simply uses down_write_killable and bails out with EINTR if the lock got interrupted by the fatal signal. do_coredump will return right away and do_group_exit will take care to zap the whole thread group.

---
 fs/coredump.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
fs/coredump.c +3 -1
index 9ea87e9fdccf..6b8aa1629891 100644
@@ -410,7 +410,9 @@ static int coredump_wait(int exit_code, struct core_state *core_state)
 	core_state->dumper.task = tsk;
 	core_state->dumper.next = NULL;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+
 	if (!mm->core_state)
 		core_waiters = zap_threads(tsk, mm, core_state, exit_code);
 	up_write(&mm->mmap_sem);
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#50 lore raw

Re: [PATCH 11/18] coredump: make coredump_wait wait for mma_sem for write killable

fs/coredump.c static int coredump_wait(int exit_code, struct core_state *core_state) · line 415

Quoted 11 lines · Michal Hocko
fs/coredump.c +3 -1
@@ -410,7 +410,9 @@ static int coredump_wait(int exit_code, struct core_state *core_state)
 	core_state->dumper.task = tsk;
 	core_state->dumper.next = NULL;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+

ACK, thanks.

Oleg.

Acked-by on v1 11/18
#51 lore raw

Re: [PATCH 11/18] coredump: make coredump_wait wait for mma_sem for write killable

In reply to Michal Hocko
Quoted 10 lines · Michal Hocko

From: Michal Hocko <[email protected]>

coredump_wait waits for mmap_sem for write currently which can prevent oom_reaper to reclaim the oom victims address space asynchronously because that requires mmap_sem for read. This might happen if the oom victim is multi threaded and some thread(s) is holding mmap_sem for read (e.g. page fault) and it is stuck in the page allocator while other thread(s) reached coredump_wait already.

Quoted 7 lines

This patch simply uses down_write_killable and bails out with EINTR if the lock got interrupted by the fatal signal. do_coredump will return right away and do_group_exit will take care to zap the whole thread group.

Quoted 10 lines
---
  fs/coredump.c | 4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)
fs/coredump.c +0 -0
index 9ea87e9fdccf..6b8aa1629891 100644

fs/coredump.c static int coredump_wait(int exit_code, struct core_state *core_state) · line 418

Quoted 10 lines
fs/coredump.c +3 -1
@@ -410,7 +410,9 @@ static int coredump_wait(int exit_code, struct core_state *core_state)
  	core_state->dumper.task = tsk;
  	core_state->dumper.next = NULL;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+
  	if (!mm->core_state)
  		core_waiters = zap_threads(tsk, mm, core_state, exit_code);
  	up_write(&mm->mmap_sem);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#52 lore raw

Re: [PATCH 11/18] coredump: make coredump_wait wait for mma_sem for write killable

Quoted 16 lines · Vlastimil Babka
Quoted 15 lines · Michal Hocko

From: Michal Hocko <[email protected]>

coredump_wait waits for mmap_sem for write currently which can prevent oom_reaper to reclaim the oom victims address space asynchronously because that requires mmap_sem for read. This might happen if the oom victim is multi threaded and some thread(s) is holding mmap_sem for read (e.g. page fault) and it is stuck in the page allocator while other thread(s) reached coredump_wait already.

This patch simply uses down_write_killable and bails out with EINTR if the lock got interrupted by the fatal signal. do_coredump will return right away and do_group_exit will take care to zap the whole thread group.

Quoted 4 lines
Quoted 2 lines

Forgot to point out typo in Subject which makes it hard to grep for mmap_sem

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#53 lore raw

Re: [PATCH 11/18] coredump: make coredump_wait wait for mma_sem for write killable

Quoted 17 lines · Vlastimil Babka
Quoted 16 lines · Vlastimil Babka
Quoted 15 lines · Michal Hocko

From: Michal Hocko <[email protected]>

coredump_wait waits for mmap_sem for write currently which can prevent oom_reaper to reclaim the oom victims address space asynchronously because that requires mmap_sem for read. This might happen if the oom victim is multi threaded and some thread(s) is holding mmap_sem for read (e.g. page fault) and it is stuck in the page allocator while other thread(s) reached coredump_wait already.

This patch simply uses down_write_killable and bails out with EINTR if the lock got interrupted by the fatal signal. do_coredump will return right away and do_group_exit will take care to zap the whole thread group.

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

Forgot to point out typo in Subject which makes it hard to grep for mmap_sem

Fixed and thanks!

Signature · 2 lines
Michal Hocko
SUSE Labs
#54 lore raw

PATCH 12/18 aio: make aio_setup_ring killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

aio_setup_ring waits for mmap_sem in writable mode. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting. This will also expedite the return to the userspace and do_exit.

Cc Benjamin LaHaise <[email protected]>
Cc Alexander Viro <[email protected]>
---
 fs/aio.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
fs/aio.c +6 -1
index 56bcdf4105f4..1c2e7e2c1b2b 100644
@@ -520,7 +520,12 @@ static int aio_setup_ring(struct kioctx *ctx)
 	ctx->mmap_size = nr_pages * PAGE_SIZE;
 	pr_debug("attempting mmap of %lu bytes\n", ctx->mmap_size);
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem)) {
+		ctx->mmap_size = 0;
+		aio_free_ring(ctx);
+		return -EINTR;
+	}
+
 	ctx->mmap_base = do_mmap_pgoff(ctx->aio_ring_file, 0, ctx->mmap_size,
 				       PROT_READ | PROT_WRITE,
 				       MAP_SHARED, 0, &unused);
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Reviewed-by on v1 12/18
#55 lore raw

Re: [PATCH 12/18] aio: make aio_setup_ring killable

Quoted 24 lines · Michal Hocko

From: Michal Hocko <[email protected]>

aio_setup_ring waits for mmap_sem in writable mode. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting. This will also expedite the return to the userspace and do_exit.

Cc Benjamin LaHaise <[email protected]>
Cc Alexander Viro <[email protected]>
---
 fs/aio.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
fs/aio.c +0 -0
index 56bcdf4105f4..1c2e7e2c1b2b 100644
@@ -520,7 +520,12 @@ static int aio_setup_ring(struct kioctx *ctx)
 	ctx->mmap_size = nr_pages * PAGE_SIZE;
 	pr_debug("attempting mmap of %lu bytes\n", ctx->mmap_size);
 

fs/aio.c static int aio_setup_ring(struct kioctx *ctx) · line 531

Quoted 10 lines
fs/aio.c +6 -1
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem)) {
+		ctx->mmap_size = 0;
+		aio_free_ring(ctx);
+		return -EINTR;
+	}
+
 	ctx->mmap_base = do_mmap_pgoff(ctx->aio_ring_file, 0, ctx->mmap_size,
 				       PROT_READ | PROT_WRITE,
 				       MAP_SHARED, 0, &unused);
Acked-by on v1 12/18
#56 lore raw

Re: [PATCH 12/18] aio: make aio_setup_ring killable

In reply to Michal Hocko
Quoted 9 lines · Michal Hocko

From: Michal Hocko <[email protected]>

aio_setup_ring waits for mmap_sem in writable mode. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting. This will also expedite the return to the userspace and do_exit.

Quoted 3 lines
Cc Benjamin LaHaise <[email protected]>
Cc Alexander Viro <[email protected]>

The error handling could be changed to labels, but:

Quoted 23 lines
---
  fs/aio.c | 7 ++++++-
  1 file changed, 6 insertions(+), 1 deletion(-)
fs/aio.c +6 -1
index 56bcdf4105f4..1c2e7e2c1b2b 100644
@@ -520,7 +520,12 @@ static int aio_setup_ring(struct kioctx *ctx)
  	ctx->mmap_size = nr_pages * PAGE_SIZE;
  	pr_debug("attempting mmap of %lu bytes\n", ctx->mmap_size);
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem)) {
+		ctx->mmap_size = 0;
+		aio_free_ring(ctx);
+		return -EINTR;
+	}
+
  	ctx->mmap_base = do_mmap_pgoff(ctx->aio_ring_file, 0, ctx->mmap_size,
  				       PROT_READ | PROT_WRITE,
  				       MAP_SHARED, 0, &unused);
#57 lore raw

PATCH 13/18 exec: make exec path waiting for mmap_sem killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

setup_arg_pages requires mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting. All the callers are already handling error path and the fatal signal doesn't need any additional treatment.

The same applies to __bprm_mm_init.

Cc Alexander Viro <[email protected]>
---
 fs/exec.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
fs/exec.c +8 -2
index c4010b8207a1..29f2f22ae067 100644
@@ -267,7 +267,10 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
 	if (!vma)
 		return -ENOMEM;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem)) {
+		err = -EINTR;
+		goto err_free;
+	}
 	vma->vm_mm = mm;
 
 	/*
@@ -294,6 +297,7 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
 	return 0;
 err:
 	up_write(&mm->mmap_sem);
+err_free:
 	bprm->vma = NULL;
 	kmem_cache_free(vm_area_cachep, vma);
 	return err;
@@ -700,7 +704,9 @@ int setup_arg_pages(struct linux_binprm *bprm,
 		bprm->loader -= stack_shift;
 	bprm->exec -= stack_shift;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+
 	vm_flags = VM_STACK_FLAGS;
 
 	/*
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#58 lore raw

Re: [PATCH 13/18] exec: make exec path waiting for mmap_sem killable

fs/exec.c static int __bprm_mm_init(struct linux_binprm *bprm) · line 274

Quoted 11 lines · Michal Hocko
fs/exec.c +4 -1
@@ -267,7 +267,10 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
 	if (!vma)
 		return -ENOMEM;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem)) {
+		err = -EINTR;
+		goto err_free;
+	}
 	vma->vm_mm = mm;

I won't argue, but this looks unnecessary. Nobody else can see this new mm, down_write() can't block.

In fact I think we can just remove down_write/up_write here. Except perhaps there is lockdep_assert_held() somewhere in these paths.

Oleg.

#59 lore raw

Re: [PATCH 13/18] exec: make exec path waiting for mmap_sem killable

Quoted 16 lines · Oleg Nesterov

fs/exec.c static int __bprm_mm_init(struct linux_binprm *bprm) · line 274

Quoted 11 lines · Michal Hocko
fs/exec.c +4 -1
@@ -267,7 +267,10 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
 	if (!vma)
 		return -ENOMEM;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem)) {
+		err = -EINTR;
+		goto err_free;
+	}
 	vma->vm_mm = mm;

I won't argue, but this looks unnecessary. Nobody else can see this new mm, down_write() can't block.

Quoted 2 lines

In fact I think we can just remove down_write/up_write here. Except perhaps there is lockdep_assert_held() somewhere in these paths.

This is what I had initially but then I've noticed that mm_alloc() does mm_init(current)->init_new_context(current) so the outside can see this mm AFAICS. Now I guess this shouldn't matter in the real life but the code doesn't seem much harder to follow, the callers are already handling all error paths so I guess it would be better to simply move on this. Or am I misunderstanding the code or missing something?

Signature · 8 lines
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#60 lore raw

Re: [PATCH 13/18] exec: make exec path waiting for mmap_sem killable

Quoted 18 lines · Michal Hocko
Quoted 16 lines · Oleg Nesterov

fs/exec.c static int __bprm_mm_init(struct linux_binprm *bprm) · line 274

Quoted 11 lines · Michal Hocko
fs/exec.c +4 -1
@@ -267,7 +267,10 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
 	if (!vma)
 		return -ENOMEM;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem)) {
+		err = -EINTR;
+		goto err_free;
+	}
 	vma->vm_mm = mm;

I won't argue, but this looks unnecessary. Nobody else can see this new mm, down_write() can't block.

Quoted 5 lines
Quoted 2 lines

In fact I think we can just remove down_write/up_write here. Except perhaps there is lockdep_assert_held() somewhere in these paths.

This is what I had initially but then I've noticed that mm_alloc() does mm_init(current)->init_new_context(current)

yes, and init_new_context() is arch dependant...

Quoted 3 lines

code doesn't seem much harder to follow, the callers are already handling all error paths so I guess it would be better to simply move on this.

Yes, agreed, please forget.

Oleg.

Acked-by on v1 13/18
#61 lore raw

Re: [PATCH 13/18] exec: make exec path waiting for mmap_sem killable

In reply to Michal Hocko
Quoted 10 lines · Michal Hocko

From: Michal Hocko <[email protected]>

setup_arg_pages requires mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting. All the callers are already handling error path and the fatal signal doesn't need any additional treatment.

Quoted 4 lines

The same applies to __bprm_mm_init.

Cc Alexander Viro <[email protected]>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#62 lore raw

PATCH 14/18 prctl: make PR_SET_THP_DISABLE wait for mmap_sem killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

PR_SET_THP_DISABLE requires mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

---
 kernel/sys.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/sys.c +2 -1
index cf8ba545c7d3..89d5be418157 100644
@@ -2246,7 +2246,8 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
 	case PR_SET_THP_DISABLE:
 		if (arg3 || arg4 || arg5)
 			return -EINVAL;
-		down_write(&me->mm->mmap_sem);
+		if (down_write_killable(&me->mm->mmap_sem))
+			return -EINTR;
 		if (arg2)
 			me->mm->def_flags |= VM_NOHUGEPAGE;
 		else
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Acked-by on v1 14/18
#63 lore raw

Re: [PATCH 14/18] prctl: make PR_SET_THP_DISABLE wait for mmap_sem killable

Quoted 10 lines · Michal Hocko

From: Michal Hocko <[email protected]>

PR_SET_THP_DISABLE requires mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Quoted 19 lines
---
  kernel/sys.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)
kernel/sys.c +2 -1
index cf8ba545c7d3..89d5be418157 100644
@@ -2246,7 +2246,8 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
  	case PR_SET_THP_DISABLE:
  		if (arg3 || arg4 || arg5)
  			return -EINVAL;
-		down_write(&me->mm->mmap_sem);
+		if (down_write_killable(&me->mm->mmap_sem))
+			return -EINTR;
  		if (arg2)
  			me->mm->def_flags |= VM_NOHUGEPAGE;
  		else
#64 lore raw

PATCH 15/18 uprobes: wait for mmap_sem for write killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

xol_add_vma needs mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

---
 kernel/events/uprobes.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/events/uprobes.c +3 -1
index 8eef5f55d3f0..a79315d0f711 100644
@@ -1130,7 +1130,9 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 	struct vm_area_struct *vma;
 	int ret;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+
 	if (mm->uprobes_state.xol_area) {
 		ret = -EALREADY;
 		goto fail;
Signature · 1 line
2.7.0
maintainer
#65 lore raw

Re: [PATCH 15/18] uprobes: wait for mmap_sem for write killable

kernel/events/uprobes.c static int xol_add_vma(struct mm_struct *mm, struct xol_area *area) · line 1135

Quoted 11 lines · Michal Hocko
kernel/events/uprobes.c +3 -1
@@ -1130,7 +1130,9 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 	struct vm_area_struct *vma;
 	int ret;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+

Yes, but then dup_xol_work() should probably check fatal_signal_pending() to suppress uprobe_warn(), the warning looks like a kernel problem.

Oleg.

#66 lore raw

Re: [PATCH 15/18] uprobes: wait for mmap_sem for write killable

Quoted 8 lines · Oleg Nesterov
Quoted 7 lines · Michal Hocko
kernel/events/uprobes.c +0 -0
@@ -1130,7 +1130,9 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 	struct vm_area_struct *vma;
 	int ret;
 
Quoted 7 lines

kernel/events/uprobes.c static int xol_add_vma(struct mm_struct *mm, struct xol_area *area) · line 1135

Quoted 4 lines
kernel/events/uprobes.c +3 -1
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+

Yes, but then dup_xol_work() should probably check fatal_signal_pending() to suppress uprobe_warn(), the warning looks like a kernel problem.

Ahh, I see. I didn't understand what is the purpose of the warning. Does the following work for you?
---

kernel/events/uprobes.c +2 -1
index a79315d0f711..fb4a6bcc88ce 100644
@@ -1470,7 +1470,8 @@ static void dup_xol_work(struct callback_head *work)
 	if (current->flags & PF_EXITING)
 		return;
 
-	if (!__create_xol_area(current->utask->dup_xol_addr))
+	if (!__create_xol_area(current->utask->dup_xol_addr) &&
+			!fatal_signal_pending(current)
 		uprobe_warn(current, "dup xol area");
 }
 
Signature · 8 lines
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#67 lore raw

Re: [PATCH 15/18] uprobes: wait for mmap_sem for write killable

Quoted 9 lines · Michal Hocko

Ahh, I see. I didn't understand what is the purpose of the warning. Does the following work for you?
---

kernel/events/uprobes.c +0 -0
index a79315d0f711..fb4a6bcc88ce 100644

kernel/events/uprobes.c static void dup_xol_work(struct callback_head *work) · line 1476

Quoted 8 lines
kernel/events/uprobes.c +2 -1
@@ -1470,7 +1470,8 @@ static void dup_xol_work(struct callback_head *work)
 	if (current->flags & PF_EXITING)
 		return;
 
-	if (!__create_xol_area(current->utask->dup_xol_addr))
+	if (!__create_xol_area(current->utask->dup_xol_addr) &&
+			!fatal_signal_pending(current)
 		uprobe_warn(current, "dup xol area");
 }

Yes, I think this is fine.

Probably deserves a cleanup, but we can do it later.

Oleg.

#68 lore raw

PATCH 1/1 uprobes: wait for mmap_sem for write killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

xol_add_vma needs mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Do not warn in dup_xol_work if __create_xol_area failed due to fatal signal pending because this is usually considered a kernel issue.

---
 kernel/events/uprobes.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
kernel/events/uprobes.c +5 -2
index 8eef5f55d3f0..fb4a6bcc88ce 100644
@@ -1130,7 +1130,9 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 	struct vm_area_struct *vma;
 	int ret;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+
 	if (mm->uprobes_state.xol_area) {
 		ret = -EALREADY;
 		goto fail;
@@ -1468,7 +1470,8 @@ static void dup_xol_work(struct callback_head *work)
 	if (current->flags & PF_EXITING)
 		return;
 
-	if (!__create_xol_area(current->utask->dup_xol_addr))
+	if (!__create_xol_area(current->utask->dup_xol_addr) &&
+			!fatal_signal_pending(current)
 		uprobe_warn(current, "dup xol area");
 }
 
Signature · 1 line
2.7.0
#69 lore raw

Re: [PATCH] uprobes: wait for mmap_sem for write killable

reproduce:

Hi Michal,

[auto build test ERROR on tip/perf/core]
[also build test ERROR on v4.5-rc6 next-20160229]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Michal-Hocko/uprobes-wait-for-mmap_sem-for-write-killable/20160301-014513
config: i386-randconfig-x003-201609 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

In file included from include/linux/linkage.h:4:0,
from include/linux/kernel.h:6,
from kernel/events/uprobes.c:25:
kernel/events/uprobes.c: In function 'xol_add_vma':
kernel/events/uprobes.c:1133:6: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]

     if (down_write_killable(&mm->mmap_sem))
         ^
   include/linux/compiler.h:147:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^
   kernel/events/uprobes.c:1133:2: note: in expansion of macro 'if'
     if (down_write_killable(&mm->mmap_sem))
     ^
   kernel/events/uprobes.c: In function 'dup_xol_work':
>> kernel/events/uprobes.c:2029:0: error: unterminated argument list invoking macro "if"
    __initcall(init_uprobes);
    ^
>> kernel/events/uprobes.c:1473:2: error: expected '(' at end of input
     if (!__create_xol_area(current->utask->dup_xol_addr) &&
     ^
>> kernel/events/uprobes.c:1473:2: error: expected declaration or statement at end of input

kernel/events/uprobes.c: At top level:
kernel/events/uprobes.c:961:12: warning: 'unapply_uprobe' defined but not used [-Wunused-function]
static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm)
^
kernel/events/uprobes.c:1293:22: warning: 'xol_get_insn_slot' defined but not used [-Wunused-function]
static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
^
kernel/events/uprobes.c:1427:28: warning: 'get_utask' defined but not used [-Wunused-function]
static struct uprobe_task *get_utask(void)
^
kernel/events/uprobes.c:1434:12: warning: 'dup_utask' defined but not used [-Wunused-function]
static int dup_utask(struct task_struct *t, struct uprobe_task *o_utask)
^
kernel/events/uprobes.c:1462:13: warning: 'uprobe_warn' defined but not used [-Wunused-function]
static void uprobe_warn(struct task_struct *t, const char *msg)
^
kernel/events/uprobes.c:1468:13: warning: 'dup_xol_work' defined but not used [-Wunused-function]
static void dup_xol_work(struct callback_head *work)
^
cc1: some warnings being treated as errors

vim +/if +2029 kernel/events/uprobes.c

0326f5a9 kernel/events/uprobes.c Srikar Dronamraju 2012-03-13  2023  
32cdba1e kernel/events/uprobes.c Oleg Nesterov     2012-11-14  2024  	if (percpu_init_rwsem(&dup_mmap_sem))
32cdba1e kernel/events/uprobes.c Oleg Nesterov     2012-11-14  2025  		return -ENOMEM;
32cdba1e kernel/events/uprobes.c Oleg Nesterov     2012-11-14  2026  
0326f5a9 kernel/events/uprobes.c Srikar Dronamraju 2012-03-13  2027  	return register_die_notifier(&uprobe_exception_nb);
2b144498 kernel/uprobes.c        Srikar Dronamraju 2012-02-09  2028  }

736e89d9 kernel/events/uprobes.c Oleg Nesterov 2013-10-31 @2029 __initcall(init_uprobes);

:::::: The code at line 2029 was first introduced by commit
:::::: 736e89d9f782a7dd9a38ecda13b2db916fa72f33 uprobes: Kill module_init() and module_exit()

:::::: TO: Oleg Nesterov <[email protected]>
:::::: CC: Oleg Nesterov <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#70 lore raw

Re: [PATCH] uprobes: wait for mmap_sem for write killable

In reply to Michal Hocko
reproduce:

Hi Michal,

[auto build test ERROR on tip/perf/core]
[also build test ERROR on v4.5-rc6 next-20160229]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Michal-Hocko/uprobes-wait-for-mmap_sem-for-write-killable/20160301-014513
config: x86_64-randconfig-x019-201609 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

kernel/events/uprobes.c: In function 'xol_add_vma':
kernel/events/uprobes.c:1133:6: error: implicit declaration of function 'down_write_killable' [-Werror=implicit-function-declaration]

     if (down_write_killable(&mm->mmap_sem))
         ^
   kernel/events/uprobes.c: In function 'dup_xol_work':
>> kernel/events/uprobes.c:1475:3: error: expected ')' before 'uprobe_warn'
      uprobe_warn(current, "dup xol area");
      ^
>> kernel/events/uprobes.c:1476:1: error: expected expression before '}' token
    }
    ^

cc1: some warnings being treated as errors

vim +1475 kernel/events/uprobes.c

aa59c53f Oleg Nesterov 2013-10-13  1469  {
aa59c53f Oleg Nesterov 2013-10-13  1470  	if (current->flags & PF_EXITING)
aa59c53f Oleg Nesterov 2013-10-13  1471  		return;
aa59c53f Oleg Nesterov 2013-10-13  1472  
6b584cb3 Michal Hocko  2016-02-29  1473  	if (!__create_xol_area(current->utask->dup_xol_addr) &&
6b584cb3 Michal Hocko  2016-02-29  1474  			!fatal_signal_pending(current)
aa59c53f Oleg Nesterov 2013-10-13 @1475  		uprobe_warn(current, "dup xol area");
aa59c53f Oleg Nesterov 2013-10-13 @1476  }
aa59c53f Oleg Nesterov 2013-10-13  1477  
e78aebfd Anton Arapov  2013-04-03  1478  /*
b68e0749 Oleg Nesterov 2013-10-13  1479   * Called in context of a new clone/fork from copy_process.

:::::: The code at line 1475 was first introduced by commit
:::::: aa59c53fd4599c91ccf9629af0c2777b89929076 uprobes: Change uprobe_copy_process() to dup xol_area

:::::: TO: Oleg Nesterov <[email protected]> :::::: CC: Oleg Nesterov <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

maintainer
#71 lore raw

Re: [PATCH] uprobes: wait for mmap_sem for write killable

In reply to Michal Hocko
Quoted 15 lines · Michal Hocko
kernel/events/uprobes.c +3 -1
@@ -1130,7 +1130,9 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 	struct vm_area_struct *vma;
 	int ret;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+
 	if (mm->uprobes_state.xol_area) {
 		ret = -EALREADY;
 		goto fail;

kernel/events/uprobes.c static void dup_xol_work(struct callback_head *work) · line 1476

Quoted 8 lines
kernel/events/uprobes.c +2 -1
@@ -1468,7 +1470,8 @@ static void dup_xol_work(struct callback_head *work)
 	if (current->flags & PF_EXITING)
 		return;
 
-	if (!__create_xol_area(current->utask->dup_xol_addr))
+	if (!__create_xol_area(current->utask->dup_xol_addr) &&
+			!fatal_signal_pending(current)
 		uprobe_warn(current, "dup xol area");
 }

Looks good, thanks.

Oleg.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#72 lore raw

Re: [PATCH] uprobes: wait for mmap_sem for write killable

Quoted 19 lines · Oleg Nesterov
Quoted 18 lines · Michal Hocko
kernel/events/uprobes.c +3 -1
@@ -1130,7 +1130,9 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 	struct vm_area_struct *vma;
 	int ret;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+
 	if (mm->uprobes_state.xol_area) {
 		ret = -EALREADY;
 		goto fail;
@@ -1468,7 +1470,8 @@ static void dup_xol_work(struct callback_head *work)
 	if (current->flags & PF_EXITING)
 		return;
 
Quoted 7 lines

kernel/events/uprobes.c static void dup_xol_work(struct callback_head *work) · line 1476

Quoted 5 lines
kernel/events/uprobes.c +2 -1
-	if (!__create_xol_area(current->utask->dup_xol_addr))
+	if (!__create_xol_area(current->utask->dup_xol_addr) &&
+			!fatal_signal_pending(current)
 		uprobe_warn(current, "dup xol area");
 }

Looks good, thanks.

Can I consider this your Acked-by?

Signature · 8 lines
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#73 lore raw

Re: [PATCH] uprobes: wait for mmap_sem for write killable

Quoted 29 lines · Michal Hocko
Quoted 19 lines · Oleg Nesterov
Quoted 18 lines · Michal Hocko
kernel/events/uprobes.c +3 -1
@@ -1130,7 +1130,9 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 	struct vm_area_struct *vma;
 	int ret;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+
 	if (mm->uprobes_state.xol_area) {
 		ret = -EALREADY;
 		goto fail;
@@ -1468,7 +1470,8 @@ static void dup_xol_work(struct callback_head *work)
 	if (current->flags & PF_EXITING)
 		return;
 
Quoted 7 lines

kernel/events/uprobes.c static void dup_xol_work(struct callback_head *work) · line 1476

Quoted 5 lines
kernel/events/uprobes.c +2 -1
-	if (!__create_xol_area(current->utask->dup_xol_addr))
+	if (!__create_xol_area(current->utask->dup_xol_addr) &&
+			!fatal_signal_pending(current)
 		uprobe_warn(current, "dup xol area");
 }

Looks good, thanks.

Quoted 1 line

Can I consider this your Acked-by?

Yes, feel free to add. I forgot to add it.

Oleg.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

Acked-by on v1 1/1
#74 lore raw

Re: [PATCH] uprobes: wait for mmap_sem for write killable

In reply to Michal Hocko
Quoted 33 lines · Michal Hocko

From: Michal Hocko <[email protected]>

xol_add_vma needs mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Do not warn in dup_xol_work if __create_xol_area failed due to fatal signal pending because this is usually considered a kernel issue.

---
  kernel/events/uprobes.c | 7 +++++--
  1 file changed, 5 insertions(+), 2 deletions(-)
kernel/events/uprobes.c +3 -1
index 8eef5f55d3f0..fb4a6bcc88ce 100644
@@ -1130,7 +1130,9 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
  	struct vm_area_struct *vma;
  	int ret;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+
  	if (mm->uprobes_state.xol_area) {
  		ret = -EALREADY;
  		goto fail;

kernel/events/uprobes.c static void dup_xol_work(struct callback_head *work) · line 1474

Quoted 6 lines
kernel/events/uprobes.c +2 -1
@@ -1468,7 +1470,8 @@ static void dup_xol_work(struct callback_head *work)
  	if (current->flags & PF_EXITING)
  		return;
 
-	if (!__create_xol_area(current->utask->dup_xol_addr))
+	if (!__create_xol_area(current->utask->dup_xol_addr) &&
+			!fatal_signal_pending(current)
                                                      ^ missing ")"

Other than that,

kernel/events/uprobes.c static void dup_xol_work(struct callback_head *work) · line 1477

Quoted 4 lines
kernel/events/uprobes.c +0 -0
  		uprobe_warn(current, "dup xol area");
  }
 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#75 lore raw

Re: [PATCH] uprobes: wait for mmap_sem for write killable

Quoted 1 line · Vlastimil Babka

On 02/29/2016 06:42 PM, Michal Hocko wrote:

[...]

Quoted 9 lines

kernel/events/uprobes.c static void dup_xol_work(struct callback_head *work) · line 1474

Quoted 7 lines
kernel/events/uprobes.c +2 -1
@@ -1468,7 +1470,8 @@ static void dup_xol_work(struct callback_head *work)
 	if (current->flags & PF_EXITING)
 		return;
 
-	if (!__create_xol_area(current->utask->dup_xol_addr))
+	if (!__create_xol_area(current->utask->dup_xol_addr) &&
+			!fatal_signal_pending(current)
                                                      ^ missing ")"

Fixed

Quoted 2 lines

Other than that,

Thanks!

Quoted 5 lines
Quoted 5 lines
kernel/events/uprobes.c +0 -0
 		uprobe_warn(current, "dup xol area");
 }
 
Signature · 8 lines
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#76 lore raw

PATCH 16/18 drm/i915: make i915_gem_mmap_ioctl wait for mmap_sem killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

i915_gem_mmap_ioctl relies on mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Cc Daniel Vetter <[email protected]>
Cc David Airlie <[email protected]>
---
 drivers/gpu/drm/i915/i915_gem.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_gem.c +4 -1
index f68f34606f2f..a50136cbd332 100644
@@ -1754,7 +1754,10 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
 		struct mm_struct *mm = current->mm;
 		struct vm_area_struct *vma;
 
-		down_write(&mm->mmap_sem);
+		if (down_write_killable(&mm->mmap_sem)) {
+			drm_gem_object_unreference_unlocked(obj);
+			return -EINTR;
+		}
 		vma = find_vma(mm, addr);
 		if (vma)
 			vma->vm_page_prot =
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Acked-by on v1 16/18
#77 lore raw

Re: [PATCH 16/18] drm/i915: make i915_gem_mmap_ioctl wait for mmap_sem killable

Quoted 11 lines · Michal Hocko

From: Michal Hocko <[email protected]>

i915_gem_mmap_ioctl relies on mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Cc Daniel Vetter <[email protected]>
Cc David Airlie <[email protected]>
Quoted 21 lines
---
  drivers/gpu/drm/i915/i915_gem.c | 5 ++++-
  1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_gem.c +4 -1
index f68f34606f2f..a50136cbd332 100644
@@ -1754,7 +1754,10 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
  		struct mm_struct *mm = current->mm;
  		struct vm_area_struct *vma;
 
-		down_write(&mm->mmap_sem);
+		if (down_write_killable(&mm->mmap_sem)) {
+			drm_gem_object_unreference_unlocked(obj);
+			return -EINTR;
+		}
  		vma = find_vma(mm, addr);
  		if (vma)
  			vma->vm_page_prot =
#78 lore raw

PATCH 17/18 drm/radeon: make radeon_mn_get wait for mmap_sem killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

radeon_mn_get which is called during ioct path relies on mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Cc Alex Deucher <[email protected]>
Cc "Christian König" <[email protected]>
Cc David Airlie <[email protected]>
---
 drivers/gpu/drm/radeon/radeon_mn.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/radeon/radeon_mn.c +3 -1
index eef006c48584..896f2cf51e4e 100644
@@ -186,7 +186,9 @@ static struct radeon_mn *radeon_mn_get(struct radeon_device *rdev)
 	struct radeon_mn *rmn;
 	int r;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return ERR_PTR(-EINTR);
+
 	mutex_lock(&rdev->mn_lock);
 
 	hash_for_each_possible(rdev->mn_hash, rmn, node, (unsigned long)mm)
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#79 lore raw

Re: [PATCH 17/18] drm/radeon: make radeon_mn_get wait for mmap_sem killable

[Dropping CCing the individual people, but adding the dri-devel mailing list as well instead].

Am 29.02.2016 um 14:26 schrieb Michal Hocko:

Quoted 8 lines

From: Michal Hocko <[email protected]>

radeon_mn_get which is called during ioct path relies on mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Quoted 4 lines
Cc Alex Deucher <[email protected]>
Cc "Christian König" <[email protected]>
Cc David Airlie <[email protected]>

This one and patch #18 in this series are Reviewed-by: Christian König <[email protected]>.

Nice to see some improvements on this side,
Christian.

Quoted 9 lines
---
  drivers/gpu/drm/radeon/radeon_mn.c | 4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/radeon/radeon_mn.c +0 -0
index eef006c48584..896f2cf51e4e 100644

drivers/gpu/drm/radeon/radeon_mn.c static struct radeon_mn *radeon_mn_get(struct radeon_device *rdev) · line 194

Quoted 10 lines
drivers/gpu/drm/radeon/radeon_mn.c +3 -1
@@ -186,7 +186,9 @@ static struct radeon_mn *radeon_mn_get(struct radeon_device *rdev)
  	struct radeon_mn *rmn;
  	int r;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return ERR_PTR(-EINTR);
+
  	mutex_lock(&rdev->mn_lock);
 
  	hash_for_each_possible(rdev->mn_hash, rmn, node, (unsigned long)mm)

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Acked-by on v1 17/18
#80 lore raw

Re: [PATCH 17/18] drm/radeon: make radeon_mn_get wait for mmap_sem killable

In reply to Michal Hocko
Quoted 8 lines · Michal Hocko

From: Michal Hocko <[email protected]>

radeon_mn_get which is called during ioct path relies on mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Quoted 4 lines
Cc Alex Deucher <[email protected]>
Cc "Christian KA?nig" <[email protected]>
Cc David Airlie <[email protected]>
Quoted 10 lines
---
  drivers/gpu/drm/radeon/radeon_mn.c | 4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/radeon/radeon_mn.c +0 -0
index eef006c48584..896f2cf51e4e 100644

drivers/gpu/drm/radeon/radeon_mn.c static struct radeon_mn *radeon_mn_get(struct radeon_device *rdev) · line 194

Quoted 10 lines
drivers/gpu/drm/radeon/radeon_mn.c +3 -1
@@ -186,7 +186,9 @@ static struct radeon_mn *radeon_mn_get(struct radeon_device *rdev)
  	struct radeon_mn *rmn;
  	int r;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return ERR_PTR(-EINTR);
+
  	mutex_lock(&rdev->mn_lock);
 
  	hash_for_each_possible(rdev->mn_hash, rmn, node, (unsigned long)mm)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#81 lore raw

PATCH 18/18 drm/amdgpu: make amdgpu_mn_get wait for mmap_sem killable

In reply to Michal Hocko

From: Michal Hocko <[email protected]>

amdgpu_mn_get which is called during ioct path relies on mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Cc David Airlie <[email protected]>
Cc Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +4 -1
index d7ec9bd6755f..6f44f1c23be3 100644
@@ -181,7 +181,10 @@ static struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev)
 	int r;
 
 	mutex_lock(&adev->mn_lock);
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem)) {
+		mutex_unlock(&adev->mn_lock);
+		return -EINTR;
+	}
 
 	hash_for_each_possible(adev->mn_hash, rmn, node, (unsigned long)mm)
 		if (rmn->mm == mm)
Signature · 7 lines
2.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Acked-by on v1 18/18
#82 lore raw

Re: [PATCH 18/18] drm/amdgpu: make amdgpu_mn_get wait for mmap_sem killable

Quoted 11 lines · Michal Hocko

From: Michal Hocko <[email protected]>

amdgpu_mn_get which is called during ioct path relies on mmap_sem for write. If the waiting task gets killed by the oom killer it would block oom_reaper from asynchronous address space reclaim and reduce the chances of timely OOM resolving. Wait for the lock in the killable mode and return with EINTR if the task got killed while waiting.

Cc David Airlie <[email protected]>
Cc Alex Deucher <[email protected]>
Quoted 11 lines
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c | 5 ++++-
  1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +0 -0
index d7ec9bd6755f..6f44f1c23be3 100644
@@ -181,7 +181,10 @@ static struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev)
  	int r;

drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c static struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev) · line 190

Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +4 -1
 
  	mutex_lock(&adev->mn_lock);
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem)) {
+		mutex_unlock(&adev->mn_lock);
+		return -EINTR;
+	}
 
  	hash_for_each_possible(adev->mn_hash, rmn, node, (unsigned long)mm)
  		if (rmn->mm == mm)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#83 lore raw
In reply to Michal Hocko

On Mon 29-02-16 14:26:39, Michal Hocko wrote:
[...]

Quoted 4 lines

As this work is touching more areas which are not directly connected I have tried to keep the CC list as small as possible and people who I believed would be familiar are CCed only to the specific patches (all should have received the cover though).

Damnt it. I thought that git-send-email will not use the same CC list for all patches and use it only for the cover if the particular patches have their CC list. I am sorry for the excessive spamming!

Signature · 8 lines
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#84 lore raw
In reply to Michal Hocko
Quoted 8 lines · Michal Hocko

Hi,
this is a follow up work for oom_reaper [1]. As the async OOM killing depends on oom_sem for read we would really appreciate if a holder for write stood in the way. This patchset is changing many of down_write calls to be killable to help those cases when the writer is blocked and waiting for readers to release the lock and so help __oom_reap_task to process the oom victim.

Quoted 6 lines

Most of the patches are really trivial because the lock is help from a shallow syscall paths where we can return EINTR trivially. Others seem to be easy as well as the callers are already handling fatal errors and bail and return to userspace which should be sufficient to handle the failure gracefully. I am not familiar with all those code paths so a deeper review is really appreciated.

What about effect on userspace? IIUC, we would have now EINTR returned from bunch of syscall, which haven't had this errno on the table before. Should we care?

Quoted 30 lines

As this work is touching more areas which are not directly connected I have tried to keep the CC list as small as possible and people who I believed would be familiar are CCed only to the specific patches (all should have received the cover though).

This patchset is based on linux-next and it depends on down_write_killable for rw_semaphores posted recently [2].

I haven't covered all the mmap_write(mm->mmap_sem) instances here

$ git grep "down_write(.*\<mmap_sem\>)" next/master | wc -l
102
$ git grep "down_write(.*\<mmap_sem\>)" | wc -l
66

I have tried to cover those which should be relatively easy to review in this series because this alone should be a nice improvement. Other places can be changed on top.

Any feedback is highly appreciated.

---
[1] http://lkml.kernel.org/r/[email protected]
[2] http://lkml.kernel.org/r/[email protected]

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

Signature · 7 lines
 Kirill A. Shutemov

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#85 lore raw

On Mon 29-02-16 17:04:16, Kirill A. Shutemov wrote:
[...]

Quoted 10 lines
Quoted 6 lines

Most of the patches are really trivial because the lock is help from a shallow syscall paths where we can return EINTR trivially. Others seem to be easy as well as the callers are already handling fatal errors and bail and return to userspace which should be sufficient to handle the failure gracefully. I am not familiar with all those code paths so a deeper review is really appreciated.

What about effect on userspace? IIUC, we would have now EINTR returned from bunch of syscall, which haven't had this errno on the table before. Should we care?

Those function will return EINTR only when the current was _killed_ when we do not return to the userspace. So there shouldn't be any visible effect.

Signature · 2 lines
Michal Hocko
SUSE Labs
#86 lore raw
Quoted 9 lines · Michal Hocko

On Mon 29-02-16 17:04:16, Kirill A. Shutemov wrote:
[...]

Quoted 7 lines
Quoted 6 lines

Most of the patches are really trivial because the lock is help from a shallow syscall paths where we can return EINTR trivially. Others seem to be easy as well as the callers are already handling fatal errors and bail and return to userspace which should be sufficient to handle the failure gracefully. I am not familiar with all those code paths so a deeper review is really appreciated.

Quoted 7 lines
Quoted 3 lines

What about effect on userspace? IIUC, we would have now EINTR returned from bunch of syscall, which haven't had this errno on the table before. Should we care?

Those function will return EINTR only when the current was _killed_ when we do not return to the userspace. So there shouldn't be any visible effect.

Ah. I confused killable with interruptible.

Signature · 1 line
 Kirill A. Shutemov