memory: fix contiguous memory calculation for unaligned buffers

We assumed spdk_mem_map_translate() translates only 2MB-aligned
addresses, but that's not true. Both vtophys and NVMf can use it
with any user-provided address and that breaks our contiguous memory
length calculations. Right now each buffer appeared to have the
first n * 2MB of memory always contiguous.

This is a bugfix for NVMf which does check the mapping length
internally. It will also become handy when adding the similar
functionality to spdk_vtophys().

Change-Id: I3bc8e0b2b8d203cb90320a79264effb7ea7037a7
Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/433076 (master)
Reviewed-on: https://review.gerrithub.io/435691
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Darek Stojaczyk 2018-11-13 17:43:46 +01:00 committed by Ben Walker
parent 77f89cbc31
commit c93b418730
3 changed files with 11 additions and 2 deletions

View File

@ -68,6 +68,7 @@ extern struct rte_pci_bus rte_pci_bus;
#define SHIFT_4KB 12 /* (1 << 12) == 4KB */
#define MASK_4KB ((1ULL << SHIFT_4KB) - 1)
#define VALUE_4KB (1 << SHIFT_4KB)
struct spdk_pci_enum_ctx {
struct rte_pci_driver driver;

View File

@ -57,6 +57,8 @@
#define MAP_256TB_IDX(vfn_2mb) ((vfn_2mb) >> (SHIFT_1GB - SHIFT_2MB))
#define MAP_1GB_IDX(vfn_2mb) ((vfn_2mb) & ((1ULL << (SHIFT_1GB - SHIFT_2MB)) - 1))
#define _2MB_OFFSET(ptr) (((uintptr_t)(ptr)) & (VALUE_2MB - 1))
/* Page is registered */
#define REG_MAP_REGISTERED (1ULL << 62)
@ -612,9 +614,9 @@ spdk_mem_map_translate(const struct spdk_mem_map *map, uint64_t vaddr, uint64_t
return map->default_translation;
}
cur_size = VALUE_2MB;
cur_size = VALUE_2MB - _2MB_OFFSET(vaddr);
if (size != NULL) {
*size = VALUE_2MB;
*size = cur_size;
}
map_2mb = &map_1gb->map[idx_1gb];

View File

@ -257,6 +257,12 @@ test_mem_map_translation(void)
CU_ASSERT(addr == 0);
CU_ASSERT(mapping_length == VALUE_2MB * 3)
/* Translate an unaligned address */
mapping_length = VALUE_2MB * 3;
addr = spdk_mem_map_translate(map, VALUE_4KB, &mapping_length);
CU_ASSERT(addr == 0);
CU_ASSERT(mapping_length == VALUE_2MB * 3 - VALUE_4KB);
/* Clear translation for the middle page of the larger region. */
rc = spdk_mem_map_clear_translation(map, VALUE_2MB, VALUE_2MB);
CU_ASSERT(rc == 0);