Skip to content

Commit ff69416

Browse files
Christoph LameterLinus Torvalds
authored andcommitted
[PATCH] slab: fix handling of pages from foreign NUMA nodes
The numa slab allocator may allocate pages from foreign nodes onto the lists for a particular node if a node runs out of memory. Inspecting the slab->nodeid field will not reflect that the page is now in use for the slabs of another node. This patch fixes that issue by adding a node field to free_block so that the caller can indicate which node currently uses a slab. Also removes the check for the current node from kmalloc_cache_node since the process may shift later to another node which may lead to an allocation on another node than intended. Signed-off-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
1 parent 57487f4 commit ff69416

File tree

1 file changed

+19
-19
lines changed

1 file changed

+19
-19
lines changed

mm/slab.c

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ static enum {
640640

641641
static DEFINE_PER_CPU(struct work_struct, reap_work);
642642

643-
static void free_block(kmem_cache_t* cachep, void** objpp, int len);
643+
static void free_block(kmem_cache_t* cachep, void** objpp, int len, int node);
644644
static void enable_cpucache (kmem_cache_t *cachep);
645645
static void cache_reap (void *unused);
646646
static int __node_shrink(kmem_cache_t *cachep, int node);
@@ -805,7 +805,7 @@ static inline void __drain_alien_cache(kmem_cache_t *cachep, struct array_cache
805805

806806
if (ac->avail) {
807807
spin_lock(&rl3->list_lock);
808-
free_block(cachep, ac->entry, ac->avail);
808+
free_block(cachep, ac->entry, ac->avail, node);
809809
ac->avail = 0;
810810
spin_unlock(&rl3->list_lock);
811811
}
@@ -926,7 +926,7 @@ static int __devinit cpuup_callback(struct notifier_block *nfb,
926926
/* Free limit for this kmem_list3 */
927927
l3->free_limit -= cachep->batchcount;
928928
if (nc)
929-
free_block(cachep, nc->entry, nc->avail);
929+
free_block(cachep, nc->entry, nc->avail, node);
930930

931931
if (!cpus_empty(mask)) {
932932
spin_unlock(&l3->list_lock);
@@ -935,7 +935,7 @@ static int __devinit cpuup_callback(struct notifier_block *nfb,
935935

936936
if (l3->shared) {
937937
free_block(cachep, l3->shared->entry,
938-
l3->shared->avail);
938+
l3->shared->avail, node);
939939
kfree(l3->shared);
940940
l3->shared = NULL;
941941
}
@@ -1883,12 +1883,13 @@ static void do_drain(void *arg)
18831883
{
18841884
kmem_cache_t *cachep = (kmem_cache_t*)arg;
18851885
struct array_cache *ac;
1886+
int node = numa_node_id();
18861887

18871888
check_irq_off();
18881889
ac = ac_data(cachep);
1889-
spin_lock(&cachep->nodelists[numa_node_id()]->list_lock);
1890-
free_block(cachep, ac->entry, ac->avail);
1891-
spin_unlock(&cachep->nodelists[numa_node_id()]->list_lock);
1890+
spin_lock(&cachep->nodelists[node]->list_lock);
1891+
free_block(cachep, ac->entry, ac->avail, node);
1892+
spin_unlock(&cachep->nodelists[node]->list_lock);
18921893
ac->avail = 0;
18931894
}
18941895

@@ -2609,7 +2610,7 @@ static void *__cache_alloc_node(kmem_cache_t *cachep, int flags, int nodeid)
26092610
/*
26102611
* Caller needs to acquire correct kmem_list's list_lock
26112612
*/
2612-
static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)
2613+
static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects, int node)
26132614
{
26142615
int i;
26152616
struct kmem_list3 *l3;
@@ -2618,14 +2619,12 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)
26182619
void *objp = objpp[i];
26192620
struct slab *slabp;
26202621
unsigned int objnr;
2621-
int nodeid = 0;
26222622

26232623
slabp = GET_PAGE_SLAB(virt_to_page(objp));
2624-
nodeid = slabp->nodeid;
2625-
l3 = cachep->nodelists[nodeid];
2624+
l3 = cachep->nodelists[node];
26262625
list_del(&slabp->list);
26272626
objnr = (objp - slabp->s_mem) / cachep->objsize;
2628-
check_spinlock_acquired_node(cachep, nodeid);
2627+
check_spinlock_acquired_node(cachep, node);
26292628
check_slabp(cachep, slabp);
26302629

26312630

@@ -2665,13 +2664,14 @@ static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac)
26652664
{
26662665
int batchcount;
26672666
struct kmem_list3 *l3;
2667+
int node = numa_node_id();
26682668

26692669
batchcount = ac->batchcount;
26702670
#if DEBUG
26712671
BUG_ON(!batchcount || batchcount > ac->avail);
26722672
#endif
26732673
check_irq_off();
2674-
l3 = cachep->nodelists[numa_node_id()];
2674+
l3 = cachep->nodelists[node];
26752675
spin_lock(&l3->list_lock);
26762676
if (l3->shared) {
26772677
struct array_cache *shared_array = l3->shared;
@@ -2687,7 +2687,7 @@ static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac)
26872687
}
26882688
}
26892689

2690-
free_block(cachep, ac->entry, batchcount);
2690+
free_block(cachep, ac->entry, batchcount, node);
26912691
free_done:
26922692
#if STATS
26932693
{
@@ -2752,7 +2752,7 @@ static inline void __cache_free(kmem_cache_t *cachep, void *objp)
27522752
} else {
27532753
spin_lock(&(cachep->nodelists[nodeid])->
27542754
list_lock);
2755-
free_block(cachep, &objp, 1);
2755+
free_block(cachep, &objp, 1, nodeid);
27562756
spin_unlock(&(cachep->nodelists[nodeid])->
27572757
list_lock);
27582758
}
@@ -2845,7 +2845,7 @@ void *kmem_cache_alloc_node(kmem_cache_t *cachep, unsigned int __nocast flags, i
28452845
unsigned long save_flags;
28462846
void *ptr;
28472847

2848-
if (nodeid == numa_node_id() || nodeid == -1)
2848+
if (nodeid == -1)
28492849
return __cache_alloc(cachep, flags);
28502850

28512851
if (unlikely(!cachep->nodelists[nodeid])) {
@@ -3080,7 +3080,7 @@ static int alloc_kmemlist(kmem_cache_t *cachep)
30803080

30813081
if ((nc = cachep->nodelists[node]->shared))
30823082
free_block(cachep, nc->entry,
3083-
nc->avail);
3083+
nc->avail, node);
30843084

30853085
l3->shared = new;
30863086
if (!cachep->nodelists[node]->alien) {
@@ -3161,7 +3161,7 @@ static int do_tune_cpucache(kmem_cache_t *cachep, int limit, int batchcount,
31613161
if (!ccold)
31623162
continue;
31633163
spin_lock_irq(&cachep->nodelists[cpu_to_node(i)]->list_lock);
3164-
free_block(cachep, ccold->entry, ccold->avail);
3164+
free_block(cachep, ccold->entry, ccold->avail, cpu_to_node(i));
31653165
spin_unlock_irq(&cachep->nodelists[cpu_to_node(i)]->list_lock);
31663166
kfree(ccold);
31673167
}
@@ -3241,7 +3241,7 @@ static void drain_array_locked(kmem_cache_t *cachep,
32413241
if (tofree > ac->avail) {
32423242
tofree = (ac->avail+1)/2;
32433243
}
3244-
free_block(cachep, ac->entry, tofree);
3244+
free_block(cachep, ac->entry, tofree, node);
32453245
ac->avail -= tofree;
32463246
memmove(ac->entry, &(ac->entry[tofree]),
32473247
sizeof(void*)*ac->avail);

0 commit comments

Comments
 (0)