On Wed, 16 Feb 2011, Minchan Kim wrote: > > Index: linux/mm/page_alloc.c > > =================================================================== > > --- linux.orig/mm/page_alloc.c Â2011-02-15 16:28:36.165921713 -0600 > > +++ linux/mm/page_alloc.c    2011-02-15 16:29:43.085502487 -0600 > > @@ -592,10 +592,24 @@ static void free_pcppages_bulk(struct zo > >    Âint batch_free = 0; > >    Âint to_free = count; > > > > +    /* > > +    Â* Quick scan of zones. If all are empty, there is nothing to do. > > +    Â*/ > > +    for (migratetype = 0; migratetype < MIGRATE_PCPTYPES; migratetype++) { > > +        struct list_head *list; > > + > > +        list = &pcp->lists[migratetype]; > > +        if (!list_empty(list)) > > +            break; > > +    } > > +    if (migratetype == MIGRATE_PCPTYPES) > > +        return; > > + > >    Âspin_lock(&zone->lock); > >    Âzone->all_unreclaimable = 0; > >    Âzone->pages_scanned = 0; > > > > +    migratetype = 0; > >    Âwhile (to_free) { > >        Âstruct page *page; > >        Âstruct list_head *list; > > It does make sense to me. > Although new code looks to be rather costly in small box, anyway we > use the same logic in while loop so cache would be hot. so cost would > be little. > I was going to mention the implications for small machines as well, this doesn't look good for callers that know free_pcppages_bulk() will do something. > But how about this? This one never affect fast-critical path. > > diff --git a/mm/page_alloc.c b/mm/page_alloc.c > index ff7e158..2dfb61a 100644 > --- a/mm/page_alloc.c > +++ b/mm/page_alloc.c > @@ -1095,8 +1095,10 @@ static void drain_pages(unsigned int cpu) > pset = per_cpu_ptr(zone->pageset, cpu); > > pcp = &pset->pcp; > - free_pcppages_bulk(zone, pcp->count, pcp); > - pcp->count = 0; > + if (pcp->count > 0) { > + free_pcppages_bulk(zone, pcp->count, pcp); > + pcp->count = 0; > + } > local_irq_restore(flags); > } > } Right, this is 2ff754fa upstream. I'm wondering if Jack still sees the same problem since 2.6.38-rc3.