Commit 96552156 authored by Andrew Morton's avatar Andrew Morton Committed by James Bottomley

[PATCH] fix possible latency in balance_dirty_pages()

Tasks which throttle in balance_dirty_pages() will loop until the amount of
dirty memory falls below the configured dirty_ratio.

This exposes the possibility that one task could be stuck in there for
arbitrary periods of time due to page dirtying activity by other tasks.

The patch changes the logic so that tasks will break out of the loop if they
have written enough pages, regardless of the current dirty memory limits.

Here "enough" pages is 1.5x the number of pages which they just dirtied.

If the amount of dirty memory in the machine happens to still exceed
dirty_ratio (say, due to MAP_SHARED activity) then the task will again
throttle after dirtying a single page.  But there is now an upper limit on
the time for which a single task will be captured in balance_dirty_pages().
parent 9a64905a
...@@ -139,6 +139,9 @@ void balance_dirty_pages(struct address_space *mapping) ...@@ -139,6 +139,9 @@ void balance_dirty_pages(struct address_space *mapping)
struct page_state ps; struct page_state ps;
long background_thresh; long background_thresh;
long dirty_thresh; long dirty_thresh;
unsigned long pages_written = 0;
unsigned long write_chunk = sync_writeback_pages();
struct backing_dev_info *bdi = mapping->backing_dev_info; struct backing_dev_info *bdi = mapping->backing_dev_info;
get_dirty_limits(&ps, &background_thresh, &dirty_thresh); get_dirty_limits(&ps, &background_thresh, &dirty_thresh);
...@@ -147,7 +150,7 @@ void balance_dirty_pages(struct address_space *mapping) ...@@ -147,7 +150,7 @@ void balance_dirty_pages(struct address_space *mapping)
.bdi = bdi, .bdi = bdi,
.sync_mode = WB_SYNC_NONE, .sync_mode = WB_SYNC_NONE,
.older_than_this = NULL, .older_than_this = NULL,
.nr_to_write = sync_writeback_pages(), .nr_to_write = write_chunk,
}; };
dirty_exceeded = 1; dirty_exceeded = 1;
...@@ -158,9 +161,13 @@ void balance_dirty_pages(struct address_space *mapping) ...@@ -158,9 +161,13 @@ void balance_dirty_pages(struct address_space *mapping)
get_dirty_limits(&ps, &background_thresh, &dirty_thresh); get_dirty_limits(&ps, &background_thresh, &dirty_thresh);
if (ps.nr_dirty + ps.nr_writeback <= dirty_thresh) if (ps.nr_dirty + ps.nr_writeback <= dirty_thresh)
break; break;
pages_written += write_chunk - wbc.nr_to_write;
if (pages_written >= write_chunk)
break; /* We've done our duty */
blk_congestion_wait(WRITE, HZ/10); blk_congestion_wait(WRITE, HZ/10);
} }
if (ps.nr_dirty + ps.nr_writeback <= dirty_thresh)
dirty_exceeded = 0; dirty_exceeded = 0;
if (!writeback_in_progress(bdi) && ps.nr_dirty > background_thresh) if (!writeback_in_progress(bdi) && ps.nr_dirty > background_thresh)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment