Skip to content

Commit 11f81be

Browse files
htejunaxboe
authored andcommitted
page_writeback: revive cancel_dirty_page() in a restricted form
cancel_dirty_page() had some issues and b9ea251 ("page_writeback: clean up mess around cancel_dirty_page()") replaced it with account_page_cleaned() which makes the caller responsible for clearing the dirty bit; unfortunately, the planned changes for cgroup writeback support requires synchronization between dirty bit manipulation and stat updates. While we can open-code such synchronization in each account_page_cleaned() callsite, that's gonna be unnecessarily awkward and verbose. This patch revives cancel_dirty_page() but in a more restricted form. All it does is TestClearPageDirty() followed by account_page_cleaned() invocation if the page was dirty. This helper covers all account_page_cleaned() usages except for __delete_from_page_cache() which is a special case anyway and left alone. As this leaves no module user for account_page_cleaned(), EXPORT_SYMBOL() is dropped from it. This patch just revives cancel_dirty_page() as a trivial wrapper to replace equivalent usages and doesn't introduce any functional changes. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> Signed-off-by: Jens Axboe <axboe@fb.com>
1 parent f26cdc8 commit 11f81be

File tree

5 files changed

+25
-15
lines changed

5 files changed

+25
-15
lines changed

drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,7 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
5555
if (PagePrivate(page))
5656
page->mapping->a_ops->invalidatepage(page, 0, PAGE_CACHE_SIZE);
5757

58-
if (TestClearPageDirty(page))
59-
account_page_cleaned(page, mapping);
60-
58+
cancel_dirty_page(page);
6159
ClearPageMappedToDisk(page);
6260
ll_delete_from_page_cache(page);
6361
}

fs/buffer.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3232,8 +3232,8 @@ int try_to_free_buffers(struct page *page)
32323232
* to synchronise against __set_page_dirty_buffers and prevent the
32333233
* dirty bit from being lost.
32343234
*/
3235-
if (ret && TestClearPageDirty(page))
3236-
account_page_cleaned(page, mapping);
3235+
if (ret)
3236+
cancel_dirty_page(page);
32373237
spin_unlock(&mapping->private_lock);
32383238
out:
32393239
if (buffers_to_free) {

include/linux/mm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,7 @@ void account_page_dirtied(struct page *page, struct address_space *mapping);
12151215
void account_page_cleaned(struct page *page, struct address_space *mapping);
12161216
int set_page_dirty(struct page *page);
12171217
int set_page_dirty_lock(struct page *page);
1218+
void cancel_dirty_page(struct page *page);
12181219
int clear_page_dirty_for_io(struct page *page);
12191220

12201221
int get_cmdline(struct task_struct *task, char *buffer, int buflen);

mm/page-writeback.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,12 +2112,6 @@ EXPORT_SYMBOL(account_page_dirtied);
21122112

21132113
/*
21142114
* Helper function for deaccounting dirty page without writeback.
2115-
*
2116-
* Doing this should *normally* only ever be done when a page
2117-
* is truncated, and is not actually mapped anywhere at all. However,
2118-
* fs/buffer.c does this when it notices that somebody has cleaned
2119-
* out all the buffers on a page without actually doing it through
2120-
* the VM. Can you say "ext3 is horribly ugly"? Thought you could.
21212115
*/
21222116
void account_page_cleaned(struct page *page, struct address_space *mapping)
21232117
{
@@ -2127,7 +2121,6 @@ void account_page_cleaned(struct page *page, struct address_space *mapping)
21272121
task_io_account_cancelled_write(PAGE_CACHE_SIZE);
21282122
}
21292123
}
2130-
EXPORT_SYMBOL(account_page_cleaned);
21312124

21322125
/*
21332126
* For address_spaces which do not use buffers. Just tag the page as dirty in
@@ -2265,6 +2258,26 @@ int set_page_dirty_lock(struct page *page)
22652258
}
22662259
EXPORT_SYMBOL(set_page_dirty_lock);
22672260

2261+
/*
2262+
* This cancels just the dirty bit on the kernel page itself, it does NOT
2263+
* actually remove dirty bits on any mmap's that may be around. It also
2264+
* leaves the page tagged dirty, so any sync activity will still find it on
2265+
* the dirty lists, and in particular, clear_page_dirty_for_io() will still
2266+
* look at the dirty bits in the VM.
2267+
*
2268+
* Doing this should *normally* only ever be done when a page is truncated,
2269+
* and is not actually mapped anywhere at all. However, fs/buffer.c does
2270+
* this when it notices that somebody has cleaned out all the buffers on a
2271+
* page without actually doing it through the VM. Can you say "ext3 is
2272+
* horribly ugly"? Thought you could.
2273+
*/
2274+
void cancel_dirty_page(struct page *page)
2275+
{
2276+
if (TestClearPageDirty(page))
2277+
account_page_cleaned(page, page_mapping(page));
2278+
}
2279+
EXPORT_SYMBOL(cancel_dirty_page);
2280+
22682281
/*
22692282
* Clear a page's dirty flag, while caring for dirty memory accounting.
22702283
* Returns true if the page was previously dirty.

mm/truncate.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,7 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
116116
* the VM has canceled the dirty bit (eg ext3 journaling).
117117
* Hence dirty accounting check is placed after invalidation.
118118
*/
119-
if (TestClearPageDirty(page))
120-
account_page_cleaned(page, mapping);
121-
119+
cancel_dirty_page(page);
122120
ClearPageMappedToDisk(page);
123121
delete_from_page_cache(page);
124122
return 0;

0 commit comments

Comments
 (0)