env: Add spdk_mem_reserve
The spdk_mem_reserve() function reserves a memory region in SPDK's memory maps. This pre-allocates all of the required data structures to hold memory address translations for that region without actually populating the region. After a region is reserved, calls to spdk_mem_register() for addresses in that range will not require any internal memory allocations. This is useful when overlaying a custom memory allocator on top of SPDK's hugepage memory, such as tcmalloc. Signed-off-by: Ben Walker <benjamin.walker@intel.com> Change-Id: Ia4e8a770e8b5c956814aa90e9119013356dfab46 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/2511 Community-CI: Mellanox Build Bot Community-CI: Broadcom CI Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
This commit is contained in:
parent
8668141b41
commit
cf450c0d7c
@ -1248,6 +1248,20 @@ int spdk_mem_register(void *vaddr, size_t len);
|
|||||||
*/
|
*/
|
||||||
int spdk_mem_unregister(void *vaddr, size_t len);
|
int spdk_mem_unregister(void *vaddr, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reserve the address space specified in all memory maps.
|
||||||
|
*
|
||||||
|
* This pre-allocates the necessary space in the memory maps such that
|
||||||
|
* future calls to spdk_mem_register() on that region require no
|
||||||
|
* internal memory allocations.
|
||||||
|
*
|
||||||
|
* \param vaddr Virtual address to reserve
|
||||||
|
* \param len Length in bytes of vaddr
|
||||||
|
*
|
||||||
|
* \return 0 on success, negated errno on failure.
|
||||||
|
*/
|
||||||
|
int spdk_mem_reserve(void *vaddr, size_t len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -509,6 +509,57 @@ spdk_mem_unregister(void *vaddr, size_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
spdk_mem_reserve(void *vaddr, size_t len)
|
||||||
|
{
|
||||||
|
struct spdk_mem_map *map;
|
||||||
|
void *seg_vaddr;
|
||||||
|
size_t seg_len;
|
||||||
|
uint64_t reg;
|
||||||
|
|
||||||
|
if ((uintptr_t)vaddr & ~MASK_256TB) {
|
||||||
|
DEBUG_PRINT("invalid usermode virtual address %p\n", vaddr);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((uintptr_t)vaddr & MASK_2MB) || (len & MASK_2MB)) {
|
||||||
|
DEBUG_PRINT("invalid %s parameters, vaddr=%p len=%ju\n",
|
||||||
|
__func__, vaddr, len);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&g_spdk_mem_map_mutex);
|
||||||
|
|
||||||
|
/* Check if any part of this range is already registered */
|
||||||
|
seg_vaddr = vaddr;
|
||||||
|
seg_len = len;
|
||||||
|
while (seg_len > 0) {
|
||||||
|
reg = spdk_mem_map_translate(g_mem_reg_map, (uint64_t)seg_vaddr, NULL);
|
||||||
|
if (reg & REG_MAP_REGISTERED) {
|
||||||
|
pthread_mutex_unlock(&g_spdk_mem_map_mutex);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
seg_vaddr += VALUE_2MB;
|
||||||
|
seg_len -= VALUE_2MB;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Simply set the translation to the memory map's default. This allocates the space in the
|
||||||
|
* map but does not provide a valid translation. */
|
||||||
|
spdk_mem_map_set_translation(g_mem_reg_map, (uint64_t)vaddr, len,
|
||||||
|
g_mem_reg_map->default_translation);
|
||||||
|
|
||||||
|
TAILQ_FOREACH(map, &g_spdk_mem_maps, tailq) {
|
||||||
|
spdk_mem_map_set_translation(map, (uint64_t)vaddr, len, map->default_translation);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&g_spdk_mem_map_mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct map_1gb *
|
static struct map_1gb *
|
||||||
spdk_mem_map_get_map_1gb(struct spdk_mem_map *map, uint64_t vfn_2mb)
|
spdk_mem_map_get_map_1gb(struct spdk_mem_map *map, uint64_t vfn_2mb)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user