From 8b42e4cc2dc16374261be92c3426dae0974beeed Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 20 Dec 2006 13:46:42 -0800 Subject: [PATCH] --- yaml --- r: 44858 b: refs/heads/master c: fba2591bf4e418b6c3f9f8794c9dd8fe40ae7bd9 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/fs/hugetlbfs/inode.c | 2 +- trunk/include/linux/page-flags.h | 8 ++------ trunk/mm/page-writeback.c | 32 -------------------------------- trunk/mm/truncate.c | 25 +++++++++++++++++-------- 5 files changed, 21 insertions(+), 48 deletions(-) diff --git a/[refs] b/[refs] index 485587502d34..15c571e997c1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 46d2277c796f9f4937bfa668c40b2e3f43e93dd0 +refs/heads/master: fba2591bf4e418b6c3f9f8794c9dd8fe40ae7bd9 diff --git a/trunk/fs/hugetlbfs/inode.c b/trunk/fs/hugetlbfs/inode.c index ed2c22340ad7..4f4cd132b571 100644 --- a/trunk/fs/hugetlbfs/inode.c +++ b/trunk/fs/hugetlbfs/inode.c @@ -176,7 +176,7 @@ static int hugetlbfs_commit_write(struct file *file, static void truncate_huge_page(struct page *page) { - clear_page_dirty(page); + cancel_dirty_page(page, /* No IO accounting for huge pages? */0); ClearPageUptodate(page); remove_from_page_cache(page); put_page(page); diff --git a/trunk/include/linux/page-flags.h b/trunk/include/linux/page-flags.h index 4830a3bedfb2..350878a2d848 100644 --- a/trunk/include/linux/page-flags.h +++ b/trunk/include/linux/page-flags.h @@ -253,15 +253,11 @@ static inline void SetPageUptodate(struct page *page) struct page; /* forward declaration */ -int test_clear_page_dirty(struct page *page); +extern void cancel_dirty_page(struct page *page, unsigned int account_size); + int test_clear_page_writeback(struct page *page); int test_set_page_writeback(struct page *page); -static inline void clear_page_dirty(struct page *page) -{ - test_clear_page_dirty(page); -} - static inline void set_page_writeback(struct page *page) { test_set_page_writeback(page); diff --git a/trunk/mm/page-writeback.c b/trunk/mm/page-writeback.c index 237107c1b084..b3a198c9248d 100644 --- a/trunk/mm/page-writeback.c +++ b/trunk/mm/page-writeback.c @@ -844,38 +844,6 @@ int set_page_dirty_lock(struct page *page) } EXPORT_SYMBOL(set_page_dirty_lock); -/* - * Clear a page's dirty flag, while caring for dirty memory accounting. - * Returns true if the page was previously dirty. - */ -int test_clear_page_dirty(struct page *page) -{ - struct address_space *mapping = page_mapping(page); - unsigned long flags; - - if (!mapping) - return TestClearPageDirty(page); - - write_lock_irqsave(&mapping->tree_lock, flags); - if (TestClearPageDirty(page)) { - radix_tree_tag_clear(&mapping->page_tree, - page_index(page), PAGECACHE_TAG_DIRTY); - write_unlock_irqrestore(&mapping->tree_lock, flags); - /* - * We can continue to use `mapping' here because the - * page is locked, which pins the address_space - */ - if (mapping_cap_account_dirty(mapping)) { - page_mkclean(page); - dec_zone_page_state(page, NR_FILE_DIRTY); - } - return 1; - } - write_unlock_irqrestore(&mapping->tree_lock, flags); - return 0; -} -EXPORT_SYMBOL(test_clear_page_dirty); - /* * Clear a page's dirty flag, while caring for dirty memory accounting. * Returns true if the page was previously dirty. diff --git a/trunk/mm/truncate.c b/trunk/mm/truncate.c index 9bfb8e853860..bf9e2965d666 100644 --- a/trunk/mm/truncate.c +++ b/trunk/mm/truncate.c @@ -51,6 +51,20 @@ static inline void truncate_partial_page(struct page *page, unsigned partial) do_invalidatepage(page, partial); } +void cancel_dirty_page(struct page *page, unsigned int account_size) +{ + /* If we're cancelling the page, it had better not be mapped any more */ + if (page_mapped(page)) { + static unsigned int warncount; + + WARN_ON(++warncount < 5); + } + + if (TestClearPageDirty(page) && account_size) + 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 @@ -70,8 +84,8 @@ truncate_complete_page(struct address_space *mapping, struct page *page) if (PagePrivate(page)) do_invalidatepage(page, 0); - if (test_clear_page_dirty(page)) - task_io_account_cancelled_write(PAGE_CACHE_SIZE); + cancel_dirty_page(page, PAGE_CACHE_SIZE); + ClearPageUptodate(page); ClearPageMappedToDisk(page); remove_from_page_cache(page); @@ -350,7 +364,6 @@ int invalidate_inode_pages2_range(struct address_space *mapping, for (i = 0; !ret && i < pagevec_count(&pvec); i++) { struct page *page = pvec.pages[i]; pgoff_t page_index; - int was_dirty; lock_page(page); if (page->mapping != mapping) { @@ -386,12 +399,8 @@ int invalidate_inode_pages2_range(struct address_space *mapping, PAGE_CACHE_SIZE, 0); } } - was_dirty = test_clear_page_dirty(page); - if (!invalidate_complete_page2(mapping, page)) { - if (was_dirty) - set_page_dirty(page); + if (!invalidate_complete_page2(mapping, page)) ret = -EIO; - } unlock_page(page); } pagevec_release(&pvec);