[PATCH] truncate: clear page dirtiness before running try_to_free_buffers()
truncate presently invalidates the dirty page's buffer_heads then shoots down the page. But try_to_free_buffers() will now bale out because the page is dirty. Net effect: the LRU gets filled with dirty pages which have invalidated buffer_heads attached. They have no ->mapping and hence cannot be cleaned. The machine leaks memory at an enormous rate. Fix this by cleaning the page before running try_to_free_buffers(), so try_to_free_buffers() can do its work. Also, remember to do dirty-page-acoounting in cancel_dirty_page() so the machine won't wedge up trying to write non-existent dirty pages. Probably still wrong, but now less so. Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
		
					parent
					
						
							
								921320210b
							
						
					
				
			
			
				commit
				
					
						3e67c0987d
					
				
			
		
					 1 changed files with 5 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -60,11 +60,12 @@ void cancel_dirty_page(struct page *page, unsigned int account_size)
 | 
			
		|||
		WARN_ON(++warncount < 5);
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
	if (TestClearPageDirty(page) && account_size)
 | 
			
		||||
	if (TestClearPageDirty(page) && account_size) {
 | 
			
		||||
		dec_zone_page_state(page, NR_FILE_DIRTY);
 | 
			
		||||
		task_io_account_cancelled_write(account_size);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * If truncate cannot remove the fs-private metadata from the page, the page
 | 
			
		||||
 * becomes anonymous.  It will be left on the LRU and may even be mapped into
 | 
			
		||||
| 
						 | 
				
			
			@ -81,11 +82,11 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
 | 
			
		|||
	if (page->mapping != mapping)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	cancel_dirty_page(page, PAGE_CACHE_SIZE);
 | 
			
		||||
 | 
			
		||||
	if (PagePrivate(page))
 | 
			
		||||
		do_invalidatepage(page, 0);
 | 
			
		||||
 | 
			
		||||
	cancel_dirty_page(page, PAGE_CACHE_SIZE);
 | 
			
		||||
 | 
			
		||||
	ClearPageUptodate(page);
 | 
			
		||||
	ClearPageMappedToDisk(page);
 | 
			
		||||
	remove_from_page_cache(page);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue