From: Hugh Dickins PageDirty BUG_ON in __remove_inode_page is, and always has been, unsafe for SMP or preemption: truncation may be racing against unmapping's set_page_dirty in zap_pte_range (amongst a few other possibilities). !PageUptodate error in __set_page_dirty_buffers is unsafe then too. 25-akpm/fs/buffer.c | 3 --- 25-akpm/mm/filemap.c | 2 -- 2 files changed, 5 deletions(-) diff -puN fs/buffer.c~truncate-vs-msync-fix fs/buffer.c --- 25/fs/buffer.c~truncate-vs-msync-fix Tue Jun 3 10:59:55 2003 +++ 25-akpm/fs/buffer.c Tue Jun 3 10:59:55 2003 @@ -822,9 +822,6 @@ int __set_page_dirty_buffers(struct page goto out; } - if (!PageUptodate(page)) - buffer_error(); - spin_lock(&mapping->private_lock); if (page_has_buffers(page)) { struct buffer_head *head = page_buffers(page); diff -puN mm/filemap.c~truncate-vs-msync-fix mm/filemap.c --- 25/mm/filemap.c~truncate-vs-msync-fix Tue Jun 3 10:59:55 2003 +++ 25-akpm/mm/filemap.c Tue Jun 3 10:59:55 2003 @@ -81,8 +81,6 @@ void __remove_from_page_cache(struct pag { struct address_space *mapping = page->mapping; - BUG_ON(PageDirty(page) && !PageSwapCache(page)); - radix_tree_delete(&mapping->page_tree, page->index); list_del(&page->list); page->mapping = NULL; _