bdevperf: use separate metadata buffers
Use separate buffers for metadata transfer if bdev supports it. Change-Id: Ie0fa3d3c1f5b14f99c13f2d6b5b22edc216c6d64 Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/451468 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
parent
d69fe7b7b9
commit
66bace41d7
@ -47,6 +47,7 @@ struct bdevperf_task {
|
||||
struct iovec iov;
|
||||
struct io_target *target;
|
||||
void *buf;
|
||||
void *md_buf;
|
||||
uint64_t offset_blocks;
|
||||
enum spdk_bdev_io_type io_type;
|
||||
TAILQ_ENTRY(bdevperf_task) link;
|
||||
@ -116,39 +117,72 @@ static int g_target_count = 0;
|
||||
static size_t g_min_alignment = 8;
|
||||
|
||||
static void
|
||||
generate_data(void *buf, int buf_len, int block_size, int md_size,
|
||||
generate_data(void *buf, int buf_len, int block_size, void *md_buf, int md_size,
|
||||
int num_blocks, int seed)
|
||||
{
|
||||
int offset_blocks = 0;
|
||||
int offset_blocks = 0, md_offset, data_block_size;
|
||||
|
||||
if (buf_len < num_blocks * block_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (md_buf == NULL) {
|
||||
data_block_size = block_size - md_size;
|
||||
md_buf = (char *)buf + data_block_size;
|
||||
md_offset = block_size;
|
||||
} else {
|
||||
data_block_size = block_size;
|
||||
md_offset = md_size;
|
||||
}
|
||||
|
||||
while (offset_blocks < num_blocks) {
|
||||
memset(buf, seed, block_size - md_size);
|
||||
memset(buf + block_size - md_size, 0, md_size);
|
||||
memset(buf, seed, data_block_size);
|
||||
memset(md_buf, seed, md_size);
|
||||
buf += block_size;
|
||||
md_buf += md_offset;
|
||||
offset_blocks++;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
verify_data(void *wr_buf, int wr_buf_len, void *rd_buf, int rd_buf_len,
|
||||
int block_size, int md_size, int num_blocks)
|
||||
verify_data(void *wr_buf, int wr_buf_len, void *rd_buf, int rd_buf_len, int block_size,
|
||||
void *wr_md_buf, void *rd_md_buf, int md_size, int num_blocks, bool md_check)
|
||||
{
|
||||
int offset_blocks = 0;
|
||||
int offset_blocks = 0, md_offset, data_block_size;
|
||||
|
||||
if (wr_buf_len < num_blocks * block_size || rd_buf_len < num_blocks * block_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
assert((wr_md_buf != NULL) == (rd_md_buf != NULL));
|
||||
|
||||
if (wr_md_buf == NULL) {
|
||||
data_block_size = block_size - md_size;
|
||||
wr_md_buf = (char *)wr_buf + data_block_size;
|
||||
rd_md_buf = (char *)rd_buf + data_block_size;
|
||||
md_offset = block_size;
|
||||
} else {
|
||||
data_block_size = block_size;
|
||||
md_offset = md_size;
|
||||
}
|
||||
|
||||
while (offset_blocks < num_blocks) {
|
||||
if (memcmp(wr_buf, rd_buf, block_size - md_size) != 0) {
|
||||
if (memcmp(wr_buf, rd_buf, data_block_size) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wr_buf += block_size;
|
||||
rd_buf += block_size;
|
||||
|
||||
if (md_check) {
|
||||
if (memcmp(wr_md_buf, rd_md_buf, md_size) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wr_md_buf += md_offset;
|
||||
rd_md_buf += md_offset;
|
||||
}
|
||||
|
||||
offset_blocks++;
|
||||
}
|
||||
|
||||
@ -191,6 +225,7 @@ bdevperf_free_target(struct io_target *target)
|
||||
TAILQ_FOREACH_SAFE(task, &target->task_list, link, tmp) {
|
||||
TAILQ_REMOVE(&target->task_list, task, link);
|
||||
spdk_dma_free(task->buf);
|
||||
spdk_dma_free(task->md_buf);
|
||||
free(task);
|
||||
}
|
||||
|
||||
@ -227,7 +262,7 @@ bdevperf_construct_target(struct spdk_bdev *bdev, struct io_target **_target)
|
||||
{
|
||||
struct io_target *target;
|
||||
size_t align;
|
||||
int block_size, md_size, data_block_size;
|
||||
int block_size, data_block_size;
|
||||
int rc;
|
||||
|
||||
*_target = NULL;
|
||||
@ -266,14 +301,7 @@ bdevperf_construct_target(struct spdk_bdev *bdev, struct io_target **_target)
|
||||
target->offset_in_ios = 0;
|
||||
|
||||
block_size = spdk_bdev_get_block_size(bdev);
|
||||
md_size = spdk_bdev_get_md_size(bdev);
|
||||
if (md_size != 0 && !spdk_bdev_is_md_interleaved(bdev)) {
|
||||
SPDK_ERRLOG("Separate metadata is not expected.\n");
|
||||
free(target->name);
|
||||
free(target);
|
||||
return -EINVAL;
|
||||
}
|
||||
data_block_size = block_size - md_size;
|
||||
data_block_size = spdk_bdev_get_data_block_size(bdev);
|
||||
target->io_size_blocks = g_io_size / data_block_size;
|
||||
if ((g_io_size % data_block_size) != 0) {
|
||||
SPDK_ERRLOG("IO size (%d) is not multiples of data block size of bdev %s (%"PRIu32")\n",
|
||||
@ -364,8 +392,10 @@ bdevperf_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
|
||||
struct spdk_event *complete;
|
||||
struct iovec *iovs;
|
||||
int iovcnt;
|
||||
bool md_check;
|
||||
|
||||
target = task->target;
|
||||
md_check = spdk_bdev_get_dif_type(target->bdev) == SPDK_DIF_DISABLE;
|
||||
|
||||
if (!success) {
|
||||
if (!g_reset) {
|
||||
@ -380,8 +410,9 @@ bdevperf_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
|
||||
assert(iovs != NULL);
|
||||
if (!verify_data(task->buf, g_buf_size, iovs[0].iov_base, iovs[0].iov_len,
|
||||
spdk_bdev_get_block_size(target->bdev),
|
||||
task->md_buf, spdk_bdev_io_get_md_buf(bdev_io),
|
||||
spdk_bdev_get_md_size(target->bdev),
|
||||
target->io_size_blocks) != 0) {
|
||||
target->io_size_blocks, md_check) != 0) {
|
||||
printf("Buffer mismatch! Disk Offset: %lu\n", task->offset_blocks);
|
||||
target->is_draining = true;
|
||||
g_run_failed = true;
|
||||
@ -423,8 +454,16 @@ bdevperf_verify_submit_read(void *cb_arg)
|
||||
target = task->target;
|
||||
|
||||
/* Read the data back in */
|
||||
rc = spdk_bdev_read_blocks(target->bdev_desc, target->ch, NULL, task->offset_blocks,
|
||||
target->io_size_blocks, bdevperf_complete, task);
|
||||
if (spdk_bdev_is_md_separate(target->bdev)) {
|
||||
rc = spdk_bdev_read_blocks_with_md(target->bdev_desc, target->ch, NULL, NULL,
|
||||
task->offset_blocks, target->io_size_blocks,
|
||||
bdevperf_complete, task);
|
||||
} else {
|
||||
rc = spdk_bdev_read_blocks(target->bdev_desc, target->ch, NULL,
|
||||
task->offset_blocks, target->io_size_blocks,
|
||||
bdevperf_complete, task);
|
||||
}
|
||||
|
||||
if (rc == -ENOMEM) {
|
||||
task->bdev_io_wait.bdev = target->bdev;
|
||||
task->bdev_io_wait.cb_fn = bdevperf_verify_submit_read;
|
||||
@ -481,7 +520,7 @@ bdevperf_prep_task(struct bdevperf_task *task)
|
||||
if (g_verify || g_reset) {
|
||||
generate_data(task->buf, g_buf_size,
|
||||
spdk_bdev_get_block_size(target->bdev),
|
||||
spdk_bdev_get_md_size(target->bdev),
|
||||
task->md_buf, spdk_bdev_get_md_size(target->bdev),
|
||||
target->io_size_blocks, rand_r(&seed) % 256);
|
||||
task->iov.iov_base = task->buf;
|
||||
task->iov.iov_len = g_buf_size;
|
||||
@ -523,9 +562,19 @@ bdevperf_generate_dif(struct bdevperf_task *task)
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = spdk_dif_generate(&task->iov, 1, target->io_size_blocks, &dif_ctx);
|
||||
if (spdk_bdev_is_md_interleaved(bdev)) {
|
||||
rc = spdk_dif_generate(&task->iov, 1, target->io_size_blocks, &dif_ctx);
|
||||
} else {
|
||||
struct iovec md_iov = {
|
||||
.iov_base = task->md_buf,
|
||||
.iov_len = spdk_bdev_get_md_size(bdev) * target->io_size_blocks,
|
||||
};
|
||||
|
||||
rc = spdk_dix_generate(&task->iov, 1, &md_iov, target->io_size_blocks, &dif_ctx);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "Generation of DIF failed\n");
|
||||
fprintf(stderr, "Generation of DIF/DIX failed\n");
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -551,8 +600,19 @@ bdevperf_submit_task(void *arg)
|
||||
}
|
||||
if (rc == 0) {
|
||||
cb_fn = (g_verify || g_reset) ? bdevperf_verify_write_complete : bdevperf_complete;
|
||||
rc = spdk_bdev_writev_blocks(desc, ch, &task->iov, 1, task->offset_blocks,
|
||||
target->io_size_blocks, cb_fn, task);
|
||||
|
||||
if (spdk_bdev_is_md_separate(target->bdev)) {
|
||||
rc = spdk_bdev_writev_blocks_with_md(desc, ch, &task->iov, 1,
|
||||
task->md_buf,
|
||||
task->offset_blocks,
|
||||
target->io_size_blocks,
|
||||
cb_fn, task);
|
||||
} else {
|
||||
rc = spdk_bdev_writev_blocks(desc, ch, &task->iov, 1,
|
||||
task->offset_blocks,
|
||||
target->io_size_blocks,
|
||||
cb_fn, task);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPDK_BDEV_IO_TYPE_FLUSH:
|
||||
@ -572,8 +632,15 @@ bdevperf_submit_task(void *arg)
|
||||
rc = spdk_bdev_zcopy_start(desc, ch, task->offset_blocks, target->io_size_blocks,
|
||||
true, bdevperf_zcopy_complete, task);
|
||||
} else {
|
||||
rc = spdk_bdev_read_blocks(desc, ch, task->buf, task->offset_blocks,
|
||||
target->io_size_blocks, bdevperf_complete, task);
|
||||
if (spdk_bdev_is_md_separate(target->bdev)) {
|
||||
rc = spdk_bdev_read_blocks_with_md(desc, ch, task->buf, task->md_buf,
|
||||
task->offset_blocks,
|
||||
target->io_size_blocks,
|
||||
bdevperf_complete, task);
|
||||
} else {
|
||||
rc = spdk_bdev_read_blocks(desc, ch, task->buf, task->offset_blocks,
|
||||
target->io_size_blocks, bdevperf_complete, task);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -827,6 +894,17 @@ static struct bdevperf_task *bdevperf_construct_task_on_target(struct io_target
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (spdk_bdev_is_md_separate(target->bdev)) {
|
||||
task->md_buf = spdk_dma_zmalloc(target->io_size_blocks *
|
||||
spdk_bdev_get_md_size(target->bdev), 0, NULL);
|
||||
if (!task->md_buf) {
|
||||
fprintf(stderr, "Cannot allocate md buf for task=%p\n", task);
|
||||
free(task->buf);
|
||||
free(task);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
task->target = target;
|
||||
|
||||
return task;
|
||||
|
Loading…
Reference in New Issue
Block a user