diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index abaf108ac..4c068d613 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -516,6 +516,15 @@ static void net_dm_packet_trace_kfree_skb_hit(void *ignore, */ nskb->tstamp = tstamp; + /* + * The tracepoint can run in preemptible context (e.g. from + * tcp_data_queue()). Pin the task to the current CPU before + * dereferencing the per-CPU pointer, otherwise this_cpu_ptr() + * triggers a "using smp_processor_id() in preemptible code" + * splat. migrate_disable() is used instead of preempt_disable() + * because the drop_queue spinlock can sleep on PREEMPT_RT. + */ + migrate_disable(); data = this_cpu_ptr(&dm_cpu_data); spin_lock_irqsave(&data->drop_queue.lock, flags); @@ -527,6 +536,7 @@ static void net_dm_packet_trace_kfree_skb_hit(void *ignore, schedule_work(&data->dm_alert_work); + migrate_enable(); return; unlock_free: @@ -534,6 +544,7 @@ static void net_dm_packet_trace_kfree_skb_hit(void *ignore, u64_stats_inc(&data->stats.dropped); u64_stats_update_end(&data->stats.syncp); spin_unlock_irqrestore(&data->drop_queue.lock, flags); + migrate_enable(); consume_skb(nskb); }