From 4a9f28a4824241ca911808cf3a1875751ff7151d Mon Sep 17 00:00:00 2001 From: paul luse Date: Fri, 6 Mar 2020 14:57:22 +0000 Subject: [PATCH] test/bdevperf: prevent overlaping w/r/v operations There was no sync between the start of a w/r/v operation at a specific block with the previous completion. This resulted in data miscompares either because the initial Q depth was sized such that a disk wrap need to occur to complete it or in the event that an IO takes longer to complete than when bdevperf loops back around to that offset. Fixes #1208 Signed-off-by: paul luse Change-Id: Ifa55da54246735e7b603fafd34718965b0f27b94 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/1180 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Jim Harris Reviewed-by: Ben Walker --- test/bdev/bdevperf/bdevperf.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/test/bdev/bdevperf/bdevperf.c b/test/bdev/bdevperf/bdevperf.c index bea459017..07df70bc5 100644 --- a/test/bdev/bdevperf/bdevperf.c +++ b/test/bdev/bdevperf/bdevperf.c @@ -43,6 +43,7 @@ #include "spdk/thread.h" #include "spdk/string.h" #include "spdk/rpc.h" +#include "spdk/bit_array.h" struct bdevperf_task { struct iovec iov; @@ -110,6 +111,7 @@ struct io_target { bool is_draining; struct spdk_poller *run_timer; struct spdk_poller *reset_timer; + struct spdk_bit_array *outstanding; TAILQ_HEAD(, bdevperf_task) task_list; }; @@ -267,6 +269,9 @@ bdevperf_free_target(struct io_target *target) free(task); } + if (g_verify) { + spdk_bit_array_free(&target->outstanding); + } free(target->name); free(target); } @@ -391,6 +396,9 @@ bdevperf_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) target->current_queue_depth--; if (success) { + if (g_verify) { + spdk_bit_array_clear(target->outstanding, task->offset_blocks / target->io_size_blocks); + } target->io_completed++; } @@ -677,6 +685,20 @@ bdevperf_submit_single(struct io_target *target, struct bdevperf_task *task) if (target->offset_in_ios == target->size_in_ios) { target->offset_in_ios = 0; } + + /* Increment of offset_in_ios if there's already an outstanding IO + * to that location. We only need this with g_verify as random + * offsets are not supported with g_verify at this time. + */ + if (g_verify && spdk_bit_array_get(target->outstanding, offset_in_ios)) { + do { + offset_in_ios++; + if (target->offset_in_ios == target->size_in_ios) { + target->offset_in_ios = 0; + } + } while (spdk_bit_array_get(target->outstanding, offset_in_ios)); + spdk_bit_array_set(target->outstanding, offset_in_ios); + } } task->offset_blocks = offset_in_ios * target->io_size_blocks; @@ -1081,7 +1103,7 @@ _bdevperf_construct_target(struct spdk_bdev *bdev, struct io_target_group *group SPDK_ERRLOG("Could not open leaf bdev %s, error=%d\n", spdk_bdev_get_name(bdev), rc); free(target->name); free(target); - return 0; + return -EINVAL; } target->bdev = bdev; @@ -1101,6 +1123,17 @@ _bdevperf_construct_target(struct spdk_bdev *bdev, struct io_target_group *group target->size_in_ios = spdk_bdev_get_num_blocks(bdev) / target->io_size_blocks; + if (g_verify) { + target->outstanding = spdk_bit_array_create(target->size_in_ios); + if (target->outstanding == NULL) { + SPDK_ERRLOG("Could not create outstanding array bitmap for bdev %s\n", spdk_bdev_get_name(bdev)); + spdk_bdev_close(target->bdev_desc); + free(target->name); + free(target); + return -ENOMEM; + } + } + TAILQ_INIT(&target->task_list); target->group = group;