Messages in this thread Patch in this message | | | Date | Tue, 29 Jun 1999 18:14:35 +0200 (CEST) | From | Andrea Arcangeli <> | Subject | free_page_and_swap_cache sleeps (so sleep also zap_page_range) |
| |
When vmtruncate calls zap_page_range() then zap_page_range() can call free_page_and_swap_cache (that can sleep in pre5). But I think vmtruncate couldn't sleep (since it owns only the i_sem and the big kernel lock).
The trivial fix is to not release the pagecache from zap_page_range (and left this task only to shrink_mmap). I am not convinced if that's what we want though...
(anyway a completly untested patch against pre-2.3.9-5 follows)
Index: linux//include/linux/swap.h =================================================================== RCS file: /var/cvs/linux/include/linux/swap.h,v retrieving revision 1.1.1.9 diff -u -r1.1.1.9 swap.h --- linux//include/linux/swap.h 1999/06/22 22:36:11 1.1.1.9 +++ linux//include/linux/swap.h 1999/06/29 16:04:50 @@ -108,7 +108,6 @@ */ extern void __delete_from_swap_cache(struct page *page); extern void delete_from_swap_cache(struct page *page); -extern void free_page_and_swap_cache(unsigned long addr); /* linux/mm/swapfile.c */ extern unsigned int nr_swapfiles; Index: linux//mm/memory.c =================================================================== RCS file: /var/cvs/linux/mm/memory.c,v retrieving revision 1.1.1.10 diff -u -r1.1.1.10 memory.c --- linux//mm/memory.c 1999/06/28 15:10:09 1.1.1.10 +++ linux//mm/memory.c 1999/06/29 16:03:59 @@ -305,7 +305,7 @@ * free_page() used to be able to clear swap cache * entries. We may now have to do it manually. */ - free_page_and_swap_cache(addr); + free_page(addr); return 1; } swap_free(pte_val(page)); Index: linux//mm/page_alloc.c =================================================================== RCS file: /var/cvs/linux/mm/page_alloc.c,v retrieving revision 1.1.1.14 diff -u -r1.1.1.14 page_alloc.c --- linux//mm/page_alloc.c 1999/06/22 22:36:36 1.1.1.14 +++ linux//mm/page_alloc.c 1999/06/29 16:04:14 @@ -403,7 +403,7 @@ } if (pte_val(*page_table) != entry) { if (page_map) - free_page_and_swap_cache(page_address(page_map)); + __free_page(page_map); return; } if (!page_map) { Index: linux//mm/swap_state.c =================================================================== RCS file: /var/cvs/linux/mm/swap_state.c,v retrieving revision 1.1.1.8 diff -u -r1.1.1.8 swap_state.c --- linux//mm/swap_state.c 1999/06/28 15:10:10 1.1.1.8 +++ linux//mm/swap_state.c 1999/06/29 16:05:05 @@ -253,31 +253,6 @@ page_cache_release(page); } -/* - * Perform a free_page(), also freeing any swap cache associated with - * this page if it is the last user of the page. - */ - -void free_page_and_swap_cache(unsigned long addr) -{ - struct page *page = mem_map + MAP_NR(addr); - - /* - * If we are the only user, then free up the swap cache. - */ - lock_page(page); - if (PageSwapCache(page) && !is_page_shared(page)) { - long entry = page->offset; - remove_from_swap_cache(page); - swap_free(entry); - page_cache_release(page); - } - UnlockPage(page); - - __free_page(page); -} - - /* * Lookup a swap entry in the swap cache. A found page will be returned * unlocked and with its refcount incremented - we rely on the kernel Andrea
- 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.tux.org/lkml/
| |