On Thu, Nov 08, 2012 at 04:52:33PM -0800, Sonny Rao wrote: > The system uses global_dirtyable_memory() to calculate > number of dirtyable pages/pages that can be allocated > to the page cache. A bug causes an underflow thus making > the page count look like a big unsigned number. This in turn > confuses the dirty writeback throttling to aggressively write > back pages as they become dirty (usually 1 page at a time). > > Fix is to ensure there is no underflow while doing the math.
Good catch, thanks! > Signed-off-by: Sonny Rao <sonny...@chromium.org> > Signed-off-by: Puneet Kumar <puneets...@chromium.org> > --- > v2: added apkm's suggestion to make the highmem calculation better > mm/page-writeback.c | 17 +++++++++++++++-- > 1 files changed, 15 insertions(+), 2 deletions(-) > > diff --git a/mm/page-writeback.c b/mm/page-writeback.c > index 830893b..ce62442 100644 > --- a/mm/page-writeback.c > +++ b/mm/page-writeback.c > @@ -201,6 +201,18 @@ static unsigned long highmem_dirtyable_memory(unsigned > long total) > zone_reclaimable_pages(z) - z->dirty_balance_reserve; > } > /* > + * Unreclaimable memory (kernel memory or anonymous memory > + * without swap) can bring down the dirtyable pages below > + * the zone's dirty balance reserve and the above calculation > + * will underflow. However we still want to add in nodes > + * which are below threshold (negative values) to get a more > + * accurate calculation but make sure that the total never > + * underflows. > + */ > + if ((long)x < 0) > + x = 0; > + > + /* > * Make sure that the number of highmem pages is never larger > * than the number of the total dirtyable memory. This can only > * occur in very strange VM situations but we want to make sure > @@ -222,8 +234,9 @@ static unsigned long global_dirtyable_memory(void) > { > unsigned long x; > > - x = global_page_state(NR_FREE_PAGES) + global_reclaimable_pages() - > - dirty_balance_reserve; > + x = global_page_state(NR_FREE_PAGES) + global_reclaimable_pages(); > + if (x >= dirty_balance_reserve) > + x -= dirty_balance_reserve; That can be converted to "if ((long)x < 0) x = 0;", too. And I suspect zone_dirtyable_memory() needs similar fix, too. Thanks, Fengguang -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/