[PATCH 36/45] writeback: sync livelock - curb dirty speed for inodes to be synced

From: Wu Fengguang
Date: Wed Oct 07 2009 - 04:08:51 EST


The inodes to be synced will be dirty throttled regardless of the dirty
threshold. This stops sync() livelock by some fast dirtier.

CC: Jan Kara <jack@xxxxxxx>
Signed-off-by: Wu Fengguang <fengguang.wu@xxxxxxxxx>
---
fs/fs-writeback.c | 4 ++++
include/linux/backing-dev.h | 1 +
mm/page-writeback.c | 13 +++++++++++++
3 files changed, 18 insertions(+)

--- linux.orig/mm/page-writeback.c 2009-10-07 10:47:09.000000000 +0800
+++ linux/mm/page-writeback.c 2009-10-07 14:32:43.000000000 +0800
@@ -478,6 +478,18 @@ static void balance_dirty_pages(struct a
global_dirty_thresh(&background_thresh, &dirty_thresh);

/*
+ * If sync() is in progress, curb the to-be-synced inodes regardless
+ * of dirty limits, so that a fast dirtier won't livelock the sync.
+ */
+ if (unlikely(bdi->sync_time &&
+ S_ISREG(mapping->host->i_mode) &&
+ time_after_eq(bdi->sync_time,
+ mapping->host->dirtied_when))) {
+ write_chunk *= 2;
+ goto throttle;
+ }
+
+ /*
* Throttle it only when the background writeback cannot
* catch-up. This skips the ramp up phase of bdi limits.
*/
@@ -510,6 +522,7 @@ static void balance_dirty_pages(struct a
if (!dirty_exceeded)
goto out;

+throttle:
if (!bdi->dirty_exceeded)
bdi->dirty_exceeded = 1;

--- linux.orig/fs/fs-writeback.c 2009-10-07 10:47:09.000000000 +0800
+++ linux/fs/fs-writeback.c 2009-10-07 14:31:47.000000000 +0800
@@ -796,6 +796,7 @@ static long wb_writeback(struct bdi_writ
if (wbc.for_sync) {
wbc.older_than_this = &oldest_jif;
oldest_jif = jiffies;
+ wbc.bdi->sync_time = oldest_jif | 1;
}
if (wbc.for_kupdate || wbc.for_background) {
wbc.older_than_this = &oldest_jif;
@@ -873,6 +874,9 @@ static long wb_writeback(struct bdi_writ
spin_unlock(&inode_lock);
}

+ if (args->for_sync)
+ wb->bdi->sync_time = 0;
+
if (args->for_background)
while (bdi_writeback_wakeup(wb->bdi))
; /* unthrottle all tasks */
--- linux.orig/include/linux/backing-dev.h 2009-10-07 10:47:09.000000000 +0800
+++ linux/include/linux/backing-dev.h 2009-10-07 14:31:53.000000000 +0800
@@ -89,6 +89,7 @@ struct backing_dev_info {
* to prevent livelocking the sync works
*/
unsigned int sync_works;
+ unsigned long sync_time;

struct list_head work_list;



--
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/