• Chen Jun's avatar
    mm/slub: Reduce memory consumption in extreme scenarios · 9198ffbd
    Chen Jun authored
    When kmalloc_node() is called without __GFP_THISNODE and the target node
    lacks sufficient memory, SLUB allocates a folio from a different node
    other than the requested node, instead of taking a partial slab from it.
    
    However, since the allocated folio does not belong to the requested
    node, on the following allocation it is deactivated and added to the
    partial slab list of the node it belongs to.
    
    This behavior can result in excessive memory usage when the requested
    node has insufficient memory, as SLUB will repeatedly allocate folios
    from other nodes without reusing the previously allocated ones.
    
    To prevent memory wastage, when a preferred node is indicated (not
    NUMA_NO_NODE) but without a prior __GFP_THISNODE constraint:
    
    1) try to get a partial slab from target node only by having
       __GFP_THISNODE in pc.flags for get_partial()
    2) if 1) failed, try to allocate a new slab from target node with
       GFP_NOWAIT | __GFP_THISNODE opportunistically.
    3) if 2) failed, retry with original gfpflags which will allow
       get_partial() try partial lists of other nodes before potentially
       allocating new page from other nodes
    
    Without a preferred node, or with __GFP_THISNODE constraint, the
    behavior remains unchanged.
    
    On qemu with 4 numa nodes and each numa has 1G memory. Write a test ko
    to call kmalloc_node(196, GFP_KERNEL, 3) for (4 * 1024 + 4) * 1024 times.
    
    cat /proc/slabinfo shows:
    kmalloc-256       4200530 13519712    256   32    2 : tunables..
    
    after this patch,
    cat /proc/slabinfo shows:
    kmalloc-256       4200558 4200768    256   32    2 : tunables..
    Signed-off-by: default avatarChen Jun <chenjun102@huawei.com>
    Signed-off-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
    Signed-off-by: default avatarVlastimil Babka <vbabka@suse.cz>
    9198ffbd
slub.c 178 KB