aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@citrix.com>2015-01-13 11:42:42 -0500
committerDavid S. Miller <davem@davemloft.net>2015-01-13 17:22:11 -0500
commit900e183301b54f8ca17a86d9835e9569090d182a (patch)
tree222e2526f5b5f7891a7f1e3bc71deffe3f0ccdd0 /drivers/net
parent25906052d953d3fbdb7e19480b9de5e6bb949f3f (diff)
xen-netfront: use different locks for Rx and Tx stats
In netfront the Rx and Tx path are independent and use different locks. The Tx lock is held with hard irqs disabled, but Rx lock is held with only BH disabled. Since both sides use the same stats lock, a deadlock may occur. [ INFO: possible irq lock inversion dependency detected ] 3.16.2 #16 Not tainted --------------------------------------------------------- swapper/0/0 just changed the state of lock: (&(&queue->tx_lock)->rlock){-.....}, at: [<c03adec8>] xennet_tx_interrupt+0x14/0x34 but this lock took another, HARDIRQ-unsafe lock in the past: (&stat->syncp.seq#2){+.-...} and interrupts could create inverse lock ordering between them. other info that might help us debug this: Possible interrupt unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&stat->syncp.seq#2); local_irq_disable(); lock(&(&queue->tx_lock)->rlock); lock(&stat->syncp.seq#2); <Interrupt> lock(&(&queue->tx_lock)->rlock); Using separate locks for the Rx and Tx stats fixes this deadlock. Reported-by: Dmitry Piotrovsky <piotrovskydmitry@gmail.com> Signed-off-by: David Vrabel <david.vrabel@citrix.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/xen-netfront.c71
1 files changed, 42 insertions, 29 deletions
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 22bcb4e12e2a..d8c10764f130 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -88,10 +88,8 @@ struct netfront_cb {
88#define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3) 88#define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3)
89 89
90struct netfront_stats { 90struct netfront_stats {
91 u64 rx_packets; 91 u64 packets;
92 u64 tx_packets; 92 u64 bytes;
93 u64 rx_bytes;
94 u64 tx_bytes;
95 struct u64_stats_sync syncp; 93 struct u64_stats_sync syncp;
96}; 94};
97 95
@@ -160,7 +158,8 @@ struct netfront_info {
160 struct netfront_queue *queues; 158 struct netfront_queue *queues;
161 159
162 /* Statistics */ 160 /* Statistics */
163 struct netfront_stats __percpu *stats; 161 struct netfront_stats __percpu *rx_stats;
162 struct netfront_stats __percpu *tx_stats;
164 163
165 atomic_t rx_gso_checksum_fixup; 164 atomic_t rx_gso_checksum_fixup;
166}; 165};
@@ -565,7 +564,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
565{ 564{
566 unsigned short id; 565 unsigned short id;
567 struct netfront_info *np = netdev_priv(dev); 566 struct netfront_info *np = netdev_priv(dev);
568 struct netfront_stats *stats = this_cpu_ptr(np->stats); 567 struct netfront_stats *tx_stats = this_cpu_ptr(np->tx_stats);
569 struct xen_netif_tx_request *tx; 568 struct xen_netif_tx_request *tx;
570 char *data = skb->data; 569 char *data = skb->data;
571 RING_IDX i; 570 RING_IDX i;
@@ -672,10 +671,10 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
672 if (notify) 671 if (notify)
673 notify_remote_via_irq(queue->tx_irq); 672 notify_remote_via_irq(queue->tx_irq);
674 673
675 u64_stats_update_begin(&stats->syncp); 674 u64_stats_update_begin(&tx_stats->syncp);
676 stats->tx_bytes += skb->len; 675 tx_stats->bytes += skb->len;
677 stats->tx_packets++; 676 tx_stats->packets++;
678 u64_stats_update_end(&stats->syncp); 677 u64_stats_update_end(&tx_stats->syncp);
679 678
680 /* Note: It is not safe to access skb after xennet_tx_buf_gc()! */ 679 /* Note: It is not safe to access skb after xennet_tx_buf_gc()! */
681 xennet_tx_buf_gc(queue); 680 xennet_tx_buf_gc(queue);
@@ -931,7 +930,7 @@ static int checksum_setup(struct net_device *dev, struct sk_buff *skb)
931static int handle_incoming_queue(struct netfront_queue *queue, 930static int handle_incoming_queue(struct netfront_queue *queue,
932 struct sk_buff_head *rxq) 931 struct sk_buff_head *rxq)
933{ 932{
934 struct netfront_stats *stats = this_cpu_ptr(queue->info->stats); 933 struct netfront_stats *rx_stats = this_cpu_ptr(queue->info->rx_stats);
935 int packets_dropped = 0; 934 int packets_dropped = 0;
936 struct sk_buff *skb; 935 struct sk_buff *skb;
937 936
@@ -952,10 +951,10 @@ static int handle_incoming_queue(struct netfront_queue *queue,
952 continue; 951 continue;
953 } 952 }
954 953
955 u64_stats_update_begin(&stats->syncp); 954 u64_stats_update_begin(&rx_stats->syncp);
956 stats->rx_packets++; 955 rx_stats->packets++;
957 stats->rx_bytes += skb->len; 956 rx_stats->bytes += skb->len;
958 u64_stats_update_end(&stats->syncp); 957 u64_stats_update_end(&rx_stats->syncp);
959 958
960 /* Pass it up. */ 959 /* Pass it up. */
961 napi_gro_receive(&queue->napi, skb); 960 napi_gro_receive(&queue->napi, skb);
@@ -1079,18 +1078,22 @@ static struct rtnl_link_stats64 *xennet_get_stats64(struct net_device *dev,
1079 int cpu; 1078 int cpu;
1080 1079
1081 for_each_possible_cpu(cpu) { 1080 for_each_possible_cpu(cpu) {
1082 struct netfront_stats *stats = per_cpu_ptr(np->stats, cpu); 1081 struct netfront_stats *rx_stats = per_cpu_ptr(np->rx_stats, cpu);
1082 struct netfront_stats *tx_stats = per_cpu_ptr(np->tx_stats, cpu);
1083 u64 rx_packets, rx_bytes, tx_packets, tx_bytes; 1083 u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
1084 unsigned int start; 1084 unsigned int start;
1085 1085
1086 do { 1086 do {
1087 start = u64_stats_fetch_begin_irq(&stats->syncp); 1087 start = u64_stats_fetch_begin_irq(&tx_stats->syncp);
1088 tx_packets = tx_stats->packets;
1089 tx_bytes = tx_stats->bytes;
1090 } while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start));
1088 1091
1089 rx_packets = stats->rx_packets; 1092 do {
1090 tx_packets = stats->tx_packets; 1093 start = u64_stats_fetch_begin_irq(&rx_stats->syncp);
1091 rx_bytes = stats->rx_bytes; 1094 rx_packets = rx_stats->packets;
1092 tx_bytes = stats->tx_bytes; 1095 rx_bytes = rx_stats->bytes;
1093 } while (u64_stats_fetch_retry_irq(&stats->syncp, start)); 1096 } while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start));
1094 1097
1095 tot->rx_packets += rx_packets; 1098 tot->rx_packets += rx_packets;
1096 tot->tx_packets += tx_packets; 1099 tot->tx_packets += tx_packets;
@@ -1275,6 +1278,15 @@ static const struct net_device_ops xennet_netdev_ops = {
1275#endif 1278#endif
1276}; 1279};
1277 1280
1281static void xennet_free_netdev(struct net_device *netdev)
1282{
1283 struct netfront_info *np = netdev_priv(netdev);
1284
1285 free_percpu(np->rx_stats);
1286 free_percpu(np->tx_stats);
1287 free_netdev(netdev);
1288}
1289
1278static struct net_device *xennet_create_dev(struct xenbus_device *dev) 1290static struct net_device *xennet_create_dev(struct xenbus_device *dev)
1279{ 1291{
1280 int err; 1292 int err;
@@ -1295,8 +1307,11 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
1295 np->queues = NULL; 1307 np->queues = NULL;
1296 1308
1297 err = -ENOMEM; 1309 err = -ENOMEM;
1298 np->stats = netdev_alloc_pcpu_stats(struct netfront_stats); 1310 np->rx_stats = netdev_alloc_pcpu_stats(struct netfront_stats);
1299 if (np->stats == NULL) 1311 if (np->rx_stats == NULL)
1312 goto exit;
1313 np->tx_stats = netdev_alloc_pcpu_stats(struct netfront_stats);
1314 if (np->tx_stats == NULL)
1300 goto exit; 1315 goto exit;
1301 1316
1302 netdev->netdev_ops = &xennet_netdev_ops; 1317 netdev->netdev_ops = &xennet_netdev_ops;
@@ -1327,7 +1342,7 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
1327 return netdev; 1342 return netdev;
1328 1343
1329 exit: 1344 exit:
1330 free_netdev(netdev); 1345 xennet_free_netdev(netdev);
1331 return ERR_PTR(err); 1346 return ERR_PTR(err);
1332} 1347}
1333 1348
@@ -1369,7 +1384,7 @@ static int netfront_probe(struct xenbus_device *dev,
1369 return 0; 1384 return 0;
1370 1385
1371 fail: 1386 fail:
1372 free_netdev(netdev); 1387 xennet_free_netdev(netdev);
1373 dev_set_drvdata(&dev->dev, NULL); 1388 dev_set_drvdata(&dev->dev, NULL);
1374 return err; 1389 return err;
1375} 1390}
@@ -2189,9 +2204,7 @@ static int xennet_remove(struct xenbus_device *dev)
2189 info->queues = NULL; 2204 info->queues = NULL;
2190 } 2205 }
2191 2206
2192 free_percpu(info->stats); 2207 xennet_free_netdev(info->netdev);
2193
2194 free_netdev(info->netdev);
2195 2208
2196 return 0; 2209 return 0;
2197} 2210}