From 81f7092d34d9ce2c674fb0ff7683188231d1b773 Mon Sep 17 00:00:00 2001 From: Shesha Sreenivasamurthy Date: Wed, 15 Jun 2016 13:47:40 -0700 Subject: 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 --- vnet/vnet/devices/dpdk/dpdk.h | 1 + vnet/vnet/devices/dpdk/vhost_user.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) 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; inregions; 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); } -- cgit 1.2.3-korg