mem: detach memsegs on cleanup
Currently, we don't detach the shared memory on EAL cleanup, which leaves the page table descriptors still holding on to the file descriptors as well as memory space occupied by them. Fix it by adding another detach stage that closes the internal memory allocator resource references, detaches shared fbarrays and unmaps the shared mem config. Bugzilla ID: 380 Bugzilla ID: 381 Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com> Acked-by: Stephen Hemminger <stephen@networkplumber.org>
This commit is contained in:
parent
3cd7290c16
commit
dfbc61a2f9
@ -1002,6 +1002,60 @@ rte_extmem_detach(void *va_addr, size_t len)
|
||||
return sync_memory(va_addr, len, false);
|
||||
}
|
||||
|
||||
/* detach all EAL memory */
|
||||
int
|
||||
rte_eal_memory_detach(void)
|
||||
{
|
||||
struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
|
||||
size_t page_sz = rte_mem_page_size();
|
||||
unsigned int i;
|
||||
|
||||
rte_rwlock_write_lock(&mcfg->memory_hotplug_lock);
|
||||
|
||||
/* detach internal memory subsystem data first */
|
||||
if (eal_memalloc_cleanup())
|
||||
RTE_LOG(ERR, EAL, "Could not release memory subsystem data\n");
|
||||
|
||||
for (i = 0; i < RTE_DIM(mcfg->memsegs); i++) {
|
||||
struct rte_memseg_list *msl = &mcfg->memsegs[i];
|
||||
|
||||
/* skip uninitialized segments */
|
||||
if (msl->base_va == NULL)
|
||||
continue;
|
||||
/*
|
||||
* external segments are supposed to be detached at this point,
|
||||
* but if they aren't, we can't really do anything about it,
|
||||
* because if we skip them here, they'll become invalid after
|
||||
* we unmap the memconfig anyway. however, if this is externally
|
||||
* referenced memory, we have no business unmapping it.
|
||||
*/
|
||||
if (!msl->external)
|
||||
if (rte_mem_unmap(msl->base_va, msl->len) != 0)
|
||||
RTE_LOG(ERR, EAL, "Could not unmap memory: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
/*
|
||||
* we are detaching the fbarray rather than destroying because
|
||||
* other processes might still reference this fbarray, and we
|
||||
* have no way of knowing if they still do.
|
||||
*/
|
||||
if (rte_fbarray_detach(&msl->memseg_arr))
|
||||
RTE_LOG(ERR, EAL, "Could not detach fbarray: %s\n",
|
||||
rte_strerror(rte_errno));
|
||||
}
|
||||
rte_rwlock_write_unlock(&mcfg->memory_hotplug_lock);
|
||||
|
||||
/*
|
||||
* we've detached the memseg lists, so we can unmap the shared mem
|
||||
* config - we can't zero it out because it might still be referenced
|
||||
* by other processes.
|
||||
*/
|
||||
rte_mem_unmap(mcfg, RTE_ALIGN(sizeof(*mcfg), page_sz));
|
||||
rte_eal_get_configuration()->mem_config = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* init memory subsystem */
|
||||
int
|
||||
rte_eal_memory_init(void)
|
||||
|
@ -93,4 +93,7 @@ eal_memalloc_get_seg_fd_offset(int list_idx, int seg_idx, size_t *offset);
|
||||
int
|
||||
eal_memalloc_init(void);
|
||||
|
||||
int
|
||||
eal_memalloc_cleanup(void);
|
||||
|
||||
#endif /* EAL_MEMALLOC_H */
|
||||
|
@ -433,6 +433,13 @@ int rte_eal_hugepage_init(void);
|
||||
*/
|
||||
int rte_eal_hugepage_attach(void);
|
||||
|
||||
/**
|
||||
* Detaches all memory mappings from a process.
|
||||
*
|
||||
* This function is private to the EAL.
|
||||
*/
|
||||
int rte_eal_memory_detach(void);
|
||||
|
||||
/**
|
||||
* Find a bus capable of identifying a device.
|
||||
*
|
||||
|
@ -964,6 +964,8 @@ rte_eal_cleanup(void)
|
||||
eal_get_internal_configuration();
|
||||
rte_service_finalize();
|
||||
rte_mp_channel_cleanup();
|
||||
/* after this point, any DPDK pointers will become dangling */
|
||||
rte_eal_memory_detach();
|
||||
rte_trace_save();
|
||||
eal_trace_fini();
|
||||
eal_cleanup_config(internal_conf);
|
||||
|
@ -74,6 +74,11 @@ eal_memalloc_get_seg_fd_offset(int list_idx __rte_unused,
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int eal_memalloc_cleanup(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
eal_memalloc_init(void)
|
||||
{
|
||||
|
@ -1360,6 +1360,8 @@ rte_eal_cleanup(void)
|
||||
rte_memseg_walk(mark_freeable, NULL);
|
||||
rte_service_finalize();
|
||||
rte_mp_channel_cleanup();
|
||||
/* after this point, any DPDK pointers will become dangling */
|
||||
rte_eal_memory_detach();
|
||||
rte_trace_save();
|
||||
eal_trace_fini();
|
||||
eal_cleanup_config(internal_conf);
|
||||
|
@ -1441,6 +1441,31 @@ secondary_msl_create_walk(const struct rte_memseg_list *msl,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
secondary_msl_destroy_walk(const struct rte_memseg_list *msl,
|
||||
void *arg __rte_unused)
|
||||
{
|
||||
struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
|
||||
struct rte_memseg_list *local_msl;
|
||||
int msl_idx, ret;
|
||||
|
||||
if (msl->external)
|
||||
return 0;
|
||||
|
||||
msl_idx = msl - mcfg->memsegs;
|
||||
local_msl = &local_memsegs[msl_idx];
|
||||
|
||||
ret = rte_fbarray_destroy(&local_msl->memseg_arr);
|
||||
if (ret < 0) {
|
||||
RTE_LOG(ERR, EAL, "Cannot destroy local memory map\n");
|
||||
return -1;
|
||||
}
|
||||
local_msl->base_va = NULL;
|
||||
local_msl->len = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
alloc_list(int list_idx, int len)
|
||||
{
|
||||
@ -1473,6 +1498,34 @@ alloc_list(int list_idx, int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
destroy_list(int list_idx)
|
||||
{
|
||||
const struct internal_config *internal_conf =
|
||||
eal_get_internal_configuration();
|
||||
|
||||
/* single-file segments mode does not need fd list */
|
||||
if (!internal_conf->single_file_segments) {
|
||||
int *fds = fd_list[list_idx].fds;
|
||||
int i;
|
||||
/* go through each fd and ensure it's closed */
|
||||
for (i = 0; i < fd_list[list_idx].len; i++) {
|
||||
if (fds[i] >= 0) {
|
||||
close(fds[i]);
|
||||
fds[i] = -1;
|
||||
}
|
||||
}
|
||||
free(fds);
|
||||
fd_list[list_idx].fds = NULL;
|
||||
fd_list[list_idx].len = 0;
|
||||
} else if (fd_list[list_idx].memseg_list_fd >= 0) {
|
||||
close(fd_list[list_idx].memseg_list_fd);
|
||||
fd_list[list_idx].count = 0;
|
||||
fd_list[list_idx].memseg_list_fd = -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fd_list_create_walk(const struct rte_memseg_list *msl,
|
||||
void *arg __rte_unused)
|
||||
@ -1490,6 +1543,20 @@ fd_list_create_walk(const struct rte_memseg_list *msl,
|
||||
return alloc_list(msl_idx, len);
|
||||
}
|
||||
|
||||
static int
|
||||
fd_list_destroy_walk(const struct rte_memseg_list *msl, void *arg __rte_unused)
|
||||
{
|
||||
struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
|
||||
int msl_idx;
|
||||
|
||||
if (msl->external)
|
||||
return 0;
|
||||
|
||||
msl_idx = msl - mcfg->memsegs;
|
||||
|
||||
return destroy_list(msl_idx);
|
||||
}
|
||||
|
||||
int
|
||||
eal_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd)
|
||||
{
|
||||
@ -1626,6 +1693,24 @@ eal_memalloc_get_seg_fd_offset(int list_idx, int seg_idx, size_t *offset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
eal_memalloc_cleanup(void)
|
||||
{
|
||||
/* close all remaining fd's - these are per-process, so it's safe */
|
||||
if (rte_memseg_list_walk_thread_unsafe(fd_list_destroy_walk, NULL))
|
||||
return -1;
|
||||
|
||||
/* destroy the shadow page table if we're a secondary process */
|
||||
if (rte_eal_process_type() == RTE_PROC_PRIMARY)
|
||||
return 0;
|
||||
|
||||
if (rte_memseg_list_walk_thread_unsafe(secondary_msl_destroy_walk,
|
||||
NULL))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
eal_memalloc_init(void)
|
||||
{
|
||||
|
@ -251,7 +251,8 @@ rte_eal_cleanup(void)
|
||||
{
|
||||
struct internal_config *internal_conf =
|
||||
eal_get_internal_configuration();
|
||||
|
||||
/* after this point, any DPDK pointers will become dangling */
|
||||
rte_eal_memory_detach();
|
||||
eal_cleanup_config(internal_conf);
|
||||
return 0;
|
||||
}
|
||||
|
@ -437,6 +437,13 @@ eal_memalloc_sync_with_primary(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
eal_memalloc_cleanup(void)
|
||||
{
|
||||
/* not implemented */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
eal_memalloc_init(void)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user