Messages in this thread Patch in this message | | | Date | Fri, 12 Aug 2016 18:16:12 +0200 | From | Oleg Nesterov <> | Subject | Re: [PATCH] sched: Avoid that __wait_on_bit_lock() hangs |
| |
On 08/11, Oleg Nesterov wrote: > > I'll send another debugging patch tomorrow, I was a bit busy today. The next > step is obvious, we need to know the caller.
Please drop two patches I sent before anf try the new one below.
Which kernel version do you use?
Oleg. ---
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index e5a3244..533da3ab 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -711,6 +711,15 @@ static inline int page_has_private(struct page *page) return !!(page->flags & PAGE_FLAGS_PRIVATE); } +void unlock_page_x(struct page *page); +static inline void __ClearPageLocked_x(struct page *page) +{ + if (PageLocked(compound_head(page))) + unlock_page_x(page); +} + +#define __ClearPageLocked(page) __ClearPageLocked_x(page) + #undef PF_ANY #undef PF_HEAD #undef PF_NO_TAIL diff --git a/mm/filemap.c b/mm/filemap.c index 20f3b1f..fb320fb 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -837,6 +837,43 @@ void unlock_page(struct page *page) } EXPORT_SYMBOL(unlock_page); +void unlock_page_x(struct page *__page) +{ + struct page *page = compound_head(__page); + wait_queue_head_t *wq = page_waitqueue(page); + struct wait_bit_key key = __WAIT_BIT_KEY_INITIALIZER(&page->flags, PG_locked); + wait_queue_t *curr, *next; + unsigned long flags; + bool w = false; + + #define W() do { \ + if (!w) { w = true; pr_crit("XXXXXXXXXXXX\n"); dump_stack(); } \ + } while (0) + + clear_bit_unlock(PG_locked, &page->flags); + smp_mb__after_atomic(); + + if (!waitqueue_active(wq)) + return; + + spin_lock_irqsave(&wq->lock, flags); + list_for_each_entry_safe(curr, next, &wq->task_list, task_list) { + if (curr->func == wake_bit_function) { + struct wait_bit_queue *wb = container_of(curr, struct wait_bit_queue, wait); + if (wb->key.flags == key.flags && wb->key.bit_nr == PG_locked) { + W(); + pr_crit("XXX flags = %x, waiter:\n", curr->flags); + sched_show_task(curr->private); + } + } else { + W(); + pr_crit("XXX flags = %x, func = %pF\n", curr->flags, curr->func); + } + curr->func(curr, TASK_NORMAL, 0, &key); + } + spin_unlock_irqrestore(&wq->lock, flags); +} + /** * end_page_writeback - end writeback against a page * @page: the page
| |