Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1383701 > unrolled thread
| Started by | Michal Hocko <mhocko@kernel.org> |
|---|---|
| First post | 2016-04-20 21:50 +0200 |
| Last post | 2016-05-12 13:10 +0200 |
| Articles | 20 on this page of 52 — 5 participants |
Back to article view | Back to linux.kernel
[PATCH 0.14] oom detection rework v6 Michal Hocko <mhocko@kernel.org> - 2016-04-20 21:50 +0200
[PATCH 07/14] mm, compaction: Simplify __alloc_pages_direct_compact feedback interface Michal Hocko <mhocko@kernel.org> - 2016-04-20 21:50 +0200
[PATCH 03/14] mm, compaction: cover all compaction mode in compact_zone Michal Hocko <mhocko@kernel.org> - 2016-04-20 21:50 +0200
[PATCH 10/14] mm, oom: rework oom detection Michal Hocko <mhocko@kernel.org> - 2016-04-20 21:50 +0200
[PATCH 14/14] mm, oom, compaction: prevent from should_compact_retry looping for ever for costly orders Michal Hocko <mhocko@kernel.org> - 2016-04-20 21:50 +0200
Re: [PATCH 14/14] mm, oom, compaction: prevent from should_compact_retry looping for ever for costly orders Vlastimil Babka <vbabka@suse.cz> - 2016-04-28 11:00 +0200
Re: [PATCH 14/14] mm, oom, compaction: prevent from should_compact_retry looping for ever for costly orders Michal Hocko <mhocko@kernel.org> - 2016-04-28 14:40 +0200
Re: [PATCH 14/14] mm, oom, compaction: prevent from should_compact_retry looping for ever for costly orders Joonsoo Kim <iamjoonsoo.kim@lge.com> - 2016-05-04 08:30 +0200
Re: [PATCH 14/14] mm, oom, compaction: prevent from should_compact_retry looping for ever for costly orders Michal Hocko <mhocko@kernel.org> - 2016-05-04 11:10 +0200
Re: [PATCH 14/14] mm, oom, compaction: prevent from should_compact_retry looping for ever for costly orders Joonsoo Kim <js1304@gmail.com> - 2016-05-04 17:20 +0200
Re: [PATCH 14/14] mm, oom, compaction: prevent from should_compact_retry looping for ever for costly orders Michal Hocko <mhocko@kernel.org> - 2016-05-04 21:30 +0200
[PATCH 11/14] mm: throttle on IO only when there are too many dirty and writeback pages Michal Hocko <mhocko@kernel.org> - 2016-04-20 21:50 +0200
[PATCH 12/14] mm, oom: protect !costly allocations some more Michal Hocko <mhocko@kernel.org> - 2016-04-20 21:50 +0200
Re: [PATCH 12/14] mm, oom: protect !costly allocations some more Joonsoo Kim <iamjoonsoo.kim@lge.com> - 2016-05-04 08:10 +0200
Re: [PATCH 12/14] mm, oom: protect !costly allocations some more Joonsoo Kim <iamjoonsoo.kim@lge.com> - 2016-05-04 08:40 +0200
Re: [PATCH 12/14] mm, oom: protect !costly allocations some more Michal Hocko <mhocko@kernel.org> - 2016-05-04 11:00 +0200
Re: [PATCH 12/14] mm, oom: protect !costly allocations some more Joonsoo Kim <js1304@gmail.com> - 2016-05-04 17:00 +0200
Re: [PATCH 12/14] mm, oom: protect !costly allocations some more Michal Hocko <mhocko@kernel.org> - 2016-05-04 20:20 +0200
Re: [PATCH 12/14] mm, oom: protect !costly allocations some more Michal Hocko <mhocko@kernel.org> - 2016-05-04 11:00 +0200
Re: [PATCH 12/14] mm, oom: protect !costly allocations some more Joonsoo Kim <js1304@gmail.com> - 2016-05-04 16:40 +0200
Re: [PATCH 12/14] mm, oom: protect !costly allocations some more Michal Hocko <mhocko@kernel.org> - 2016-05-04 20:30 +0200
[PATCH 01/14] vmscan: consider classzone_idx in compaction_ready Michal Hocko <mhocko@kernel.org> - 2016-04-20 21:50 +0200
Re: [PATCH 01/14] vmscan: consider classzone_idx in compaction_ready "Hillf Danton" <hillf.zj@alibaba-inc.com> - 2016-04-21 06:40 +0200
Re: [PATCH 01/14] vmscan: consider classzone_idx in compaction_ready Michal Hocko <mhocko@kernel.org> - 2016-05-04 16:00 +0200
[PATCH 05/14] mm, compaction: distinguish between full and partial COMPACT_COMPLETE Michal Hocko <mhocko@kernel.org> - 2016-04-20 21:50 +0200
Re: [PATCH 05/14] mm, compaction: distinguish between full and partial COMPACT_COMPLETE "Hillf Danton" <hillf.zj@alibaba-inc.com> - 2016-04-21 08:40 +0200
[PATCH 08/14] mm, compaction: Abstract compaction feedback to helpers Michal Hocko <mhocko@kernel.org> - 2016-04-20 21:50 +0200
Re: [PATCH 08/14] mm, compaction: Abstract compaction feedback to helpers Vlastimil Babka <vbabka@suse.cz> - 2016-04-28 10:50 +0200
[PATCH 09/14] mm: use compaction feedback for thp backoff conditions Michal Hocko <mhocko@kernel.org> - 2016-04-20 21:50 +0200
Re: [PATCH 09/14] mm: use compaction feedback for thp backoff conditions "Hillf Danton" <hillf.zj@alibaba-inc.com> - 2016-04-21 09:10 +0200
Re: [PATCH 09/14] mm: use compaction feedback for thp backoff conditions Vlastimil Babka <vbabka@suse.cz> - 2016-04-28 11:00 +0200
Re: [PATCH 09/14] mm: use compaction feedback for thp backoff conditions Michal Hocko <mhocko@kernel.org> - 2016-04-28 14:40 +0200
Re: [PATCH 09/14] mm: use compaction feedback for thp backoff conditions Vlastimil Babka <vbabka@suse.cz> - 2016-04-29 11:20 +0200
Re: [PATCH 09/14] mm: use compaction feedback for thp backoff conditions Michal Hocko <mhocko@kernel.org> - 2016-04-29 11:30 +0200
[PATCH 13/14] mm: consider compaction feedback also for costly allocation Michal Hocko <mhocko@kernel.org> - 2016-04-20 21:50 +0200
[PATCH 04/14] mm, compaction: distinguish COMPACT_DEFERRED from COMPACT_SKIPPED Michal Hocko <mhocko@kernel.org> - 2016-04-20 22:00 +0200
[PATCH 02/14] mm, compaction: change COMPACT_ constants into enum Michal Hocko <mhocko@kernel.org> - 2016-04-20 22:00 +0200
Re: [PATCH 0.14] oom detection rework v6 Joonsoo Kim <iamjoonsoo.kim@lge.com> - 2016-05-04 07:50 +0200
Re: [PATCH 0.14] oom detection rework v6 Vlastimil Babka <vbabka@suse.cz> - 2016-05-04 10:20 +0200
Re: [PATCH 0.14] oom detection rework v6 Joonsoo Kim <iamjoonsoo.kim@lge.com> - 2016-05-04 10:40 +0200
Re: [PATCH 0.14] oom detection rework v6 Michal Hocko <mhocko@kernel.org> - 2016-05-04 11:00 +0200
Re: [PATCH 0.14] oom detection rework v6 Michal Hocko <mhocko@kernel.org> - 2016-05-04 10:50 +0200
Re: [PATCH 0.14] oom detection rework v6 Joonsoo Kim <js1304@gmail.com> - 2016-05-04 16:40 +0200
Re: [PATCH 0.14] oom detection rework v6 Michal Hocko <mhocko@kernel.org> - 2016-05-04 20:20 +0200
Re: [PATCH 0.14] oom detection rework v6 Joonsoo Kim <js1304@gmail.com> - 2016-05-10 08:50 +0200
Re: [PATCH 0.14] oom detection rework v6 Vlastimil Babka <vbabka@suse.cz> - 2016-05-10 09:10 +0200
Re: [PATCH 0.14] oom detection rework v6 Joonsoo Kim <js1304@gmail.com> - 2016-05-10 10:10 +0200
Re: [PATCH 0.14] oom detection rework v6 Michal Hocko <mhocko@kernel.org> - 2016-05-10 11:50 +0200
Re: [PATCH 0.14] oom detection rework v6 Michal Hocko <mhocko@kernel.org> - 2016-05-10 11:50 +0200
Re: [PATCH 0.14] oom detection rework v6 Joonsoo Kim <iamjoonsoo.kim@lge.com> - 2016-05-12 04:30 +0200
Re: [PATCH 0.14] oom detection rework v6 Joonsoo Kim <iamjoonsoo.kim@lge.com> - 2016-05-12 07:20 +0200
Re: [PATCH 0.14] oom detection rework v6 Michal Hocko <mhocko@kernel.org> - 2016-05-12 13:10 +0200
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-05-04 20:30 +0200 |
| Subject | Re: [PATCH 12/14] mm, oom: protect !costly allocations some more |
| Message-ID | <rv9IC-Ky-17@gated-at.bofh.it> |
| In reply to | #1394355 |
On Wed 04-05-16 23:39:14, Joonsoo Kim wrote:
> 2016-05-04 17:53 GMT+09:00 Michal Hocko <mhocko@kernel.org>:
> > On Wed 04-05-16 15:01:24, Joonsoo Kim wrote:
> >> On Wed, Apr 20, 2016 at 03:47:25PM -0400, Michal Hocko wrote:
> > [...]
> >
> > Please try to trim your responses it makes it much easier to follow the
> > discussion
>
> Okay.
>
> >> > +static inline bool
> >> > +should_compact_retry(unsigned int order, enum compact_result compact_result,
> >> > + enum migrate_mode *migrate_mode,
> >> > + int compaction_retries)
> >> > +{
> >> > + if (!order)
> >> > + return false;
> >> > +
> >> > + /*
> >> > + * 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.
> >> > + */
> >> > + if (compaction_failed(compact_result)) {
> >>
> >> IIUC, this compaction_failed() means that at least one zone is
> >> compacted and failed. This is not same with your assumption in the
> >> comment. If compaction is done and failed on ZONE_DMA, it would be
> >> premature decision.
> >
> > Not really, because if other zones are making some progress then their
> > result will override COMPACT_COMPLETE
>
> Think about the situation that DMA zone fails to compact and
> the other zones are deferred or skipped. In this case, COMPACT_COMPLETE
> will be returned as a final result and should_compact_retry() return false.
> I don't think that it means all the zones are desperately out of memory.
But that would mean that the ZONE_DMA would be eligible for compaction,
no? And considering the watermark check this zone should COMPACT_SKIP
for most allocation request. Or am I missing something?
--
Michal Hocko
SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-04-20 21:50 +0200 |
| Subject | [PATCH 01/14] vmscan: consider classzone_idx in compaction_ready |
| Message-ID | <rq6in-4F2-35@gated-at.bofh.it> |
| In reply to | #1383701 |
From: Michal Hocko <mhocko@suse.com>
while playing with the oom detection rework [1] I have noticed
that my heavy order-9 (hugetlb) load close to OOM ended up in an
endless loop where the reclaim hasn't made any progress but
did_some_progress didn't reflect that and compaction_suitable
was backing off because no zone is above low wmark + 1 << order.
It turned out that this is in fact an old standing bug in compaction_ready
which ignores the requested_highidx and did the watermark check for
0 classzone_idx. This succeeds for zone DMA most of the time as the zone
is mostly unused because of lowmem protection. This also means that the
OOM killer wouldn't be triggered for higher order requests even when
there is no reclaim progress and we essentially rely on order-0 request
to find this out. This has been broken in one way or another since
fe4b1b244bdb ("mm: vmscan: when reclaiming for compaction, ensure there
are sufficient free pages available") but only since 7335084d446b ("mm:
vmscan: do not OOM if aborting reclaim to start compaction") we are not
invoking the OOM killer based on the wrong calculation.
Propagate requested_highidx down to compaction_ready and use it for both
the watermak check and compaction_suitable to fix this issue.
[1] http://lkml.kernel.org/r/1459855533-4600-1-git-send-email-mhocko@kernel.org
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Michal Hocko <mhocko@suse.com>
---
mm/vmscan.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index c839adc13efd..3e6347e2a5fc 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2482,7 +2482,7 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc,
* Returns true if compaction should go ahead for a high-order request, or
* the high-order allocation would succeed without compaction.
*/
-static inline bool compaction_ready(struct zone *zone, int order)
+static inline bool compaction_ready(struct zone *zone, int order, int classzone_idx)
{
unsigned long balance_gap, watermark;
bool watermark_ok;
@@ -2496,7 +2496,7 @@ static inline bool compaction_ready(struct zone *zone, int order)
balance_gap = min(low_wmark_pages(zone), DIV_ROUND_UP(
zone->managed_pages, KSWAPD_ZONE_BALANCE_GAP_RATIO));
watermark = high_wmark_pages(zone) + balance_gap + (2UL << order);
- watermark_ok = zone_watermark_ok_safe(zone, 0, watermark, 0);
+ watermark_ok = zone_watermark_ok_safe(zone, 0, watermark, classzone_idx);
/*
* If compaction is deferred, reclaim up to a point where
@@ -2509,7 +2509,7 @@ static inline bool compaction_ready(struct zone *zone, int order)
* If compaction is not ready to start and allocation is not likely
* to succeed without it, then keep reclaiming.
*/
- if (compaction_suitable(zone, order, 0, 0) == COMPACT_SKIPPED)
+ if (compaction_suitable(zone, order, 0, classzone_idx) == COMPACT_SKIPPED)
return false;
return watermark_ok;
@@ -2589,7 +2589,7 @@ static bool shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
if (IS_ENABLED(CONFIG_COMPACTION) &&
sc->order > PAGE_ALLOC_COSTLY_ORDER &&
zonelist_zone_idx(z) <= requested_highidx &&
- compaction_ready(zone, sc->order)) {
+ compaction_ready(zone, sc->order, requested_highidx)) {
sc->compaction_ready = true;
continue;
}
--
2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | "Hillf Danton" <hillf.zj@alibaba-inc.com> |
|---|---|
| Date | 2016-04-21 06:40 +0200 |
| Subject | Re: [PATCH 01/14] vmscan: consider classzone_idx in compaction_ready |
| Message-ID | <rqezf-35V-1@gated-at.bofh.it> |
| In reply to | #1383709 |
>
> From: Michal Hocko <mhocko@suse.com>
>
> while playing with the oom detection rework [1] I have noticed
> that my heavy order-9 (hugetlb) load close to OOM ended up in an
> endless loop where the reclaim hasn't made any progress but
> did_some_progress didn't reflect that and compaction_suitable
> was backing off because no zone is above low wmark + 1 << order.
>
> It turned out that this is in fact an old standing bug in compaction_ready
> which ignores the requested_highidx and did the watermark check for
> 0 classzone_idx. This succeeds for zone DMA most of the time as the zone
> is mostly unused because of lowmem protection. This also means that the
> OOM killer wouldn't be triggered for higher order requests even when
> there is no reclaim progress and we essentially rely on order-0 request
> to find this out.
Thanks.
> This has been broken in one way or another since
> fe4b1b244bdb ("mm: vmscan: when reclaiming for compaction, ensure there
> are sufficient free pages available") but only since 7335084d446b ("mm:
> vmscan: do not OOM if aborting reclaim to start compaction") we are not
> invoking the OOM killer based on the wrong calculation.
>
> Propagate requested_highidx down to compaction_ready and use it for both
> the watermak check and compaction_suitable to fix this issue.
>
> [1] http://lkml.kernel.org/r/1459855533-4600-1-git-send-email-mhocko@kernel.org
>
> Acked-by: Vlastimil Babka <vbabka@suse.cz>
> Signed-off-by: Michal Hocko <mhocko@suse.com>
> ---
Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
> mm/vmscan.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index c839adc13efd..3e6347e2a5fc 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -2482,7 +2482,7 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc,
> * Returns true if compaction should go ahead for a high-order request, or
> * the high-order allocation would succeed without compaction.
> */
> -static inline bool compaction_ready(struct zone *zone, int order)
> +static inline bool compaction_ready(struct zone *zone, int order, int classzone_idx)
> {
> unsigned long balance_gap, watermark;
> bool watermark_ok;
> @@ -2496,7 +2496,7 @@ static inline bool compaction_ready(struct zone *zone, int order)
> balance_gap = min(low_wmark_pages(zone), DIV_ROUND_UP(
> zone->managed_pages, KSWAPD_ZONE_BALANCE_GAP_RATIO));
> watermark = high_wmark_pages(zone) + balance_gap + (2UL << order);
> - watermark_ok = zone_watermark_ok_safe(zone, 0, watermark, 0);
> + watermark_ok = zone_watermark_ok_safe(zone, 0, watermark, classzone_idx);
>
> /*
> * If compaction is deferred, reclaim up to a point where
> @@ -2509,7 +2509,7 @@ static inline bool compaction_ready(struct zone *zone, int order)
> * If compaction is not ready to start and allocation is not likely
> * to succeed without it, then keep reclaiming.
> */
> - if (compaction_suitable(zone, order, 0, 0) == COMPACT_SKIPPED)
> + if (compaction_suitable(zone, order, 0, classzone_idx) == COMPACT_SKIPPED)
> return false;
>
> return watermark_ok;
> @@ -2589,7 +2589,7 @@ static bool shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
> if (IS_ENABLED(CONFIG_COMPACTION) &&
> sc->order > PAGE_ALLOC_COSTLY_ORDER &&
> zonelist_zone_idx(z) <= requested_highidx &&
> - compaction_ready(zone, sc->order)) {
> + compaction_ready(zone, sc->order, requested_highidx)) {
> sc->compaction_ready = true;
> continue;
> }
> --
> 2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-05-04 16:00 +0200 |
| Subject | Re: [PATCH 01/14] vmscan: consider classzone_idx in compaction_ready |
| Message-ID | <rv5vk-4VB-7@gated-at.bofh.it> |
| In reply to | #1383709 |
On Wed 20-04-16 15:47:14, Michal Hocko wrote:
> From: Michal Hocko <mhocko@suse.com>
>
> while playing with the oom detection rework [1] I have noticed
> that my heavy order-9 (hugetlb) load close to OOM ended up in an
> endless loop where the reclaim hasn't made any progress but
> did_some_progress didn't reflect that and compaction_suitable
> was backing off because no zone is above low wmark + 1 << order.
>
> It turned out that this is in fact an old standing bug in compaction_ready
> which ignores the requested_highidx and did the watermark check for
> 0 classzone_idx. This succeeds for zone DMA most of the time as the zone
> is mostly unused because of lowmem protection.
so far so good
> This also means that the
> OOM killer wouldn't be triggered for higher order requests even when
> there is no reclaim progress and we essentially rely on order-0 request
> to find this out. This has been broken in one way or another since
> fe4b1b244bdb ("mm: vmscan: when reclaiming for compaction, ensure there
> are sufficient free pages available") but only since 7335084d446b ("mm:
> vmscan: do not OOM if aborting reclaim to start compaction") we are not
> invoking the OOM killer based on the wrong calculation.
but now that I was looking at the code again I realize I have missed one
important thing:
shrink_zones()
if (IS_ENABLED(CONFIG_COMPACTION) &&
sc->order > PAGE_ALLOC_COSTLY_ORDER &&
zonelist_zone_idx(z) <= requested_highidx &&
compaction_ready(zone, sc->order, requested_highidx)) {
sc->compaction_ready = true;
continue;
}
so the whole argument about OOM is bogus because this whole thing is
done only for costly requests.
So the bug has not been that serious before and it started to matter
only after the oom detection rework (especially after patch 13) where we
really need even costly allocations to not lie about the progress.
Andrew, could you update the changelog to the following please?
"
while playing with the oom detection rework [1] I have noticed that my
heavy order-9 (hugetlb) load close to OOM ended up in an endless loop
where the reclaim hasn't made any progress but did_some_progress didn't
reflect that and compaction_suitable was backing off because no zone is
above low wmark + 1 << order.
It turned out that this is in fact an old standing bug in compaction_ready
which ignores the requested_highidx and did the watermark check for
0 classzone_idx. This succeeds for zone DMA most of the time as the zone
is mostly unused because of lowmem protection. As a result costly high
order allocatios always report a successfull progress even when there
was none. This wasn't a problem so far because these allocations usually
fail quite early or retry only few times with __GFP_REPEAT but this will
change after later patch in this series so make sure to not lie about
the progress and propagate requested_highidx down to compaction_ready
and use it for both the watermak check and compaction_suitable to fix
this issue.
[1] http://lkml.kernel.org/r/1459855533-4600-1-git-send-email-mhocko@kernel.org
"
Thanks and sorry for the confusion!
--
Michal Hocko
SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-04-20 21:50 +0200 |
| Subject | [PATCH 05/14] mm, compaction: distinguish between full and partial COMPACT_COMPLETE |
| Message-ID | <rq6io-4F2-47@gated-at.bofh.it> |
| In reply to | #1383701 |
From: Michal Hocko <mhocko@suse.com>
COMPACT_COMPLETE now means that compaction and free scanner met. This is
not very useful information if somebody just wants to use this feedback
and make any decisions based on that. The current caller might be a poor
guy who just happened to scan tiny portion of the zone and that could be
the reason no suitable pages were compacted. Make sure we distinguish
the full and partial zone walks.
Consumers should treat COMPACT_PARTIAL_SKIPPED as a potential success
and be optimistic in retrying.
The existing users of COMPACT_COMPLETE are conservatively changed to
use COMPACT_PARTIAL_SKIPPED as well but some of them should be probably
reconsidered and only defer the compaction only for COMPACT_COMPLETE
with the new semantic.
This patch shouldn't introduce any functional changes.
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Michal Hocko <mhocko@suse.com>
---
include/linux/compaction.h | 10 +++++++++-
include/trace/events/compaction.h | 1 +
mm/compaction.c | 14 +++++++++++---
mm/internal.h | 1 +
4 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/include/linux/compaction.h b/include/linux/compaction.h
index 7e177d111c39..7c4de92d12cc 100644
--- a/include/linux/compaction.h
+++ b/include/linux/compaction.h
@@ -21,7 +21,15 @@ enum compact_result {
* pages
*/
COMPACT_PARTIAL,
- /* The full zone was compacted */
+ /*
+ * direct compaction has scanned part of the zone but wasn't successfull
+ * to compact suitable pages.
+ */
+ COMPACT_PARTIAL_SKIPPED,
+ /*
+ * The full zone was compacted scanned but wasn't successfull to compact
+ * suitable pages.
+ */
COMPACT_COMPLETE,
/* For more detailed tracepoint output */
COMPACT_NO_SUITABLE_PAGE,
diff --git a/include/trace/events/compaction.h b/include/trace/events/compaction.h
index 6ba16c86d7db..36e2d6fb1360 100644
--- a/include/trace/events/compaction.h
+++ b/include/trace/events/compaction.h
@@ -14,6 +14,7 @@
EM( COMPACT_DEFERRED, "deferred") \
EM( COMPACT_CONTINUE, "continue") \
EM( COMPACT_PARTIAL, "partial") \
+ EM( COMPACT_PARTIAL_SKIPPED, "partial_skipped") \
EM( COMPACT_COMPLETE, "complete") \
EM( COMPACT_NO_SUITABLE_PAGE, "no_suitable_page") \
EM( COMPACT_NOT_SUITABLE_ZONE, "not_suitable_zone") \
diff --git a/mm/compaction.c b/mm/compaction.c
index 13709e33a2fc..e2e487cea5ea 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1304,7 +1304,10 @@ static enum compact_result __compact_finished(struct zone *zone, struct compact_
if (cc->direct_compaction)
zone->compact_blockskip_flush = true;
- return COMPACT_COMPLETE;
+ if (cc->whole_zone)
+ return COMPACT_COMPLETE;
+ else
+ return COMPACT_PARTIAL_SKIPPED;
}
if (is_via_compact_memory(cc->order))
@@ -1463,6 +1466,10 @@ static enum compact_result compact_zone(struct zone *zone, struct compact_contro
zone->compact_cached_migrate_pfn[0] = cc->migrate_pfn;
zone->compact_cached_migrate_pfn[1] = cc->migrate_pfn;
}
+
+ if (cc->migrate_pfn == start_pfn)
+ cc->whole_zone = true;
+
cc->last_migrated_pfn = 0;
trace_mm_compaction_begin(start_pfn, cc->migrate_pfn,
@@ -1693,7 +1700,8 @@ 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 (mode != MIGRATE_ASYNC && (status == COMPACT_COMPLETE ||
+ status == COMPACT_PARTIAL_SKIPPED)) {
/*
* We think that allocation won't succeed in this zone
* so we defer compaction there. If it ends up
@@ -1939,7 +1947,7 @@ static void kcompactd_do_work(pg_data_t *pgdat)
cc.classzone_idx, 0)) {
success = true;
compaction_defer_reset(zone, cc.order, false);
- } else if (status == COMPACT_COMPLETE) {
+ } else if (status == COMPACT_PARTIAL_SKIPPED || status == COMPACT_COMPLETE) {
/*
* We use sync migration mode here, so we defer like
* sync direct compaction does.
diff --git a/mm/internal.h b/mm/internal.h
index e9aacea1a0d1..4423dfe69382 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -182,6 +182,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 */
int order; /* order a direct compactor needs */
const gfp_t gfp_mask; /* gfp mask of a direct compactor */
const int alloc_flags; /* alloc flags of a direct compactor */
--
2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | "Hillf Danton" <hillf.zj@alibaba-inc.com> |
|---|---|
| Date | 2016-04-21 08:40 +0200 |
| Subject | Re: [PATCH 05/14] mm, compaction: distinguish between full and partial COMPACT_COMPLETE |
| Message-ID | <rqgrn-4xr-1@gated-at.bofh.it> |
| In reply to | #1383712 |
>
> From: Michal Hocko <mhocko@suse.com>
>
> COMPACT_COMPLETE now means that compaction and free scanner met. This is
> not very useful information if somebody just wants to use this feedback
> and make any decisions based on that. The current caller might be a poor
> guy who just happened to scan tiny portion of the zone and that could be
> the reason no suitable pages were compacted. Make sure we distinguish
> the full and partial zone walks.
>
> Consumers should treat COMPACT_PARTIAL_SKIPPED as a potential success
> and be optimistic in retrying.
>
> The existing users of COMPACT_COMPLETE are conservatively changed to
> use COMPACT_PARTIAL_SKIPPED as well but some of them should be probably
> reconsidered and only defer the compaction only for COMPACT_COMPLETE
> with the new semantic.
>
> This patch shouldn't introduce any functional changes.
>
> Acked-by: Vlastimil Babka <vbabka@suse.cz>
> Signed-off-by: Michal Hocko <mhocko@suse.com>
> ---
Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
> include/linux/compaction.h | 10 +++++++++-
> include/trace/events/compaction.h | 1 +
> mm/compaction.c | 14 +++++++++++---
> mm/internal.h | 1 +
> 4 files changed, 22 insertions(+), 4 deletions(-)
>
> diff --git a/include/linux/compaction.h b/include/linux/compaction.h
> index 7e177d111c39..7c4de92d12cc 100644
> --- a/include/linux/compaction.h
> +++ b/include/linux/compaction.h
> @@ -21,7 +21,15 @@ enum compact_result {
> * pages
> */
> COMPACT_PARTIAL,
> - /* The full zone was compacted */
> + /*
> + * direct compaction has scanned part of the zone but wasn't successfull
> + * to compact suitable pages.
> + */
> + COMPACT_PARTIAL_SKIPPED,
> + /*
> + * The full zone was compacted scanned but wasn't successfull to compact
> + * suitable pages.
> + */
> COMPACT_COMPLETE,
> /* For more detailed tracepoint output */
> COMPACT_NO_SUITABLE_PAGE,
> diff --git a/include/trace/events/compaction.h b/include/trace/events/compaction.h
> index 6ba16c86d7db..36e2d6fb1360 100644
> --- a/include/trace/events/compaction.h
> +++ b/include/trace/events/compaction.h
> @@ -14,6 +14,7 @@
> EM( COMPACT_DEFERRED, "deferred") \
> EM( COMPACT_CONTINUE, "continue") \
> EM( COMPACT_PARTIAL, "partial") \
> + EM( COMPACT_PARTIAL_SKIPPED, "partial_skipped") \
> EM( COMPACT_COMPLETE, "complete") \
> EM( COMPACT_NO_SUITABLE_PAGE, "no_suitable_page") \
> EM( COMPACT_NOT_SUITABLE_ZONE, "not_suitable_zone") \
> diff --git a/mm/compaction.c b/mm/compaction.c
> index 13709e33a2fc..e2e487cea5ea 100644
> --- a/mm/compaction.c
> +++ b/mm/compaction.c
> @@ -1304,7 +1304,10 @@ static enum compact_result __compact_finished(struct zone *zone, struct compact_
> if (cc->direct_compaction)
> zone->compact_blockskip_flush = true;
>
> - return COMPACT_COMPLETE;
> + if (cc->whole_zone)
> + return COMPACT_COMPLETE;
> + else
> + return COMPACT_PARTIAL_SKIPPED;
> }
>
> if (is_via_compact_memory(cc->order))
> @@ -1463,6 +1466,10 @@ static enum compact_result compact_zone(struct zone *zone, struct compact_contro
> zone->compact_cached_migrate_pfn[0] = cc->migrate_pfn;
> zone->compact_cached_migrate_pfn[1] = cc->migrate_pfn;
> }
> +
> + if (cc->migrate_pfn == start_pfn)
> + cc->whole_zone = true;
> +
> cc->last_migrated_pfn = 0;
>
> trace_mm_compaction_begin(start_pfn, cc->migrate_pfn,
> @@ -1693,7 +1700,8 @@ 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 (mode != MIGRATE_ASYNC && (status == COMPACT_COMPLETE ||
> + status == COMPACT_PARTIAL_SKIPPED)) {
> /*
> * We think that allocation won't succeed in this zone
> * so we defer compaction there. If it ends up
> @@ -1939,7 +1947,7 @@ static void kcompactd_do_work(pg_data_t *pgdat)
> cc.classzone_idx, 0)) {
> success = true;
> compaction_defer_reset(zone, cc.order, false);
> - } else if (status == COMPACT_COMPLETE) {
> + } else if (status == COMPACT_PARTIAL_SKIPPED || status == COMPACT_COMPLETE) {
> /*
> * We use sync migration mode here, so we defer like
> * sync direct compaction does.
> diff --git a/mm/internal.h b/mm/internal.h
> index e9aacea1a0d1..4423dfe69382 100644
> --- a/mm/internal.h
> +++ b/mm/internal.h
> @@ -182,6 +182,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 */
> int order; /* order a direct compactor needs */
> const gfp_t gfp_mask; /* gfp mask of a direct compactor */
> const int alloc_flags; /* alloc flags of a direct compactor */
> --
> 2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-04-20 21:50 +0200 |
| Subject | [PATCH 08/14] mm, compaction: Abstract compaction feedback to helpers |
| Message-ID | <rq6io-4F2-45@gated-at.bofh.it> |
| In reply to | #1383701 |
From: Michal Hocko <mhocko@suse.com>
Compaction can provide a wild variation of feedback to the caller. Many
of them are implementation specific and the caller of the compaction
(especially the page allocator) shouldn't be bound to specifics of the
current implementation.
This patch abstracts the feedback into three basic types:
- compaction_made_progress - compaction was active and made some
progress.
- compaction_failed - compaction failed and further attempts to
invoke it would most probably fail and therefore it is not
worth retrying
- compaction_withdrawn - compaction wasn't invoked for an
implementation specific reasons. In the current implementation
it means that the compaction was deferred, contended or the
page scanners met too early without any progress. Retrying is
still worthwhile.
[vbabka@suse.cz: do not change thp back off behavior]
Signed-off-by: Michal Hocko <mhocko@suse.com>
---
include/linux/compaction.h | 79 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/include/linux/compaction.h b/include/linux/compaction.h
index a7b9091ff349..a002ca55c513 100644
--- a/include/linux/compaction.h
+++ b/include/linux/compaction.h
@@ -78,6 +78,70 @@ extern void compaction_defer_reset(struct zone *zone, int order,
bool alloc_success);
extern bool compaction_restarting(struct zone *zone, int order);
+/* Compaction has made some progress and retrying makes sense */
+static inline bool compaction_made_progress(enum compact_result result)
+{
+ /*
+ * Even though this might sound confusing this in fact tells us
+ * that the compaction successfully isolated and migrated some
+ * pageblocks.
+ */
+ if (result == COMPACT_PARTIAL)
+ return true;
+
+ return false;
+}
+
+/* Compaction has failed and it doesn't make much sense to keep retrying. */
+static inline bool compaction_failed(enum compact_result result)
+{
+ /* All zones where scanned completely and still not result. */
+ if (result == COMPACT_COMPLETE)
+ return true;
+
+ return false;
+}
+
+/*
+ * Compaction has backed off for some reason. It might be throttling or
+ * lock contention. Retrying is still worthwhile.
+ */
+static inline bool compaction_withdrawn(enum compact_result result)
+{
+ /*
+ * Compaction backed off due to watermark checks for order-0
+ * so the regular reclaim has to try harder and reclaim something.
+ */
+ if (result == COMPACT_SKIPPED)
+ return true;
+
+ /*
+ * If compaction is deferred for high-order allocations, it is
+ * because sync compaction recently failed. If this is the case
+ * and the caller requested a THP allocation, we do not want
+ * to heavily disrupt the system, so we fail the allocation
+ * instead of entering direct reclaim.
+ */
+ if (result == COMPACT_DEFERRED)
+ return true;
+
+ /*
+ * If compaction in async mode encounters contention or blocks higher
+ * priority task we back off early rather than cause stalls.
+ */
+ if (result == COMPACT_CONTENDED)
+ return true;
+
+ /*
+ * Page scanners have met but we haven't scanned full zones so this
+ * is a back off in fact.
+ */
+ if (result == COMPACT_PARTIAL_SKIPPED)
+ return true;
+
+ return false;
+}
+
extern int kcompactd_run(int nid);
extern void kcompactd_stop(int nid);
extern void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx);
@@ -114,6 +178,21 @@ static inline bool compaction_deferred(struct zone *zone, int order)
return true;
}
+static inline bool compaction_made_progress(enum compact_result result)
+{
+ return false;
+}
+
+static inline bool compaction_failed(enum compact_result result)
+{
+ return false;
+}
+
+static inline bool compaction_withdrawn(enum compact_result result)
+{
+ return true;
+}
+
static inline int kcompactd_run(int nid)
{
return 0;
--
2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | Vlastimil Babka <vbabka@suse.cz> |
|---|---|
| Date | 2016-04-28 10:50 +0200 |
| Subject | Re: [PATCH 08/14] mm, compaction: Abstract compaction feedback to helpers |
| Message-ID | <rsPO2-e7-11@gated-at.bofh.it> |
| In reply to | #1383713 |
On 04/20/2016 09:47 PM, Michal Hocko wrote: > From: Michal Hocko <mhocko@suse.com> > > Compaction can provide a wild variation of feedback to the caller. Many > of them are implementation specific and the caller of the compaction > (especially the page allocator) shouldn't be bound to specifics of the > current implementation. > > This patch abstracts the feedback into three basic types: > - compaction_made_progress - compaction was active and made some > progress. > - compaction_failed - compaction failed and further attempts to > invoke it would most probably fail and therefore it is not > worth retrying > - compaction_withdrawn - compaction wasn't invoked for an > implementation specific reasons. In the current implementation > it means that the compaction was deferred, contended or the > page scanners met too early without any progress. Retrying is > still worthwhile. > > [vbabka@suse.cz: do not change thp back off behavior] > Signed-off-by: Michal Hocko <mhocko@suse.com> Acked-by: Vlastimil Babka <vbabka@suse.cz>
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-04-20 21:50 +0200 |
| Subject | [PATCH 09/14] mm: use compaction feedback for thp backoff conditions |
| Message-ID | <rq6io-4F2-55@gated-at.bofh.it> |
| In reply to | #1383701 |
From: Michal Hocko <mhocko@suse.com>
THP requests skip the direct reclaim if the compaction is either
deferred or contended to reduce stalls which wouldn't help the
allocation success anyway. These checks are ignoring other potential
feedback modes which we have available now.
It clearly doesn't make much sense to go and reclaim few pages if the
previous compaction has failed.
We can also simplify the check by using compaction_withdrawn which
checks for both COMPACT_CONTENDED and COMPACT_DEFERRED. This check
is however covering more reasons why the compaction was withdrawn.
None of them should be a problem for the THP case though.
It is safe to back of if we see COMPACT_SKIPPED because that means
that compaction_suitable failed and a single round of the reclaim is
unlikely to make any difference here. We would have to be close to
the low watermark to reclaim enough and even then there is no guarantee
that the compaction would make any progress while the direct reclaim
would have caused the stall.
COMPACT_PARTIAL_SKIPPED is slightly different because that means that we
have only seen a part of the zone so a retry would make some sense. But
it would be a compaction retry not a reclaim retry to perform. We are
not doing that and that might indeed lead to situations where THP fails
but this should happen only rarely and it would be really hard to
measure.
Signed-off-by: Michal Hocko <mhocko@suse.com>
---
mm/page_alloc.c | 27 ++++++++-------------------
1 file changed, 8 insertions(+), 19 deletions(-)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 350d13f3709b..d551fe326c33 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3257,25 +3257,14 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
if (page)
goto got_pg;
- /* Checks for THP-specific high-order allocations */
- if (is_thp_gfp_mask(gfp_mask)) {
- /*
- * If compaction is deferred for high-order allocations, it is
- * because sync compaction recently failed. If this is the case
- * and the caller requested a THP allocation, we do not want
- * to heavily disrupt the system, so we fail the allocation
- * instead of entering direct reclaim.
- */
- if (compact_result == COMPACT_DEFERRED)
- goto nopage;
-
- /*
- * Compaction is contended so rather back off than cause
- * excessive stalls.
- */
- if(compact_result == COMPACT_CONTENDED)
- goto nopage;
- }
+ /*
+ * Checks for THP-specific high-order allocations and back off
+ * if the the compaction backed off or failed
+ */
+ if (is_thp_gfp_mask(gfp_mask) &&
+ (compaction_withdrawn(compact_result) ||
+ compaction_failed(compact_result)))
+ goto nopage;
/*
* It can become very expensive to allocate transparent hugepages at
--
2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | "Hillf Danton" <hillf.zj@alibaba-inc.com> |
|---|---|
| Date | 2016-04-21 09:10 +0200 |
| Subject | Re: [PATCH 09/14] mm: use compaction feedback for thp backoff conditions |
| Message-ID | <rqgUq-59Y-17@gated-at.bofh.it> |
| In reply to | #1383714 |
>
> From: Michal Hocko <mhocko@suse.com>
>
> THP requests skip the direct reclaim if the compaction is either
> deferred or contended to reduce stalls which wouldn't help the
> allocation success anyway. These checks are ignoring other potential
> feedback modes which we have available now.
>
> It clearly doesn't make much sense to go and reclaim few pages if the
> previous compaction has failed.
>
> We can also simplify the check by using compaction_withdrawn which
> checks for both COMPACT_CONTENDED and COMPACT_DEFERRED. This check
> is however covering more reasons why the compaction was withdrawn.
> None of them should be a problem for the THP case though.
>
> It is safe to back of if we see COMPACT_SKIPPED because that means
> that compaction_suitable failed and a single round of the reclaim is
> unlikely to make any difference here. We would have to be close to
> the low watermark to reclaim enough and even then there is no guarantee
> that the compaction would make any progress while the direct reclaim
> would have caused the stall.
>
> COMPACT_PARTIAL_SKIPPED is slightly different because that means that we
> have only seen a part of the zone so a retry would make some sense. But
> it would be a compaction retry not a reclaim retry to perform. We are
> not doing that and that might indeed lead to situations where THP fails
> but this should happen only rarely and it would be really hard to
> measure.
>
> Signed-off-by: Michal Hocko <mhocko@suse.com>
> ---
Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
> mm/page_alloc.c | 27 ++++++++-------------------
> 1 file changed, 8 insertions(+), 19 deletions(-)
>
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index 350d13f3709b..d551fe326c33 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -3257,25 +3257,14 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
> if (page)
> goto got_pg;
>
> - /* Checks for THP-specific high-order allocations */
> - if (is_thp_gfp_mask(gfp_mask)) {
> - /*
> - * If compaction is deferred for high-order allocations, it is
> - * because sync compaction recently failed. If this is the case
> - * and the caller requested a THP allocation, we do not want
> - * to heavily disrupt the system, so we fail the allocation
> - * instead of entering direct reclaim.
> - */
> - if (compact_result == COMPACT_DEFERRED)
> - goto nopage;
> -
> - /*
> - * Compaction is contended so rather back off than cause
> - * excessive stalls.
> - */
> - if(compact_result == COMPACT_CONTENDED)
> - goto nopage;
> - }
> + /*
> + * Checks for THP-specific high-order allocations and back off
> + * if the the compaction backed off or failed
> + */
Alternatively,
/*
* Check THP allocations and back off
* if the compaction bailed out or failed
*/
> + if (is_thp_gfp_mask(gfp_mask) &&
> + (compaction_withdrawn(compact_result) ||
> + compaction_failed(compact_result)))
> + goto nopage;
>
> /*
> * It can become very expensive to allocate transparent hugepages at
> --
> 2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | Vlastimil Babka <vbabka@suse.cz> |
|---|---|
| Date | 2016-04-28 11:00 +0200 |
| Subject | Re: [PATCH 09/14] mm: use compaction feedback for thp backoff conditions |
| Message-ID | <rsPXI-hT-19@gated-at.bofh.it> |
| In reply to | #1383714 |
On 04/20/2016 09:47 PM, Michal Hocko wrote: > From: Michal Hocko <mhocko@suse.com> > > THP requests skip the direct reclaim if the compaction is either > deferred or contended to reduce stalls which wouldn't help the > allocation success anyway. These checks are ignoring other potential > feedback modes which we have available now. > > It clearly doesn't make much sense to go and reclaim few pages if the > previous compaction has failed. > > We can also simplify the check by using compaction_withdrawn which > checks for both COMPACT_CONTENDED and COMPACT_DEFERRED. This check > is however covering more reasons why the compaction was withdrawn. > None of them should be a problem for the THP case though. > > It is safe to back of if we see COMPACT_SKIPPED because that means > that compaction_suitable failed and a single round of the reclaim is > unlikely to make any difference here. We would have to be close to > the low watermark to reclaim enough and even then there is no guarantee > that the compaction would make any progress while the direct reclaim > would have caused the stall. > > COMPACT_PARTIAL_SKIPPED is slightly different because that means that we > have only seen a part of the zone so a retry would make some sense. But > it would be a compaction retry not a reclaim retry to perform. We are > not doing that and that might indeed lead to situations where THP fails > but this should happen only rarely and it would be really hard to > measure. > > Signed-off-by: Michal Hocko <mhocko@suse.com> THP's don't compact by default in page fault path anymore, so we don't need to restrict them even more. And hopefully we'll replace the is_thp_gfp_mask() hack with something better soon, so this might be just extra code churn. But I don't feel strongly enough to nack it.
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-04-28 14:40 +0200 |
| Subject | Re: [PATCH 09/14] mm: use compaction feedback for thp backoff conditions |
| Message-ID | <rsToB-36j-13@gated-at.bofh.it> |
| In reply to | #1389899 |
On Thu 28-04-16 10:53:18, Vlastimil Babka wrote: > On 04/20/2016 09:47 PM, Michal Hocko wrote: > >From: Michal Hocko <mhocko@suse.com> > > > >THP requests skip the direct reclaim if the compaction is either > >deferred or contended to reduce stalls which wouldn't help the > >allocation success anyway. These checks are ignoring other potential > >feedback modes which we have available now. > > > >It clearly doesn't make much sense to go and reclaim few pages if the > >previous compaction has failed. > > > >We can also simplify the check by using compaction_withdrawn which > >checks for both COMPACT_CONTENDED and COMPACT_DEFERRED. This check > >is however covering more reasons why the compaction was withdrawn. > >None of them should be a problem for the THP case though. > > > >It is safe to back of if we see COMPACT_SKIPPED because that means > >that compaction_suitable failed and a single round of the reclaim is > >unlikely to make any difference here. We would have to be close to > >the low watermark to reclaim enough and even then there is no guarantee > >that the compaction would make any progress while the direct reclaim > >would have caused the stall. > > > >COMPACT_PARTIAL_SKIPPED is slightly different because that means that we > >have only seen a part of the zone so a retry would make some sense. But > >it would be a compaction retry not a reclaim retry to perform. We are > >not doing that and that might indeed lead to situations where THP fails > >but this should happen only rarely and it would be really hard to > >measure. > > > >Signed-off-by: Michal Hocko <mhocko@suse.com> > > THP's don't compact by default in page fault path anymore, so we don't need > to restrict them even more. And hopefully we'll replace the > is_thp_gfp_mask() hack with something better soon, so this might be just > extra code churn. But I don't feel strongly enough to nack it. My main point was to simplify the code and get rid of as much compaction specific hacks as possible. We might very well drop this later on but it would be at least less code to grasp through. I do not have any problem with dropping this but I think this shouldn't collide with other patches much so reducing the number of lines is worth it. -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Vlastimil Babka <vbabka@suse.cz> |
|---|---|
| Date | 2016-04-29 11:20 +0200 |
| Subject | Re: [PATCH 09/14] mm: use compaction feedback for thp backoff conditions |
| Message-ID | <rtcKC-3oy-19@gated-at.bofh.it> |
| In reply to | #1390130 |
On 04/28/2016 02:35 PM, Michal Hocko wrote: > On Thu 28-04-16 10:53:18, Vlastimil Babka wrote: >> On 04/20/2016 09:47 PM, Michal Hocko wrote: >>> From: Michal Hocko <mhocko@suse.com> >>> >>> THP requests skip the direct reclaim if the compaction is either >>> deferred or contended to reduce stalls which wouldn't help the >>> allocation success anyway. These checks are ignoring other potential >>> feedback modes which we have available now. >>> >>> It clearly doesn't make much sense to go and reclaim few pages if the >>> previous compaction has failed. >>> >>> We can also simplify the check by using compaction_withdrawn which >>> checks for both COMPACT_CONTENDED and COMPACT_DEFERRED. This check >>> is however covering more reasons why the compaction was withdrawn. >>> None of them should be a problem for the THP case though. >>> >>> It is safe to back of if we see COMPACT_SKIPPED because that means >>> that compaction_suitable failed and a single round of the reclaim is >>> unlikely to make any difference here. We would have to be close to Hmm this is actually incorrect, as should_continue_reclaim() will keep shrink_zone() going as much as needed for compaction to become enabled, so it doesn't reclaim just SWAP_CLUSTER_MAX. >>> the low watermark to reclaim enough and even then there is no guarantee >>> that the compaction would make any progress while the direct reclaim >>> would have caused the stall. >>> >>> COMPACT_PARTIAL_SKIPPED is slightly different because that means that we >>> have only seen a part of the zone so a retry would make some sense. But >>> it would be a compaction retry not a reclaim retry to perform. We are >>> not doing that and that might indeed lead to situations where THP fails >>> but this should happen only rarely and it would be really hard to >>> measure. >>> >>> Signed-off-by: Michal Hocko <mhocko@suse.com> >> >> THP's don't compact by default in page fault path anymore, so we don't need >> to restrict them even more. And hopefully we'll replace the >> is_thp_gfp_mask() hack with something better soon, so this might be just >> extra code churn. But I don't feel strongly enough to nack it. > > My main point was to simplify the code and get rid of as much compaction > specific hacks as possible. We might very well drop this later on but it > would be at least less code to grasp through. I do not have any problem > with dropping this but I think this shouldn't collide with other patches > much so reducing the number of lines is worth it. I just realized it also affects khugepaged, and not just THP page faults, so it may potentially cripple THP's completely. My main issue is that the reasons to bail out includes COMPACT_SKIPPED, and for a wrong reason (see the comment above). It also goes against the comment below the noretry label: * High-order allocations do not necessarily loop after direct reclaim * and reclaim/compaction depends on compaction being called after * reclaim so call directly if necessary. Given that THP's are large, I expect reclaim would indeed be quite often necessary before compaction, and the first optimistic async compaction attempt will just return SKIPPED. After this patch, there will be no more reclaim/compaction attempts for THP's, including khugepaged. And given the change of THP page fault defaults, even crippling that path should no longer be necessary. So I would just drop this for now indeed.
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-04-29 11:30 +0200 |
| Subject | Re: [PATCH 09/14] mm: use compaction feedback for thp backoff conditions |
| Message-ID | <rtcUi-3th-17@gated-at.bofh.it> |
| In reply to | #1390917 |
On Fri 29-04-16 11:16:44, Vlastimil Babka wrote: > On 04/28/2016 02:35 PM, Michal Hocko wrote: [...] > >My main point was to simplify the code and get rid of as much compaction > >specific hacks as possible. We might very well drop this later on but it > >would be at least less code to grasp through. I do not have any problem > >with dropping this but I think this shouldn't collide with other patches > >much so reducing the number of lines is worth it. Good point, I have completely missed this part. > I just realized it also affects khugepaged, and not just THP page faults, so > it may potentially cripple THP's completely. My main issue is that the > reasons to bail out includes COMPACT_SKIPPED, and for a wrong reason (see > the comment above). It also goes against the comment below the noretry > label: > > * High-order allocations do not necessarily loop after direct reclaim > * and reclaim/compaction depends on compaction being called after > * reclaim so call directly if necessary. > > Given that THP's are large, I expect reclaim would indeed be quite often > necessary before compaction, and the first optimistic async compaction > attempt will just return SKIPPED. After this patch, there will be no more > reclaim/compaction attempts for THP's, including khugepaged. And given the > change of THP page fault defaults, even crippling that path should no longer > be necessary. > > So I would just drop this for now indeed. Agreed, thanks for catching this. Andrew, could you drop this patch please? It was supposed to be a mere clean up without any effect on the oom detection. Thanks! -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-04-20 21:50 +0200 |
| Subject | [PATCH 13/14] mm: consider compaction feedback also for costly allocation |
| Message-ID | <rq6io-4F2-59@gated-at.bofh.it> |
| In reply to | #1383701 |
From: Michal Hocko <mhocko@suse.com>
PAGE_ALLOC_COSTLY_ORDER retry logic is mostly handled inside
should_reclaim_retry currently where we decide to not retry after at
least order worth of pages were reclaimed or the watermark check for at
least one zone would succeed after reclaiming all pages if the reclaim
hasn't made any progress. Compaction feedback is mostly ignored and we
just try to make sure that the compaction did at least something before
giving up.
The first condition was added by a41f24ea9fd6 ("page allocator: smarter
retry of costly-order allocations) and it assumed that lumpy reclaim
could have created a page of the sufficient order. Lumpy reclaim,
has been removed quite some time ago so the assumption doesn't hold
anymore. Remove the check for the number of reclaimed pages and rely
on the compaction feedback solely. should_reclaim_retry now only
makes sure that we keep retrying reclaim for high order pages only
if they are hidden by watermaks so order-0 reclaim makes really sense.
should_compact_retry now keeps retrying even for the costly allocations.
The number of retries is reduced wrt. !costly requests because they are
less important and harder to grant and so their pressure shouldn't cause
contention for other requests or cause an over reclaim. We also do not
reset no_progress_loops for costly request to make sure we do not keep
reclaiming too agressively.
This has been tested by running a process which fragments memory:
- compact memory
- mmap large portion of the memory (1920M on 2GRAM machine with 2G
of swapspace)
- MADV_DONTNEED single page in PAGE_SIZE*((1UL<<MAX_ORDER)-1)
steps until certain amount of memory is freed (250M in my test)
and reduce the step to (step / 2) + 1 after reaching the end of
the mapping
- then run a script which populates the page cache 2G (MemTotal)
from /dev/zero to a new file
And then tries to allocate
nr_hugepages=$(awk '/MemAvailable/{printf "%d\n", $2/(2*1024)}' /proc/meminfo)
huge pages.
root@test1:~# echo 1 > /proc/sys/vm/overcommit_memory;echo 1 > /proc/sys/vm/compact_memory; ./fragment-mem-and-run /root/alloc_hugepages.sh 1920M 250M
Node 0, zone DMA 31 28 31 10 2 0 2 1 2 3 1
Node 0, zone DMA32 437 319 171 50 28 25 20 16 16 14 437
* This is the /proc/buddyinfo after the compaction
Done fragmenting. size=2013265920 freed=262144000
Node 0, zone DMA 165 48 3 1 2 0 2 2 2 2 0
Node 0, zone DMA32 35109 14575 185 51 41 12 6 0 0 0 0
* /proc/buddyinfo after memory got fragmented
Executing "/root/alloc_hugepages.sh"
Eating some pagecache
508623+0 records in
508623+0 records out
2083319808 bytes (2.1 GB) copied, 11.7292 s, 178 MB/s
Node 0, zone DMA 3 5 3 1 2 0 2 2 2 2 0
Node 0, zone DMA32 111 344 153 20 24 10 3 0 0 0 0
* /proc/buddyinfo after page cache got eaten
Trying to allocate 129
129
* 129 hugepages requested and all of them granted.
Node 0, zone DMA 3 5 3 1 2 0 2 2 2 2 0
Node 0, zone DMA32 127 97 30 99 11 6 2 1 4 0 0
* /proc/buddyinfo after hugetlb allocation.
10 runs will behave as follows:
Trying to allocate 130
130
--
Trying to allocate 129
129
--
Trying to allocate 128
128
--
Trying to allocate 129
129
--
Trying to allocate 128
128
--
Trying to allocate 129
129
--
Trying to allocate 132
132
--
Trying to allocate 129
129
--
Trying to allocate 128
128
--
Trying to allocate 129
129
So basically 100% success for all 10 attempts.
Without the patch numbers looked much worse:
Trying to allocate 128
12
--
Trying to allocate 129
14
--
Trying to allocate 129
7
--
Trying to allocate 129
16
--
Trying to allocate 129
30
--
Trying to allocate 129
38
--
Trying to allocate 129
19
--
Trying to allocate 129
37
--
Trying to allocate 129
28
--
Trying to allocate 129
37
Just for completness the base kernel without oom detection rework looks
as follows:
Trying to allocate 127
30
--
Trying to allocate 129
12
--
Trying to allocate 129
52
--
Trying to allocate 128
32
--
Trying to allocate 129
12
--
Trying to allocate 129
10
--
Trying to allocate 129
32
--
Trying to allocate 128
14
--
Trying to allocate 128
16
--
Trying to allocate 129
8
As we can see the success rate is much more volatile and smaller without
this patch. So the patch not only makes the retry logic for costly
requests more sensible the success rate is even higher.
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Michal Hocko <mhocko@suse.com>
---
mm/page_alloc.c | 63 +++++++++++++++++++++++++++++----------------------------
1 file changed, 32 insertions(+), 31 deletions(-)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index bb4df1be0d43..d5a938f12554 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3019,6 +3019,8 @@ should_compact_retry(unsigned int order, enum compact_result compact_result,
enum migrate_mode *migrate_mode,
int compaction_retries)
{
+ int max_retries = MAX_COMPACT_RETRIES;
+
if (!order)
return false;
@@ -3036,17 +3038,24 @@ should_compact_retry(unsigned int order, enum compact_result compact_result,
}
/*
- * !costly allocations are really important and we have to make sure
- * the compaction wasn't deferred or didn't bail out early due to locks
- * contention before we go OOM. Still cap the reclaim retry loops with
- * progress to prevent from looping forever and potential trashing.
+ * make sure the compaction wasn't deferred or didn't bail out early
+ * due to locks contention before we declare that we should give up.
*/
- if (order <= PAGE_ALLOC_COSTLY_ORDER) {
- if (compaction_withdrawn(compact_result))
- return true;
- if (compaction_retries <= MAX_COMPACT_RETRIES)
- return true;
- }
+ if (compaction_withdrawn(compact_result))
+ return true;
+
+ /*
+ * !costly requests are much more important than __GFP_REPEAT
+ * costly ones because they are de facto nofail and invoke OOM
+ * killer to move on while costly can fail and users are ready
+ * to cope with that. 1/4 retries is rather arbitrary but we
+ * would need much more detailed feedback from compaction to
+ * make a better decision.
+ */
+ if (order > PAGE_ALLOC_COSTLY_ORDER)
+ max_retries /= 4;
+ if (compaction_retries <= max_retries)
+ return true;
return false;
}
@@ -3207,18 +3216,17 @@ static inline bool is_thp_gfp_mask(gfp_t gfp_mask)
* Checks whether it makes sense to retry the reclaim to make a forward progress
* for the given allocation request.
* The reclaim feedback represented by did_some_progress (any progress during
- * the last reclaim round), pages_reclaimed (cumulative number of reclaimed
- * pages) and no_progress_loops (number of reclaim rounds without any progress
- * in a row) is considered as well as the reclaimable pages on the applicable
- * zone list (with a backoff mechanism which is a function of no_progress_loops).
+ * the last reclaim round) and no_progress_loops (number of reclaim rounds without
+ * any progress in a row) is considered as well as the reclaimable pages on the
+ * applicable zone list (with a backoff mechanism which is a function of
+ * no_progress_loops).
*
* Returns true if a retry is viable or false to enter the oom path.
*/
static inline bool
should_reclaim_retry(gfp_t gfp_mask, unsigned order,
struct alloc_context *ac, int alloc_flags,
- bool did_some_progress, unsigned long pages_reclaimed,
- int no_progress_loops)
+ bool did_some_progress, int no_progress_loops)
{
struct zone *zone;
struct zoneref *z;
@@ -3230,14 +3238,6 @@ should_reclaim_retry(gfp_t gfp_mask, unsigned order,
if (no_progress_loops > MAX_RECLAIM_RETRIES)
return false;
- if (order > PAGE_ALLOC_COSTLY_ORDER) {
- if (pages_reclaimed >= (1<<order))
- return false;
-
- if (did_some_progress)
- return true;
- }
-
/*
* Keep reclaiming pages while there is a chance this will lead somewhere.
* If none of the target zones can satisfy our allocation request even
@@ -3308,7 +3308,6 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
bool can_direct_reclaim = gfp_mask & __GFP_DIRECT_RECLAIM;
struct page *page = NULL;
int alloc_flags;
- unsigned long pages_reclaimed = 0;
unsigned long did_some_progress;
enum migrate_mode migration_mode = MIGRATE_ASYNC;
enum compact_result compact_result;
@@ -3444,16 +3443,18 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
if (order > PAGE_ALLOC_COSTLY_ORDER && !(gfp_mask & __GFP_REPEAT))
goto noretry;
- if (did_some_progress) {
+ /*
+ * Costly allocations might have made a progress but this doesn't mean
+ * their order will become available due to high fragmentation so
+ * always increment the no progress counter for them
+ */
+ if (did_some_progress && order <= PAGE_ALLOC_COSTLY_ORDER)
no_progress_loops = 0;
- pages_reclaimed += did_some_progress;
- } else {
+ else
no_progress_loops++;
- }
if (should_reclaim_retry(gfp_mask, order, ac, alloc_flags,
- did_some_progress > 0, pages_reclaimed,
- no_progress_loops))
+ did_some_progress > 0, no_progress_loops))
goto retry;
/*
--
2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-04-20 22:00 +0200 |
| Subject | [PATCH 04/14] mm, compaction: distinguish COMPACT_DEFERRED from COMPACT_SKIPPED |
| Message-ID | <rq6s1-4Jb-9@gated-at.bofh.it> |
| In reply to | #1383701 |
From: Michal Hocko <mhocko@suse.com>
try_to_compact_pages can currently return COMPACT_SKIPPED even when the
compaction is defered for some zone just because zone DMA is skipped
in 99% of cases due to watermark checks. This makes COMPACT_DEFERRED
basically unusable for the page allocator as a feedback mechanism.
Make sure we distinguish those two states properly and switch their
ordering in the enum. This would mean that the COMPACT_SKIPPED will be
returned only when all eligible zones are skipped.
As a result COMPACT_DEFERRED handling for THP in __alloc_pages_slowpath
will be more precise and we would bail out rather than reclaim.
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Michal Hocko <mhocko@suse.com>
---
include/linux/compaction.h | 7 +++++--
include/trace/events/compaction.h | 2 +-
mm/compaction.c | 8 +++++---
3 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/include/linux/compaction.h b/include/linux/compaction.h
index 4458fd94170f..7e177d111c39 100644
--- a/include/linux/compaction.h
+++ b/include/linux/compaction.h
@@ -4,13 +4,16 @@
/* Return values for compact_zone() and try_to_compact_pages() */
/* When adding new states, please adjust include/trace/events/compaction.h */
enum compact_result {
- /* compaction didn't start as it was deferred due to past failures */
- COMPACT_DEFERRED,
/*
* compaction didn't start as it was not possible or direct reclaim
* was more suitable
*/
COMPACT_SKIPPED,
+ /* compaction didn't start as it was deferred due to past failures */
+ COMPACT_DEFERRED,
+ /* compaction not active last round */
+ COMPACT_INACTIVE = COMPACT_DEFERRED,
+
/* compaction should continue to another pageblock */
COMPACT_CONTINUE,
/*
diff --git a/include/trace/events/compaction.h b/include/trace/events/compaction.h
index e215bf68f521..6ba16c86d7db 100644
--- a/include/trace/events/compaction.h
+++ b/include/trace/events/compaction.h
@@ -10,8 +10,8 @@
#include <trace/events/mmflags.h>
#define COMPACTION_STATUS \
- EM( COMPACT_DEFERRED, "deferred") \
EM( COMPACT_SKIPPED, "skipped") \
+ EM( COMPACT_DEFERRED, "deferred") \
EM( COMPACT_CONTINUE, "continue") \
EM( COMPACT_PARTIAL, "partial") \
EM( COMPACT_COMPLETE, "complete") \
diff --git a/mm/compaction.c b/mm/compaction.c
index b06de27b7f72..13709e33a2fc 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1637,7 +1637,7 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
int may_perform_io = gfp_mask & __GFP_IO;
struct zoneref *z;
struct zone *zone;
- enum compact_result rc = COMPACT_DEFERRED;
+ enum compact_result rc = COMPACT_SKIPPED;
int all_zones_contended = COMPACT_CONTENDED_LOCK; /* init for &= op */
*contended = COMPACT_CONTENDED_NONE;
@@ -1654,8 +1654,10 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
enum compact_result status;
int zone_contended;
- if (compaction_deferred(zone, order))
+ if (compaction_deferred(zone, order)) {
+ rc = max_t(enum compact_result, COMPACT_DEFERRED, rc);
continue;
+ }
status = compact_zone_order(zone, order, gfp_mask, mode,
&zone_contended, alloc_flags,
@@ -1726,7 +1728,7 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
* If at least one zone wasn't deferred or skipped, we report if all
* zones that were tried were lock contended.
*/
- if (rc > COMPACT_SKIPPED && all_zones_contended)
+ if (rc > COMPACT_INACTIVE && all_zones_contended)
*contended = COMPACT_CONTENDED_LOCK;
return rc;
--
2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2016-04-20 22:00 +0200 |
| Subject | [PATCH 02/14] mm, compaction: change COMPACT_ constants into enum |
| Message-ID | <rq6s2-4Jb-11@gated-at.bofh.it> |
| In reply to | #1383701 |
From: Michal Hocko <mhocko@suse.com>
compaction code is doing weird dances between
COMPACT_FOO -> int -> unsigned long
but there doesn't seem to be any reason for that. All functions which
return/use one of those constants are not expecting any other value
so it really makes sense to define an enum for them and make it clear
that no other values are expected.
This is a pure cleanup and shouldn't introduce any functional changes.
Signed-off-by: Michal Hocko <mhocko@suse.com>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
---
include/linux/compaction.h | 45 +++++++++++++++++++++++++++------------------
mm/compaction.c | 27 ++++++++++++++-------------
mm/page_alloc.c | 2 +-
3 files changed, 42 insertions(+), 32 deletions(-)
diff --git a/include/linux/compaction.h b/include/linux/compaction.h
index d7c8de583a23..4458fd94170f 100644
--- a/include/linux/compaction.h
+++ b/include/linux/compaction.h
@@ -2,21 +2,29 @@
#define _LINUX_COMPACTION_H
/* Return values for compact_zone() and try_to_compact_pages() */
-/* compaction didn't start as it was deferred due to past failures */
-#define COMPACT_DEFERRED 0
-/* compaction didn't start as it was not possible or direct reclaim was more suitable */
-#define COMPACT_SKIPPED 1
-/* compaction should continue to another pageblock */
-#define COMPACT_CONTINUE 2
-/* direct compaction partially compacted a zone and there are suitable pages */
-#define COMPACT_PARTIAL 3
-/* The full zone was compacted */
-#define COMPACT_COMPLETE 4
-/* For more detailed tracepoint output */
-#define COMPACT_NO_SUITABLE_PAGE 5
-#define COMPACT_NOT_SUITABLE_ZONE 6
-#define COMPACT_CONTENDED 7
/* When adding new states, please adjust include/trace/events/compaction.h */
+enum compact_result {
+ /* compaction didn't start as it was deferred due to past failures */
+ COMPACT_DEFERRED,
+ /*
+ * compaction didn't start as it was not possible or direct reclaim
+ * was more suitable
+ */
+ COMPACT_SKIPPED,
+ /* compaction should continue to another pageblock */
+ COMPACT_CONTINUE,
+ /*
+ * direct compaction partially compacted a zone and there are suitable
+ * pages
+ */
+ COMPACT_PARTIAL,
+ /* The full zone was compacted */
+ COMPACT_COMPLETE,
+ /* For more detailed tracepoint output */
+ COMPACT_NO_SUITABLE_PAGE,
+ COMPACT_NOT_SUITABLE_ZONE,
+ COMPACT_CONTENDED,
+};
/* Used to signal whether compaction detected need_sched() or lock contention */
/* No contention detected */
@@ -38,12 +46,13 @@ extern int sysctl_extfrag_handler(struct ctl_table *table, int write,
extern int sysctl_compact_unevictable_allowed;
extern int fragmentation_index(struct zone *zone, unsigned int order);
-extern unsigned long try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
+extern 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);
extern void compact_pgdat(pg_data_t *pgdat, int order);
extern void reset_isolation_suitable(pg_data_t *pgdat);
-extern unsigned long compaction_suitable(struct zone *zone, int order,
+extern enum compact_result compaction_suitable(struct zone *zone, int order,
int alloc_flags, int classzone_idx);
extern void defer_compaction(struct zone *zone, int order);
@@ -57,7 +66,7 @@ extern void kcompactd_stop(int nid);
extern void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx);
#else
-static inline unsigned long try_to_compact_pages(gfp_t gfp_mask,
+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)
@@ -73,7 +82,7 @@ static inline void reset_isolation_suitable(pg_data_t *pgdat)
{
}
-static inline unsigned long compaction_suitable(struct zone *zone, int order,
+static inline enum compact_result compaction_suitable(struct zone *zone, int order,
int alloc_flags, int classzone_idx)
{
return COMPACT_SKIPPED;
diff --git a/mm/compaction.c b/mm/compaction.c
index 8cc495042303..8ae7b1c46c72 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1281,7 +1281,7 @@ static inline bool is_via_compact_memory(int order)
return order == -1;
}
-static int __compact_finished(struct zone *zone, struct compact_control *cc,
+static enum compact_result __compact_finished(struct zone *zone, struct compact_control *cc,
const int migratetype)
{
unsigned int order;
@@ -1344,8 +1344,9 @@ static int __compact_finished(struct zone *zone, struct compact_control *cc,
return COMPACT_NO_SUITABLE_PAGE;
}
-static int compact_finished(struct zone *zone, struct compact_control *cc,
- const int migratetype)
+static enum compact_result compact_finished(struct zone *zone,
+ struct compact_control *cc,
+ const int migratetype)
{
int ret;
@@ -1364,7 +1365,7 @@ static int compact_finished(struct zone *zone, struct compact_control *cc,
* COMPACT_PARTIAL - If the allocation would succeed without compaction
* COMPACT_CONTINUE - If compaction should run now
*/
-static unsigned long __compaction_suitable(struct zone *zone, int order,
+static enum compact_result __compaction_suitable(struct zone *zone, int order,
int alloc_flags, int classzone_idx)
{
int fragindex;
@@ -1409,10 +1410,10 @@ static unsigned long __compaction_suitable(struct zone *zone, int order,
return COMPACT_CONTINUE;
}
-unsigned long compaction_suitable(struct zone *zone, int order,
+enum compact_result compaction_suitable(struct zone *zone, int order,
int alloc_flags, int classzone_idx)
{
- unsigned long ret;
+ enum compact_result ret;
ret = __compaction_suitable(zone, order, alloc_flags, classzone_idx);
trace_mm_compaction_suitable(zone, order, ret);
@@ -1422,9 +1423,9 @@ unsigned long compaction_suitable(struct zone *zone, int order,
return ret;
}
-static int compact_zone(struct zone *zone, struct compact_control *cc)
+static enum compact_result compact_zone(struct zone *zone, struct compact_control *cc)
{
- int ret;
+ enum compact_result ret;
unsigned long start_pfn = zone->zone_start_pfn;
unsigned long end_pfn = zone_end_pfn(zone);
const int migratetype = gfpflags_to_migratetype(cc->gfp_mask);
@@ -1588,11 +1589,11 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
return ret;
}
-static unsigned long compact_zone_order(struct zone *zone, int order,
+static enum compact_result compact_zone_order(struct zone *zone, int order,
gfp_t gfp_mask, enum migrate_mode mode, int *contended,
int alloc_flags, int classzone_idx)
{
- unsigned long ret;
+ enum compact_result ret;
struct compact_control cc = {
.nr_freepages = 0,
.nr_migratepages = 0,
@@ -1631,7 +1632,7 @@ int sysctl_extfrag_threshold = 500;
*
* This is the main entry point for direct page compaction.
*/
-unsigned long try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
+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)
{
@@ -1639,7 +1640,7 @@ unsigned long try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
int may_perform_io = gfp_mask & __GFP_IO;
struct zoneref *z;
struct zone *zone;
- int rc = COMPACT_DEFERRED;
+ enum compact_result rc = COMPACT_DEFERRED;
int all_zones_contended = COMPACT_CONTENDED_LOCK; /* init for &= op */
*contended = COMPACT_CONTENDED_NONE;
@@ -1653,7 +1654,7 @@ unsigned long try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
/* Compact each zone in the list */
for_each_zone_zonelist_nodemask(zone, z, ac->zonelist, ac->high_zoneidx,
ac->nodemask) {
- int status;
+ enum compact_result status;
int zone_contended;
if (compaction_deferred(zone, order))
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index c4efafc38273..06af8a757d52 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2947,7 +2947,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
enum migrate_mode mode, int *contended_compaction,
bool *deferred_compaction)
{
- unsigned long compact_result;
+ enum compact_result compact_result;
struct page *page;
if (!order)
--
2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | Joonsoo Kim <iamjoonsoo.kim@lge.com> |
|---|---|
| Date | 2016-05-04 07:50 +0200 |
| Message-ID | <ruXR7-6ki-1@gated-at.bofh.it> |
| In reply to | #1383701 |
On Wed, Apr 20, 2016 at 03:47:13PM -0400, Michal Hocko wrote:
> Hi,
>
> This is v6 of the series. The previous version was posted [1]. The
> code hasn't changed much since then. I have found one old standing
> bug (patch 1) which just got much more severe and visible with this
> series. Other than that I have reorganized the series and put the
> compaction feedback abstraction to the front just in case we find out
> that parts of the series would have to be reverted later on for some
> reason. The premature oom killer invocation reported by Hugh [2] seems
> to be addressed.
>
> We have discussed this series at LSF/MM summit in Raleigh and there
> didn't seem to be any concerns/objections to go on with the patch set
> and target it for the next merge window.
I still don't agree with some part of this patchset that deal with
!costly order. As you know, there was two regression reports from Hugh
and Aaron and you fixed them by ensuring to trigger compaction. I
think that these show the problem of this patchset. Previous kernel
doesn't need to ensure to trigger compaction and just works fine in
any case. Your series make compaction necessary for all. OOM handling
is essential part in MM but compaction isn't. OOM handling should not
depend on compaction. I tested my own benchmark without
CONFIG_COMPACTION and found that premature OOM happens.
I hope that you try to test something without CONFIG_COMPACTION.
Thanks.
>
> Motivation:
> As pointed by Linus [3][4] relying on zone_reclaimable as a way to
> communicate the reclaim progress is rater dubious. I tend to agree,
> not only it is really obscure, it is not hard to imagine cases where a
> single page freed in the loop keeps all the reclaimers looping without
> getting any progress because their gfp_mask wouldn't allow to get that
> page anyway (e.g. single GFP_ATOMIC alloc and free loop). This is rather
> rare so it doesn't happen in the practice but the current logic which we
> have is rather obscure and hard to follow a also non-deterministic.
>
> This is an attempt to make the OOM detection more deterministic and
> easier to follow because each reclaimer basically tracks its own
> progress which is implemented at the page allocator layer rather spread
> out between the allocator and the reclaim. The more on the implementation
> is described in the first patch.
>
> I have tested several different scenarios but it should be clear that
> testing OOM killer is quite hard to be representative. There is usually
> a tiny gap between almost OOM and full blown OOM which is often time
> sensitive. Anyway, I have tested the following 2 scenarios and I would
> appreciate if there are more to test.
>
> Testing environment: a virtual machine with 2G of RAM and 2CPUs without
> any swap to make the OOM more deterministic.
>
> 1) 2 writers (each doing dd with 4M blocks to an xfs partition with 1G
> file size, removes the files and starts over again) running in
> parallel for 10s to build up a lot of dirty pages when 100 parallel
> mem_eaters (anon private populated mmap which waits until it gets
> signal) with 80M each.
>
> This causes an OOM flood of course and I have compared both patched
> and unpatched kernels. The test is considered finished after there
> are no OOM conditions detected. This should tell us whether there are
> any excessive kills or some of them premature (e.g. due to dirty pages):
>
> I have performed two runs this time each after a fresh boot.
>
> * base kernel
> $ grep "Out of memory:" base-oom-run1.log | wc -l
> 78
> $ grep "Out of memory:" base-oom-run2.log | wc -l
> 78
>
> $ grep "Kill process" base-oom-run1.log | tail -n1
> [ 91.391203] Out of memory: Kill process 3061 (mem_eater) score 39 or sacrifice child
> $ grep "Kill process" base-oom-run2.log | tail -n1
> [ 82.141919] Out of memory: Kill process 3086 (mem_eater) score 39 or sacrifice child
>
> $ grep "DMA32 free:" base-oom-run1.log | sed 's@.*free:\([0-9]*\)kB.*@\1@' | calc_min_max.awk
> min: 5376.00 max: 6776.00 avg: 5530.75 std: 166.50 nr: 61
> $ grep "DMA32 free:" base-oom-run2.log | sed 's@.*free:\([0-9]*\)kB.*@\1@' | calc_min_max.awk
> min: 5416.00 max: 5608.00 avg: 5514.15 std: 42.94 nr: 52
>
> $ grep "DMA32.*all_unreclaimable? no" base-oom-run1.log | wc -l
> 1
> $ grep "DMA32.*all_unreclaimable? no" base-oom-run2.log | wc -l
> 3
>
> * patched kernel
> $ grep "Out of memory:" patched-oom-run1.log | wc -l
> 78
> miso@tiehlicka /mnt/share/devel/miso/kvm $ grep "Out of memory:" patched-oom-run2.log | wc -l
> 77
>
> e grep "Kill process" patched-oom-run1.log | tail -n1
> [ 497.317732] Out of memory: Kill process 3108 (mem_eater) score 39 or sacrifice child
> $ grep "Kill process" patched-oom-run2.log | tail -n1
> [ 316.169920] Out of memory: Kill process 3093 (mem_eater) score 39 or sacrifice child
>
> $ grep "DMA32 free:" patched-oom-run1.log | sed 's@.*free:\([0-9]*\)kB.*@\1@' | calc_min_max.awk
> min: 5420.00 max: 5808.00 avg: 5513.90 std: 60.45 nr: 78
> $ grep "DMA32 free:" patched-oom-run2.log | sed 's@.*free:\([0-9]*\)kB.*@\1@' | calc_min_max.awk
> min: 5380.00 max: 6384.00 avg: 5520.94 std: 136.84 nr: 77
>
> e grep "DMA32.*all_unreclaimable? no" patched-oom-run1.log | wc -l
> 2
> $ grep "DMA32.*all_unreclaimable? no" patched-oom-run2.log | wc -l
> 3
>
> The patched kernel run noticeably longer while invoking OOM killer same
> number of times. This means that the original implementation is much
> more aggressive and triggers the OOM killer sooner. free pages stats
> show that neither kernels went OOM too early most of the time, though. I
> guess the difference is in the backoff when retries without any progress
> do sleep for a while if there is memory under writeback or dirty which
> is highly likely considering the parallel IO.
> Both kernels have seen races where zone wasn't marked unreclaimable
> and we still hit the OOM killer. This is most likely a race where
> a task managed to exit between the last allocation attempt and the oom
> killer invocation.
>
> 2) 2 writers again with 10s of run and then 10 mem_eaters to consume as much
> memory as possible without triggering the OOM killer. This required a lot
> of tuning but I've considered 3 consecutive runs in three different boots
> without OOM as a success.
>
> * base kernel
> size=$(awk '/MemFree/{printf "%dK", ($2/10)-(16*1024)}' /proc/meminfo)
>
> * patched kernel
> size=$(awk '/MemFree/{printf "%dK", ($2/10)-(12*1024)}' /proc/meminfo)
>
> That means 40M more memory was usable without triggering OOM killer. The
> base kernel sometimes managed to handle the same as patched but it
> wasn't consistent and failed in at least on of the 3 runs. This seems
> like a minor improvement.
>
> I was testing also GPF_REPEAT costly requests (hughetlb) with fragmented
> memory and under memory pressure. The results are in patch 11 where the
> logic is implemented. In short I can see huge improvement there.
>
> I am certainly interested in other usecases as well as well as any
> feedback. Especially those which require higher order requests.
>
> * Changes since v5
> - added "vmscan: consider classzone_idx in compaction_ready"
> - added "mm, oom, compaction: prevent from should_compact_retry looping
> for ever for costly orders"
> - acked-bys from Vlastimil
> - integrated feedback from review
> * Changes since v4
> - dropped __GFP_REPEAT for costly allocation as it is now replaced by
> the compaction based feedback logic
> - !costly high order requests are retried based on the compaction feedback
> - compaction feedback has been tweaked to give us an useful information
> to make decisions in the page allocator
> - rebased on the current mmotm-2016-04-01-16-24 with the previous version
> of the rework reverted
>
> * Changes since v3
> - factor out the new heuristic into its own function as suggested by
> Johannes (no functional changes)
>
> * Changes since v2
> - rebased on top of mmotm-2015-11-25-17-08 which includes
> wait_iff_congested related changes which needed refresh in
> patch#1 and patch#2
> - use zone_page_state_snapshot for NR_FREE_PAGES per David
> - shrink_zones doesn't need to return anything per David
> - retested because the major kernel version has changed since
> the last time (4.2 -> 4.3 based kernel + mmotm patches)
>
> * Changes since v1
> - backoff calculation was de-obfuscated by using DIV_ROUND_UP
> - __GFP_NOFAIL high order migh fail fixed - theoretical bug
>
> [1] http://lkml.kernel.org/r/1459855533-4600-1-git-send-email-mhocko@kernel.org
> [2] http://lkml.kernel.org/r/alpine.LSU.2.11.1602241832160.15564@eggly.anvils
> [3] http://lkml.kernel.org/r/CA+55aFwapaED7JV6zm-NVkP-jKie+eQ1vDXWrKD=SkbshZSgmw@mail.gmail.com
> [4] http://lkml.kernel.org/r/CA+55aFxwg=vS2nrXsQhAUzPQDGb8aQpZi0M7UUh21ftBo-z46Q@mail.gmail.com
>
> --
> 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>
[toc] | [prev] | [next] | [standalone]
| From | Vlastimil Babka <vbabka@suse.cz> |
|---|---|
| Date | 2016-05-04 10:20 +0200 |
| Message-ID | <rv0ci-oI-7@gated-at.bofh.it> |
| In reply to | #1393956 |
On 05/04/2016 07:45 AM, Joonsoo Kim wrote: > I still don't agree with some part of this patchset that deal with > !costly order. As you know, there was two regression reports from Hugh > and Aaron and you fixed them by ensuring to trigger compaction. I > think that these show the problem of this patchset. Previous kernel > doesn't need to ensure to trigger compaction and just works fine in > any case. IIRC previous kernel somehow subtly never OOM'd for !costly orders. So anything that introduces the possibility of OOM may look like regression for some corner case workloads. But I don't think that it's OK to not OOM for e.g. kernel stack allocations? > Your series make compaction necessary for all. OOM handling > is essential part in MM but compaction isn't. OOM handling should not > depend on compaction. I tested my own benchmark without > CONFIG_COMPACTION and found that premature OOM happens. > > I hope that you try to test something without CONFIG_COMPACTION. Hmm a valid point, !CONFIG_COMPACTION should be considered. But reclaim cannot guarantee forming an order>0 page. But neither does OOM. So would you suggest we keep reclaiming without OOM as before, to prevent these regressions? Or where to draw the line here? > Thanks.
[toc] | [prev] | [next] | [standalone]
| From | Joonsoo Kim <iamjoonsoo.kim@lge.com> |
|---|---|
| Date | 2016-05-04 10:40 +0200 |
| Message-ID | <rv0vD-zg-3@gated-at.bofh.it> |
| In reply to | #1394077 |
On Wed, May 04, 2016 at 10:12:43AM +0200, Vlastimil Babka wrote: > On 05/04/2016 07:45 AM, Joonsoo Kim wrote: > >I still don't agree with some part of this patchset that deal with > >!costly order. As you know, there was two regression reports from Hugh > >and Aaron and you fixed them by ensuring to trigger compaction. I > >think that these show the problem of this patchset. Previous kernel > >doesn't need to ensure to trigger compaction and just works fine in > >any case. > > IIRC previous kernel somehow subtly never OOM'd for !costly orders. IIRC, it would not OOM in thrashing case. But, it could OOM in other cases. > So anything that introduces the possibility of OOM may look like > regression for some corner case workloads. But I don't think that > it's OK to not OOM for e.g. kernel stack allocations? Sorry. Double negation makes me hard to understand since I'm not native. So, you think that it's OK to OOM for kernel stack allocation? I think so, too. But, I want not to OOM prematurely. > >Your series make compaction necessary for all. OOM handling > >is essential part in MM but compaction isn't. OOM handling should not > >depend on compaction. I tested my own benchmark without > >CONFIG_COMPACTION and found that premature OOM happens. > > > >I hope that you try to test something without CONFIG_COMPACTION. > > Hmm a valid point, !CONFIG_COMPACTION should be considered. But > reclaim cannot guarantee forming an order>0 page. But neither does > OOM. So would you suggest we keep reclaiming without OOM as before, > to prevent these regressions? Or where to draw the line here? I suggested that memorizing number of reclaimable pages when entering allocation slowpath and try to reclaim at least that amount. Thrashing is effectively prevented in this algorithm and we don't trigger OOM prematurely. Thanks.
[toc] | [prev] | [next] | [standalone]
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
Back to top | Article view | linux.kernel
csiph-web