aboutsummaryrefslogtreecommitdiffstats
path: root/mm/truncate.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/truncate.c')
-rw-r--r--mm/truncate.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/mm/truncate.c b/mm/truncate.c
index 9bfb8e853860..ecdfdcc50522 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -51,6 +51,26 @@ static inline void truncate_partial_page(struct page *page, unsigned partial)
51 do_invalidatepage(page, partial); 51 do_invalidatepage(page, partial);
52} 52}
53 53
54void cancel_dirty_page(struct page *page, unsigned int account_size)
55{
56 /* If we're cancelling the page, it had better not be mapped any more */
57 if (page_mapped(page)) {
58 static unsigned int warncount;
59
60 WARN_ON(++warncount < 5);
61 }
62
63 if (TestClearPageDirty(page)) {
64 struct address_space *mapping = page->mapping;
65 if (mapping && mapping_cap_account_dirty(mapping)) {
66 dec_zone_page_state(page, NR_FILE_DIRTY);
67 if (account_size)
68 task_io_account_cancelled_write(account_size);
69 }
70 }
71}
72EXPORT_SYMBOL(cancel_dirty_page);
73
54/* 74/*
55 * If truncate cannot remove the fs-private metadata from the page, the page 75 * If truncate cannot remove the fs-private metadata from the page, the page
56 * becomes anonymous. It will be left on the LRU and may even be mapped into 76 * becomes anonymous. It will be left on the LRU and may even be mapped into
@@ -67,11 +87,11 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
67 if (page->mapping != mapping) 87 if (page->mapping != mapping)
68 return; 88 return;
69 89
90 cancel_dirty_page(page, PAGE_CACHE_SIZE);
91
70 if (PagePrivate(page)) 92 if (PagePrivate(page))
71 do_invalidatepage(page, 0); 93 do_invalidatepage(page, 0);
72 94
73 if (test_clear_page_dirty(page))
74 task_io_account_cancelled_write(PAGE_CACHE_SIZE);
75 ClearPageUptodate(page); 95 ClearPageUptodate(page);
76 ClearPageMappedToDisk(page); 96 ClearPageMappedToDisk(page);
77 remove_from_page_cache(page); 97 remove_from_page_cache(page);
@@ -350,7 +370,6 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
350 for (i = 0; !ret && i < pagevec_count(&pvec); i++) { 370 for (i = 0; !ret && i < pagevec_count(&pvec); i++) {
351 struct page *page = pvec.pages[i]; 371 struct page *page = pvec.pages[i];
352 pgoff_t page_index; 372 pgoff_t page_index;
353 int was_dirty;
354 373
355 lock_page(page); 374 lock_page(page);
356 if (page->mapping != mapping) { 375 if (page->mapping != mapping) {
@@ -386,12 +405,8 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
386 PAGE_CACHE_SIZE, 0); 405 PAGE_CACHE_SIZE, 0);
387 } 406 }
388 } 407 }
389 was_dirty = test_clear_page_dirty(page); 408 if (!invalidate_complete_page2(mapping, page))
390 if (!invalidate_complete_page2(mapping, page)) {
391 if (was_dirty)
392 set_page_dirty(page);
393 ret = -EIO; 409 ret = -EIO;
394 }
395 unlock_page(page); 410 unlock_page(page);
396 } 411 }
397 pagevec_release(&pvec); 412 pagevec_release(&pvec);