|
@@ -816,6 +816,7 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
|
|
|
static int compact_finished(struct zone *zone,
|
|
|
struct compact_control *cc)
|
|
|
{
|
|
|
+ unsigned int order;
|
|
|
unsigned long watermark;
|
|
|
|
|
|
if (fatal_signal_pending(current))
|
|
@@ -850,22 +851,16 @@ static int compact_finished(struct zone *zone,
|
|
|
return COMPACT_CONTINUE;
|
|
|
|
|
|
/* Direct compactor: Is a suitable page free? */
|
|
|
- if (cc->page) {
|
|
|
- /* Was a suitable page captured? */
|
|
|
- if (*cc->page)
|
|
|
+ for (order = cc->order; order < MAX_ORDER; order++) {
|
|
|
+ struct free_area *area = &zone->free_area[order];
|
|
|
+
|
|
|
+ /* Job done if page is free of the right migratetype */
|
|
|
+ if (!list_empty(&area->free_list[cc->migratetype]))
|
|
|
+ return COMPACT_PARTIAL;
|
|
|
+
|
|
|
+ /* Job done if allocation would set block type */
|
|
|
+ if (cc->order >= pageblock_order && area->nr_free)
|
|
|
return COMPACT_PARTIAL;
|
|
|
- } else {
|
|
|
- unsigned int order;
|
|
|
- for (order = cc->order; order < MAX_ORDER; order++) {
|
|
|
- struct free_area *area = &zone->free_area[cc->order];
|
|
|
- /* Job done if page is free of the right migratetype */
|
|
|
- if (!list_empty(&area->free_list[cc->migratetype]))
|
|
|
- return COMPACT_PARTIAL;
|
|
|
-
|
|
|
- /* Job done if allocation would set block type */
|
|
|
- if (cc->order >= pageblock_order && area->nr_free)
|
|
|
- return COMPACT_PARTIAL;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
return COMPACT_CONTINUE;
|
|
@@ -921,60 +916,6 @@ unsigned long compaction_suitable(struct zone *zone, int order)
|
|
|
return COMPACT_CONTINUE;
|
|
|
}
|
|
|
|
|
|
-static void compact_capture_page(struct compact_control *cc)
|
|
|
-{
|
|
|
- unsigned long flags;
|
|
|
- int mtype, mtype_low, mtype_high;
|
|
|
-
|
|
|
- if (!cc->page || *cc->page)
|
|
|
- return;
|
|
|
-
|
|
|
- /*
|
|
|
- * For MIGRATE_MOVABLE allocations we capture a suitable page ASAP
|
|
|
- * regardless of the migratetype of the freelist is is captured from.
|
|
|
- * This is fine because the order for a high-order MIGRATE_MOVABLE
|
|
|
- * allocation is typically at least a pageblock size and overall
|
|
|
- * fragmentation is not impaired. Other allocation types must
|
|
|
- * capture pages from their own migratelist because otherwise they
|
|
|
- * could pollute other pageblocks like MIGRATE_MOVABLE with
|
|
|
- * difficult to move pages and making fragmentation worse overall.
|
|
|
- */
|
|
|
- if (cc->migratetype == MIGRATE_MOVABLE) {
|
|
|
- mtype_low = 0;
|
|
|
- mtype_high = MIGRATE_PCPTYPES;
|
|
|
- } else {
|
|
|
- mtype_low = cc->migratetype;
|
|
|
- mtype_high = cc->migratetype + 1;
|
|
|
- }
|
|
|
-
|
|
|
- /* Speculatively examine the free lists without zone lock */
|
|
|
- for (mtype = mtype_low; mtype < mtype_high; mtype++) {
|
|
|
- int order;
|
|
|
- for (order = cc->order; order < MAX_ORDER; order++) {
|
|
|
- struct page *page;
|
|
|
- struct free_area *area;
|
|
|
- area = &(cc->zone->free_area[order]);
|
|
|
- if (list_empty(&area->free_list[mtype]))
|
|
|
- continue;
|
|
|
-
|
|
|
- /* Take the lock and attempt capture of the page */
|
|
|
- if (!compact_trylock_irqsave(&cc->zone->lock, &flags, cc))
|
|
|
- return;
|
|
|
- if (!list_empty(&area->free_list[mtype])) {
|
|
|
- page = list_entry(area->free_list[mtype].next,
|
|
|
- struct page, lru);
|
|
|
- if (capture_free_page(page, cc->order, mtype)) {
|
|
|
- spin_unlock_irqrestore(&cc->zone->lock,
|
|
|
- flags);
|
|
|
- *cc->page = page;
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- spin_unlock_irqrestore(&cc->zone->lock, flags);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
static int compact_zone(struct zone *zone, struct compact_control *cc)
|
|
|
{
|
|
|
int ret;
|
|
@@ -1054,9 +995,6 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
|
|
|
goto out;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- /* Capture a page now if it is a suitable size */
|
|
|
- compact_capture_page(cc);
|
|
|
}
|
|
|
|
|
|
out:
|
|
@@ -1069,8 +1007,7 @@ out:
|
|
|
|
|
|
static unsigned long compact_zone_order(struct zone *zone,
|
|
|
int order, gfp_t gfp_mask,
|
|
|
- bool sync, bool *contended,
|
|
|
- struct page **page)
|
|
|
+ bool sync, bool *contended)
|
|
|
{
|
|
|
unsigned long ret;
|
|
|
struct compact_control cc = {
|
|
@@ -1080,7 +1017,6 @@ static unsigned long compact_zone_order(struct zone *zone,
|
|
|
.migratetype = allocflags_to_migratetype(gfp_mask),
|
|
|
.zone = zone,
|
|
|
.sync = sync,
|
|
|
- .page = page,
|
|
|
};
|
|
|
INIT_LIST_HEAD(&cc.freepages);
|
|
|
INIT_LIST_HEAD(&cc.migratepages);
|
|
@@ -1110,7 +1046,7 @@ int sysctl_extfrag_threshold = 500;
|
|
|
*/
|
|
|
unsigned long try_to_compact_pages(struct zonelist *zonelist,
|
|
|
int order, gfp_t gfp_mask, nodemask_t *nodemask,
|
|
|
- bool sync, bool *contended, struct page **page)
|
|
|
+ bool sync, bool *contended)
|
|
|
{
|
|
|
enum zone_type high_zoneidx = gfp_zone(gfp_mask);
|
|
|
int may_enter_fs = gfp_mask & __GFP_FS;
|
|
@@ -1136,7 +1072,7 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist,
|
|
|
int status;
|
|
|
|
|
|
status = compact_zone_order(zone, order, gfp_mask, sync,
|
|
|
- contended, page);
|
|
|
+ contended);
|
|
|
rc = max(status, rc);
|
|
|
|
|
|
/* If a normal allocation would succeed, stop compacting */
|
|
@@ -1192,7 +1128,6 @@ int compact_pgdat(pg_data_t *pgdat, int order)
|
|
|
struct compact_control cc = {
|
|
|
.order = order,
|
|
|
.sync = false,
|
|
|
- .page = NULL,
|
|
|
};
|
|
|
|
|
|
return __compact_pgdat(pgdat, &cc);
|
|
@@ -1203,7 +1138,6 @@ static int compact_node(int nid)
|
|
|
struct compact_control cc = {
|
|
|
.order = -1,
|
|
|
.sync = true,
|
|
|
- .page = NULL,
|
|
|
};
|
|
|
|
|
|
return __compact_pgdat(NODE_DATA(nid), &cc);
|