diff options
author | Shesha Sreenivasamurthy <shesha@cisco.com> | 2016-06-15 13:47:40 -0700 |
---|---|---|
committer | Damjan Marion <damarion@cisco.com> | 2016-06-16 15:11:51 +0000 |
commit | 81f7092d34d9ce2c674fb0ff7683188231d1b773 (patch) | |
tree | 5bdc482bcd91d6a027199af0bed7d856b50d0aec /vnet | |
parent | c0959c9c47fe056a35fb33ef70b23087172a54ee (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>
Diffstat (limited to 'vnet')
-rw-r--r-- | vnet/vnet/devices/dpdk/dpdk.h | 1 | ||||
-rw-r--r-- | vnet/vnet/devices/dpdk/vhost_user.c | 35 |
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); } |