
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
---

 arch/i386/mm/ioremap.c                    |    0 
 memhotplug-dave/arch/i386/kernel/traps.c  |    2 -
 memhotplug-dave/arch/i386/mm/init.c       |   15 ++++++----
 memhotplug-dave/drivers/base/memory.c     |   41 ++++++++++++++++++++----------
 memhotplug-dave/fs/sysfs/file.c           |    4 ++
 memhotplug-dave/include/linux/list.h      |    4 ++
 memhotplug-dave/include/linux/mm.h        |    1 
 memhotplug-dave/include/linux/mm_inline.h |   16 ++++++++++-
 memhotplug-dave/include/linux/nonlinear.h |    2 +
 memhotplug-dave/kernel/panic.c            |    2 +
 memhotplug-dave/mm/memory_hotplug.c       |   11 +++++---
 memhotplug-dave/mm/nonlinear.c            |   36 ++++++++++++++++++++++++--
 memhotplug-dave/mm/page_alloc.c           |   31 ++++++++++++++++------
 memhotplug-dave/mm/swap.c                 |    1 
 memhotplug-dave/mm/vmscan.c               |    5 +++
 15 files changed, 133 insertions(+), 38 deletions(-)

diff -puN mm/memory_hotplug.c~P-i386-debug mm/memory_hotplug.c
--- memhotplug/mm/memory_hotplug.c~P-i386-debug	2004-10-08 00:15:12.000000000 -0700
+++ memhotplug-dave/mm/memory_hotplug.c	2004-10-08 00:15:12.000000000 -0700
@@ -24,7 +24,8 @@
 
 #include <asm/tlbflush.h>
 
-static struct page *__kmalloc_section_memmap(unsigned long nr_pages)
+/* not static for the nonlinear code that records a pointer to this function */
+struct page *__kmalloc_section_memmap(unsigned long nr_pages)
 {
 	struct page *page, *ret;
 	unsigned long memmap_size = sizeof(struct page) * nr_pages;
@@ -35,6 +36,7 @@ static struct page *__kmalloc_section_me
 		return NULL;
 	}
 	SetPageReserved(page);
+	page->mapping = __kmalloc_section_memmap;
 
 	printk(KERN_DEBUG "%s() set page: %p set mapping to %p\n", __func__,
 		page, page->mapping);
@@ -149,6 +151,9 @@ int online_pages(unsigned long pfn, unsi
 
 	page_zone(pfn_to_page(pfn))->present_pages += nr_pages;
 
+	printk(KERN_DEBUG "%s: onlining if 0x%lx pages done.\n",
+		__func__, nr_pages);
+
 	/* need error checking */
 	return 0;
 }
@@ -172,8 +177,8 @@ int __remove_pages(struct zone *zone, un
 	}
 
 	for (i = 0; i < nr_pages; i += SECTION_SIZE) {
-		unsigned int section = pfn_to_section(start_pfn + i);
-		unregister_memory_section(section);
+		unsigned short phys_section = pfn_to_section(start_pfn + i);
+		unregister_memory_section(phys_section);
 	}
 
 	/*
diff -puN mm/page_alloc.c~P-i386-debug mm/page_alloc.c
--- memhotplug/mm/page_alloc.c~P-i386-debug	2004-10-08 00:15:12.000000000 -0700
+++ memhotplug-dave/mm/page_alloc.c	2004-10-08 00:15:12.000000000 -0700
@@ -39,6 +39,8 @@
 
 #include <asm/tlbflush.h>
 
+#define inline
+
 nodemask_t node_online_map = NODE_MASK_NONE;
 nodemask_t node_possible_map = NODE_MASK_ALL;
 struct pglist_data *pgdat_list;
@@ -82,7 +84,7 @@ static int bad_range(struct zone *zone, 
 	return 0;
 }
 
-static void bad_page(const char *function, struct page *page)
+void bad_page(const char *function, struct page *page)
 {
 	printk(KERN_EMERG "Bad page state at %s (in process '%s', page %p)\n",
 		function, current->comm, page);
@@ -414,6 +416,7 @@ void __free_pages_ok(struct page *page, 
 		return;
 	}
 	list_add(&page->lru, &list);
+	page->lru_list_type = 6;
 	kernel_map_pages(page, 1<<order, 0);
 	free_pages_bulk(page_zone(page), 1, &list, order);
 }
@@ -541,6 +544,7 @@ static int rmqueue_bulk(struct zone *zon
 			break;
 		allocated++;
 		list_add_tail(&page->lru, list);
+		page->lru_list_type = 8;
 	}
 	spin_unlock_irqrestore(&zone->lock, flags);
 	return allocated;
@@ -614,12 +618,11 @@ static inline int first_uncaptured_page(
 	int count = 0;
 	unsigned long end_pfn = start_pfn + nr_pages;
 
-	printk(KERN_DEBUG "%s(%ld, %d) begin\n",
-			__func__, start_pfn, nr_pages);
+	//printk(KERN_DEBUG "%s(%ld, %d) begin end_pfn: %ld\n",
+	//		__func__, start_pfn, nr_pages, end_pfn);
 
 	for (i = start_pfn; i < end_pfn; i++) {
 		struct page *page = pfn_to_page(i);
-		struct scan_control;
 
 		if (!page_under_capture(page))
 			continue;
@@ -628,8 +631,8 @@ static inline int first_uncaptured_page(
 		if (res == -1)
 			res = i;
 	}
-	printk(KERN_DEBUG "%s(%ld, %d) end\n",
-			__func__, start_pfn, nr_pages);
+	//printk(KERN_DEBUG "%s(%ld, %d) end ret: %d\n",
+	//		__func__, start_pfn, nr_pages, res);
 	return res;
 }
 
@@ -693,6 +696,7 @@ int capture_page_range(unsigned long sta
 
 	page = pfn_to_page(start_pfn);
 	remove_page_freearea(page, order);
+	force_captured_to_inactive_list(page);
 	/*
 	 * storing the last result (fp) keeps up from having
 	 * to walk the entire range each time
@@ -765,6 +769,7 @@ static void fastcall free_hot_cold_page(
 	if (pcp->count >= pcp->high)
 		pcp->count -= free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
 	list_add(&page->lru, &pcp->list);
+	page->lru_list_type = 8;
 	pcp->count++;
 	local_irq_restore(flags);
 	put_cpu();
@@ -798,12 +803,15 @@ int perthread_pages_reserve(int nrpages,
 		struct page *page;
 
 		page = alloc_page(gfp);
-		if (page != NULL)
+		if (page != NULL) {
 			list_add(&page->lru, &accumulator);
+			page->lru_list_type = 9;
+		}
 		else {
 			for (; i > 0; --i) {
 				page = list_entry(accumulator.next, struct page, lru);
 				list_del(&page->lru);
+				page->lru_list_type = 10;
 				page_cache_release(page);
 			}
 			return -ENOMEM;
@@ -835,6 +843,7 @@ void perthread_pages_release(int nrpages
 		BUG_ON(list_empty(per_thread));
 		page = list_entry(per_thread->next, struct page, lru);
 		list_del(&page->lru);
+		page->lru_list_type = 11;
 		page_cache_release(page);
 	}
 }
@@ -862,6 +871,7 @@ perthread_pages_alloc(void)
 
 		page = list_entry(perthread_pages->next, struct page, lru);
 		list_del(&page->lru);
+		page->lru_list_type = 12;
 		current->private_pages_count--;
 		/*
 		 * per-thread page is already initialized, just return it.
@@ -895,6 +905,7 @@ buffered_rmqueue(struct zone *zone, int 
 		if (pcp->count) {
 			page = list_entry(pcp->list.next, struct page, lru);
 			list_del(&page->lru);
+			page->lru_list_type = 1;
 			pcp->count--;
 		}
 		local_irq_restore(flags);
@@ -1081,7 +1092,7 @@ rebalance:
 	}
 
 nopage:
-	if (!(gfp_mask & __GFP_NOWARN) && printk_ratelimit()) {
+	if (0 && !(gfp_mask & __GFP_NOWARN) && printk_ratelimit()) {
 		printk(KERN_WARNING "%s: page allocation failure."
 			" order:%d, mode:0x%x\n",
 			p->comm, order, gfp_mask);
@@ -1753,9 +1764,11 @@ static void __init calculate_zone_totalp
 void __devinit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
 		unsigned long start_pfn)
 {
-	struct page *start = pfn_to_page(start_pfn);
+	struct page *start;
 	struct page *page;
 
+	start = pfn_to_page(start_pfn);
+
 	for (page = start; page < (start + size); page++) {
 		set_page_zone(page, NODEZONE(nid, zone));
 		set_page_count(page, 0);
diff -puN include/linux/mm.h~P-i386-debug include/linux/mm.h
--- memhotplug/include/linux/mm.h~P-i386-debug	2004-10-08 00:15:12.000000000 -0700
+++ memhotplug-dave/include/linux/mm.h	2004-10-08 00:15:12.000000000 -0700
@@ -228,6 +228,7 @@ struct page {
 	struct list_head lru;		/* Pageout list, eg. active_list
 					 * protected by zone->lru_lock !
 					 */
+	int lru_list_type;
 	/*
 	 * On machines where all RAM is mapped into kernel address space,
 	 * we can simply calculate the virtual address. On machines with
diff -puN include/asm-i386/page.h~P-i386-debug include/asm-i386/page.h
diff -puN arch/i386/Kconfig~P-i386-debug arch/i386/Kconfig
diff -puN mm/nonlinear.c~P-i386-debug mm/nonlinear.c
--- memhotplug/mm/nonlinear.c~P-i386-debug	2004-10-08 00:15:12.000000000 -0700
+++ memhotplug-dave/mm/nonlinear.c	2004-10-08 00:15:12.000000000 -0700
@@ -46,6 +46,8 @@ setup_memsections(void)
 {
 	int index;
 
+	printk(KERN_DEBUG "%s()\n", __func__);
+
 	for (index = 0; index < NR_SECTIONS; index++) {
 		mem_section[index].phys_section = INVALID_SECTION;
 		mem_section[index].mem_map = NULL;
@@ -64,17 +66,28 @@ alloc_memsections(unsigned long start_pf
 	unsigned int sect_count;
 	unsigned short sect_index;
 
+	printk(KERN_DEBUG "%s(%08lx, %08lx, %08lx)\n", __func__, start_pfn, start_phys_pfn, pfn_count);
+
 	sect_count = pfn_to_section_roundup(pfn_count);
 	sect_index = index = pfn_to_section(start_pfn);
 	limit = index + sect_count;
 	physid = pfn_to_section(start_phys_pfn);
-	for (; index < limit; index++, physid++)
+	for (; index < limit; index++, physid++) {
+		BUG_ON(mem_section[index].phys_section != INVALID_SECTION);
 		mem_section[index].phys_section = physid;
+		printk(KERN_DEBUG "set mem_section[%d].phys_section: %d\n", index, mem_section[index].phys_section);
+	}
 
 	index = pfn_to_section(start_phys_pfn);
 	limit = index + sect_count;
-	for (; index < limit; index++, sect_index++)
+	for (; index < limit; index++, sect_index++) {
+		if (phys_section[index] != INVALID_PHYS_SECTION) {
+			printk(KERN_DEBUG "phys_section[%d]: %d\n", index, phys_section[index]);
+			BUG();
+		}
 		phys_section[index] = sect_index;
+		printk(KERN_DEBUG "set phys_section[%d]: %d\n", index, phys_section[index]);
+	}
 }
 
 void
@@ -99,6 +112,7 @@ memmap_init(unsigned long num_pages, int
 {
 	unsigned long offset;
 
+	printk(KERN_DEBUG "nonlinear memmap_init(%ld, %d, %ld, %ld)\n", num_pages, nid, zone, start_pfn);
 	offset = section_offset_pfn(start_pfn);
 	while (num_pages) {
 		unsigned long npages;
@@ -126,7 +140,12 @@ pfn_to_page(unsigned long pfn)
 {
 	struct page *page;
 
-	BUG_ON(!mem_section[phys_section[pfn_to_section(pfn)]].mem_map);
+	if (!mem_section[phys_section[pfn_to_section(pfn)]].mem_map) {
+		printk(KERN_ERR "%s() pfn: %08lx phys_section: %d mem_section: %d has no mem_map\n",
+				__func__, pfn, pfn_to_section(pfn),
+				phys_section[pfn_to_section(pfn)]);
+		BUG();
+	}
 	page = &mem_section[phys_section[pfn_to_section(pfn)]].mem_map[section_offset_pfn(pfn)];
 	return page;
 }
@@ -158,6 +177,17 @@ int invalidate_phys_mapping(unsigned lon
 	for (i = section_nr; i < section_nr + nr_sections; i++) {
 		 struct mem_section *ms = &mem_section[phys_section[i]];
 		 struct page *mem_map_page = virt_to_page(ms->mem_map);
+		 // hack for now.  use constants and #defines, probably
+		 extern struct page *__kmalloc_section_memmap(unsigned long nr_pages);
+
+		 if (mem_map_page->mapping == __kmalloc_section_memmap) {
+			printk(KERN_DEBUG "%s() mem_map_page: %p mapping: %p\n",
+				__func__, mem_map_page,
+				mem_map_page->mapping);
+			printk(KERN_DEBUG "\tpage_count(mem_map_page): %d\n",
+				page_count(mem_map_page));
+			__free_pages(mem_map_page, get_order(memmap_size));
+		 }
 
 		 ms->mem_map = NULL;
 		 printk(KERN_DEBUG "%s(%08lx, %08lx)\n", __func__, pfn, nr_pages);
diff -puN mm/bootmem.c~P-i386-debug mm/bootmem.c
diff -puN include/linux/rmap.h~P-i386-debug include/linux/rmap.h
diff -puN include/linux/nonlinear.h~P-i386-debug include/linux/nonlinear.h
--- memhotplug/include/linux/nonlinear.h~P-i386-debug	2004-10-08 00:15:12.000000000 -0700
+++ memhotplug-dave/include/linux/nonlinear.h	2004-10-08 00:15:12.000000000 -0700
@@ -1,6 +1,8 @@
 #ifndef __LINUX_NONLINEAR_H_
 #define __LINUX_NONLINEAR_H_
 
+#include <asm/bug.h>
+
 struct page;
 
 #ifndef CONFIG_NONLINEAR
diff -puN include/linux/memory_hotplug.h~P-i386-debug include/linux/memory_hotplug.h
diff -puN drivers/base/memory.c~P-i386-debug drivers/base/memory.c
--- memhotplug/drivers/base/memory.c~P-i386-debug	2004-10-08 00:15:12.000000000 -0700
+++ memhotplug-dave/drivers/base/memory.c	2004-10-08 00:15:12.000000000 -0700
@@ -63,6 +63,7 @@ register_memory(struct memory_block *mem
 
 	memory->sysdev.cls = &memory_sysdev_class;
 	memory->sysdev.id = section;
+	printk(KERN_DEBUG "register_memory() with section: %d\n", section);
 
 	error = sysdev_register(&memory->sysdev);
 
@@ -81,6 +82,8 @@ unregister_memory(struct memory_block *m
 	BUG_ON(memory->sysdev.cls != &memory_sysdev_class);
 	BUG_ON(memory->sysdev.id != section);
 
+	printk(KERN_DEBUG "%s(%p, %d, %p)\n", __func__, memory, section, root);
+
 	sysdev_unregister(&memory->sysdev);
 	if (root)
 		sysfs_remove_link(&root->sysdev.kobj, kobject_name(&memory->sysdev.kobj));
@@ -153,8 +156,10 @@ memory_block_action(struct memory_block 
 	printk(KERN_DEBUG "%s()\n"
 	       KERN_DEBUG "\tpsection: %ld\n"
 	       KERN_DEBUG "\tfirst_page: %p\n"
-	       KERN_DEBUG "\tphys_index: %08lx\n",
-		__func__, psection, first_page, mem->phys_index);
+	       KERN_DEBUG "\t last_page: %p\n"
+	       KERN_DEBUG "\tphys_index: %ld\n",
+		__func__, psection, first_page, first_page + PAGES_PER_SECTION -1,
+		mem->phys_index);
 	printk(KERN_DEBUG "\tphys_section[%2ld]: %d\n", psection, phys_section[psection]);
 	for (i = 0; i < PAGES_PER_SECTION; i++) {
 		if ((action == MEM_ONLINE) && !PageReserved(first_page)) {
@@ -233,6 +238,13 @@ store_mem_state(struct sys_device *dev, 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
+	/*
+	printk(KERN_DEBUG "%s(%p, \"%s\", %d\n)\n", __func__,
+			dev, buf, count);
+	printk(KERN_DEBUG "\tmem->phys_index: %ld\n", mem->phys_index);
+	printk(KERN_DEBUG "section: %d\n", section);
+	*/
+
 	if (mem_section[section].phys_section == INVALID_SECTION) {
 		printk("%s: Ummm.. this section (%d) is not currently mapped!\n",
 			__func__, section);
@@ -348,7 +360,7 @@ int add_memory_block(unsigned long node_
 {
 	size_t size = sizeof(struct memory_block);
 	struct memory_block *mem = kmalloc(size, GFP_KERNEL);
-	int ret0, ret1, ret2, ret3;
+	int ret = 0;
 
 	if (!mem)
 		return -ENOMEM;
@@ -368,12 +380,15 @@ int add_memory_block(unsigned long node_
 		callback(mem);
 #endif
 
-	ret0 = register_memory(mem, section, NULL);
-	ret1 = mem_create_simple_file(mem, phys_index);
-	ret2 = mem_create_simple_file(mem, state);
-	ret3 = mem_create_simple_file(mem, phys_device);
+	ret = register_memory(mem, section, NULL);
+	if (!ret)
+		ret = mem_create_simple_file(mem, phys_index);
+	if (!ret)
+		ret = mem_create_simple_file(mem, state);
+	if (!ret)
+		ret = mem_create_simple_file(mem, phys_device);
 
-	return 0;
+	return ret;
 }
 
 #define online_section(...) 	do {} while(0)
@@ -481,17 +496,17 @@ int register_new_memory(unsigned int sec
 	return add_memory_block(0, section, phys_index, MEM_OFFLINE, 0);
 }
 
-int unregister_memory_section(unsigned int section)
+int unregister_memory_section(unsigned int phys_section_nr)
 {
-	unsigned int phys_index = mem_section[section].phys_section;
+	unsigned short section = phys_section[phys_section_nr];
 
-	if (phys_index == INVALID_SECTION) {
-		printk(KERN_WARNING "%s: phys_index 0x%x is BOGUS!\n", __func__, phys_index);
+	if (section == INVALID_PHYS_SECTION) {
+		printk(KERN_WARNING "%s: phys_index 0x%x for section: %d is BOGUS!\n", __func__, section, phys_section_nr);
 		return -EINVAL;
 	}
 
 	/* need some node info here and some sort of callback .... */
-	return remove_memory_block(0, section, phys_index, 0);
+	return remove_memory_block(0, section, phys_section_nr, 0);
 }
 
 /*
diff -puN arch/i386/mm/init.c~P-i386-debug arch/i386/mm/init.c
--- memhotplug/arch/i386/mm/init.c~P-i386-debug	2004-10-08 00:15:12.000000000 -0700
+++ memhotplug-dave/arch/i386/mm/init.c	2004-10-08 00:15:12.000000000 -0700
@@ -344,6 +344,8 @@ int add_memory(u64 start, u64 size, unsi
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
 
+	printk(KERN_DEBUG "%s(%016Lx, %016lx, %08lx\n", __func__, start, size, attr);
+
 	return __add_pages(zone, start_pfn, nr_pages, attr);
 }
 
@@ -363,8 +365,9 @@ int remove_memory(u64 start, u64 size, u
 	 */
 	zone = page_zone(pfn_to_page(start_pfn));
 
-	printk("%s(): memory will be removed from "
-			"the %s zone\n", __func__, zone->name);
+	printk(KERN_DEBUG "%s(%016Lx, %016Lx, %ld):\n\tmemory will be removed from "
+			"a %s zone\n", __func__, start, size, attr,
+			zone->name);
 
 	/*
 	 * not handling removing memory ranges that
@@ -383,10 +386,10 @@ int remove_memory(u64 start, u64 size, u
 	return __remove_pages(zone, start_pfn, nr_pages, attr);
 
 overlap:
-	printk("%s(): memory range to be removed overlaps "
+	printk(KERN_WARNING "%s(): memory range to be removed overlaps "
 		"multiple zones!!!\n", __func__);
 not_highmem:
-	return -1;
+	return -EINVAL;
 }
 #endif
 
@@ -702,9 +705,9 @@ void __init mem_init(void)
 	set_max_mapnr_init();
 
 #ifdef CONFIG_HIGHMEM
-	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE);
+	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1);
 #else
-	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
+	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1);
 #endif
 
 	/* this will put all low memory onto the freelists */
diff -puN mm/vmscan.c~P-i386-debug mm/vmscan.c
--- memhotplug/mm/vmscan.c~P-i386-debug	2004-10-08 00:15:12.000000000 -0700
+++ memhotplug-dave/mm/vmscan.c	2004-10-08 00:15:12.000000000 -0700
@@ -366,6 +366,7 @@ static int shrink_list(struct list_head 
 
 		page = lru_to_page(page_list);
 		list_del(&page->lru);
+		page->lru_list_type = 31;
 
 		if (TestSetPageLocked(page))
 			goto keep;
@@ -572,6 +573,7 @@ static void shrink_cache(struct zone *zo
 			if (!TestClearPageLRU(page))
 				BUG();
 			list_del(&page->lru);
+			page->lru_list_type = 32;
 			if (get_page_testone(page)) {
 				/*
 				 * It is being freed elsewhere
@@ -611,6 +613,7 @@ static void shrink_cache(struct zone *zo
 			if (TestSetPageLRU(page))
 				BUG();
 			list_del(&page->lru);
+			page->lru_list_type = 33;
 			if (PageActive(page) && !page_under_capture(page))
 				add_page_to_active_list(zone, page);
 			else
@@ -670,6 +673,7 @@ refill_inactive_zone(struct zone *zone, 
 		if (!TestClearPageLRU(page))
 			BUG();
 		list_del(&page->lru);
+		page->lru_list_type = 34;
 		if (get_page_testone(page)) {
 			/*
 			 * It was already free!  release_pages() or put_page()
@@ -724,6 +728,7 @@ refill_inactive_zone(struct zone *zone, 
 		cond_resched();
 		page = lru_to_page(&l_hold);
 		list_del(&page->lru);
+		page->lru_list_type = 35;
 		if (page_mapped(page)) {
 			if (!reclaim_mapped ||
 			    (total_swap_pages == 0 && PageAnon(page)) ||
diff -puN fs/sysfs/file.c~P-i386-debug fs/sysfs/file.c
--- memhotplug/fs/sysfs/file.c~P-i386-debug	2004-10-08 00:15:12.000000000 -0700
+++ memhotplug-dave/fs/sysfs/file.c	2004-10-08 00:15:12.000000000 -0700
@@ -375,7 +375,9 @@ int sysfs_add_file(struct dentry * dir, 
 
 int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
 {
-	BUG_ON(!kobj || !kobj->dentry || !attr);
+	BUG_ON(!kobj);
+	BUG_ON(!kobj->dentry);
+	BUG_ON(!attr);
 
 	return sysfs_add_file(kobj->dentry, attr, SYSFS_KOBJ_ATTR);
 
diff -puN include/asm-generic/bug.h~P-i386-debug include/asm-generic/bug.h
diff -puN kernel/panic.c~P-i386-debug kernel/panic.c
--- memhotplug/kernel/panic.c~P-i386-debug	2004-10-08 00:15:12.000000000 -0700
+++ memhotplug-dave/kernel/panic.c	2004-10-08 00:15:12.000000000 -0700
@@ -68,12 +68,14 @@ NORET_TYPE void panic(const char * fmt, 
 	/* If we have crashed, perform a kexec reboot, for dump write-out */
 	crash_machine_kexec();
 
+	machine_restart(NULL);
 #ifdef CONFIG_SMP
 	smp_send_stop();
 #endif
 
        notifier_call_chain(&panic_notifier_list, 0, buf);
 
+        panic_timeout = 1;
 	if (panic_timeout > 0)
 	{
 		int i;
diff -puN mm/highmem.c~P-i386-debug mm/highmem.c
diff -puN include/linux/list.h~P-i386-debug include/linux/list.h
--- memhotplug/include/linux/list.h~P-i386-debug	2004-10-08 00:15:12.000000000 -0700
+++ memhotplug-dave/include/linux/list.h	2004-10-08 00:15:12.000000000 -0700
@@ -159,13 +159,15 @@ static inline void __list_del(struct lis
  * Note: list_empty on entry does not return true after this, the entry is
  * in an undefined state.
  */
-static inline void list_del(struct list_head *entry)
+static void list_del(struct list_head *entry)
 {
 	BUG_ON(entry->prev->next != entry);
 	BUG_ON(entry->next->prev != entry);
 	__list_del(entry->prev, entry->next);
 	entry->next = LIST_POISON1;
 	entry->prev = LIST_POISON2;
+	if (0)
+		list_del(entry);
 }
 
 /**
diff -puN include/linux/mm_inline.h~P-i386-debug include/linux/mm_inline.h
--- memhotplug/include/linux/mm_inline.h~P-i386-debug	2004-10-08 00:15:12.000000000 -0700
+++ memhotplug-dave/include/linux/mm_inline.h	2004-10-08 00:15:12.000000000 -0700
@@ -3,6 +3,7 @@ static inline void
 add_page_to_active_list(struct zone *zone, struct page *page)
 {
 	list_add(&page->lru, &zone->active_list);
+	page->lru_list_type = 20;
 	zone->nr_active++;
 }
 
@@ -10,6 +11,7 @@ static inline void
 add_page_to_inactive_list(struct zone *zone, struct page *page)
 {
 	list_add(&page->lru, &zone->inactive_list);
+	page->lru_list_type = 21;
 	zone->nr_inactive++;
 }
 
@@ -17,6 +19,7 @@ static inline void
 del_page_from_active_list(struct zone *zone, struct page *page)
 {
 	list_del(&page->lru);
+	page->lru_list_type = 22;
 	zone->nr_active--;
 }
 
@@ -24,17 +27,28 @@ static inline void
 del_page_from_inactive_list(struct zone *zone, struct page *page)
 {
 	list_del(&page->lru);
+	page->lru_list_type = 23;
 	zone->nr_inactive--;
 }
 
-static inline void
+extern void bad_page(const char *function, struct page *page);
+static void
 del_page_from_lru(struct zone *zone, struct page *page)
 {
+	if (page->lru.next == LIST_POISON1 ||
+	    page->lru.prev == LIST_POISON2) {
+		printk("%s(%p, %p) page poison\n", __func__, zone, page);
+		printk("\t pfn: %ld\n", page_to_pfn(page));
+		bad_page(__func__, page);
+	}
 	list_del(&page->lru);
+	page->lru_list_type = 24;
 	if (PageActive(page)) {
 		ClearPageActive(page);
 		zone->nr_active--;
 	} else {
 		zone->nr_inactive--;
 	}
+	if (0)
+		del_page_from_lru(zone, page);
 }
diff -puN include/linux/mmzone.h~P-i386-debug include/linux/mmzone.h
diff -puN ./arch/i386/mm/fault.c~P-i386-debug ./arch/i386/mm/fault.c
diff -puN arch/i386/kernel/traps.c~P-i386-debug arch/i386/kernel/traps.c
--- memhotplug/arch/i386/kernel/traps.c~P-i386-debug	2004-10-08 00:15:12.000000000 -0700
+++ memhotplug-dave/arch/i386/kernel/traps.c	2004-10-08 00:15:12.000000000 -0700
@@ -403,7 +403,7 @@ void die(const char * str, struct pt_reg
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
 
-	if (panic_on_oops) {
+	if (1 || panic_on_oops) {
 		printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule_timeout(5 * HZ);
diff -puN mm/swap.c~P-i386-debug mm/swap.c
--- memhotplug/mm/swap.c~P-i386-debug	2004-10-08 00:15:12.000000000 -0700
+++ memhotplug-dave/mm/swap.c	2004-10-08 00:15:12.000000000 -0700
@@ -86,6 +86,7 @@ int rotate_reclaimable_page(struct page 
 	zone = page_zone(page);
 	spin_lock_irqsave(&zone->lru_lock, flags);
 	if (PageLRU(page) && !PageActive(page)) {
+		page->lru_list_type = 30;
 		list_del(&page->lru);
 		list_add_tail(&page->lru, &zone->inactive_list);
 		inc_page_state(pgrotated);
diff -puN arch/i386/mm/pgtable.c~P-i386-debug arch/i386/mm/pgtable.c
diff -puN arch/i386/kernel/setup.c~P-i386-debug arch/i386/kernel/setup.c
diff -puN arch/i386/mm/pageattr.c~P-i386-debug arch/i386/mm/pageattr.c
diff -puN arch/i386/mm/ioremap.c~P-i386-debug arch/i386/mm/ioremap.c
_
