patch for 2.1.112 mm/swap_state.c

Bill Hawes (whawes@transmeta.com)
Wed, 29 Jul 1998 12:09:16 -0700


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

The attached patch fixes a problem that can lead to floods of error
messages or possible corruption of swapped pages. A couple of people
have reported this on the kernel list, so it does need to be fixed.

The current remove_from_swap_cache code checks for removing an unshared
page and prints a message, but fails to remove the page. Since the call
may occur when shrink_mmap wants to free a leftover swap cache page, the
message will keep recurring each time it finds the page.

To make matters worse, the associated swap entry is actually freed in
delete_from_swap_cache, allowing it to be reused for another page. Then
subsequent attempts to remove the first page will keep freeing the swap
entry, possibly leading to lost data or crashes.

The patch corrects this by leaving the warning message but allowing the
page to be removed from the cache. (Some dead code is also removed.)

Regards,
Bill

--------------DB025CD4202776F59AA2729A
Content-Type: text/plain; charset=us-ascii; name="mm_swstate112-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="mm_swstate112-patch"

--- linux-2.1.112/mm/swap_state.c.old Tue Mar 10 10:51:02 1998
+++ linux-2.1.112/mm/swap_state.c Wed Jul 29 11:38:13 1998
@@ -146,41 +146,22 @@
"on page %08lx\n", page_address(page));
}
/*
- * This will be a legal case once we have a more mature swap cache.
+ * This is a legal case, but warn about it.
*/
if (atomic_read(&page->count) == 1) {
- printk ("VM: Removing page cache on unshared page %08lx\n",
+ printk (KERN_WARNING
+ "VM: Removing page cache on unshared page %08lx\n",
page_address(page));
- return;
}

-
#ifdef DEBUG_SWAP
printk("DebugVM: remove_from_swap_cache(%08lx count %d)\n",
page_address(page), atomic_read(&page->count));
#endif
- remove_page_from_hash_queue (page);
- remove_page_from_inode_queue (page);
PageClearSwapCache (page);
- __free_page (page);
+ remove_inode_page(page);
}

-
-long find_in_swap_cache(struct page *page)
-{
-#ifdef SWAP_CACHE_INFO
- swap_cache_find_total++;
-#endif
- if (PageSwapCache (page)) {
- long entry = page->offset;
-#ifdef SWAP_CACHE_INFO
- swap_cache_find_success++;
-#endif
- remove_from_swap_cache (page);
- return entry;
- }
- return 0;
-}

int delete_from_swap_cache(struct page *page)
{

--------------DB025CD4202776F59AA2729A--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html