aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/page_alloc.c')
-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;