Messages in this thread | | | Subject | Re: [PATCH 1/2] mm/compaction: fix invalid free_pfn and compact_cached_free_pfn | From | Vlastimil Babka <> | Date | Mon, 14 Dec 2015 11:07:02 +0100 |
| |
On 12/14/2015 06:02 AM, Joonsoo Kim wrote: > free_pfn and compact_cached_free_pfn are the pointer that remember > restart position of freepage scanner. When they are reset or invalid, > we set them to zone_end_pfn because freepage scanner works in reverse > direction. But, because zone range is defined as [zone_start_pfn, > zone_end_pfn), zone_end_pfn is invalid to access. Therefore, we should > not store it to free_pfn and compact_cached_free_pfn. Instead, we need > to store zone_end_pfn - 1 to them. There is one more thing we should > consider. Freepage scanner scan reversely by pageblock unit. If free_pfn > and compact_cached_free_pfn are set to middle of pageblock, it regards > that sitiation as that it already scans front part of pageblock so we > lose opportunity to scan there. To fix-up, this patch do round_down() > to guarantee that reset position will be pageblock aligned. > > Note that thanks to the current pageblock_pfn_to_page() implementation, > actual access to zone_end_pfn doesn't happen until now. But, following > patch will change pageblock_pfn_to_page() so this patch is needed > from now on. > > Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Note that until now in compaction we've used basically an open-coded round_down(), and ALIGN() for rounding up. You introduce a first use of round_down(), and it would be nice to standardize on round_down() and round_up() everywhere. I think it's more obvious than open-coding and ALIGN() (which doesn't tell the reader if it's aligning up or down). Hopefully they really do the same thing and there are no caveats...
> --- > mm/compaction.c | 9 +++++---- > 1 file changed, 5 insertions(+), 4 deletions(-) > > diff --git a/mm/compaction.c b/mm/compaction.c > index 585de54..56fa321 100644 > --- a/mm/compaction.c > +++ b/mm/compaction.c > @@ -200,7 +200,8 @@ static void reset_cached_positions(struct zone *zone) > { > zone->compact_cached_migrate_pfn[0] = zone->zone_start_pfn; > zone->compact_cached_migrate_pfn[1] = zone->zone_start_pfn; > - zone->compact_cached_free_pfn = zone_end_pfn(zone); > + zone->compact_cached_free_pfn = > + round_down(zone_end_pfn(zone) - 1, pageblock_nr_pages); > } > > /* > @@ -1371,11 +1372,11 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) > */ > cc->migrate_pfn = zone->compact_cached_migrate_pfn[sync]; > cc->free_pfn = zone->compact_cached_free_pfn; > - if (cc->free_pfn < start_pfn || cc->free_pfn > end_pfn) { > - cc->free_pfn = end_pfn & ~(pageblock_nr_pages-1); > + if (cc->free_pfn < start_pfn || cc->free_pfn >= end_pfn) { > + cc->free_pfn = round_down(end_pfn - 1, pageblock_nr_pages); > zone->compact_cached_free_pfn = cc->free_pfn; > } > - if (cc->migrate_pfn < start_pfn || cc->migrate_pfn > end_pfn) { > + if (cc->migrate_pfn < start_pfn || cc->migrate_pfn >= end_pfn) { > cc->migrate_pfn = start_pfn; > zone->compact_cached_migrate_pfn[0] = cc->migrate_pfn; > zone->compact_cached_migrate_pfn[1] = cc->migrate_pfn; >
| |