aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/slub.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/mm/slub.c b/mm/slub.c
index 545a170ebf9f..2b1a6970e46f 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -355,6 +355,21 @@ static __always_inline void slab_unlock(struct page *page)
355 __bit_spin_unlock(PG_locked, &page->flags); 355 __bit_spin_unlock(PG_locked, &page->flags);
356} 356}
357 357
358static inline void set_page_slub_counters(struct page *page, unsigned long counters_new)
359{
360 struct page tmp;
361 tmp.counters = counters_new;
362 /*
363 * page->counters can cover frozen/inuse/objects as well
364 * as page->_count. If we assign to ->counters directly
365 * we run the risk of losing updates to page->_count, so
366 * be careful and only assign to the fields we need.
367 */
368 page->frozen = tmp.frozen;
369 page->inuse = tmp.inuse;
370 page->objects = tmp.objects;
371}
372
358/* Interrupts must be disabled (for the fallback code to work right) */ 373/* Interrupts must be disabled (for the fallback code to work right) */
359static inline bool __cmpxchg_double_slab(struct kmem_cache *s, struct page *page, 374static inline bool __cmpxchg_double_slab(struct kmem_cache *s, struct page *page,
360 void *freelist_old, unsigned long counters_old, 375 void *freelist_old, unsigned long counters_old,
@@ -376,7 +391,7 @@ static inline bool __cmpxchg_double_slab(struct kmem_cache *s, struct page *page
376 if (page->freelist == freelist_old && 391 if (page->freelist == freelist_old &&
377 page->counters == counters_old) { 392 page->counters == counters_old) {
378 page->freelist = freelist_new; 393 page->freelist = freelist_new;
379 page->counters = counters_new; 394 set_page_slub_counters(page, counters_new);
380 slab_unlock(page); 395 slab_unlock(page);
381 return 1; 396 return 1;
382 } 397 }
@@ -415,7 +430,7 @@ static inline bool cmpxchg_double_slab(struct kmem_cache *s, struct page *page,
415 if (page->freelist == freelist_old && 430 if (page->freelist == freelist_old &&
416 page->counters == counters_old) { 431 page->counters == counters_old) {
417 page->freelist = freelist_new; 432 page->freelist = freelist_new;
418 page->counters = counters_new; 433 set_page_slub_counters(page, counters_new);
419 slab_unlock(page); 434 slab_unlock(page);
420 local_irq_restore(flags); 435 local_irq_restore(flags);
421 return 1; 436 return 1;