| From foo@baz Wed Jan 3 18:58:12 CET 2018 |
| From: Hugh Dickins <hughd@google.com> |
| Date: Fri, 13 Oct 2017 12:10:00 -0700 |
| Subject: kaiser: _pgd_alloc() without __GFP_REPEAT to avoid stalls |
| |
| From: Hugh Dickins <hughd@google.com> |
| |
| |
| Synthetic filesystem mempressure testing has shown softlockups, with |
| hour-long page allocation stalls, and pgd_alloc() trying for order:1 |
| with __GFP_REPEAT in one of the backtraces each time. |
| |
| That's _pgd_alloc() going for a Kaiser double-pgd, using the __GFP_REPEAT |
| common to all page table allocations, but actually having no effect on |
| order:0 (see should_alloc_oom() and should_continue_reclaim() in this |
| tree, but beware that ports to another tree might behave differently). |
| |
| Order:1 stack allocation has been working satisfactorily without |
| __GFP_REPEAT forever, and page table allocation only asks __GFP_REPEAT |
| for awkward occasions in a long-running process: it's not appropriate |
| at fork or exec time, and seems to be doing much more harm than good: |
| getting those contiguous pages under very heavy mempressure can be |
| hard (though even without it, Kaiser does generate more mempressure). |
| |
| Mask out that __GFP_REPEAT inside _pgd_alloc(). Why not take it out |
| of the PGALLOG_GFP altogether, as v4.7 commit a3a9a59d2067 ("x86: get |
| rid of superfluous __GFP_REPEAT") did? Because I think that might |
| make a difference to our page table memcg charging, which I'd prefer |
| not to interfere with at this time. |
| |
| hughd adds: __alloc_pages_slowpath() in the 4.4.89-stable tree handles |
| __GFP_REPEAT a little differently than in prod kernel or 3.18.72-stable, |
| so it may not always be exactly a no-op on order:0 pages, as said above; |
| but I think still appropriate to omit it from Kaiser or non-Kaiser pgd. |
| |
| Signed-off-by: Hugh Dickins <hughd@google.com> |
| Acked-by: Jiri Kosina <jkosina@suse.cz> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/x86/mm/pgtable.c | 6 ++++-- |
| 1 file changed, 4 insertions(+), 2 deletions(-) |
| |
| --- a/arch/x86/mm/pgtable.c |
| +++ b/arch/x86/mm/pgtable.c |
| @@ -6,7 +6,7 @@ |
| #include <asm/fixmap.h> |
| #include <asm/mtrr.h> |
| |
| -#define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO |
| +#define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO) |
| |
| #ifdef CONFIG_HIGHPTE |
| #define PGALLOC_USER_GFP __GFP_HIGHMEM |
| @@ -354,7 +354,9 @@ static inline void _pgd_free(pgd_t *pgd) |
| |
| static inline pgd_t *_pgd_alloc(void) |
| { |
| - return (pgd_t *)__get_free_pages(PGALLOC_GFP, PGD_ALLOCATION_ORDER); |
| + /* No __GFP_REPEAT: to avoid page allocation stalls in order-1 case */ |
| + return (pgd_t *)__get_free_pages(PGALLOC_GFP & ~__GFP_REPEAT, |
| + PGD_ALLOCATION_ORDER); |
| } |
| |
| static inline void _pgd_free(pgd_t *pgd) |