Re: [PATCH] sched: Avoid that __wait_on_bit_lock() hangs
From: Oleg Nesterov
Date: Wed Aug 10 2016 - 15:01:41 EST
On 08/09, Bart Van Assche wrote:
>
> On 08/09/2016 10:15 AM, Oleg Nesterov wrote:
> >
> > --- x/kernel/sched/wait.c
> > +++ x/kernel/sched/wait.c
> > @@ -283,7 +283,7 @@ void abort_exclusive_wait(wait_queue_hea
> > if (!list_empty(&wait->task_list))
> > list_del_init(&wait->task_list);
> > else if (waitqueue_active(q))
> > - __wake_up_locked_key(q, mode, key);
> > + __wake_up_locked_key(q, TASK_NORMAL, key);
> > spin_unlock_irqrestore(&q->lock, flags);
> > }
> > EXPORT_SYMBOL(abort_exclusive_wait);
>
> Hello Oleg,
>
> That patch looks interesting to me.
And I'll redo/resend it, __wake_up_locked_key(mode) is simply wrong I think.
But it can't affect lock_page() because TASK_KILLABLE includes TASK_UNINTERRUPTIBLE
and we do not have lock_page_interruptible().
> Unfortunately even with that patch
> applied I still see lockups.
Thanks. I hoped this change can fix some another exclusive wait...
OK. Could you try another debugging patch below?
Oleg.
---
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index e5a3244..9d5f892 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(struct page *page);
+static inline void __ClearPageLocked_x(struct page *page)
+{
+ if (PageLocked(compound_head(page)))
+ unlock_page(page);
+}
+
+#define __ClearPageLocked(page) __ClearPageLocked_x(page)
+
#undef PF_ANY
#undef PF_HEAD
#undef PF_NO_TAIL