]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
mm, slub: use migrate_disable() on PREEMPT_RT
authorVlastimil Babka <vbabka@suse.cz>
Mon, 23 Aug 2021 23:59:02 +0000 (09:59 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Wed, 25 Aug 2021 23:33:33 +0000 (09:33 +1000)
We currently use preempt_disable() (directly or via get_cpu_ptr()) to
stabilize the pointer to kmem_cache_cpu.  On PREEMPT_RT this would be
incompatible with the list_lock spinlock.  We can use migrate_disable()
instead, but that increases overhead on !PREEMPT_RT as it's an
unconditional function call.

In order to get the best available mechanism on both PREEMPT_RT and
!PREEMPT_RT, introduce private slub_get_cpu_ptr() and slub_put_cpu_ptr()
wrappers and use them.

Link: https://lkml.kernel.org/r/20210805152000.12817-35-vbabka@suse.cz
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Cc: Christoph Lameter <cl@linux.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Jann Horn <jannh@google.com>
Cc: Jesper Dangaard Brouer <brouer@redhat.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
mm/slub.c

index 2362efab53df4b597ff559fba2e0a22472ffb3ed..cd78b7844273cf1b11a0c09f2e885ca0c8e82fa7 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
  *                     the fast path and disables lockless freelists.
  */
 
+/*
+ * We could simply use migrate_disable()/enable() but as long as it's a
+ * function call even on !PREEMPT_RT, use inline preempt_disable() there.
+ */
+#ifndef CONFIG_PREEMPT_RT
+#define slub_get_cpu_ptr(var)  get_cpu_ptr(var)
+#define slub_put_cpu_ptr(var)  put_cpu_ptr(var)
+#else
+#define slub_get_cpu_ptr(var)          \
+({                                     \
+       migrate_disable();              \
+       this_cpu_ptr(var);              \
+})
+#define slub_put_cpu_ptr(var)          \
+do {                                   \
+       (void)(var);                    \
+       migrate_enable();               \
+} while (0)
+#endif
+
 #ifdef CONFIG_SLUB_DEBUG
 #ifdef CONFIG_SLUB_DEBUG_ON
 DEFINE_STATIC_KEY_TRUE(slub_debug_enabled);
@@ -2828,7 +2848,7 @@ redo:
        if (unlikely(!pfmemalloc_match_unsafe(page, gfpflags)))
                goto deactivate_slab;
 
-       /* must check again c->page in case IRQ handler changed it */
+       /* must check again c->page in case we got preempted and it changed */
        local_irq_save(flags);
        if (unlikely(page != c->page)) {
                local_irq_restore(flags);
@@ -2887,7 +2907,8 @@ new_slab:
                }
                if (unlikely(!slub_percpu_partial(c))) {
                        local_irq_restore(flags);
-                       goto new_objects; /* stolen by an IRQ handler */
+                       /* we were preempted and partial list got empty */
+                       goto new_objects;
                }
 
                page = c->page = slub_percpu_partial(c);
@@ -2903,9 +2924,9 @@ new_objects:
        if (freelist)
                goto check_new_page;
 
-       put_cpu_ptr(s->cpu_slab);
+       slub_put_cpu_ptr(s->cpu_slab);
        page = new_slab(s, gfpflags, node);
-       c = get_cpu_ptr(s->cpu_slab);
+       c = slub_get_cpu_ptr(s->cpu_slab);
 
        if (unlikely(!page)) {
                slab_out_of_memory(s, gfpflags, node);
@@ -2988,12 +3009,12 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
         * cpu before disabling preemption. Need to reload cpu area
         * pointer.
         */
-       c = get_cpu_ptr(s->cpu_slab);
+       c = slub_get_cpu_ptr(s->cpu_slab);
 #endif
 
        p = ___slab_alloc(s, gfpflags, node, addr, c);
 #ifdef CONFIG_PREEMPT_COUNT
-       put_cpu_ptr(s->cpu_slab);
+       slub_put_cpu_ptr(s->cpu_slab);
 #endif
        return p;
 }
@@ -3522,7 +3543,7 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
         * IRQs, which protects against PREEMPT and interrupts
         * handlers invoking normal fastpath.
         */
-       c = get_cpu_ptr(s->cpu_slab);
+       c = slub_get_cpu_ptr(s->cpu_slab);
        local_irq_disable();
 
        for (i = 0; i < size; i++) {
@@ -3568,7 +3589,7 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
        }
        c->tid = next_tid(c->tid);
        local_irq_enable();
-       put_cpu_ptr(s->cpu_slab);
+       slub_put_cpu_ptr(s->cpu_slab);
 
        /*
         * memcg and kmem_cache debug support and memory initialization.
@@ -3578,7 +3599,7 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
                                slab_want_init_on_alloc(flags, s));
        return i;
 error:
-       put_cpu_ptr(s->cpu_slab);
+       slub_put_cpu_ptr(s->cpu_slab);
        slab_post_alloc_hook(s, objcg, flags, i, p, false);
        __kmem_cache_free_bulk(s, i, p);
        return 0;