[PATCH 5/5] page_writeback: put account_page_redirty() afterset_page_dirty()

From: Konstantin Khlebnikov
Date: Mon Jul 08 2013 - 05:52:29 EST


Function account_page_redirty() fixes dirty pages counter for redieried pages.
This patch prevents temporary underflows of dirty pages counters on zone/bdi
and current->nr_dirtied. This puts decrement after increment.

__set_page_dirty_nobuffers() in redirty_page_for_writeback() always returns true
because this page is locked and all ptes are write-protected by previously
called clear_page_dirty_for_io(). Thus nobody can mark it dirty except current
task. This prevents multy-threaded scenarios of taks->nr_dirtied underflows.

Signed-off-by: Konstantin Khlebnikov <khlebnikov@xxxxxxxxxx>
---
fs/btrfs/extent_io.c | 2 +-
mm/page-writeback.c | 7 ++++++-
2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 6bca947..d17fb9b 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1311,8 +1311,8 @@ int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end)
while (index <= end_index) {
page = find_get_page(inode->i_mapping, index);
BUG_ON(!page); /* Pages should be in the extent_io_tree */
- account_page_redirty(page);
__set_page_dirty_nobuffers(page);
+ account_page_redirty(page);
page_cache_release(page);
index++;
}
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 4514ad7..a599f38 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2061,6 +2061,8 @@ EXPORT_SYMBOL(__set_page_dirty_nobuffers);
* counters (NR_WRITTEN, BDI_WRITTEN) in long term. The mismatches will lead to
* systematic errors in balanced_dirty_ratelimit and the dirty pages position
* control.
+ *
+ * Must be called after marking page dirty.
*/
void account_page_redirty(struct page *page)
{
@@ -2080,9 +2082,12 @@ EXPORT_SYMBOL(account_page_redirty);
*/
int redirty_page_for_writepage(struct writeback_control *wbc, struct page *page)
{
+ int ret;
+
wbc->pages_skipped++;
+ ret = __set_page_dirty_nobuffers(page);
account_page_redirty(page);
- return __set_page_dirty_nobuffers(page);
+ return ret;
}
EXPORT_SYMBOL(redirty_page_for_writepage);


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/