minor patch for 2.1.103 swap

Bill Hawes (whawes@star.net)
Sat, 23 May 1998 10:09:26 -0400


This is a multi-part message in MIME format.
--------------AAFF33316909AD5E16104EE3
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

The attached patch makes some minor changes to the swap code to help
diagnose the "writable swap cache page" problems, and to downgrade a
panic to a warning.

When a writable swap cache page is found, the patch does a find_page to
verify that the page really is in the swap cache. This will help
determine whether the swap cache flag has somehow become out of sync
with the cache.

In the free_page() routines there is a panic if a swap cache page has a
ref count of 1, but according to code and comments elsewhere this
shouldn't be a problem. Shrink_mmap has a test to remove pages from the
swap cache when count == 1, and a comment in vmscan.c states that a page
might occasionally be left in the swap cache after having other
references freed. Since these cases would all come through free_page()
with the count set to 1, there's no longer any reason to cause a panic.
(And possibly the warning should be removed as well at some point.)

The patch makes one other minor cleanup, to pass the page struct * to
page_unuse to avoid recalculating it.

Regards,
Bill
--------------AAFF33316909AD5E16104EE3
Content-Type: text/plain; charset=us-ascii; name="swap_vm103-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="swap_vm103-patch"

--- linux-2.1.103/include/linux/mm.h.old Thu May 21 15:07:52 1998
+++ linux-2.1.103/include/linux/mm.h Fri May 22 11:09:50 1998
@@ -308,7 +308,7 @@
extern unsigned long get_unmapped_area(unsigned long, unsigned long);

/* filemap.c */
-extern unsigned long page_unuse(unsigned long);
+extern unsigned long page_unuse(struct page *);
extern int shrink_mmap(int, int);
extern void truncate_inode_pages(struct inode *, unsigned long);
extern unsigned long get_cached_page(struct inode *, unsigned long, int);
--- linux-2.1.103/mm/vmscan.c.old Sun May 17 12:19:41 1998
+++ linux-2.1.103/mm/vmscan.c Fri May 22 11:33:13 1998
@@ -107,7 +107,17 @@

if (PageSwapCache(page_map)) {
if (pte_write(pte)) {
+ struct page *found;
printk ("VM: Found a writable swap-cached page!\n");
+ /* Try to diagnose the problem ... */
+ found = find_page(&swapper_inode, page_map->offset);
+ if (found) {
+ printk("page=%p@%08lx, found=%p, count=%d\n",
+ page_map, page_map->offset,
+ found, atomic_read(&found->count));
+ __free_page(found);
+ } else
+ printk ("Spurious, page not in cache\n");
return 0;
}
}
@@ -144,9 +154,8 @@
* we have the swap cache set up to associate the
* page with that swap entry.
*/
- if (PageSwapCache(page_map)) {
- entry = page_map->offset;
- } else {
+ entry = in_swap_cache(page_map);
+ if (!entry) {
entry = get_swap_page();
if (!entry)
return 0; /* No swap space left */
@@ -219,8 +228,8 @@
flush_cache_page(vma, address);
pte_clear(page_table);
flush_tlb_page(vma, address);
- entry = page_unuse(page);
- free_page(page);
+ entry = page_unuse(page_map);
+ __free_page(page_map);
return entry;
}

--- linux-2.1.103/mm/filemap.c.old Thu Mar 26 23:17:41 1998
+++ linux-2.1.103/mm/filemap.c Fri May 22 11:08:02 1998
@@ -216,20 +216,19 @@
* free it from the page hash-queues etc, as we don't want to keep it
* in-core unnecessarily.
*/
-unsigned long page_unuse(unsigned long page)
+unsigned long page_unuse(struct page * page)
{
- struct page * p = mem_map + MAP_NR(page);
- int count = atomic_read(&p->count);
+ int count = atomic_read(&page->count);

if (count != 2)
return count;
- if (!p->inode)
+ if (!page->inode)
return count;
- if (PageSwapCache(p))
+ if (PageSwapCache(page))
panic ("Doing a normal page_unuse of a swap cache page");
- remove_page_from_hash_queue(p);
- remove_page_from_inode_queue(p);
- free_page(page);
+ remove_page_from_hash_queue(page);
+ remove_page_from_inode_queue(page);
+ __free_page(page);
return 1;
}

--- linux-2.1.103/mm/page_alloc.c.old Sun May 17 12:21:09 1998
+++ linux-2.1.103/mm/page_alloc.c Fri May 22 11:20:25 1998
@@ -182,9 +182,11 @@
if (PageSwapCache(page))
panic ("Freeing swap cache page");
free_pages_ok(page->map_nr, 0);
+ return;
}
if (PageSwapCache(page) && atomic_read(&page->count) == 1)
- panic ("Releasing swap cache page");
+ printk(KERN_WARNING "VM: Releasing swap cache page at %p",
+ __builtin_return_address(0));
}

void free_pages(unsigned long addr, unsigned long order)
@@ -202,8 +204,9 @@
return;
}
if (PageSwapCache(map) && atomic_read(&map->count) == 1)
- panic ("Releasing swap cache pages at %p",
- __builtin_return_address(0));
+ printk(KERN_WARNING
+ "VM: Releasing swap cache pages at %p",
+ __builtin_return_address(0));
}
}

--------------AAFF33316909AD5E16104EE3--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu