mm: use aligned zone start for pfn_to_bitidx calculation
authorLaura Abbott <lauraa@codeaurora.org>
Fri, 11 Jan 2013 22:31:51 +0000 (14:31 -0800)
committerBen Hutchings <ben@decadent.org.uk>
Wed, 6 Feb 2013 04:33:31 +0000 (04:33 +0000)
commit458b03804988d061567a1a0f0d17c86967dfdc21
tree5406bc8a55c7ab1dd6f0b0ebaa24a6646e7df4f4
parent2c7ff1aa06ba37b36e07d4b47c55d7431ec9dff9
mm: use aligned zone start for pfn_to_bitidx calculation

commit c060f943d0929f3e429c5d9522290584f6281d6e upstream.

The current calculation in pfn_to_bitidx assumes that (pfn -
zone->zone_start_pfn) >> pageblock_order will return the same bit for
all pfn in a pageblock.  If zone_start_pfn is not aligned to
pageblock_nr_pages, this may not always be correct.

Consider the following with pageblock order = 10, zone start 2MB:

  pfn     | pfn - zone start | (pfn - zone start) >> page block order
  ----------------------------------------------------------------
  0x26000 | 0x25e00    |  0x97
  0x26100 | 0x25f00    |  0x97
  0x26200 | 0x26000    |  0x98
  0x26300 | 0x26100    |  0x98

This means that calling {get,set}_pageblock_migratetype on a single page
will not set the migratetype for the full block.  Fix this by rounding
down zone_start_pfn when doing the bitidx calculation.

For our use case, the effects of this bug were mostly tied to the fact
that CMA allocations would either take a long time or fail to happen.
Depending on the driver using CMA, this could result in anything from
visual glitches to application failures.

Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
Acked-by: Mel Gorman <mgorman@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
mm/page_alloc.c