Commit d89ede6d authored by David S. Miller's avatar David S. Miller

Merge branch 'xen-netback-leaks'

Igor Druzhinin says:

====================
xen-netback: fix memory leaks on XenBus disconnect

Just split the initial patch in two as proposed by Wei.

Since the approach for locking netdev statistics is inconsistent (tends not
to have any locking at all) accross the kernel we'd better to rely on our
internal lock for this purpose.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6acbe371 f16f1df6
...@@ -221,18 +221,18 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev) ...@@ -221,18 +221,18 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev)
{ {
struct xenvif *vif = netdev_priv(dev); struct xenvif *vif = netdev_priv(dev);
struct xenvif_queue *queue = NULL; struct xenvif_queue *queue = NULL;
unsigned int num_queues = vif->num_queues;
unsigned long rx_bytes = 0; unsigned long rx_bytes = 0;
unsigned long rx_packets = 0; unsigned long rx_packets = 0;
unsigned long tx_bytes = 0; unsigned long tx_bytes = 0;
unsigned long tx_packets = 0; unsigned long tx_packets = 0;
unsigned int index; unsigned int index;
spin_lock(&vif->lock);
if (vif->queues == NULL) if (vif->queues == NULL)
goto out; goto out;
/* Aggregate tx and rx stats from each queue */ /* Aggregate tx and rx stats from each queue */
for (index = 0; index < num_queues; ++index) { for (index = 0; index < vif->num_queues; ++index) {
queue = &vif->queues[index]; queue = &vif->queues[index];
rx_bytes += queue->stats.rx_bytes; rx_bytes += queue->stats.rx_bytes;
rx_packets += queue->stats.rx_packets; rx_packets += queue->stats.rx_packets;
...@@ -241,6 +241,8 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev) ...@@ -241,6 +241,8 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev)
} }
out: out:
spin_unlock(&vif->lock);
vif->dev->stats.rx_bytes = rx_bytes; vif->dev->stats.rx_bytes = rx_bytes;
vif->dev->stats.rx_packets = rx_packets; vif->dev->stats.rx_packets = rx_packets;
vif->dev->stats.tx_bytes = tx_bytes; vif->dev->stats.tx_bytes = tx_bytes;
......
...@@ -493,11 +493,22 @@ static int backend_create_xenvif(struct backend_info *be) ...@@ -493,11 +493,22 @@ static int backend_create_xenvif(struct backend_info *be)
static void backend_disconnect(struct backend_info *be) static void backend_disconnect(struct backend_info *be)
{ {
if (be->vif) { if (be->vif) {
unsigned int queue_index;
xen_unregister_watchers(be->vif); xen_unregister_watchers(be->vif);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
xenvif_debugfs_delif(be->vif); xenvif_debugfs_delif(be->vif);
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
xenvif_disconnect_data(be->vif); xenvif_disconnect_data(be->vif);
for (queue_index = 0; queue_index < be->vif->num_queues; ++queue_index)
xenvif_deinit_queue(&be->vif->queues[queue_index]);
spin_lock(&be->vif->lock);
vfree(be->vif->queues);
be->vif->num_queues = 0;
be->vif->queues = NULL;
spin_unlock(&be->vif->lock);
xenvif_disconnect_ctrl(be->vif); xenvif_disconnect_ctrl(be->vif);
} }
} }
...@@ -1034,6 +1045,8 @@ static void connect(struct backend_info *be) ...@@ -1034,6 +1045,8 @@ static void connect(struct backend_info *be)
err: err:
if (be->vif->num_queues > 0) if (be->vif->num_queues > 0)
xenvif_disconnect_data(be->vif); /* Clean up existing queues */ xenvif_disconnect_data(be->vif); /* Clean up existing queues */
for (queue_index = 0; queue_index < be->vif->num_queues; ++queue_index)
xenvif_deinit_queue(&be->vif->queues[queue_index]);
vfree(be->vif->queues); vfree(be->vif->queues);
be->vif->queues = NULL; be->vif->queues = NULL;
be->vif->num_queues = 0; be->vif->num_queues = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment