fix a race between set_page_dirty and truncate
Subsystems (2)
PATCH 12/12 fix a race between set_page_dirty and truncate
Fix a race between set_page_dirty() and truncate.
The page could have been removed from the mapping while this CPU is spinning on the lock. __free_pages_ok() will go BUG.
This has not been observed in practice - most callers of set_page_dirty() hold the page lock which gives exclusion from truncate. But zap_pte_range() does not.
A fix for this has been sent to Marcelo also.
page-writeback.c | 12 ++++++++---- 1 files changed, 8 insertions, 4 deletions
mm/page-writeback.c renamed from mm/page-writeback.c~set_page_dirty-race +8 -4
@@ -477,8 +477,10 @@ int __set_page_dirty_buffers(struct pageif (!TestSetPageDirty (page)) {write_lock (&mapping->page_lock); -list_del (&page->list); -list_add (&page->list, &mapping->dirty_pages); +if (page->mapping) {/* Race with truncate? */ +list_del (&page->list); +list_add (&page->list, &mapping->dirty_pages); + }write_unlock (&mapping->page_lock);__mark_inode_dirty (mapping->host,I_DIRTY_PAGES ); }
@@ -511,8 +513,10 @@ int __set_page_dirty_nobuffers(struct paif (mapping) {write_lock (&mapping->page_lock); -list_del (&page->list); -list_add (&page->list, &mapping->dirty_pages); +if (page->mapping) {/* Race with truncate? */ +list_del (&page->list); +list_add (&page->list, &mapping->dirty_pages); + }write_unlock (&mapping->page_lock);__mark_inode_dirty (mapping->host,I_DIRTY_PAGES ); }
.