From 4eedb77a9cd8f2e68b31c8b9a20524a50727c16f Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Fri, 17 May 2013 10:51:33 +0200 Subject: locking: Fix copy/paste errors of "ARCH_INLINE_*_UNLOCK_BH" The Kconfig symbols ARCH_INLINE_READ_UNLOCK_IRQ, ARCH_INLINE_SPIN_UNLOCK_IRQ, and ARCH_INLINE_WRITE_UNLOCK_IRQ were added in v2.6.33, but have never actually been used. Ingo Molnar spotted that this is caused by three identical copy/paste erros. Eg, the Kconfig entry for INLINE_READ_UNLOCK_IRQ has an (optional) dependency on: ARCH_INLINE_READ_UNLOCK_BH were it apparently should depend on: ARCH_INLINE_READ_UNLOCK_IRQ instead. Likewise for the Kconfig entries for INLINE_SPIN_UNLOCK_IRQ and INLINE_WRITE_UNLOCK_IRQ. Fix these three errors. This never really caused any real problems as these symbols are set (or unset) in a group - but it's worth fixing it nevertheless. Reported-by: Ingo Molnar Signed-off-by: Paul Bolle Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1368780693.1350.228.camel@x61.thuisdomein Signed-off-by: Ingo Molnar --- kernel/Kconfig.locks | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/Kconfig.locks b/kernel/Kconfig.locks index 44511d100eaa..d2b32ac27a39 100644 --- a/kernel/Kconfig.locks +++ b/kernel/Kconfig.locks @@ -138,7 +138,7 @@ config INLINE_SPIN_UNLOCK_BH config INLINE_SPIN_UNLOCK_IRQ def_bool y - depends on !PREEMPT || ARCH_INLINE_SPIN_UNLOCK_BH + depends on !PREEMPT || ARCH_INLINE_SPIN_UNLOCK_IRQ config INLINE_SPIN_UNLOCK_IRQRESTORE def_bool y @@ -175,7 +175,7 @@ config INLINE_READ_UNLOCK_BH config INLINE_READ_UNLOCK_IRQ def_bool y - depends on !PREEMPT || ARCH_INLINE_READ_UNLOCK_BH + depends on !PREEMPT || ARCH_INLINE_READ_UNLOCK_IRQ config INLINE_READ_UNLOCK_IRQRESTORE def_bool y @@ -212,7 +212,7 @@ config INLINE_WRITE_UNLOCK_BH config INLINE_WRITE_UNLOCK_IRQ def_bool y - depends on !PREEMPT || ARCH_INLINE_WRITE_UNLOCK_BH + depends on !PREEMPT || ARCH_INLINE_WRITE_UNLOCK_IRQ config INLINE_WRITE_UNLOCK_IRQRESTORE def_bool y -- cgit v1.2.3-58-ga151 From 0c1061733aa0303e6536c0bc7f86d68f5eb55446 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Wed, 15 May 2013 11:04:10 +0200 Subject: rtmutex: Document rt_mutex_adjust_prio_chain() Parameters and usage of rt_mutex_adjust_prio_chain() are already documented in Documentation/rt-mutex-design.txt. However, since this function is called from several paths with different semantics (related to the arguments), it is handy to have a quick reference directly in the code. Signed-off-by: Juri Lelli Cc: Clark Williams Cc: Steven Rostedt Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1368608650-7935-1-git-send-email-juri.lelli@gmail.com Signed-off-by: Ingo Molnar --- kernel/rtmutex.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c index 1e09308bf2a1..0dd6aec1cb6a 100644 --- a/kernel/rtmutex.c +++ b/kernel/rtmutex.c @@ -145,6 +145,19 @@ int max_lock_depth = 1024; /* * Adjust the priority chain. Also used for deadlock detection. * Decreases task's usage by one - may thus free the task. + * + * @task: the task owning the mutex (owner) for which a chain walk is probably + * needed + * @deadlock_detect: do we have to carry out deadlock detection? + * @orig_lock: the mutex (can be NULL if we are walking the chain to recheck + * things for a task that has just got its priority adjusted, and + * is waiting on a mutex) + * @orig_waiter: rt_mutex_waiter struct for the task that has just donated + * its priority to the mutex owner (can be NULL in the case + * depicted above or if the top waiter is gone away and we are + * actually deboosting the owner) + * @top_task: the current top waiter + * * Returns 0 or -EDEADLK. */ static int rt_mutex_adjust_prio_chain(struct task_struct *task, -- cgit v1.2.3-58-ga151 From 13d60f4b6ab5b702dc8d2ee20999f98a93728aec Mon Sep 17 00:00:00 2001 From: Zhang Yi Date: Tue, 25 Jun 2013 21:19:31 +0800 Subject: futex: Take hugepages into account when generating futex_key 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 Reviewed-by: Jiang Biao Tested-by: Ma Chenggong Reviewed-by: 'Mel Gorman' Acked-by: 'Darren Hart' Cc: 'Peter Zijlstra' Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/000101ce71a6%24a83c5880%24f8b50980%24@com Signed-off-by: Thomas Gleixner --- include/linux/hugetlb.h | 16 ++++++++++++++++ kernel/futex.c | 3 ++- mm/hugetlb.c | 17 +++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 6b4890fa57e7..feaf0c7fb7d8 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -358,6 +358,17 @@ static inline int hstate_index(struct hstate *h) return h - hstates; } +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 @@ -378,6 +389,11 @@ static inline unsigned int pages_per_huge_page(struct hstate *h) } #define hstate_index_to_shift(index) 0 #define hstate_index(h) 0 + +static inline pgoff_t basepage_index(struct page *page) +{ + return page->index; +} #endif /* CONFIG_HUGETLB_PAGE */ #endif /* _LINUX_HUGETLB_H */ diff --git a/kernel/futex.c b/kernel/futex.c index b26dcfc02c94..49dacfb45745 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -61,6 +61,7 @@ #include #include #include +#include #include @@ -365,7 +366,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); diff --git a/mm/hugetlb.c b/mm/hugetlb.c index f8feeeca6686..aea87ced4268 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -690,6 +690,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; -- cgit v1.2.3-58-ga151 From 88c8004fd3a5fdd2378069de86b90b21110d33a4 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 1 May 2013 18:35:05 -0700 Subject: futex: Use freezable blocking call Avoid waking up every thread sleeping in a futex_wait call during suspend and resume by calling a freezable blocking call. Previous patches modified the freezer to avoid sending wakeups to threads that are blocked in freezable blocking calls. This call was selected to be converted to a freezable call because it doesn't hold any locks or release any resources when interrupted that might be needed by another freezing task or a kernel driver during suspend, and is a common site where idle userspace tasks are blocked. Signed-off-by: Colin Cross Cc: Rafael J. Wysocki Cc: arve@android.com Cc: Tejun Heo Cc: Oleg Nesterov Cc: Darren Hart Cc: Randy Dunlap Cc: Al Viro Link: http://lkml.kernel.org/r/1367458508-9133-8-git-send-email-ccross@android.com Signed-off-by: Thomas Gleixner --- kernel/futex.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/futex.c b/kernel/futex.c index 49dacfb45745..c3a1a55a5214 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -62,6 +62,7 @@ #include #include #include +#include #include @@ -1808,7 +1809,7 @@ static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q, * is no timeout, or if it has yet to expire. */ if (!timeout || timeout->task) - schedule(); + freezable_schedule(); } __set_current_state(TASK_RUNNING); } -- cgit v1.2.3-58-ga151