Por que o kernel do Linux não pode alocar a ordem: 0 quando a memória é altamente fragmentada?

2

Ao solucionar um recente kernel panic, houve uma falha de alocação de página solicitando uma ordem: 0 página. A memória é altamente fragmentada e mostra apenas order: 0 memory free (422 * 4kb na verdade). Por que o kernel não pode usar essa memória nesse caso? Eu entendo que uma solicitação de pedido mais alto está falhando, mas não tenho certeza de por que isso falhou.

Falha:

kworker/u8:0: page allocation failure: order:0, mode:0x2284020(GFP_ATOMIC|__GFP_COMP|__GFP_NOTRACK)

E os detalhes da fragmentação mostram que apenas blocos de ordem 0 estão disponíveis no intervalo Normal:

Node 0 DMA: 0*4kB 1*8kB (U) 0*16kB 1*32kB (U) 2*64kB (U) 1*128kB (U) 1*256kB (U) 0*512kB 1*1024kB (U) 1*2048kB (M) 3*4096kB (M) = 15912kB
Node 0 DMA32: 2471*4kB (UM) 542*8kB (UM) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 14220kB
Node 0 Normal: 422*4kB (UM) 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 1688kB

O callstack mostra:

<IRQ>  [<ffffffff8131c805>] ? dump_stack+0x5c/0x77
[<ffffffff8118XXX6>] ? warn_alloc_failed+0x106/0x170
[<ffffffff8118XXX3>] ? __alloc_pages_nodemask+0x4f3/0xf20
[<ffffffff811dXXX2>] ? cache_grow_begin+0x82/0x330
[<ffffffff811dXXX1>] ? fallback_alloc+0x151/0x1d0
[<ffffffff811dXXX2>] ? kmem_cache_alloc+0x202/0x230
[<ffffffff814cXXXf>] ? sk_prot_alloc+0x2f/0x130
[<ffffffff814cXXX9>] ? sk_clone_lock+0x19/0x390
[<ffffffff8152XXX1>] ? inet_csk_clone_lock+0x11/0xd0
[<ffffffff8154XXXe>] ? tcp_create_openreq_child+0x1e/0x490
[<ffffffff8154XXX3>] ? tcp_v4_syn_recv_sock+0x43/0x2e0
[<ffffffff8154XXX4>] ? tcp_check_req+0x3a4/0x4f0
[<ffffffff815dXXX0>] ? tcp_v4_inbound_md5_hash+0x67/0x177
[<ffffffff8154XXXf>] ? tcp_v4_rcv+0x6bf/0xa90
[<ffffffff8151XXXb>] ? ip_local_deliver_finish+0x8b/0x1c0
[<ffffffff8151XXXb>] ? ip_local_deliver+0x6b/0xf0
[<ffffffff8151XXX0>] ? ip_rcv_finish+0x3e0/0x3e0
[<ffffffff8151XXX1>] ? ip_rcv+0x281/0x3b0
[<ffffffff8151XXX0>] ? inet_del_offload+0x40/0x40
[<ffffffff814dXXXe>] ? __netif_receive_skb_core+0x2be/0xa50
[<ffffffff8155XXX5>] ? inet_gro_receive+0x265/0x2a0
[<ffffffff814dXXXf>] ? netif_receive_skb_internal+0x2f/0xa0
[<ffffffff814eXXXb>] ? napi_gro_receive+0xbb/0x110
[<ffffffffc002XXX6>] ? xennet_poll+0xb16/0xbc0 [xen_netfront]
[<ffffffff814eXXX8>] ? net_rx_action+0x238/0x370
[<ffffffff815eXXX6>] ? __do_softirq+0x106/0x294
[<ffffffff810fXXX0>] ? proc_dma_show+0x60/0x60
[<ffffffff8108XXX6>] ? irq_exit+0x86/0x90
[<ffffffff813eXXX1>] ? xen_evtchn_do_upcall+0x31/0x40
[<ffffffff815eXXXe>] ? xen_do_hypervisor_callback+0x1e/0x40
<EOI>  [<ffffffff810fXXX0>] ? proc_dma_show+0x60/0x60
[<ffffffff810fXXX2>] ? smp_call_function_many+0x1f2/0x250
[<ffffffff810fXXX2>] ? kick_all_cpus_sync+0x22/0x30
[<ffffffff811dXXXa>] ? __do_tune_cpucache+0x5a/0x200
[<ffffffff811dXXX6>] ? do_tune_cpucache+0x26/0x90
[<ffffffff811dXXX6>] ? cache_alloc_refill+0x256/0x2b0
[<ffffffff811dXXX4>] ? enable_cpucache+0x64/0x100
[<ffffffff811dXXXc>] ? __kmem_cache_create+0x17c/0x200
[<ffffffff811aXXX3>] ? create_cache+0x93/0x160
[<ffffffff811aXXX7>] ? memcg_create_kmem_cache+0xe7/0x130
[<ffffffff811eXXXb>] ? memcg_kmem_cache_create_func+0x1b/0x60
[<ffffffff8109XXXb>] ? process_one_work+0x14b/0x400
[<ffffffff8109XXX5>] ? worker_thread+0x65/0x4a0
[<ffffffff8109XXX0>] ? rescuer_thread+0x340/0x340
[<ffffffff8109XXXf>] ? kthread+0xdf/0x100
[<ffffffff815dXXXf>] ? ret_from_fork+0x1f/0x40
[<ffffffff8109XXX0>] ? kthread_park+0x50/0x50 

Não tenho certeza se o seguinte é relevante: O pânico estava certo em torno de uma migração ao vivo do Xen.

Minha teoria é que a alocação de páginas estava tentando alocar o DMA, que enquanto páginas de ordem mais alta estão disponíveis, o GFP_ATOMIC sinalizador no pedido de memória essencialmente exige alocação imediata, então o sistema não teve tempo para quebrar o livre 8kb em 2 blocos de 4kb? Eu sou novo no gerenciamento de memória Linux, então esta é uma teoria baseada em muita ignorância no meu fim ...

    
por Chad Jessup 24.03.2017 / 19:05

0 respostas