On Thu, 12 Jun 2008 01:57:46 -0700
Andrew Morton <akpm@linux-foundation.org> wrote:
at first look,
==
truncate_inode_pages_range()
-> TestSetPageLocked() //
-> truncate_complete_page()
-> remove_from_page_cache() // makes page->mapping to be NULL.
-> clear_page_mlock()
-> __clear_page_mlock()
-> putback_lru_page()
-> unlock_page() // page->mapping is NULL
-> unlock_page() //BUG
==
It seems truncate_complete_page() is bad.
==
static void
truncate_complete_page(struct address_space *mapping, struct page *page)
{
if (page->mapping != mapping)
return;
if (PagePrivate(page))
do_invalidatepage(page, 0);
cancel_dirty_page(page, PAGE_CACHE_SIZE);
remove_from_page_cache(page); -----------------(A)
clear_page_mlock(page); -----------------(B)
ClearPageUptodate(page);
ClearPageMappedToDisk(page);
page_cache_release(page); /* pagecache ref */
}
==
(B) should be called before (A) as invalidate_complete_page() does.
Thanks,
-Kame
--