aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoonsoo Kim <iamjoonsoo.kim@lge.com>2015-04-14 18:45:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-14 19:49:01 -0400
commit4eb7dce62007113f1a2778213980fd6d8034ef5e (patch)
tree1e12d962e5417af66e5c88ee7c23d007dfe078c9
parentdc67647b78b92d9497f01fab95ac6764ed886b40 (diff)
mm/page_alloc: factor out fallback freepage checking
This is preparation step to use page allocator's anti fragmentation logic in compaction. This patch just separates fallback freepage checking part from fallback freepage management part. Therefore, there is no functional change. Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com> Acked-by: Vlastimil Babka <vbabka@suse.cz> Cc: Mel Gorman <mgorman@suse.de> Cc: David Rientjes <rientjes@google.com> Cc: Rik van Riel <riel@redhat.com> Cc: Zhang Yanfei <zhangyanfei@cn.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/page_alloc.c143
1 files changed, 91 insertions, 52 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 9ca626756927..31aa943365d8 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1145,14 +1145,40 @@ static void change_pageblock_range(struct page *pageblock_page,
1145 * as fragmentation caused by those allocations polluting movable pageblocks 1145 * as fragmentation caused by those allocations polluting movable pageblocks
1146 * is worse than movable allocations stealing from unmovable and reclaimable 1146 * is worse than movable allocations stealing from unmovable and reclaimable
1147 * pageblocks. 1147 * pageblocks.
1148 *
1149 * If we claim more than half of the pageblock, change pageblock's migratetype
1150 * as well.
1151 */ 1148 */
1152static void try_to_steal_freepages(struct zone *zone, struct page *page, 1149static bool can_steal_fallback(unsigned int order, int start_mt)
1153 int start_type, int fallback_type) 1150{
1151 /*
1152 * Leaving this order check is intended, although there is
1153 * relaxed order check in next check. The reason is that
1154 * we can actually steal whole pageblock if this condition met,
1155 * but, below check doesn't guarantee it and that is just heuristic
1156 * so could be changed anytime.
1157 */
1158 if (order >= pageblock_order)
1159 return true;
1160
1161 if (order >= pageblock_order / 2 ||
1162 start_mt == MIGRATE_RECLAIMABLE ||
1163 start_mt == MIGRATE_UNMOVABLE ||
1164 page_group_by_mobility_disabled)
1165 return true;
1166
1167 return false;
1168}
1169
1170/*
1171 * This function implements actual steal behaviour. If order is large enough,
1172 * we can steal whole pageblock. If not, we first move freepages in this
1173 * pageblock and check whether half of pages are moved or not. If half of
1174 * pages are moved, we can change migratetype of pageblock and permanently
1175 * use it's pages as requested migratetype in the future.
1176 */
1177static void steal_suitable_fallback(struct zone *zone, struct page *page,
1178 int start_type)
1154{ 1179{
1155 int current_order = page_order(page); 1180 int current_order = page_order(page);
1181 int pages;
1156 1182
1157 /* Take ownership for orders >= pageblock_order */ 1183 /* Take ownership for orders >= pageblock_order */
1158 if (current_order >= pageblock_order) { 1184 if (current_order >= pageblock_order) {
@@ -1160,19 +1186,40 @@ static void try_to_steal_freepages(struct zone *zone, struct page *page,
1160 return; 1186 return;
1161 } 1187 }
1162 1188
1163 if (current_order >= pageblock_order / 2 || 1189 pages = move_freepages_block(zone, page, start_type);
1164 start_type == MIGRATE_RECLAIMABLE || 1190
1165 start_type == MIGRATE_UNMOVABLE || 1191 /* Claim the whole block if over half of it is free */
1166 page_group_by_mobility_disabled) { 1192 if (pages >= (1 << (pageblock_order-1)) ||
1167 int pages; 1193 page_group_by_mobility_disabled)
1194 set_pageblock_migratetype(page, start_type);
1195}
1196
1197/* Check whether there is a suitable fallback freepage with requested order. */
1198static int find_suitable_fallback(struct free_area *area, unsigned int order,
1199 int migratetype, bool *can_steal)
1200{
1201 int i;
1202 int fallback_mt;
1203
1204 if (area->nr_free == 0)
1205 return -1;
1206
1207 *can_steal = false;
1208 for (i = 0;; i++) {
1209 fallback_mt = fallbacks[migratetype][i];
1210 if (fallback_mt == MIGRATE_RESERVE)
1211 break;
1212
1213 if (list_empty(&area->free_list[fallback_mt]))
1214 continue;
1168 1215
1169 pages = move_freepages_block(zone, page, start_type); 1216 if (can_steal_fallback(order, migratetype))
1217 *can_steal = true;
1170 1218
1171 /* Claim the whole block if over half of it is free */ 1219 return fallback_mt;
1172 if (pages >= (1 << (pageblock_order-1)) ||
1173 page_group_by_mobility_disabled)
1174 set_pageblock_migratetype(page, start_type);
1175 } 1220 }
1221
1222 return -1;
1176} 1223}
1177 1224
1178/* Remove an element from the buddy allocator from the fallback list */ 1225/* Remove an element from the buddy allocator from the fallback list */
@@ -1182,53 +1229,45 @@ __rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype)
1182 struct free_area *area; 1229 struct free_area *area;
1183 unsigned int current_order; 1230 unsigned int current_order;
1184 struct page *page; 1231 struct page *page;
1232 int fallback_mt;
1233 bool can_steal;
1185 1234
1186 /* Find the largest possible block of pages in the other list */ 1235 /* Find the largest possible block of pages in the other list */
1187 for (current_order = MAX_ORDER-1; 1236 for (current_order = MAX_ORDER-1;
1188 current_order >= order && current_order <= MAX_ORDER-1; 1237 current_order >= order && current_order <= MAX_ORDER-1;
1189 --current_order) { 1238 --current_order) {
1190 int i; 1239 area = &(zone->free_area[current_order]);
1191 for (i = 0;; i++) { 1240 fallback_mt = find_suitable_fallback(area, current_order,
1192 int migratetype = fallbacks[start_migratetype][i]; 1241 start_migratetype, &can_steal);
1193 int buddy_type = start_migratetype; 1242 if (fallback_mt == -1)
1194 1243 continue;
1195 /* MIGRATE_RESERVE handled later if necessary */
1196 if (migratetype == MIGRATE_RESERVE)
1197 break;
1198
1199 area = &(zone->free_area[current_order]);
1200 if (list_empty(&area->free_list[migratetype]))
1201 continue;
1202
1203 page = list_entry(area->free_list[migratetype].next,
1204 struct page, lru);
1205 area->nr_free--;
1206
1207 try_to_steal_freepages(zone, page, start_migratetype,
1208 migratetype);
1209 1244
1210 /* Remove the page from the freelists */ 1245 page = list_entry(area->free_list[fallback_mt].next,
1211 list_del(&page->lru); 1246 struct page, lru);
1212 rmv_page_order(page); 1247 if (can_steal)
1248 steal_suitable_fallback(zone, page, start_migratetype);
1213 1249
1214 expand(zone, page, order, current_order, area, 1250 /* Remove the page from the freelists */
1215 buddy_type); 1251 area->nr_free--;
1252 list_del(&page->lru);
1253 rmv_page_order(page);
1216 1254
1217 /* 1255 expand(zone, page, order, current_order, area,
1218 * The freepage_migratetype may differ from pageblock's 1256 start_migratetype);
1219 * migratetype depending on the decisions in 1257 /*
1220 * try_to_steal_freepages(). This is OK as long as it 1258 * The freepage_migratetype may differ from pageblock's
1221 * does not differ for MIGRATE_CMA pageblocks. For CMA 1259 * migratetype depending on the decisions in
1222 * we need to make sure unallocated pages flushed from 1260 * try_to_steal_freepages(). This is OK as long as it
1223 * pcp lists are returned to the correct freelist. 1261 * does not differ for MIGRATE_CMA pageblocks. For CMA
1224 */ 1262 * we need to make sure unallocated pages flushed from
1225 set_freepage_migratetype(page, buddy_type); 1263 * pcp lists are returned to the correct freelist.
1264 */
1265 set_freepage_migratetype(page, start_migratetype);
1226 1266
1227 trace_mm_page_alloc_extfrag(page, order, current_order, 1267 trace_mm_page_alloc_extfrag(page, order, current_order,
1228 start_migratetype, migratetype); 1268 start_migratetype, fallback_mt);
1229 1269
1230 return page; 1270 return page;
1231 }
1232 } 1271 }
1233 1272
1234 return NULL; 1273 return NULL;