Re: [PATCH v3] kcov: move kcov_remote_data to task_struct for RT and remove local_lock
From: Tetsuo Handa
Date: Thu May 21 2026 - 11:53:38 EST
On 2026/05/21 22:06, Alexander Potapenko wrote:
> I think a deadlock is possible if a softirq is delivered while a
> background task is executing kcov_remote_start():
Indeed. Since kcov_remote_start() is called by
static int vhost_run_work_kthread_list(void *data)
{
kcov_remote_start_common(worker->kcov_handle);
work->fn(work);
kcov_remote_stop();
}
and it can be preempted by
static void usb_giveback_urb_bh(struct work_struct *work)
{
static void __usb_hcd_giveback_urb(struct urb *urb)
{
kcov_remote_start_usb_softirq((u64)urb->dev->bus->busnum);
urb->complete(urb);
kcov_remote_stop_softirq();
}
}
, we need to use _irq{save,restore} version. Any other concerns?
kernel/kcov.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/kernel/kcov.c b/kernel/kcov.c
index 965c11a75b36..70ce99c3205d 100644
--- a/kernel/kcov.c
+++ b/kernel/kcov.c
@@ -897,6 +897,7 @@ void kcov_remote_start(u64 handle)
void *area;
unsigned int size;
int sequence;
+ unsigned long flags;
/* Don't use in_task() in order to allow consistent checks in RT kernels. */
if (in_hardirq() || in_nmi())
@@ -918,10 +919,10 @@ void kcov_remote_start(u64 handle)
if (WARN_ON(in_serving_softirq() && t->kcov_softirq))
return;
- spin_lock(&kcov_remote_lock);
+ spin_lock_irqsave(&kcov_remote_lock, flags);
remote = kcov_remote_find(handle);
if (!remote) {
- spin_unlock(&kcov_remote_lock);
+ spin_unlock_irqrestore(&kcov_remote_lock, flags);
return;
}
kcov_debug("handle = %llx, context: %s\n", handle,
@@ -949,7 +950,7 @@ void kcov_remote_start(u64 handle)
area = this_cpu_ptr(&kcov_percpu_data)->irq_area;
}
#endif
- spin_unlock(&kcov_remote_lock);
+ spin_unlock_irqrestore(&kcov_remote_lock, flags);
/* Can only happen when CONFIG_PREEMPT_RT=y or in_task(). */
if (!area) {
@@ -1044,6 +1045,7 @@ void kcov_remote_stop(void)
void *area;
unsigned int size;
int sequence;
+ unsigned long flags;
/* Don't use in_task() in order to allow consistent checks in RT kernels. */
if (in_hardirq() || in_nmi())
@@ -1084,9 +1086,9 @@ void kcov_remote_stop(void)
spin_unlock(&kcov->lock);
if (IS_ENABLED(CONFIG_PREEMPT_RT) || in_task()) {
- spin_lock(&kcov_remote_lock);
+ spin_lock_irqsave(&kcov_remote_lock, flags);
kcov_remote_area_put(area, size);
- spin_unlock(&kcov_remote_lock);
+ spin_unlock_irqrestore(&kcov_remote_lock, flags);
}
/* Get in kcov_remote_start(). */