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]>
---
 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


Reply via email to