As M.S.T mentioned, set affinity will not work very well when
CPU IDs are not consecutive, this can happen with hot unplug.
Fix this bug by traversal the online CPUs.

Cc: Rusty Russell <ru...@rustcorp.com.au>
Cc: "Michael S. Tsirkin" <m...@redhat.com>
Cc: Jason Wang <jasow...@redhat.com>
Cc: Eric Dumazet <erdnet...@gmail.com>
Cc: virtualizat...@lists.linux-foundation.org
Cc: net...@vger.kernel.org
Signed-off-by: Wanlong Gao <gaowanl...@cn.fujitsu.com>
---
 drivers/net/virtio_net.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index a6fcf15..b483fb5 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1016,6 +1016,7 @@ static int virtnet_vlan_rx_kill_vid(struct net_device 
*dev, u16 vid)
 static void virtnet_set_affinity(struct virtnet_info *vi, bool set)
 {
        int i;
+       int cpu;
 
        /* In multiqueue mode, when the number of cpu is equal to the number of
         * queue pairs, we let the queue pairs to be private to one cpu by
@@ -1029,16 +1030,25 @@ static void virtnet_set_affinity(struct virtnet_info 
*vi, bool set)
                        return;
        }
 
-       for (i = 0; i < vi->max_queue_pairs; i++) {
-               int cpu = set ? i : -1;
-               virtqueue_set_affinity(vi->rq[i].vq, cpu);
-               virtqueue_set_affinity(vi->sq[i].vq, cpu);
-       }
+       if (set) {
+               i = 0;
+               for_each_online_cpu(cpu) {
+                       virtqueue_set_affinity(vi->rq[i].vq, cpu);
+                       virtqueue_set_affinity(vi->sq[i].vq, cpu);
+                       i++;
+                       if (i >= vi->max_queue_pairs)
+                               break;
+               }
 
-       if (set)
                vi->affinity_hint_set = true;
-       else
+       } else {
+               for(i = 0; i < vi->max_queue_pairs; i++) {
+                       virtqueue_set_affinity(vi->rq[i].vq, -1);
+                       virtqueue_set_affinity(vi->sq[i].vq, -1);
+               }
+
                vi->affinity_hint_set = false;
+       }
 }
 
 static void virtnet_get_ringparam(struct net_device *dev,
-- 
1.8.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to