fix dirty page management
Subsystems (3)
PATCH 4/15 fix dirty page management
Fixes a bug in ext3 - when ext3 decides that it wants to fail its writepage(), it is running SetPageDirty(). But ->writepage has just put the page on ->clean_pages(). The page ends up dirty, on ->clean_pages and the normal writeback paths don't know about it any more.
So run set_page_dirty() instead, to place the page back on the dirty list.
And in move_from_swap_cache(), shuffle the page across to ->dirty_pages so that it's eligible for writeout. ___add_to_page_cache() forgets to look at the page state when deciding which list to attach it to.
All SetPageDirty() callers otherwise look OK.
=====================================
fs/ext3/inode.c renamed from fs/ext3/inode.c~set_page_dirty +1 -1
@@ -1325,7 +1325,7 @@ static int ext3_writepage(struct page *p out_fail:unlock_kernel (); -SetPageDirty (page); +set_page_dirty (page);unlock_page (page);return ret; }
mm/filemap.c renamed from mm/filemap.c~set_page_dirty +3 -0
@@ -425,6 +425,9 @@ void invalidate_inode_pages2(struct addr* - activate the page so that the page stealer * doesn't try to write it out over and over * again. +* +* NOTE! The livelock in fdatasync went away, due to io_pages. +* So this function can now call set_page_dirty(). */ int fail_writepage (struct page *page) {
mm/swap_state.c renamed from mm/swap_state.c~set_page_dirty +8 -0
@@ -220,8 +220,16 @@ int move_from_swap_cache(struct page *pa page->flags &= ~(1 << PG_uptodate |1 << PG_error |1 << PG_referenced |1 << PG_arch_1 |1 << PG_checked); +/* +* ___add_to_page_cache puts the page on ->clean_pages, +* but it's dirty. If it's on ->clean_pages, it will basically +* never get written out. +*/ SetPageDirty (page);___add_to_page_cache (page, mapping, index); +/* fix that up */ +list_del (&page->list); +list_add (&page->list, &mapping->dirty_pages); }write_unlock (&mapping->page_lock);
mm/swapfile.c renamed from mm/swapfile.c~set_page_dirty +5 -0
@@ -311,6 +311,11 @@ int remove_exclusive_swap_page(struct pawrite_lock (&swapper_space.page_lock);if (page_count (page) - !!PagePrivate (page) ==2 ) {__delete_from_swap_cache (page); +/* +* NOTE: if/when swap gets buffer/page coherency +* like other mappings, we'll need to mark the buffers +* dirty here too. set_page_dirty(). +*/ SetPageDirty (page); retval =1 ; }
-