2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-02 07:15:17 +00:00

netdev-dpdk: fix memory leak

DPDK v16.07 introduces the ability to free memzones.
Up until this point, DPDK memory pools created in OVS could
not be destroyed, thus incurring a memory leak.

Leverage the DPDK v16.07 rte_mempool API to free DPDK
mempools when their associated reference count reaches 0 (this
indicates that the memory pool is no longer in use).

Signed-off-by: Mark Kavanagh <mark.b.kavanagh@intel.com>
Signed-off-by: Daniele Di Proietto <diproiettod@vmware.com>
This commit is contained in:
Mark Kavanagh
2016-08-04 10:49:12 +01:00
committed by Daniele Di Proietto
parent 94cf215ed4
commit 8d38823bdf

View File

@@ -506,23 +506,18 @@ dpdk_mp_get(int socket_id, int mtu) OVS_REQUIRES(dpdk_mutex)
} }
static void static void
dpdk_mp_put(struct dpdk_mp *dmp) dpdk_mp_put(struct dpdk_mp *dmp) OVS_REQUIRES(dpdk_mutex)
{ {
if (!dmp) { if (!dmp) {
return; return;
} }
dmp->refcount--; ovs_assert(dmp->refcount);
ovs_assert(dmp->refcount >= 0);
#if 0 if (!--dmp->refcount) {
/* I could not find any API to destroy mp. */ ovs_list_remove(&dmp->list_node);
if (dmp->refcount == 0) { rte_mempool_free(dmp->mp);
list_delete(dmp->list_node);
/* destroy mp-pool. */
} }
#endif
} }
static void static void
@@ -928,16 +923,18 @@ netdev_dpdk_destruct(struct netdev *netdev)
{ {
struct netdev_dpdk *dev = netdev_dpdk_cast(netdev); struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
ovs_mutex_lock(&dpdk_mutex);
ovs_mutex_lock(&dev->mutex); ovs_mutex_lock(&dev->mutex);
rte_eth_dev_stop(dev->port_id); rte_eth_dev_stop(dev->port_id);
free(ovsrcu_get_protected(struct ingress_policer *, free(ovsrcu_get_protected(struct ingress_policer *,
&dev->ingress_policer)); &dev->ingress_policer));
ovs_mutex_unlock(&dev->mutex);
ovs_mutex_lock(&dpdk_mutex);
rte_free(dev->tx_q); rte_free(dev->tx_q);
ovs_list_remove(&dev->list_node); ovs_list_remove(&dev->list_node);
dpdk_mp_put(dev->dpdk_mp); dpdk_mp_put(dev->dpdk_mp);
ovs_mutex_unlock(&dev->mutex);
ovs_mutex_unlock(&dpdk_mutex); ovs_mutex_unlock(&dpdk_mutex);
} }
@@ -946,6 +943,9 @@ netdev_dpdk_vhost_destruct(struct netdev *netdev)
{ {
struct netdev_dpdk *dev = netdev_dpdk_cast(netdev); struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
ovs_mutex_lock(&dpdk_mutex);
ovs_mutex_lock(&dev->mutex);
/* Guest becomes an orphan if still attached. */ /* Guest becomes an orphan if still attached. */
if (netdev_dpdk_get_vid(dev) >= 0) { if (netdev_dpdk_get_vid(dev) >= 0) {
VLOG_ERR("Removing port '%s' while vhost device still attached.", VLOG_ERR("Removing port '%s' while vhost device still attached.",
@@ -961,15 +961,14 @@ netdev_dpdk_vhost_destruct(struct netdev *netdev)
fatal_signal_remove_file_to_unlink(dev->vhost_id); fatal_signal_remove_file_to_unlink(dev->vhost_id);
} }
ovs_mutex_lock(&dev->mutex);
free(ovsrcu_get_protected(struct ingress_policer *, free(ovsrcu_get_protected(struct ingress_policer *,
&dev->ingress_policer)); &dev->ingress_policer));
ovs_mutex_unlock(&dev->mutex);
ovs_mutex_lock(&dpdk_mutex);
rte_free(dev->tx_q); rte_free(dev->tx_q);
ovs_list_remove(&dev->list_node); ovs_list_remove(&dev->list_node);
dpdk_mp_put(dev->dpdk_mp); dpdk_mp_put(dev->dpdk_mp);
ovs_mutex_unlock(&dev->mutex);
ovs_mutex_unlock(&dpdk_mutex); ovs_mutex_unlock(&dpdk_mutex);
} }