mem: fix ivshmem freeing

There is no sync between host and guest to allow removal of memzones,
and freeing them result in undefined behavior.

In the guest, we identify IVSHMEM memsegs/memzones by having
ioremap_addr != 0. In the host, nothing is done to the memzone, meaning
ioremap_addr == 0.

As a solution, mark memzones being added to IVSHMEM in the host, by
setting ioremap_addr, then return an error whenever we try to free an
IVSHMEM memzone.

Fixes: ff909fe21f0 ("mem: introduce memzone freeing")

Signed-off-by: Sergio Gonzalez Monroy <sergio.gonzalez.monroy@intel.com>
This commit is contained in:
Sergio Gonzalez Monroy 2015-08-07 16:27:33 +01:00 committed by Thomas Monjalon
parent d1668c9762
commit cd10c42eb5
3 changed files with 26 additions and 1 deletions

View File

@ -322,6 +322,14 @@ rte_memzone_free(const struct rte_memzone *mz)
idx = idx / sizeof(struct rte_memzone);
addr = mcfg->memzone[idx].addr;
#ifdef RTE_LIBRTE_IVSHMEM
/*
* If ioremap_addr is set, it's an IVSHMEM memzone and we cannot
* free it.
*/
if (mcfg->memzone[idx].ioremap_addr != 0)
ret = -EINVAL;
#endif
if (addr == NULL)
ret = -EINVAL;
else if (mcfg->memzone_cnt == 0) {

View File

@ -258,10 +258,12 @@ const struct rte_memzone *rte_memzone_reserve_bounded(const char *name,
/**
* Free a memzone.
*
* Note: an IVSHMEM zone cannot be freed.
*
* @param mz
* A pointer to the memzone
* @return
* -EINVAL - invalid parameter
* -EINVAL - invalid parameter, IVSHMEM memzone.
* 0 - success
*/
int rte_memzone_free(const struct rte_memzone *mz);

View File

@ -504,7 +504,22 @@ add_memzone_to_metadata(const struct rte_memzone * mz,
config->metadata->name);
goto fail;
}
#ifdef RTE_LIBRTE_IVSHMEM
struct rte_mem_config *mcfg;
unsigned int idx;
mcfg = rte_eal_get_configuration()->mem_config;
rte_rwlock_write_lock(&mcfg->mlock);
idx = ((uintptr_t)mz - (uintptr_t)mcfg->memzone);
idx = idx / sizeof(struct rte_memzone);
/* mark the memzone not freeable */
mcfg->memzone[idx].ioremap_addr = mz->phys_addr;
rte_rwlock_write_unlock(&mcfg->mlock);
#endif
rte_spinlock_unlock(&config->sl);
return 0;
fail: