bpf/stackmap: Dont trylock mmap_sem with PREEMPT_RT and interrupts disabled
authorDavid Miller <davem@davemloft.net>
Mon, 24 Feb 2020 14:01:53 +0000 (15:01 +0100)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 25 Feb 2020 00:20:10 +0000 (16:20 -0800)
In a RT kernel down_read_trylock() cannot be used from NMI context and
up_read_non_owner() is another problematic issue.

So in such a configuration, simply elide the annotated stackmap and
just report the raw IPs.

In the longer term, it might be possible to provide a atomic friendly
versions of the page cache traversal which will at least provide the info
if the pages are resident and don't need to be paged in.

[ tglx: Use IS_ENABLED() to avoid the #ifdeffery, fixup the irq work
   callback and add a comment ]

Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20200224145644.708960317@linutronix.de
kernel/bpf/stackmap.c

index 3f958b9..db76339 100644 (file)
@@ -40,6 +40,9 @@ static void do_up_read(struct irq_work *entry)
 {
        struct stack_map_irq_work *work;
 
+       if (WARN_ON_ONCE(IS_ENABLED(CONFIG_PREEMPT_RT)))
+               return;
+
        work = container_of(entry, struct stack_map_irq_work, irq_work);
        up_read_non_owner(work->sem);
        work->sem = NULL;
@@ -288,10 +291,19 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
        struct stack_map_irq_work *work = NULL;
 
        if (irqs_disabled()) {
-               work = this_cpu_ptr(&up_read_work);
-               if (atomic_read(&work->irq_work.flags) & IRQ_WORK_BUSY)
-                       /* cannot queue more up_read, fallback */
+               if (!IS_ENABLED(CONFIG_PREEMPT_RT)) {
+                       work = this_cpu_ptr(&up_read_work);
+                       if (atomic_read(&work->irq_work.flags) & IRQ_WORK_BUSY) {
+                               /* cannot queue more up_read, fallback */
+                               irq_work_busy = true;
+                       }
+               } else {
+                       /*
+                        * PREEMPT_RT does not allow to trylock mmap sem in
+                        * interrupt disabled context. Force the fallback code.
+                        */
                        irq_work_busy = true;
+               }
        }
 
        /*