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

Reply via email to