diff options
Diffstat (limited to 'mm/truncate.c')
-rw-r--r-- | mm/truncate.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/mm/truncate.c b/mm/truncate.c index 9bfb8e853860..bf9e2965d666 100644 --- a/mm/truncate.c +++ b/mm/truncate.c | |||
@@ -51,6 +51,20 @@ 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 | ||
54 | void 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) && account_size) | ||
64 | task_io_account_cancelled_write(account_size); | ||
65 | } | ||
66 | |||
67 | |||
54 | /* | 68 | /* |
55 | * If truncate cannot remove the fs-private metadata from the page, the page | 69 | * 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 | 70 | * 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) | |||
70 | if (PagePrivate(page)) | 84 | if (PagePrivate(page)) |
71 | do_invalidatepage(page, 0); | 85 | do_invalidatepage(page, 0); |
72 | 86 | ||
73 | if (test_clear_page_dirty(page)) | 87 | cancel_dirty_page(page, PAGE_CACHE_SIZE); |
74 | task_io_account_cancelled_write(PAGE_CACHE_SIZE); | 88 | |
75 | ClearPageUptodate(page); | 89 | ClearPageUptodate(page); |
76 | ClearPageMappedToDisk(page); | 90 | ClearPageMappedToDisk(page); |
77 | remove_from_page_cache(page); | 91 | remove_from_page_cache(page); |
@@ -350,7 +364,6 @@ int invalidate_inode_pages2_range(struct address_space *mapping, | |||
350 | for (i = 0; !ret && i < pagevec_count(&pvec); i++) { | 364 | for (i = 0; !ret && i < pagevec_count(&pvec); i++) { |
351 | struct page *page = pvec.pages[i]; | 365 | struct page *page = pvec.pages[i]; |
352 | pgoff_t page_index; | 366 | pgoff_t page_index; |
353 | int was_dirty; | ||
354 | 367 | ||
355 | lock_page(page); | 368 | lock_page(page); |
356 | if (page->mapping != mapping) { | 369 | if (page->mapping != mapping) { |
@@ -386,12 +399,8 @@ int invalidate_inode_pages2_range(struct address_space *mapping, | |||
386 | PAGE_CACHE_SIZE, 0); | 399 | PAGE_CACHE_SIZE, 0); |
387 | } | 400 | } |
388 | } | 401 | } |
389 | was_dirty = test_clear_page_dirty(page); | 402 | 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; | 403 | ret = -EIO; |
394 | } | ||
395 | unlock_page(page); | 404 | unlock_page(page); |
396 | } | 405 | } |
397 | pagevec_release(&pvec); | 406 | pagevec_release(&pvec); |