aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShesha Sreenivasamurthy <shesha@cisco.com>2016-06-15 13:47:40 -0700
committerDamjan Marion <damarion@cisco.com>2016-06-16 15:11:51 +0000
commit81f7092d34d9ce2c674fb0ff7683188231d1b773 (patch)
tree5bdc482bcd91d6a027199af0bed7d856b50d0aec
parentc0959c9c47fe056a35fb33ef70b23087172a54ee (diff)
Fix hugepage leak on VM termination
When VM is terminated, the hugepages mapped should be unmapped so that the system does not run out of hugepage resources. Therefore, mapped pages are unmapped when VPP notices a disconnect. Change-Id: I7398fb20028036738ab87db0b0e79609e95d69a4 Signed-off-by: Shesha Sreenivasamurthy <shesha@cisco.com>
-rw-r--r--vnet/vnet/devices/dpdk/dpdk.h1
-rw-r--r--vnet/vnet/devices/dpdk/vhost_user.c35
2 files changed, 36 insertions, 0 deletions
diff --git a/vnet/vnet/devices/dpdk/dpdk.h b/vnet/vnet/devices/dpdk/dpdk.h
index 8cd344cff16..116be3632fd 100644
--- a/vnet/vnet/devices/dpdk/dpdk.h
+++ b/vnet/vnet/devices/dpdk/dpdk.h
@@ -170,6 +170,7 @@ typedef struct {
#endif
u64 region_addr[VHOST_MEMORY_MAX_NREGIONS];
u32 region_fd[VHOST_MEMORY_MAX_NREGIONS];
+ u64 region_offset[VHOST_MEMORY_MAX_NREGIONS];
} dpdk_vu_intf_t;
typedef void (*dpdk_flowcontrol_callback_t) (vlib_main_t *vm,
diff --git a/vnet/vnet/devices/dpdk/vhost_user.c b/vnet/vnet/devices/dpdk/vhost_user.c
index 92b5d0e5e02..fd1bd221062 100644
--- a/vnet/vnet/devices/dpdk/vhost_user.c
+++ b/vnet/vnet/devices/dpdk/vhost_user.c
@@ -527,8 +527,12 @@ dpdk_vhost_user_set_mem_table(u32 hw_if_index, vhost_user_memory_t * vum, int fd
mapped_address += vum->regions[i].mmap_offset;
vui->region_addr[i] = mapped_address;
vui->region_fd[i] = fd[i];
+ vui->region_offset[i] = vum->regions[i].mmap_offset;
mem->regions[i].address_offset = mapped_address - mem->regions[i].guest_phys_address;
+ DBG_SOCK("map memory region %d addr 0x%lx off 0x%lx len 0x%lx",
+ i, vui->region_addr[i], vui->region_offset[i], mapped_size);
+
if (vum->regions[i].guest_phys_addr == 0) {
mem->base_address = vum->regions[i].userspace_addr;
mem->mapped_address = mem->regions[i].address_offset;
@@ -913,6 +917,36 @@ dpdk_vhost_user_vui_register(vlib_main_t * vm, dpdk_device_t *xd)
xd->vlib_sw_if_index);
}
+static void dpdk_unmap_all_mem_regions(dpdk_device_t * xd)
+{
+ int i, r;
+ dpdk_vu_intf_t *vui = xd->vu_intf;
+ struct virtio_memory * mem = xd->vu_vhost_dev.mem;
+
+ for (i=0; i<mem->nregions; i++) {
+ if (vui->region_addr[i] != -1) {
+
+ long page_sz = get_huge_page_size(vui->region_fd[i]);
+
+ ssize_t map_sz = (mem->regions[i].memory_size +
+ vui->region_offset[i] + page_sz) & ~(page_sz - 1);
+
+ r = munmap((void *)(vui->region_addr[i] - vui->region_offset[i]), map_sz);
+
+ DBG_SOCK("unmap memory region %d addr 0x%lx off 0x%lx len 0x%lx page_sz 0x%x",
+ i, vui->region_addr[i], vui->region_offset[i], map_sz, page_sz);
+
+ vui->region_addr[i]= -1;
+
+ if (r == -1) {
+ clib_warning("failed to unmap memory region (errno %d)", errno);
+ }
+ close(vui->region_fd[i]);
+ }
+ }
+ mem->nregions = 0;
+}
+
static inline void
dpdk_vhost_user_if_disconnect(dpdk_device_t * xd)
{
@@ -934,6 +968,7 @@ dpdk_vhost_user_if_disconnect(dpdk_device_t * xd)
vui->unix_fd = -1;
vui->is_up = 0;
+ dpdk_unmap_all_mem_regions(xd);
DBG_SOCK("interface ifindex %d disconnected", xd->vlib_sw_if_index);
}