]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Aug 2013 18:57:53 +0000 (11:57 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Aug 2013 18:57:53 +0000 (11:57 -0700)
added patches:
futex-take-hugepages-into-account-when-generating-futex_key.patch

queue-3.4/futex-take-hugepages-into-account-when-generating-futex_key.patch [new file with mode: 0644]
queue-3.4/series

diff --git a/queue-3.4/futex-take-hugepages-into-account-when-generating-futex_key.patch b/queue-3.4/futex-take-hugepages-into-account-when-generating-futex_key.patch
new file mode 100644 (file)
index 0000000..f8f7f43
--- /dev/null
@@ -0,0 +1,151 @@
+From 13d60f4b6ab5b702dc8d2ee20999f98a93728aec Mon Sep 17 00:00:00 2001
+From: Zhang Yi <wetpzy@gmail.com>
+Date: Tue, 25 Jun 2013 21:19:31 +0800
+Subject: futex: Take hugepages into account when generating futex_key
+
+From: Zhang Yi <wetpzy@gmail.com>
+
+commit 13d60f4b6ab5b702dc8d2ee20999f98a93728aec upstream.
+
+The futex_keys of process shared futexes are generated from the page
+offset, the mapping host and the mapping index of the futex user space
+address. This should result in an unique identifier for each futex.
+
+Though this is not true when futexes are located in different subpages
+of an hugepage. The reason is, that the mapping index for all those
+futexes evaluates to the index of the base page of the hugetlbfs
+mapping. So a futex at offset 0 of the hugepage mapping and another
+one at offset PAGE_SIZE of the same hugepage mapping have identical
+futex_keys. This happens because the futex code blindly uses
+page->index.
+
+Steps to reproduce the bug:
+
+1. Map a file from hugetlbfs. Initialize pthread_mutex1 at offset 0
+   and pthread_mutex2 at offset PAGE_SIZE of the hugetlbfs
+   mapping.
+
+   The mutexes must be initialized as PTHREAD_PROCESS_SHARED because
+   PTHREAD_PROCESS_PRIVATE mutexes are not affected by this issue as
+   their keys solely depend on the user space address.
+
+2. Lock mutex1 and mutex2
+
+3. Create thread1 and in the thread function lock mutex1, which
+   results in thread1 blocking on the locked mutex1.
+
+4. Create thread2 and in the thread function lock mutex2, which
+   results in thread2 blocking on the locked mutex2.
+
+5. Unlock mutex2. Despite the fact that mutex2 got unlocked, thread2
+   still blocks on mutex2 because the futex_key points to mutex1.
+
+To solve this issue we need to take the normal page index of the page
+which contains the futex into account, if the futex is in an hugetlbfs
+mapping. In other words, we calculate the normal page mapping index of
+the subpage in the hugetlbfs mapping.
+
+Mappings which are not based on hugetlbfs are not affected and still
+use page->index.
+
+Thanks to Mel Gorman who provided a patch for adding proper evaluation
+functions to the hugetlbfs code to avoid exposing hugetlbfs specific
+details to the futex code.
+
+[ tglx: Massaged changelog ]
+
+Signed-off-by: Zhang Yi <zhang.yi20@zte.com.cn>
+Reviewed-by: Jiang Biao <jiang.biao2@zte.com.cn>
+Tested-by: Ma Chenggong <ma.chenggong@zte.com.cn>
+Reviewed-by: 'Mel Gorman' <mgorman@suse.de>
+Acked-by: 'Darren Hart' <dvhart@linux.intel.com>
+Cc: 'Peter Zijlstra' <peterz@infradead.org>
+Link: http://lkml.kernel.org/r/000101ce71a6%24a83c5880%24f8b50980%24@com
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Mike Galbraith <mgalbraith@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ include/linux/hugetlb.h |   16 ++++++++++++++++
+ kernel/futex.c          |    3 ++-
+ mm/hugetlb.c            |   17 +++++++++++++++++
+ 3 files changed, 35 insertions(+), 1 deletion(-)
+
+--- a/include/linux/hugetlb.h
++++ b/include/linux/hugetlb.h
+@@ -293,6 +293,17 @@ static inline unsigned hstate_index_to_s
+       return hstates[index].order + PAGE_SHIFT;
+ }
++pgoff_t __basepage_index(struct page *page);
++
++/* Return page->index in PAGE_SIZE units */
++static inline pgoff_t basepage_index(struct page *page)
++{
++      if (!PageCompound(page))
++              return page->index;
++
++      return __basepage_index(page);
++}
++
+ #else /* CONFIG_HUGETLB_PAGE */
+ struct hstate {};
+ #define alloc_huge_page_node(h, nid) NULL
+@@ -311,6 +322,11 @@ static inline unsigned int pages_per_hug
+       return 1;
+ }
+ #define hstate_index_to_shift(index) 0
++
++static inline pgoff_t basepage_index(struct page *page)
++{
++      return page->index;
++}
+ #endif
+ #endif /* _LINUX_HUGETLB_H */
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -60,6 +60,7 @@
+ #include <linux/pid.h>
+ #include <linux/nsproxy.h>
+ #include <linux/ptrace.h>
++#include <linux/hugetlb.h>
+ #include <asm/futex.h>
+@@ -363,7 +364,7 @@ again:
+       } else {
+               key->both.offset |= FUT_OFF_INODE; /* inode-based key */
+               key->shared.inode = page_head->mapping->host;
+-              key->shared.pgoff = page_head->index;
++              key->shared.pgoff = basepage_index(page);
+       }
+       get_futex_key_refs(key);
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -679,6 +679,23 @@ int PageHuge(struct page *page)
+ }
+ EXPORT_SYMBOL_GPL(PageHuge);
++pgoff_t __basepage_index(struct page *page)
++{
++      struct page *page_head = compound_head(page);
++      pgoff_t index = page_index(page_head);
++      unsigned long compound_idx;
++
++      if (!PageHuge(page_head))
++              return page_index(page);
++
++      if (compound_order(page_head) >= MAX_ORDER)
++              compound_idx = page_to_pfn(page) - page_to_pfn(page_head);
++      else
++              compound_idx = page - page_head;
++
++      return (index << compound_order(page_head)) + compound_idx;
++}
++
+ static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid)
+ {
+       struct page *page;
index 1bd61861f09958cb0c5df2f12c89d1595bfb99d3..79a3b0b0117d0ca15b4772f25ecc8d8a58e27327 100644 (file)
@@ -11,3 +11,4 @@ vm-add-no-mmu-vm_iomap_memory-stub.patch
 cris-posix_types.h-include-asm-generic-posix_types.h.patch
 cris-remove-old-legacy-traditional-flag-from-arch-v10-lib-makefile.patch
 cris-add-_sdata-to-vmlinux.lds.s.patch
+futex-take-hugepages-into-account-when-generating-futex_key.patch