From 6b7a187bef15e1f32df7820f2c54e20033c44574 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Tue, 17 Jul 2007 04:03:34 -0700 Subject: [PATCH] --- yaml --- r: 60753 b: refs/heads/master c: 787d2214c19bcc9b6ac48af0ce098277a801eded h: refs/heads/master i: 60751: 29e68c0700571de3f859527eb2145497402ffb87 v: v3 --- [refs] | 2 +- trunk/fs/buffer.c | 54 +++++++++++++++++++++++++++------------ trunk/mm/page-writeback.c | 1 + trunk/mm/truncate.c | 2 +- 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/[refs] b/[refs] index 87b7e4947d7a..ec24c90f3df4 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a1ed3dda0ad181532f1e0f0d548067fb9fdddac4 +refs/heads/master: 787d2214c19bcc9b6ac48af0ce098277a801eded diff --git a/trunk/fs/buffer.c b/trunk/fs/buffer.c index d654a3b6209e..0f9006714230 100644 --- a/trunk/fs/buffer.c +++ b/trunk/fs/buffer.c @@ -675,6 +675,39 @@ void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode) } EXPORT_SYMBOL(mark_buffer_dirty_inode); +/* + * Mark the page dirty, and set it dirty in the radix tree, and mark the inode + * dirty. + * + * If warn is true, then emit a warning if the page is not uptodate and has + * not been truncated. + */ +static int __set_page_dirty(struct page *page, + struct address_space *mapping, int warn) +{ + if (unlikely(!mapping)) + return !TestSetPageDirty(page); + + if (TestSetPageDirty(page)) + return 0; + + write_lock_irq(&mapping->tree_lock); + if (page->mapping) { /* Race with truncate? */ + WARN_ON_ONCE(warn && !PageUptodate(page)); + + if (mapping_cap_account_dirty(mapping)) { + __inc_zone_page_state(page, NR_FILE_DIRTY); + task_io_account_write(PAGE_CACHE_SIZE); + } + radix_tree_tag_set(&mapping->page_tree, + page_index(page), PAGECACHE_TAG_DIRTY); + } + write_unlock_irq(&mapping->tree_lock); + __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); + + return 1; +} + /* * Add a page to the dirty page list. * @@ -702,7 +735,7 @@ EXPORT_SYMBOL(mark_buffer_dirty_inode); */ int __set_page_dirty_buffers(struct page *page) { - struct address_space * const mapping = page_mapping(page); + struct address_space *mapping = page_mapping(page); if (unlikely(!mapping)) return !TestSetPageDirty(page); @@ -719,21 +752,7 @@ int __set_page_dirty_buffers(struct page *page) } spin_unlock(&mapping->private_lock); - if (TestSetPageDirty(page)) - return 0; - - write_lock_irq(&mapping->tree_lock); - if (page->mapping) { /* Race with truncate? */ - if (mapping_cap_account_dirty(mapping)) { - __inc_zone_page_state(page, NR_FILE_DIRTY); - task_io_account_write(PAGE_CACHE_SIZE); - } - radix_tree_tag_set(&mapping->page_tree, - page_index(page), PAGECACHE_TAG_DIRTY); - } - write_unlock_irq(&mapping->tree_lock); - __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); - return 1; + return __set_page_dirty(page, mapping, 1); } EXPORT_SYMBOL(__set_page_dirty_buffers); @@ -1132,8 +1151,9 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size) */ void fastcall mark_buffer_dirty(struct buffer_head *bh) { + WARN_ON_ONCE(!buffer_uptodate(bh)); if (!buffer_dirty(bh) && !test_set_buffer_dirty(bh)) - __set_page_dirty_nobuffers(bh->b_page); + __set_page_dirty(bh->b_page, page_mapping(bh->b_page), 0); } /* diff --git a/trunk/mm/page-writeback.c b/trunk/mm/page-writeback.c index ea9da3bed3e9..886ea0d5a136 100644 --- a/trunk/mm/page-writeback.c +++ b/trunk/mm/page-writeback.c @@ -824,6 +824,7 @@ int __set_page_dirty_nobuffers(struct page *page) mapping2 = page_mapping(page); if (mapping2) { /* Race with truncate? */ BUG_ON(mapping2 != mapping); + WARN_ON_ONCE(!PagePrivate(page) && !PageUptodate(page)); if (mapping_cap_account_dirty(mapping)) { __inc_zone_page_state(page, NR_FILE_DIRTY); task_io_account_write(PAGE_CACHE_SIZE); diff --git a/trunk/mm/truncate.c b/trunk/mm/truncate.c index 7c994f2d6145..f47e46d1be3b 100644 --- a/trunk/mm/truncate.c +++ b/trunk/mm/truncate.c @@ -100,9 +100,9 @@ truncate_complete_page(struct address_space *mapping, struct page *page) if (PagePrivate(page)) do_invalidatepage(page, 0); + remove_from_page_cache(page); ClearPageUptodate(page); ClearPageMappedToDisk(page); - remove_from_page_cache(page); page_cache_release(page); /* pagecache ref */ }