On Wed, Apr 22, 2026 at 02:30:24AM +0000, Kohei Enju wrote:
> syzbot reported "sleeping function called from invalid context" in
> vhost_net_busy_poll().
>
> Commit 030881372460 ("vhost_net: basic polling support") introduced a
> busy-poll loop and preempt_{disable,enable}() around it, where each
> iteration calls a sleepable function inside the loop.
>
> The purpose of disabling preemption was to keep local_clock()-based
> timeout accounting on a single CPU, rather than as a requirement of
> busy-poll itself:
>
> https://lore.kernel.org/netdev/[email protected]/T/#u
>
> Changes from RFC V1:
> ...
> - Disable preemption during busy looping to make sure local_clock()
> was correctly used.
>
> >From this perspective, migrate_disable() is sufficient here, so replace
> preempt_disable() with migrate_disable(), avoiding sleepable accesses
> from a preempt-disabled context.
>
> Fixes: 030881372460 ("vhost_net: basic polling support")
> Tested-by: [email protected]
> Reported-by: [email protected]
> Closes:
> https://lore.kernel.org/all/[email protected]/T/
> Signed-off-by: Kohei Enju <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
> ---
> drivers/vhost/net.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
> index 80965181920c..c6536cad9c4f 100644
> --- a/drivers/vhost/net.c
> +++ b/drivers/vhost/net.c
> @@ -560,7 +560,7 @@ static void vhost_net_busy_poll(struct vhost_net *net,
> busyloop_timeout = poll_rx ? rvq->busyloop_timeout:
> tvq->busyloop_timeout;
>
> - preempt_disable();
> + migrate_disable();
> endtime = busy_clock() + busyloop_timeout;
>
> while (vhost_can_busy_poll(endtime)) {
> @@ -577,7 +577,7 @@ static void vhost_net_busy_poll(struct vhost_net *net,
> cpu_relax();
> }
>
> - preempt_enable();
> + migrate_enable();
>
> if (poll_rx || sock_has_rx_data(sock))
> vhost_net_busy_poll_try_queue(net, vq);
> --
> 2.51.0