Skip to content

Commit 4ec1a08

Browse files
committed
slab: allow NUMA restricted allocations to use percpu sheaves
Currently allocations asking for a specific node explicitly or via mempolicy in strict_numa node bypass percpu sheaves. Since sheaves contain mostly local objects, we can try allocating from them if the local node happens to be the requested node or allowed by the mempolicy. If we find the object from percpu sheaves is not from the expected node, we skip the sheaves - this should be rare. Reviewed-by: Harry Yoo <[email protected]> Reviewed-by: Suren Baghdasaryan <[email protected]> Signed-off-by: Vlastimil Babka <[email protected]>
1 parent 989b09b commit 4ec1a08

File tree

1 file changed

+46
-7
lines changed

1 file changed

+46
-7
lines changed

mm/slub.c

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4882,18 +4882,43 @@ __pcs_replace_empty_main(struct kmem_cache *s, struct slub_percpu_sheaves *pcs,
48824882
}
48834883

48844884
static __fastpath_inline
4885-
void *alloc_from_pcs(struct kmem_cache *s, gfp_t gfp)
4885+
void *alloc_from_pcs(struct kmem_cache *s, gfp_t gfp, int node)
48864886
{
48874887
struct slub_percpu_sheaves *pcs;
4888+
bool node_requested;
48884889
void *object;
48894890

48904891
#ifdef CONFIG_NUMA
4891-
if (static_branch_unlikely(&strict_numa)) {
4892-
if (current->mempolicy)
4893-
return NULL;
4892+
if (static_branch_unlikely(&strict_numa) &&
4893+
node == NUMA_NO_NODE) {
4894+
4895+
struct mempolicy *mpol = current->mempolicy;
4896+
4897+
if (mpol) {
4898+
/*
4899+
* Special BIND rule support. If the local node
4900+
* is in permitted set then do not redirect
4901+
* to a particular node.
4902+
* Otherwise we apply the memory policy to get
4903+
* the node we need to allocate on.
4904+
*/
4905+
if (mpol->mode != MPOL_BIND ||
4906+
!node_isset(numa_mem_id(), mpol->nodes))
4907+
4908+
node = mempolicy_slab_node();
4909+
}
48944910
}
48954911
#endif
48964912

4913+
node_requested = IS_ENABLED(CONFIG_NUMA) && node != NUMA_NO_NODE;
4914+
4915+
/*
4916+
* We assume the percpu sheaves contain only local objects although it's
4917+
* not completely guaranteed, so we verify later.
4918+
*/
4919+
if (unlikely(node_requested && node != numa_mem_id()))
4920+
return NULL;
4921+
48974922
if (!local_trylock(&s->cpu_sheaves->lock))
48984923
return NULL;
48994924

@@ -4905,7 +4930,21 @@ void *alloc_from_pcs(struct kmem_cache *s, gfp_t gfp)
49054930
return NULL;
49064931
}
49074932

4908-
object = pcs->main->objects[--pcs->main->size];
4933+
object = pcs->main->objects[pcs->main->size - 1];
4934+
4935+
if (unlikely(node_requested)) {
4936+
/*
4937+
* Verify that the object was from the node we want. This could
4938+
* be false because of cpu migration during an unlocked part of
4939+
* the current allocation or previous freeing process.
4940+
*/
4941+
if (folio_nid(virt_to_folio(object)) != node) {
4942+
local_unlock(&s->cpu_sheaves->lock);
4943+
return NULL;
4944+
}
4945+
}
4946+
4947+
pcs->main->size--;
49094948

49104949
local_unlock(&s->cpu_sheaves->lock);
49114950

@@ -5005,8 +5044,8 @@ static __fastpath_inline void *slab_alloc_node(struct kmem_cache *s, struct list
50055044
if (unlikely(object))
50065045
goto out;
50075046

5008-
if (s->cpu_sheaves && node == NUMA_NO_NODE)
5009-
object = alloc_from_pcs(s, gfpflags);
5047+
if (s->cpu_sheaves)
5048+
object = alloc_from_pcs(s, gfpflags, node);
50105049

50115050
if (!object)
50125051
object = __slab_alloc_node(s, gfpflags, node, addr, orig_size);

0 commit comments

Comments
 (0)