lib/reduce: fix problem with size of chunk map area in PMEM

This fixes a segfault found by using a very small logical volume.
The PMEM file chunk map area wasn't including the chunk map struct
itself.  In PMEM, a single entry as returned by _reduce_vol_get_chunk_map()
is made up of a 'struct spdk_reduce_chunk_map' plus one uint64_t for
each backing IO unit for the volume (# depends on vol parms). So when
an app got close to the end of the chunk map indices it would run off
the end of PMEM and segfault.

With this fix that no longer happens however data integrity issues now
show up with fio. I believe this fix is valid though and am pursuing the data
integrity issue as something new.

Signed-off-by: paul luse <paul.e.luse@intel.com>
Change-Id: I69a223064c7bbd44bcd0a62d155cf409603970a3
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/461316
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
paul luse 2019-07-10 20:30:50 -04:00 committed by Jim Harris
parent 30ca1a9083
commit 0242a80793

View File

@ -208,6 +208,12 @@ _get_total_chunks(uint64_t vol_size, uint64_t chunk_size)
return num_chunks;
}
static inline uint32_t
_reduce_vol_get_chunk_struct_size(uint64_t backing_io_units_per_chunk)
{
return sizeof(struct spdk_reduce_chunk_map) + sizeof(uint64_t) * backing_io_units_per_chunk;
}
static uint64_t
_get_pm_total_chunks_size(uint64_t vol_size, uint64_t chunk_size, uint64_t backing_io_unit_size)
{
@ -215,18 +221,13 @@ _get_pm_total_chunks_size(uint64_t vol_size, uint64_t chunk_size, uint64_t backi
num_chunks = _get_total_chunks(vol_size, chunk_size);
io_units_per_chunk = chunk_size / backing_io_unit_size;
total_chunks_size = num_chunks * io_units_per_chunk * sizeof(uint64_t);
total_chunks_size = num_chunks * _reduce_vol_get_chunk_struct_size(io_units_per_chunk);
return spdk_divide_round_up(total_chunks_size, REDUCE_PM_SIZE_ALIGNMENT) *
REDUCE_PM_SIZE_ALIGNMENT;
}
static inline uint32_t
_reduce_vol_get_chunk_struct_size(struct spdk_reduce_vol *vol)
{
return sizeof(struct spdk_reduce_chunk_map) + sizeof(uint64_t) * vol->backing_io_units_per_chunk;
}
static struct spdk_reduce_chunk_map *
_reduce_vol_get_chunk_map(struct spdk_reduce_vol *vol, uint64_t chunk_map_index)
{
@ -235,7 +236,8 @@ _reduce_vol_get_chunk_map(struct spdk_reduce_vol *vol, uint64_t chunk_map_index)
assert(chunk_map_index < _get_total_chunks(vol->params.vol_size, vol->params.chunk_size));
chunk_map_addr = (uintptr_t)vol->pm_chunk_maps;
chunk_map_addr += chunk_map_index * _reduce_vol_get_chunk_struct_size(vol);
chunk_map_addr += chunk_map_index *
_reduce_vol_get_chunk_struct_size(vol->backing_io_units_per_chunk);
return (struct spdk_reduce_chunk_map *)chunk_map_addr;
}
@ -993,7 +995,8 @@ _write_write_done(void *_req, int reduce_errno)
*/
/* Persist the new chunk map. This must be persisted before we update the logical map. */
_reduce_persist(vol, req->chunk, _reduce_vol_get_chunk_struct_size(vol));
_reduce_persist(vol, req->chunk,
_reduce_vol_get_chunk_struct_size(vol->backing_io_units_per_chunk));
vol->pm_logical_map[req->logical_map_index] = req->chunk_map_index;
@ -1537,7 +1540,7 @@ void spdk_reduce_vol_print_info(struct spdk_reduce_vol *vol)
ttl_chunk_sz = _get_pm_total_chunks_size(vol->params.vol_size, vol->params.chunk_size,
vol->params.backing_io_unit_size);
SPDK_NOTICELOG("\ttotal_chunks_size = 0x%" PRIx64 "\n", ttl_chunk_sz);
struct_size = _reduce_vol_get_chunk_struct_size(vol);
struct_size = _reduce_vol_get_chunk_struct_size(vol->backing_io_units_per_chunk);
SPDK_NOTICELOG("\tchunk_struct_size = 0x%x\n", struct_size);
SPDK_NOTICELOG("pmem info:\n");