Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1410275 > unrolled thread
| Started by | Vlastimil Babka <vbabka@suse.cz> |
|---|---|
| First post | 2016-05-31 15:10 +0200 |
| Last post | 2016-05-31 15:20 +0200 |
| Articles | 11 on this page of 31 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH v2 00/18] make direct compaction more deterministic Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:10 +0200
[PATCH v2 02/18] mm, page_alloc: set alloc_flags only once in slowpath Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:10 +0200
[PATCH v2 15/18] mm, compaction: use proper alloc_flags in __compaction_suitable() Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:10 +0200
[PATCH v2 14/18] mm, compaction: create compact_gap wrapper Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:10 +0200
Re: [PATCH v2 14/18] mm, compaction: create compact_gap wrapper Michal Hocko <mhocko@kernel.org> - 2016-06-01 16:10 +0200
[PATCH v2 17/18] mm, vmscan: make compaction_ready() more accurate and readable Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:10 +0200
Re: [PATCH v2 17/18] mm, vmscan: make compaction_ready() more accurate and readable Michal Hocko <mhocko@kernel.org> - 2016-06-01 16:20 +0200
[PATCH v2 04/18] mm, page_alloc: restructure direct compaction handling in slowpath Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:20 +0200
[PATCH v2 03/18] mm, page_alloc: don't retry initial attempt in slowpath Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:20 +0200
Re: [PATCH v2 03/18] mm, page_alloc: don't retry initial attempt in slowpath Michal Hocko <mhocko@kernel.org> - 2016-06-01 15:30 +0200
Re: [PATCH v2 03/18] mm, page_alloc: don't retry initial attempt in slowpath Vlastimil Babka <vbabka@suse.cz> - 2016-06-01 17:00 +0200
[PATCH v2 05/18] mm, page_alloc: make THP-specific decisions more generic Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:20 +0200
[PATCH v2 13/18] mm, compaction: use correct watermark when checking allocation success Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:20 +0200
Re: [PATCH v2 13/18] mm, compaction: use correct watermark when checking allocation success Michal Hocko <mhocko@kernel.org> - 2016-06-01 16:00 +0200
[PATCH v2 06/18] mm, thp: remove __GFP_NORETRY from khugepaged and madvised allocations Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:20 +0200
Re: [PATCH v2 06/18] mm, thp: remove __GFP_NORETRY from khugepaged and madvised allocations Michal Hocko <mhocko@kernel.org> - 2016-06-01 15:40 +0200
[PATCH v2 12/18] mm, compaction: more reliably increase direct compaction priority Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:20 +0200
Re: [PATCH v2 12/18] mm, compaction: more reliably increase direct compaction priority Michal Hocko <mhocko@kernel.org> - 2016-06-01 16:00 +0200
[PATCH v2 11/18] mm, compaction: add the ultimate direct compaction priority Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:20 +0200
[PATCH v2 10/18] mm, compaction: cleanup unused functions Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:20 +0200
Re: [PATCH v2 10/18] mm, compaction: cleanup unused functions Michal Hocko <mhocko@kernel.org> - 2016-06-01 15:50 +0200
[PATCH v2 01/18] mm, compaction: don't isolate PageWriteback pages in MIGRATE_SYNC_LIGHT mode Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:20 +0200
[PATCH v2 09/18] mm, compaction: make whole_zone flag ignore cached scanner positions Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:20 +0200
[PATCH v2 18/18] mm, vmscan: use proper classzone_idx in should_continue_reclaim() Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:20 +0200
Re: [PATCH v2 18/18] mm, vmscan: use proper classzone_idx in should_continue_reclaim() Michal Hocko <mhocko@kernel.org> - 2016-06-01 16:30 +0200
Re: [PATCH v2 18/18] mm, vmscan: use proper classzone_idx in should_continue_reclaim() Vlastimil Babka <vbabka@suse.cz> - 2016-06-01 17:20 +0200
Re: [PATCH v2 18/18] mm, vmscan: use proper classzone_idx in should_continue_reclaim() Michal Hocko <mhocko@kernel.org> - 2016-06-01 17:50 +0200
[PATCH v2 08/18] mm, compaction: simplify contended compaction handling Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:20 +0200
[PATCH v2 16/18] mm, compaction: require only min watermarks for non-costly orders Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:20 +0200
Re: [PATCH v2 16/18] mm, compaction: require only min watermarks for non-costly orders Michal Hocko <mhocko@kernel.org> - 2016-06-01 16:10 +0200
[PATCH v2 07/18] mm, compaction: introduce direct compaction priority Vlastimil Babka <vbabka@suse.cz> - 2016-05-31 15:20 +0200
Page 2 of 2 — ← Prev page 1 [2]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-06-01 15:50 +0200 |
| Subject | Re: [PATCH v2 10/18] mm, compaction: cleanup unused functions |
| Message-ID | <rFeGZ-BQ-1@gated-at.bofh.it> |
| In reply to | #1410294 |
On Tue 31-05-16 15:08:10, Vlastimil Babka wrote:
> Since kswapd compaction moved to kcompactd, compact_pgdat() is not called
> anymore, so we remove it. The only caller of __compact_pgdat() is
> compact_node(), so we merge them and remove code that was only reachable from
> kswapd.
>
> Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: Michal Hocko <mhocko@suse.com>
> ---
> include/linux/compaction.h | 5 ----
> mm/compaction.c | 60 +++++++++++++---------------------------------
> 2 files changed, 17 insertions(+), 48 deletions(-)
>
> diff --git a/include/linux/compaction.h b/include/linux/compaction.h
> index b3bb66e7ce55..22a5fb9c509c 100644
> --- a/include/linux/compaction.h
> +++ b/include/linux/compaction.h
> @@ -70,7 +70,6 @@ extern int fragmentation_index(struct zone *zone, unsigned int order);
> extern enum compact_result try_to_compact_pages(gfp_t gfp_mask,
> unsigned int order, unsigned int alloc_flags,
> const struct alloc_context *ac, enum compact_priority prio);
> -extern void compact_pgdat(pg_data_t *pgdat, int order);
> extern void reset_isolation_suitable(pg_data_t *pgdat);
> extern enum compact_result compaction_suitable(struct zone *zone, int order,
> unsigned int alloc_flags, int classzone_idx);
> @@ -154,10 +153,6 @@ extern void kcompactd_stop(int nid);
> extern void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx);
>
> #else
> -static inline void compact_pgdat(pg_data_t *pgdat, int order)
> -{
> -}
> -
> static inline void reset_isolation_suitable(pg_data_t *pgdat)
> {
> }
> diff --git a/mm/compaction.c b/mm/compaction.c
> index 78c99300b911..af50f20de369 100644
> --- a/mm/compaction.c
> +++ b/mm/compaction.c
> @@ -1678,10 +1678,18 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
>
>
> /* Compact all zones within a node */
> -static void __compact_pgdat(pg_data_t *pgdat, struct compact_control *cc)
> +static void compact_node(int nid)
> {
> + pg_data_t *pgdat = NODE_DATA(nid);
> int zoneid;
> struct zone *zone;
> + struct compact_control cc = {
> + .order = -1,
> + .mode = MIGRATE_SYNC,
> + .ignore_skip_hint = true,
> + .whole_zone = true,
> + };
> +
>
> for (zoneid = 0; zoneid < MAX_NR_ZONES; zoneid++) {
>
> @@ -1689,53 +1697,19 @@ static void __compact_pgdat(pg_data_t *pgdat, struct compact_control *cc)
> if (!populated_zone(zone))
> continue;
>
> - cc->nr_freepages = 0;
> - cc->nr_migratepages = 0;
> - cc->zone = zone;
> - INIT_LIST_HEAD(&cc->freepages);
> - INIT_LIST_HEAD(&cc->migratepages);
> -
> - if (is_via_compact_memory(cc->order) ||
> - !compaction_deferred(zone, cc->order))
> - compact_zone(zone, cc);
> -
> - VM_BUG_ON(!list_empty(&cc->freepages));
> - VM_BUG_ON(!list_empty(&cc->migratepages));
> + cc.nr_freepages = 0;
> + cc.nr_migratepages = 0;
> + cc.zone = zone;
> + INIT_LIST_HEAD(&cc.freepages);
> + INIT_LIST_HEAD(&cc.migratepages);
>
> - if (is_via_compact_memory(cc->order))
> - continue;
> + compact_zone(zone, &cc);
>
> - if (zone_watermark_ok(zone, cc->order,
> - low_wmark_pages(zone), 0, 0))
> - compaction_defer_reset(zone, cc->order, false);
> + VM_BUG_ON(!list_empty(&cc.freepages));
> + VM_BUG_ON(!list_empty(&cc.migratepages));
> }
> }
>
> -void compact_pgdat(pg_data_t *pgdat, int order)
> -{
> - struct compact_control cc = {
> - .order = order,
> - .mode = MIGRATE_ASYNC,
> - };
> -
> - if (!order)
> - return;
> -
> - __compact_pgdat(pgdat, &cc);
> -}
> -
> -static void compact_node(int nid)
> -{
> - struct compact_control cc = {
> - .order = -1,
> - .mode = MIGRATE_SYNC,
> - .ignore_skip_hint = true,
> - .whole_zone = true,
> - };
> -
> - __compact_pgdat(NODE_DATA(nid), &cc);
> -}
> -
> /* Compact all nodes in the system */
> static void compact_nodes(void)
> {
> --
> 2.8.3
>
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo@kvack.org. For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
--
Michal Hocko
SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Vlastimil Babka <vbabka@suse.cz> |
|---|---|
| Date | 2016-05-31 15:20 +0200 |
| Subject | [PATCH v2 01/18] mm, compaction: don't isolate PageWriteback pages in MIGRATE_SYNC_LIGHT mode |
| Message-ID | <rERKr-3dI-41@gated-at.bofh.it> |
| In reply to | #1410275 |
From: Hugh Dickins <hughd@google.com> At present MIGRATE_SYNC_LIGHT is allowing __isolate_lru_page() to isolate a PageWriteback page, which __unmap_and_move() then rejects with -EBUSY: of course the writeback might complete in between, but that's not what we usually expect, so probably better not to isolate it. When tested by stress-highalloc from mmtests, this has reduced the number of page migrate failures by 60-70%. Signed-off-by: Hugh Dickins <hughd@google.com> Signed-off-by: Vlastimil Babka <vbabka@suse.cz> Acked-by: Michal Hocko <mhocko@suse.com> --- mm/compaction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/compaction.c b/mm/compaction.c index 1427366ad673..e611f3f90f5f 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -1146,7 +1146,7 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, struct page *page; const isolate_mode_t isolate_mode = (sysctl_compact_unevictable_allowed ? ISOLATE_UNEVICTABLE : 0) | - (cc->mode == MIGRATE_ASYNC ? ISOLATE_ASYNC_MIGRATE : 0); + (cc->mode != MIGRATE_SYNC ? ISOLATE_ASYNC_MIGRATE : 0); /* * Start at where we last stopped, or beginning of the zone as -- 2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Vlastimil Babka <vbabka@suse.cz> |
|---|---|
| Date | 2016-05-31 15:20 +0200 |
| Subject | [PATCH v2 09/18] mm, compaction: make whole_zone flag ignore cached scanner positions |
| Message-ID | <rERKq-3dI-37@gated-at.bofh.it> |
| In reply to | #1410275 |
A recent patch has added whole_zone flag that compaction sets when scanning
starts from the zone boundary, in order to report that zone has been fully
scanned in one attempt. For allocations that want to try really hard or cannot
fail, we will want to introduce a mode where scanning whole zone is guaranteed
regardless of the cached positions.
This patch reuses the whole_zone flag in a way that if it's already passed true
to compaction, the cached scanner positions are ignored. Employing this flag
during reclaim/compaction loop will be done in the next patch. This patch
however converts compaction invoked from userspace via procfs to use this flag.
Before this patch, the cached positions were first reset to zone boundaries and
then read back from struct zone, so there was a window where a parallel
compaction could replace the reset values, making the manual compaction less
effective. Using the flag instead of performing reset is more robust.
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: Michal Hocko <mhocko@suse.com>
---
mm/compaction.c | 15 +++++----------
mm/internal.h | 2 +-
2 files changed, 6 insertions(+), 11 deletions(-)
diff --git a/mm/compaction.c b/mm/compaction.c
index 826b6d95a05b..78c99300b911 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1443,11 +1443,13 @@ static enum compact_result compact_zone(struct zone *zone, struct compact_contro
*/
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) {
+ if (cc->whole_zone || cc->free_pfn < start_pfn ||
+ cc->free_pfn >= end_pfn) {
cc->free_pfn = pageblock_start_pfn(end_pfn - 1);
zone->compact_cached_free_pfn = cc->free_pfn;
}
- if (cc->migrate_pfn < start_pfn || cc->migrate_pfn >= end_pfn) {
+ if (cc->whole_zone || 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;
@@ -1693,14 +1695,6 @@ static void __compact_pgdat(pg_data_t *pgdat, struct compact_control *cc)
INIT_LIST_HEAD(&cc->freepages);
INIT_LIST_HEAD(&cc->migratepages);
- /*
- * When called via /proc/sys/vm/compact_memory
- * this makes sure we compact the whole zone regardless of
- * cached scanner positions.
- */
- if (is_via_compact_memory(cc->order))
- __reset_isolation_suitable(zone);
-
if (is_via_compact_memory(cc->order) ||
!compaction_deferred(zone, cc->order))
compact_zone(zone, cc);
@@ -1736,6 +1730,7 @@ static void compact_node(int nid)
.order = -1,
.mode = MIGRATE_SYNC,
.ignore_skip_hint = true,
+ .whole_zone = true,
};
__compact_pgdat(NODE_DATA(nid), &cc);
diff --git a/mm/internal.h b/mm/internal.h
index c7d6a395385b..a4d3ce761839 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -174,7 +174,7 @@ struct compact_control {
enum migrate_mode mode; /* Async or sync migration mode */
bool ignore_skip_hint; /* Scan blocks even if marked skip */
bool direct_compaction; /* False from kcompactd or /proc/... */
- bool whole_zone; /* Whole zone has been scanned */
+ bool whole_zone; /* Whole zone should/has been scanned */
int order; /* order a direct compactor needs */
const gfp_t gfp_mask; /* gfp mask of a direct compactor */
const unsigned int alloc_flags; /* alloc flags of a direct compactor */
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Vlastimil Babka <vbabka@suse.cz> |
|---|---|
| Date | 2016-05-31 15:20 +0200 |
| Subject | [PATCH v2 18/18] mm, vmscan: use proper classzone_idx in should_continue_reclaim() |
| Message-ID | <rERKr-3dI-49@gated-at.bofh.it> |
| In reply to | #1410275 |
The should_continue_reclaim() function decides during direct reclaim/compaction
whether shrink_zone() should continue reclaming, or whether compaction is ready
to proceed in that zone. This relies mainly on the compaction_suitable() check,
but by passing a zero classzone_idx, there can be false positives and reclaim
terminates prematurely. Fix this by passing proper classzone_idx.
Additionally, the function checks whether (2UL << pages) were reclaimed. This
however overlaps with the same gap used by compaction_suitable(), and since the
number sc->nr_reclaimed is accumulated over all reclaimed zones, it doesn't
make much sense for deciding about a given single zone anyway. So just drop
this code.
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
---
mm/vmscan.c | 31 +++++++++----------------------
1 file changed, 9 insertions(+), 22 deletions(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 640d2e615c36..391e5d2c4e32 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2309,11 +2309,9 @@ static bool in_reclaim_compaction(struct scan_control *sc)
static inline bool should_continue_reclaim(struct zone *zone,
unsigned long nr_reclaimed,
unsigned long nr_scanned,
- struct scan_control *sc)
+ struct scan_control *sc,
+ int classzone_idx)
{
- unsigned long pages_for_compaction;
- unsigned long inactive_lru_pages;
-
/* If not in reclaim/compaction mode, stop */
if (!in_reclaim_compaction(sc))
return false;
@@ -2341,20 +2339,8 @@ static inline bool should_continue_reclaim(struct zone *zone,
return false;
}
- /*
- * If we have not reclaimed enough pages for compaction and the
- * inactive lists are large enough, continue reclaiming
- */
- pages_for_compaction = compact_gap(sc->order);
- inactive_lru_pages = zone_page_state(zone, NR_INACTIVE_FILE);
- if (get_nr_swap_pages() > 0)
- inactive_lru_pages += zone_page_state(zone, NR_INACTIVE_ANON);
- if (sc->nr_reclaimed < pages_for_compaction &&
- inactive_lru_pages > pages_for_compaction)
- return true;
-
/* If compaction would go ahead or the allocation would succeed, stop */
- switch (compaction_suitable(zone, sc->order, 0, 0)) {
+ switch (compaction_suitable(zone, sc->order, 0, classzone_idx)) {
case COMPACT_PARTIAL:
case COMPACT_CONTINUE:
return false;
@@ -2364,11 +2350,12 @@ static inline bool should_continue_reclaim(struct zone *zone,
}
static bool shrink_zone(struct zone *zone, struct scan_control *sc,
- bool is_classzone)
+ int classzone_idx)
{
struct reclaim_state *reclaim_state = current->reclaim_state;
unsigned long nr_reclaimed, nr_scanned;
bool reclaimable = false;
+ bool is_classzone = (classzone_idx == zone_idx(zone));
do {
struct mem_cgroup *root = sc->target_mem_cgroup;
@@ -2450,7 +2437,7 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc,
reclaimable = true;
} while (should_continue_reclaim(zone, sc->nr_reclaimed - nr_reclaimed,
- sc->nr_scanned - nr_scanned, sc));
+ sc->nr_scanned - nr_scanned, sc, classzone_idx));
return reclaimable;
}
@@ -2580,7 +2567,7 @@ static void shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
/* need some check for avoid more shrink_zone() */
}
- shrink_zone(zone, sc, zone_idx(zone) == classzone_idx);
+ shrink_zone(zone, sc, classzone_idx);
}
/*
@@ -3076,7 +3063,7 @@ static bool kswapd_shrink_zone(struct zone *zone,
balance_gap, classzone_idx))
return true;
- shrink_zone(zone, sc, zone_idx(zone) == classzone_idx);
+ shrink_zone(zone, sc, classzone_idx);
clear_bit(ZONE_WRITEBACK, &zone->flags);
@@ -3678,7 +3665,7 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
* priorities until we have enough memory freed.
*/
do {
- shrink_zone(zone, &sc, true);
+ shrink_zone(zone, &sc, zone_idx(zone));
} while (sc.nr_reclaimed < nr_pages && --sc.priority >= 0);
}
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-06-01 16:30 +0200 |
| Subject | Re: [PATCH v2 18/18] mm, vmscan: use proper classzone_idx in should_continue_reclaim() |
| Message-ID | <rFfjI-14J-9@gated-at.bofh.it> |
| In reply to | #1410299 |
On Tue 31-05-16 15:08:18, Vlastimil Babka wrote:
[...]
> @@ -2364,11 +2350,12 @@ static inline bool should_continue_reclaim(struct zone *zone,
> }
>
> static bool shrink_zone(struct zone *zone, struct scan_control *sc,
> - bool is_classzone)
> + int classzone_idx)
> {
> struct reclaim_state *reclaim_state = current->reclaim_state;
> unsigned long nr_reclaimed, nr_scanned;
> bool reclaimable = false;
> + bool is_classzone = (classzone_idx == zone_idx(zone));
>
> do {
> struct mem_cgroup *root = sc->target_mem_cgroup;
> @@ -2450,7 +2437,7 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc,
> reclaimable = true;
>
> } while (should_continue_reclaim(zone, sc->nr_reclaimed - nr_reclaimed,
> - sc->nr_scanned - nr_scanned, sc));
> + sc->nr_scanned - nr_scanned, sc, classzone_idx));
>
> return reclaimable;
> }
> @@ -2580,7 +2567,7 @@ static void shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
> /* need some check for avoid more shrink_zone() */
> }
>
> - shrink_zone(zone, sc, zone_idx(zone) == classzone_idx);
> + shrink_zone(zone, sc, classzone_idx);
this should be is_classzone, right?
--
Michal Hocko
SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Vlastimil Babka <vbabka@suse.cz> |
|---|---|
| Date | 2016-06-01 17:20 +0200 |
| Subject | Re: [PATCH v2 18/18] mm, vmscan: use proper classzone_idx in should_continue_reclaim() |
| Message-ID | <rFg65-1A8-13@gated-at.bofh.it> |
| In reply to | #1411267 |
On 06/01/2016 04:21 PM, Michal Hocko wrote:
> On Tue 31-05-16 15:08:18, Vlastimil Babka wrote:
> [...]
>> @@ -2364,11 +2350,12 @@ static inline bool should_continue_reclaim(struct zone *zone,
>> }
>>
>> static bool shrink_zone(struct zone *zone, struct scan_control *sc,
>> - bool is_classzone)
>> + int classzone_idx)
>> {
>> struct reclaim_state *reclaim_state = current->reclaim_state;
>> unsigned long nr_reclaimed, nr_scanned;
>> bool reclaimable = false;
>> + bool is_classzone = (classzone_idx == zone_idx(zone));
>>
>> do {
>> struct mem_cgroup *root = sc->target_mem_cgroup;
>> @@ -2450,7 +2437,7 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc,
>> reclaimable = true;
>>
>> } while (should_continue_reclaim(zone, sc->nr_reclaimed - nr_reclaimed,
>> - sc->nr_scanned - nr_scanned, sc));
>> + sc->nr_scanned - nr_scanned, sc, classzone_idx));
>>
>> return reclaimable;
>> }
>> @@ -2580,7 +2567,7 @@ static void shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
>> /* need some check for avoid more shrink_zone() */
>> }
>>
>> - shrink_zone(zone, sc, zone_idx(zone) == classzone_idx);
>> + shrink_zone(zone, sc, classzone_idx);
>
> this should be is_classzone, right?
No, this is shrink_zones() context, not shrink_zone().
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-06-01 17:50 +0200 |
| Subject | Re: [PATCH v2 18/18] mm, vmscan: use proper classzone_idx in should_continue_reclaim() |
| Message-ID | <rFgz9-1Kx-33@gated-at.bofh.it> |
| In reply to | #1411313 |
On Wed 01-06-16 17:19:26, Vlastimil Babka wrote:
> On 06/01/2016 04:21 PM, Michal Hocko wrote:
> > On Tue 31-05-16 15:08:18, Vlastimil Babka wrote:
> > [...]
> >> @@ -2364,11 +2350,12 @@ static inline bool should_continue_reclaim(struct zone *zone,
> >> }
> >>
> >> static bool shrink_zone(struct zone *zone, struct scan_control *sc,
> >> - bool is_classzone)
> >> + int classzone_idx)
> >> {
> >> struct reclaim_state *reclaim_state = current->reclaim_state;
> >> unsigned long nr_reclaimed, nr_scanned;
> >> bool reclaimable = false;
> >> + bool is_classzone = (classzone_idx == zone_idx(zone));
> >>
> >> do {
> >> struct mem_cgroup *root = sc->target_mem_cgroup;
> >> @@ -2450,7 +2437,7 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc,
> >> reclaimable = true;
> >>
> >> } while (should_continue_reclaim(zone, sc->nr_reclaimed - nr_reclaimed,
> >> - sc->nr_scanned - nr_scanned, sc));
> >> + sc->nr_scanned - nr_scanned, sc, classzone_idx));
> >>
> >> return reclaimable;
> >> }
> >> @@ -2580,7 +2567,7 @@ static void shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
> >> /* need some check for avoid more shrink_zone() */
> >> }
> >>
> >> - shrink_zone(zone, sc, zone_idx(zone) == classzone_idx);
> >> + shrink_zone(zone, sc, classzone_idx);
> >
> > this should be is_classzone, right?
>
> No, this is shrink_zones() context, not shrink_zone().
Ohh, right. They read to similar. I didn't spot anything else.
Acked-by: Michal Hocko <mhocko@suse.com>
--
Michal Hocko
SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Vlastimil Babka <vbabka@suse.cz> |
|---|---|
| Date | 2016-05-31 15:20 +0200 |
| Subject | [PATCH v2 08/18] mm, compaction: simplify contended compaction handling |
| Message-ID | <rERKr-3dI-51@gated-at.bofh.it> |
| In reply to | #1410275 |
Async compaction detects contention either due to failing trylock on zone->lock
or lru_lock, or by need_resched(). Since 1f9efdef4f3f ("mm, compaction:
khugepaged should not give up due to need_resched()") the code got quite
complicated to distinguish these two up to the __alloc_pages_slowpath() level,
so different decisions could be taken for khugepaged allocations.
After the recent changes, khugepaged allocations don't check for contended
compaction anymore, so we again don't need to distinguish lock and sched
contention, and simplify the current convoluted code a lot.
However, I believe it's also possible to simplify even more and completely
remove the check for contended compaction after the initial async compaction
for costly orders, which was originally aimed at THP page fault allocations.
There are several reasons why this can be done now:
- with the new defaults, THP page faults no longer do reclaim/compaction at
all, unless the system admin has overridden the default, or application has
indicated via madvise that it can benefit from THP's. In both cases, it
means that the potential extra latency is expected and worth the benefits.
- even if reclaim/compaction proceeds after this patch where it previously
wouldn't, the second compaction attempt is still async and will detect the
contention and back off, if the contention persists
- there are still heuristics like deferred compaction and pageblock skip bits
in place that prevent excessive THP page fault latencies
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: Michal Hocko <mhocko@suse.com>
---
include/linux/compaction.h | 13 ++-------
mm/compaction.c | 72 +++++++++-------------------------------------
mm/internal.h | 5 +---
mm/page_alloc.c | 28 +-----------------
4 files changed, 17 insertions(+), 101 deletions(-)
diff --git a/include/linux/compaction.h b/include/linux/compaction.h
index ba67bc8edbb6..b3bb66e7ce55 100644
--- a/include/linux/compaction.h
+++ b/include/linux/compaction.h
@@ -55,14 +55,6 @@ enum compact_result {
COMPACT_PARTIAL,
};
-/* Used to signal whether compaction detected need_sched() or lock contention */
-/* No contention detected */
-#define COMPACT_CONTENDED_NONE 0
-/* Either need_sched() was true or fatal signal pending */
-#define COMPACT_CONTENDED_SCHED 1
-/* Zone lock or lru_lock was contended in async compaction */
-#define COMPACT_CONTENDED_LOCK 2
-
struct alloc_context; /* in mm/internal.h */
#ifdef CONFIG_COMPACTION
@@ -76,9 +68,8 @@ extern int sysctl_compact_unevictable_allowed;
extern int fragmentation_index(struct zone *zone, unsigned int order);
extern enum compact_result try_to_compact_pages(gfp_t gfp_mask,
- unsigned int order,
- unsigned int alloc_flags, const struct alloc_context *ac,
- enum compact_priority prio, int *contended);
+ unsigned int order, unsigned int alloc_flags,
+ const struct alloc_context *ac, enum compact_priority prio);
extern void compact_pgdat(pg_data_t *pgdat, int order);
extern void reset_isolation_suitable(pg_data_t *pgdat);
extern enum compact_result compaction_suitable(struct zone *zone, int order,
diff --git a/mm/compaction.c b/mm/compaction.c
index 19a4f4fd6632..826b6d95a05b 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -279,7 +279,7 @@ static bool compact_trylock_irqsave(spinlock_t *lock, unsigned long *flags,
{
if (cc->mode == MIGRATE_ASYNC) {
if (!spin_trylock_irqsave(lock, *flags)) {
- cc->contended = COMPACT_CONTENDED_LOCK;
+ cc->contended = true;
return false;
}
} else {
@@ -313,13 +313,13 @@ static bool compact_unlock_should_abort(spinlock_t *lock,
}
if (fatal_signal_pending(current)) {
- cc->contended = COMPACT_CONTENDED_SCHED;
+ cc->contended = true;
return true;
}
if (need_resched()) {
if (cc->mode == MIGRATE_ASYNC) {
- cc->contended = COMPACT_CONTENDED_SCHED;
+ cc->contended = true;
return true;
}
cond_resched();
@@ -342,7 +342,7 @@ static inline bool compact_should_abort(struct compact_control *cc)
/* async compaction aborts if contended */
if (need_resched()) {
if (cc->mode == MIGRATE_ASYNC) {
- cc->contended = COMPACT_CONTENDED_SCHED;
+ cc->contended = true;
return true;
}
@@ -1565,14 +1565,11 @@ static enum compact_result compact_zone(struct zone *zone, struct compact_contro
trace_mm_compaction_end(start_pfn, cc->migrate_pfn,
cc->free_pfn, end_pfn, sync, ret);
- if (ret == COMPACT_CONTENDED)
- ret = COMPACT_PARTIAL;
-
return ret;
}
static enum compact_result compact_zone_order(struct zone *zone, int order,
- gfp_t gfp_mask, enum compact_priority prio, int *contended,
+ gfp_t gfp_mask, enum compact_priority prio,
unsigned int alloc_flags, int classzone_idx)
{
enum compact_result ret;
@@ -1596,7 +1593,6 @@ static enum compact_result compact_zone_order(struct zone *zone, int order,
VM_BUG_ON(!list_empty(&cc.freepages));
VM_BUG_ON(!list_empty(&cc.migratepages));
- *contended = cc.contended;
return ret;
}
@@ -1609,23 +1605,18 @@ int sysctl_extfrag_threshold = 500;
* @alloc_flags: The allocation flags of the current allocation
* @ac: The context of current allocation
* @mode: The migration mode for async, sync light, or sync migration
- * @contended: Return value that determines if compaction was aborted due to
- * need_resched() or lock contention
*
* This is the main entry point for direct page compaction.
*/
enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
unsigned int alloc_flags, const struct alloc_context *ac,
- enum compact_priority prio, int *contended)
+ enum compact_priority prio)
{
int may_enter_fs = gfp_mask & __GFP_FS;
int may_perform_io = gfp_mask & __GFP_IO;
struct zoneref *z;
struct zone *zone;
enum compact_result rc = COMPACT_SKIPPED;
- int all_zones_contended = COMPACT_CONTENDED_LOCK; /* init for &= op */
-
- *contended = COMPACT_CONTENDED_NONE;
/* Check if the GFP flags allow compaction */
if (!order || !may_enter_fs || !may_perform_io)
@@ -1637,7 +1628,6 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
for_each_zone_zonelist_nodemask(zone, z, ac->zonelist, ac->high_zoneidx,
ac->nodemask) {
enum compact_result status;
- int zone_contended;
if (compaction_deferred(zone, order)) {
rc = max_t(enum compact_result, COMPACT_DEFERRED, rc);
@@ -1645,14 +1635,8 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
}
status = compact_zone_order(zone, order, gfp_mask, prio,
- &zone_contended, alloc_flags,
- ac_classzone_idx(ac));
+ alloc_flags, ac_classzone_idx(ac));
rc = max(status, rc);
- /*
- * It takes at least one zone that wasn't lock contended
- * to clear all_zones_contended.
- */
- all_zones_contended &= zone_contended;
/* If a normal allocation would succeed, stop compacting */
if (zone_watermark_ok(zone, order, low_wmark_pages(zone),
@@ -1664,59 +1648,29 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
* succeeds in this zone.
*/
compaction_defer_reset(zone, order, false);
- /*
- * It is possible that async compaction aborted due to
- * need_resched() and the watermarks were ok thanks to
- * somebody else freeing memory. The allocation can
- * however still fail so we better signal the
- * need_resched() contention anyway (this will not
- * prevent the allocation attempt).
- */
- if (zone_contended == COMPACT_CONTENDED_SCHED)
- *contended = COMPACT_CONTENDED_SCHED;
- goto break_loop;
+ break;
}
if (prio != COMPACT_PRIO_ASYNC && (status == COMPACT_COMPLETE ||
- status == COMPACT_PARTIAL_SKIPPED)) {
+ status == COMPACT_PARTIAL_SKIPPED))
/*
* We think that allocation won't succeed in this zone
* so we defer compaction there. If it ends up
* succeeding after all, it will be reset.
*/
defer_compaction(zone, order);
- }
/*
* We might have stopped compacting due to need_resched() in
* async compaction, or due to a fatal signal detected. In that
- * case do not try further zones and signal need_resched()
- * contention.
- */
- if ((zone_contended == COMPACT_CONTENDED_SCHED)
- || fatal_signal_pending(current)) {
- *contended = COMPACT_CONTENDED_SCHED;
- goto break_loop;
- }
-
- continue;
-break_loop:
- /*
- * We might not have tried all the zones, so be conservative
- * and assume they are not all lock contended.
+ * case do not try further zones
*/
- all_zones_contended = 0;
- break;
+ if ((prio == COMPACT_PRIO_ASYNC && need_resched())
+ || fatal_signal_pending(current))
+ break;
}
- /*
- * If at least one zone wasn't deferred or skipped, we report if all
- * zones that were tried were lock contended.
- */
- if (rc > COMPACT_INACTIVE && all_zones_contended)
- *contended = COMPACT_CONTENDED_LOCK;
-
return rc;
}
diff --git a/mm/internal.h b/mm/internal.h
index a37e5b6f9d25..c7d6a395385b 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -180,10 +180,7 @@ struct compact_control {
const unsigned int alloc_flags; /* alloc flags of a direct compactor */
const int classzone_idx; /* zone index of a direct compactor */
struct zone *zone;
- int contended; /* Signal need_sched() or lock
- * contention detected during
- * compaction
- */
+ bool contended; /* Signal lock or sched contention */
};
unsigned long
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 4466543a57ab..27923af8e534 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3183,14 +3183,13 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
enum compact_priority prio, enum compact_result *compact_result)
{
struct page *page;
- int contended_compaction;
if (!order)
return NULL;
current->flags |= PF_MEMALLOC;
*compact_result = try_to_compact_pages(gfp_mask, order, alloc_flags, ac,
- prio, &contended_compaction);
+ prio);
current->flags &= ~PF_MEMALLOC;
if (*compact_result <= COMPACT_INACTIVE)
@@ -3219,24 +3218,6 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
*/
count_vm_event(COMPACTFAIL);
- /*
- * In all zones where compaction was attempted (and not
- * deferred or skipped), lock contention has been detected.
- * For THP allocation we do not want to disrupt the others
- * so we fallback to base pages instead.
- */
- if (contended_compaction == COMPACT_CONTENDED_LOCK)
- *compact_result = COMPACT_CONTENDED;
-
- /*
- * If compaction was aborted due to need_resched(), we do not
- * want to further increase allocation latency, unless it is
- * khugepaged trying to collapse.
- */
- if (contended_compaction == COMPACT_CONTENDED_SCHED
- && !(current->flags & PF_KTHREAD))
- *compact_result = COMPACT_CONTENDED;
-
cond_resched();
return NULL;
@@ -3626,13 +3607,6 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
goto nopage;
/*
- * Compaction is contended so rather back off than cause
- * excessive stalls.
- */
- if (compact_result == COMPACT_CONTENDED)
- goto nopage;
-
- /*
* Looks like reclaim/compaction is worth trying, but
* sync compaction could be very expensive, so keep
* using async compaction.
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Vlastimil Babka <vbabka@suse.cz> |
|---|---|
| Date | 2016-05-31 15:20 +0200 |
| Subject | [PATCH v2 16/18] mm, compaction: require only min watermarks for non-costly orders |
| Message-ID | <rERKr-3dI-53@gated-at.bofh.it> |
| In reply to | #1410275 |
The __compaction_suitable() function checks the low watermark plus a
compact_gap() gap to decide if there's enough free memory to perform
compaction. Then __isolate_free_page uses low watermark check to decide if
particular free page can be isolated. In the latter case, using low watermark
is needlessly pessimistic, as the free page isolations are only temporary. For
__compaction_suitable() the higher watermark makes sense for high-order
allocations where more freepages increase the chance of success, and we can
typically fail with some order-0 fallback when the system is struggling to
reach that watermark. But for low-order allocation, forming the page should not
be that hard. So using low watermark here might just prevent compaction from
even trying, and eventually lead to OOM killer even if we are above min
watermarks.
So after this patch, we use min watermark for non-costly orders in
__compaction_suitable(), and for all orders in __isolate_free_page().
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
---
mm/compaction.c | 6 +++++-
mm/page_alloc.c | 2 +-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/mm/compaction.c b/mm/compaction.c
index 4ffa0870192b..d854519a5302 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1345,10 +1345,14 @@ static enum compact_result __compaction_suitable(struct zone *zone, int order,
* isolation. We however do use the direct compactor's classzone_idx to
* skip over zones where lowmem reserves would prevent allocation even
* if compaction succeeds.
+ * For costly orders, we require low watermark instead of min for
+ * compaction to proceed to increase its chances.
* ALLOC_CMA is used, as pages in CMA pageblocks are considered
* suitable migration targets
*/
- watermark = low_wmark_pages(zone) + compact_gap(order);
+ watermark = (order > PAGE_ALLOC_COSTLY_ORDER) ?
+ low_wmark_pages(zone) : min_wmark_pages(zone);
+ watermark += compact_gap(order);
if (!__zone_watermark_ok(zone, 0, watermark, classzone_idx,
ALLOC_CMA, wmark_target))
return COMPACT_SKIPPED;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 09dc9db8a7e9..5b4c9e567fc1 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2489,7 +2489,7 @@ int __isolate_free_page(struct page *page, unsigned int order)
if (!is_migrate_isolate(mt)) {
/* Obey watermarks as if the page was being allocated */
- watermark = low_wmark_pages(zone) + (1 << order);
+ watermark = min_wmark_pages(zone) + (1UL << order);
if (!zone_watermark_ok(zone, 0, watermark, 0, ALLOC_CMA))
return 0;
--
2.8.3
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-06-01 16:10 +0200 |
| Subject | Re: [PATCH v2 16/18] mm, compaction: require only min watermarks for non-costly orders |
| Message-ID | <rFf0l-Xx-7@gated-at.bofh.it> |
| In reply to | #1410301 |
On Tue 31-05-16 15:08:16, Vlastimil Babka wrote:
> The __compaction_suitable() function checks the low watermark plus a
> compact_gap() gap to decide if there's enough free memory to perform
> compaction. Then __isolate_free_page uses low watermark check to decide if
> particular free page can be isolated. In the latter case, using low watermark
> is needlessly pessimistic, as the free page isolations are only temporary. For
> __compaction_suitable() the higher watermark makes sense for high-order
> allocations where more freepages increase the chance of success, and we can
> typically fail with some order-0 fallback when the system is struggling to
> reach that watermark. But for low-order allocation, forming the page should not
> be that hard. So using low watermark here might just prevent compaction from
> even trying, and eventually lead to OOM killer even if we are above min
> watermarks.
>
> So after this patch, we use min watermark for non-costly orders in
> __compaction_suitable(), and for all orders in __isolate_free_page().
>
> Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: Michal Hocko <mhocko@suse.com>
> ---
> mm/compaction.c | 6 +++++-
> mm/page_alloc.c | 2 +-
> 2 files changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/mm/compaction.c b/mm/compaction.c
> index 4ffa0870192b..d854519a5302 100644
> --- a/mm/compaction.c
> +++ b/mm/compaction.c
> @@ -1345,10 +1345,14 @@ static enum compact_result __compaction_suitable(struct zone *zone, int order,
> * isolation. We however do use the direct compactor's classzone_idx to
> * skip over zones where lowmem reserves would prevent allocation even
> * if compaction succeeds.
> + * For costly orders, we require low watermark instead of min for
> + * compaction to proceed to increase its chances.
> * ALLOC_CMA is used, as pages in CMA pageblocks are considered
> * suitable migration targets
> */
> - watermark = low_wmark_pages(zone) + compact_gap(order);
> + watermark = (order > PAGE_ALLOC_COSTLY_ORDER) ?
> + low_wmark_pages(zone) : min_wmark_pages(zone);
> + watermark += compact_gap(order);
> if (!__zone_watermark_ok(zone, 0, watermark, classzone_idx,
> ALLOC_CMA, wmark_target))
> return COMPACT_SKIPPED;
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index 09dc9db8a7e9..5b4c9e567fc1 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -2489,7 +2489,7 @@ int __isolate_free_page(struct page *page, unsigned int order)
>
> if (!is_migrate_isolate(mt)) {
> /* Obey watermarks as if the page was being allocated */
> - watermark = low_wmark_pages(zone) + (1 << order);
> + watermark = min_wmark_pages(zone) + (1UL << order);
> if (!zone_watermark_ok(zone, 0, watermark, 0, ALLOC_CMA))
> return 0;
>
> --
> 2.8.3
--
Michal Hocko
SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Vlastimil Babka <vbabka@suse.cz> |
|---|---|
| Date | 2016-05-31 15:20 +0200 |
| Subject | [PATCH v2 07/18] mm, compaction: introduce direct compaction priority |
| Message-ID | <rERKr-3dI-59@gated-at.bofh.it> |
| In reply to | #1410275 |
In the context of direct compaction, for some types of allocations we would
like the compaction to either succeed or definitely fail while trying as hard
as possible. Current async/sync_light migration mode is insufficient, as there
are heuristics such as caching scanner positions, marking pageblocks as
unsuitable or deferring compaction for a zone. At least the final compaction
attempt should be able to override these heuristics.
To communicate how hard compaction should try, we replace migration mode with
a new enum compact_priority and change the relevant function signatures. In
compact_zone_order() where struct compact_control is constructed, the priority
is mapped to suitable control flags. This patch itself has no functional
change, as the current priority levels are mapped back to the same migration
modes as before. Expanding them will be done next.
Note that !CONFIG_COMPACTION variant of try_to_compact_pages() is removed, as
the only caller exists under CONFIG_COMPACTION.
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: Michal Hocko <mhocko@suse.com>
---
include/linux/compaction.h | 22 +++++++++++++---------
include/trace/events/compaction.h | 12 ++++++------
mm/compaction.c | 13 +++++++------
mm/page_alloc.c | 28 ++++++++++++++--------------
4 files changed, 40 insertions(+), 35 deletions(-)
diff --git a/include/linux/compaction.h b/include/linux/compaction.h
index a58c852a268f..ba67bc8edbb6 100644
--- a/include/linux/compaction.h
+++ b/include/linux/compaction.h
@@ -1,6 +1,18 @@
#ifndef _LINUX_COMPACTION_H
#define _LINUX_COMPACTION_H
+/*
+ * Determines how hard direct compaction should try to succeed.
+ * Lower value means higher priority, analogically to reclaim priority.
+ */
+enum compact_priority {
+ COMPACT_PRIO_SYNC_LIGHT,
+ MIN_COMPACT_PRIORITY = COMPACT_PRIO_SYNC_LIGHT,
+ DEF_COMPACT_PRIORITY = COMPACT_PRIO_SYNC_LIGHT,
+ COMPACT_PRIO_ASYNC,
+ INIT_COMPACT_PRIORITY = COMPACT_PRIO_ASYNC
+};
+
/* Return values for compact_zone() and try_to_compact_pages() */
/* When adding new states, please adjust include/trace/events/compaction.h */
enum compact_result {
@@ -66,7 +78,7 @@ extern int fragmentation_index(struct zone *zone, unsigned int order);
extern enum compact_result try_to_compact_pages(gfp_t gfp_mask,
unsigned int order,
unsigned int alloc_flags, const struct alloc_context *ac,
- enum migrate_mode mode, int *contended);
+ enum compact_priority prio, int *contended);
extern void compact_pgdat(pg_data_t *pgdat, int order);
extern void reset_isolation_suitable(pg_data_t *pgdat);
extern enum compact_result compaction_suitable(struct zone *zone, int order,
@@ -151,14 +163,6 @@ extern void kcompactd_stop(int nid);
extern void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx);
#else
-static inline enum compact_result try_to_compact_pages(gfp_t gfp_mask,
- unsigned int order, int alloc_flags,
- const struct alloc_context *ac,
- enum migrate_mode mode, int *contended)
-{
- return COMPACT_CONTINUE;
-}
-
static inline void compact_pgdat(pg_data_t *pgdat, int order)
{
}
diff --git a/include/trace/events/compaction.h b/include/trace/events/compaction.h
index 36e2d6fb1360..c2ba402ab256 100644
--- a/include/trace/events/compaction.h
+++ b/include/trace/events/compaction.h
@@ -226,26 +226,26 @@ TRACE_EVENT(mm_compaction_try_to_compact_pages,
TP_PROTO(
int order,
gfp_t gfp_mask,
- enum migrate_mode mode),
+ int prio),
- TP_ARGS(order, gfp_mask, mode),
+ TP_ARGS(order, gfp_mask, prio),
TP_STRUCT__entry(
__field(int, order)
__field(gfp_t, gfp_mask)
- __field(enum migrate_mode, mode)
+ __field(int, prio)
),
TP_fast_assign(
__entry->order = order;
__entry->gfp_mask = gfp_mask;
- __entry->mode = mode;
+ __entry->prio = prio;
),
- TP_printk("order=%d gfp_mask=0x%x mode=%d",
+ TP_printk("order=%d gfp_mask=0x%x priority=%d",
__entry->order,
__entry->gfp_mask,
- (int)__entry->mode)
+ __entry->prio)
);
DECLARE_EVENT_CLASS(mm_compaction_suitable_template,
diff --git a/mm/compaction.c b/mm/compaction.c
index e611f3f90f5f..19a4f4fd6632 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1572,7 +1572,7 @@ static enum compact_result compact_zone(struct zone *zone, struct compact_contro
}
static enum compact_result compact_zone_order(struct zone *zone, int order,
- gfp_t gfp_mask, enum migrate_mode mode, int *contended,
+ gfp_t gfp_mask, enum compact_priority prio, int *contended,
unsigned int alloc_flags, int classzone_idx)
{
enum compact_result ret;
@@ -1582,7 +1582,8 @@ static enum compact_result compact_zone_order(struct zone *zone, int order,
.order = order,
.gfp_mask = gfp_mask,
.zone = zone,
- .mode = mode,
+ .mode = (prio == COMPACT_PRIO_ASYNC) ?
+ MIGRATE_ASYNC : MIGRATE_SYNC_LIGHT,
.alloc_flags = alloc_flags,
.classzone_idx = classzone_idx,
.direct_compaction = true,
@@ -1615,7 +1616,7 @@ int sysctl_extfrag_threshold = 500;
*/
enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
unsigned int alloc_flags, const struct alloc_context *ac,
- enum migrate_mode mode, int *contended)
+ enum compact_priority prio, int *contended)
{
int may_enter_fs = gfp_mask & __GFP_FS;
int may_perform_io = gfp_mask & __GFP_IO;
@@ -1630,7 +1631,7 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
if (!order || !may_enter_fs || !may_perform_io)
return COMPACT_SKIPPED;
- trace_mm_compaction_try_to_compact_pages(order, gfp_mask, mode);
+ trace_mm_compaction_try_to_compact_pages(order, gfp_mask, prio);
/* Compact each zone in the list */
for_each_zone_zonelist_nodemask(zone, z, ac->zonelist, ac->high_zoneidx,
@@ -1643,7 +1644,7 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
continue;
}
- status = compact_zone_order(zone, order, gfp_mask, mode,
+ status = compact_zone_order(zone, order, gfp_mask, prio,
&zone_contended, alloc_flags,
ac_classzone_idx(ac));
rc = max(status, rc);
@@ -1677,7 +1678,7 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
goto break_loop;
}
- if (mode != MIGRATE_ASYNC && (status == COMPACT_COMPLETE ||
+ if (prio != COMPACT_PRIO_ASYNC && (status == COMPACT_COMPLETE ||
status == COMPACT_PARTIAL_SKIPPED)) {
/*
* We think that allocation won't succeed in this zone
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index d7fc4c86e077..4466543a57ab 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3180,7 +3180,7 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
static struct page *
__alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
unsigned int alloc_flags, const struct alloc_context *ac,
- enum migrate_mode mode, enum compact_result *compact_result)
+ enum compact_priority prio, enum compact_result *compact_result)
{
struct page *page;
int contended_compaction;
@@ -3190,7 +3190,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
current->flags |= PF_MEMALLOC;
*compact_result = try_to_compact_pages(gfp_mask, order, alloc_flags, ac,
- mode, &contended_compaction);
+ prio, &contended_compaction);
current->flags &= ~PF_MEMALLOC;
if (*compact_result <= COMPACT_INACTIVE)
@@ -3244,7 +3244,8 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
static inline bool
should_compact_retry(struct alloc_context *ac, int order, int alloc_flags,
- enum compact_result compact_result, enum migrate_mode *migrate_mode,
+ enum compact_result compact_result,
+ enum compact_priority *compact_priority,
int compaction_retries)
{
int max_retries = MAX_COMPACT_RETRIES;
@@ -3255,11 +3256,11 @@ should_compact_retry(struct alloc_context *ac, int order, int alloc_flags,
/*
* compaction considers all the zone as desperately out of memory
* so it doesn't really make much sense to retry except when the
- * failure could be caused by weak migration mode.
+ * failure could be caused by insufficient priority
*/
if (compaction_failed(compact_result)) {
- if (*migrate_mode == MIGRATE_ASYNC) {
- *migrate_mode = MIGRATE_SYNC_LIGHT;
+ if (*compact_priority > MIN_COMPACT_PRIORITY) {
+ (*compact_priority)--;
return true;
}
return false;
@@ -3293,7 +3294,7 @@ should_compact_retry(struct alloc_context *ac, int order, int alloc_flags,
static inline struct page *
__alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
unsigned int alloc_flags, const struct alloc_context *ac,
- enum migrate_mode mode, enum compact_result *compact_result)
+ enum compact_priority prio, enum compact_result *compact_result)
{
*compact_result = COMPACT_SKIPPED;
return NULL;
@@ -3302,7 +3303,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
static inline bool
should_compact_retry(struct alloc_context *ac, unsigned int order, int alloc_flags,
enum compact_result compact_result,
- enum migrate_mode *migrate_mode,
+ enum compact_priority *compact_priority,
int compaction_retries)
{
struct zone *zone;
@@ -3554,7 +3555,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
struct page *page = NULL;
unsigned int alloc_flags;
unsigned long did_some_progress;
- enum migrate_mode migration_mode = MIGRATE_SYNC_LIGHT;
+ enum compact_priority compact_priority = DEF_COMPACT_PRIORITY;
enum compact_result compact_result;
int compaction_retries = 0;
int no_progress_loops = 0;
@@ -3603,7 +3604,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
if (can_direct_reclaim && order > PAGE_ALLOC_COSTLY_ORDER) {
page = __alloc_pages_direct_compact(gfp_mask, order,
alloc_flags, ac,
- MIGRATE_ASYNC,
+ INIT_COMPACT_PRIORITY,
&compact_result);
if (page)
goto got_pg;
@@ -3636,7 +3637,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
* sync compaction could be very expensive, so keep
* using async compaction.
*/
- migration_mode = MIGRATE_ASYNC;
+ compact_priority = INIT_COMPACT_PRIORITY;
}
}
@@ -3697,8 +3698,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
/* Try direct compaction and then allocating */
page = __alloc_pages_direct_compact(gfp_mask, order, alloc_flags, ac,
- migration_mode,
- &compact_result);
+ compact_priority, &compact_result);
if (page)
goto got_pg;
@@ -3738,7 +3738,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
*/
if (did_some_progress > 0 &&
should_compact_retry(ac, order, alloc_flags,
- compact_result, &migration_mode,
+ compact_result, &compact_priority,
compaction_retries))
goto retry;
--
2.8.3
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | linux.kernel
csiph-web