All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] futex: Fix ZERO_PAGE cause infinite loop
@ 2009-12-24  9:29 KOSAKI Motohiro
  2009-12-24  9:39 ` Peter Zijlstra
  0 siblings, 1 reply; 15+ messages in thread
From: KOSAKI Motohiro @ 2009-12-24  9:29 UTC (permalink / raw)
  To: Hugh Dickins, KAMEZAWA Hiroyuki, Nick Piggin, Peter Zijlstra,
	Ingo Molnar, LKML
  Cc: kosaki.motohiro


This patch need both futex and zero-page developer's ack.
==========================================================

commit a13ea5b7 (mm: reinstate ZERO_PAGE) made the unfortunate regression.
following test program never finish and waste 100% cpu time.

At the making commit 38d47c1b7 (rely on get_user_pages() for shared
futexes). There isn't zero page in linux kernel. then, futex developers
thought gup retry is safe. but we reinstated zero page later...

This patch fixes it.

futex-zero.c
---------------------------------------------------------------------
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/mman.h>
 #include <syscall.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
 #include <linux/futex.h>
 #include <pthread.h>

int main(int argc, char **argv)
{
        long page_size;
        int ret;
        void *buf;

        page_size = sysconf(_SC_PAGESIZE);

        buf = mmap(NULL, page_size, PROT_READ|PROT_WRITE,
			MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
        if (buf == (void *)-1) {
                perror("mmap error.\n");
                exit(1);
        }

        fprintf(stderr, "futex wait\n");
        ret = syscall( SYS_futex, buf, FUTEX_WAIT, 1, NULL, NULL, NULL);
        if (ret != 0 && errno != EWOULDBLOCK) {
                perror("futex error.\n");
                exit(1);
        }
        fprintf(stderr, "futex_wait: ret = %d, errno = %d\n", ret, errno);

        return 0;
}
---------------------------------------------------------------------

Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Hugh Dickins <hugh.dickins@tiscali.co.uk>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Nick Piggin <npiggin@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Ingo Molnar <mingo@elte.hu>
---
 include/linux/mm.h |   16 ++++++++++++++++
 kernel/futex.c     |    3 +++
 mm/memory.c        |   14 --------------
 3 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 2265f28..dd755ea 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -751,6 +751,22 @@ struct zap_details {
 	unsigned long truncate_count;		/* Compare vm_truncate_count */
 };
 
+#ifndef is_zero_pfn
+extern unsigned long zero_pfn;
+static inline int is_zero_pfn(unsigned long pfn)
+{
+	return pfn == zero_pfn;
+}
+#endif
+
+#ifndef my_zero_pfn
+extern unsigned long zero_pfn;
+static inline unsigned long my_zero_pfn(unsigned long addr)
+{
+	return zero_pfn;
+}
+#endif
+
 struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
 		pte_t pte);
 
diff --git a/kernel/futex.c b/kernel/futex.c
index 8e3c3ff..79b89cc 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -254,6 +254,8 @@ again:
 
 	page = compound_head(page);
 	lock_page(page);
+	if (is_zero_pfn(page_to_pfn(page)))
+		goto anon_key;
 	if (!page->mapping) {
 		unlock_page(page);
 		put_page(page);
@@ -268,6 +270,7 @@ again:
 	 * the object not the particular process.
 	 */
 	if (PageAnon(page)) {
+ anon_key:
 		key->both.offset |= FUT_OFF_MMSHARED; /* ref taken on mm */
 		key->private.mm = mm;
 		key->private.address = address;
diff --git a/mm/memory.c b/mm/memory.c
index 09e4b1b..3743fb5 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -457,20 +457,6 @@ static inline int is_cow_mapping(unsigned int flags)
 	return (flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
 }
 
-#ifndef is_zero_pfn
-static inline int is_zero_pfn(unsigned long pfn)
-{
-	return pfn == zero_pfn;
-}
-#endif
-
-#ifndef my_zero_pfn
-static inline unsigned long my_zero_pfn(unsigned long addr)
-{
-	return zero_pfn;
-}
-#endif
-
 /*
  * vm_normal_page -- This function gets the "struct page" associated with a pte.
  *
-- 
1.6.5.2




^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2010-01-13 10:33 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-12-24  9:29 [PATCH] futex: Fix ZERO_PAGE cause infinite loop KOSAKI Motohiro
2009-12-24  9:39 ` Peter Zijlstra
2009-12-24 17:15   ` Ulrich Drepper
2009-12-25  1:51   ` KOSAKI Motohiro
2009-12-30 16:03     ` Hugh Dickins
2010-01-05  7:32       ` [PATCH v2] futex: remove rw parameter from get_futex_key() KOSAKI Motohiro
2010-01-05 11:21         ` Hugh Dickins
2010-01-05 20:41           ` Darren Hart
2010-01-06  2:27             ` KOSAKI Motohiro
2010-01-06 23:14               ` Darren Hart
2010-01-06 23:29         ` Darren Hart
2010-01-13 10:30         ` [tip:core/urgent] futexes: Remove " tip-bot for KOSAKI Motohiro
2010-01-07  6:32       ` [PATCH] mips,mm: Reinstate move_pte optimization KOSAKI Motohiro
2010-01-11 10:15         ` Ralf Baechle
2010-01-05 18:04     ` [PATCH] futex: Fix ZERO_PAGE cause infinite loop Darren Hart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.