|
@@ -165,13 +165,17 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
{
|
|
|
struct xenvif *vif = netdev_priv(dev);
|
|
|
struct xenvif_queue *queue = NULL;
|
|
|
- unsigned int num_queues = vif->num_queues;
|
|
|
+ unsigned int num_queues;
|
|
|
u16 index;
|
|
|
struct xenvif_rx_cb *cb;
|
|
|
|
|
|
BUG_ON(skb->dev != dev);
|
|
|
|
|
|
- /* Drop the packet if queues are not set up */
|
|
|
+ /* Drop the packet if queues are not set up.
|
|
|
+ * This handler should be called inside an RCU read section
|
|
|
+ * so we don't need to enter it here explicitly.
|
|
|
+ */
|
|
|
+ num_queues = READ_ONCE(vif->num_queues);
|
|
|
if (num_queues < 1)
|
|
|
goto drop;
|
|
|
|
|
@@ -222,18 +226,18 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev)
|
|
|
{
|
|
|
struct xenvif *vif = netdev_priv(dev);
|
|
|
struct xenvif_queue *queue = NULL;
|
|
|
+ unsigned int num_queues;
|
|
|
u64 rx_bytes = 0;
|
|
|
u64 rx_packets = 0;
|
|
|
u64 tx_bytes = 0;
|
|
|
u64 tx_packets = 0;
|
|
|
unsigned int index;
|
|
|
|
|
|
- spin_lock(&vif->lock);
|
|
|
- if (vif->queues == NULL)
|
|
|
- goto out;
|
|
|
+ rcu_read_lock();
|
|
|
+ num_queues = READ_ONCE(vif->num_queues);
|
|
|
|
|
|
/* Aggregate tx and rx stats from each queue */
|
|
|
- for (index = 0; index < vif->num_queues; ++index) {
|
|
|
+ for (index = 0; index < num_queues; ++index) {
|
|
|
queue = &vif->queues[index];
|
|
|
rx_bytes += queue->stats.rx_bytes;
|
|
|
rx_packets += queue->stats.rx_packets;
|
|
@@ -241,8 +245,7 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev)
|
|
|
tx_packets += queue->stats.tx_packets;
|
|
|
}
|
|
|
|
|
|
-out:
|
|
|
- spin_unlock(&vif->lock);
|
|
|
+ rcu_read_unlock();
|
|
|
|
|
|
vif->dev->stats.rx_bytes = rx_bytes;
|
|
|
vif->dev->stats.rx_packets = rx_packets;
|
|
@@ -378,10 +381,13 @@ static void xenvif_get_ethtool_stats(struct net_device *dev,
|
|
|
struct ethtool_stats *stats, u64 * data)
|
|
|
{
|
|
|
struct xenvif *vif = netdev_priv(dev);
|
|
|
- unsigned int num_queues = vif->num_queues;
|
|
|
+ unsigned int num_queues;
|
|
|
int i;
|
|
|
unsigned int queue_index;
|
|
|
|
|
|
+ rcu_read_lock();
|
|
|
+ num_queues = READ_ONCE(vif->num_queues);
|
|
|
+
|
|
|
for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++) {
|
|
|
unsigned long accum = 0;
|
|
|
for (queue_index = 0; queue_index < num_queues; ++queue_index) {
|
|
@@ -390,6 +396,8 @@ static void xenvif_get_ethtool_stats(struct net_device *dev,
|
|
|
}
|
|
|
data[i] = accum;
|
|
|
}
|
|
|
+
|
|
|
+ rcu_read_unlock();
|
|
|
}
|
|
|
|
|
|
static void xenvif_get_strings(struct net_device *dev, u32 stringset, u8 * data)
|