diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c index 836c218..cd8499c 100644 --- a/arch/x86_64/mm/pageattr.c +++ b/arch/x86_64/mm/pageattr.c @@ -112,7 +112,14 @@ static inline void save_page(struct page *fpage, int data) return; SetPageFlush(fpage); } + printk("ADD (%s): E=%p, H=%p, H->N=%p, N->P=%p, N->N=%p; PREV0=%p, " + "NEXT0=%p, ", + current->comm, &fpage->lru, + &deferred_pages, deferred_pages.next, + deferred_pages.next->prev, deferred_pages.next->next, + fpage->lru.prev, fpage->lru.next); list_add(&fpage->lru, &deferred_pages); + printk("PREV1=%p, NEXT1=%p\n", fpage->lru.prev, fpage->lru.next); } /* @@ -274,6 +281,7 @@ void global_flush_tlb(void) down_read(&init_mm.mmap_sem); arg.full_flush = full_flush; full_flush = 0; + printk("FLUSH\n"); list_replace_init(&deferred_pages, &arg.l); up_read(&init_mm.mmap_sem); diff --git a/include/linux/list.h b/include/linux/list.h index f29fc9c..1add963 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -265,6 +265,8 @@ static inline void list_del_init(struct list_head *entry) static inline void list_move(struct list_head *list, struct list_head *head) { __list_del(list->prev, list->next); + list->next = LIST_POISON1; + list->prev = LIST_POISON2; list_add(list, head); } @@ -277,6 +279,8 @@ static inline void list_move_tail(struct list_head *list, struct list_head *head) { __list_del(list->prev, list->next); + list->next = LIST_POISON1; + list->prev = LIST_POISON2; list_add_tail(list, head); } diff --git a/lib/list_debug.c b/lib/list_debug.c index 4350ba9..57573d5 100644 --- a/lib/list_debug.c +++ b/lib/list_debug.c @@ -15,15 +15,34 @@ * This is only for internal list manipulation where we know * the prev/next entries already! */ - +#include void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { + static unsigned int a, b; + unsigned long off; + + if (unlikely(!a && current && current->comm[0] == 'X')) + a++; + + if (unlikely(a && !b && (void *)new >= (void *)mem_map && + (void *)new < (void *)(mem_map + 1048576) && + (new->prev != LIST_POISON2 || new->next != LIST_POISON1) && + (new->prev != NULL || new->next != NULL) && + (new->prev != new || new->next != new))) { + off = ((void *)new - (void *)mem_map) % sizeof(struct page); + if (off == offsetof(struct page, lru)) { + printk(KERN_DEBUG "POISONS (%p): " + "%p, %p\n", new, new->prev, new->next); + dump_stack(); + } + } if (unlikely(next->prev != prev)) { printk(KERN_ERR "list_add corruption. next->prev should be " "prev (%p), but was %p. (next=%p).\n", prev, next->prev, next); + b++; BUG(); } if (unlikely(prev->next != next)) { diff --git a/mm/slub.c b/mm/slub.c index ac4f157..8aec6aa 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2680,6 +2680,7 @@ int kmem_cache_shrink(struct kmem_cache *s) slab_unlock(page); discard_slab(s, page); } else { + printk("MOVE: %p\n", &page->lru); list_move(&page->lru, slabs_by_inuse + page->inuse); }