examples/perf: add application verification for e2e data protection tests
For end-to-end data protection tests with extended lba format, when Protection Information Action bit was cleared to 0, the perf application can do some comparison based on the flags we used for writes. For the unexptected protection information value, print a notice for users. Change-Id: I9851ce6338030f9b57180cd5e46368e0c94bc212 Signed-off-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-on: https://review.gerrithub.io/394158 Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
This commit is contained in:
parent
f35f395b82
commit
450ee00944
@ -137,6 +137,8 @@ struct perf_task {
|
||||
uint64_t submit_tsc;
|
||||
uint16_t appmask;
|
||||
uint16_t apptag;
|
||||
uint64_t lba;
|
||||
bool is_read;
|
||||
#if HAVE_LIBAIO
|
||||
struct iocb iocb;
|
||||
#endif
|
||||
@ -539,6 +541,72 @@ task_extended_lba_setup_pi(struct ns_entry *entry, struct perf_task *task, uint6
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
task_extended_lba_pi_verify(struct ns_entry *entry, struct perf_task *task,
|
||||
uint64_t lba, uint32_t lba_count)
|
||||
{
|
||||
struct spdk_nvme_protection_info *pi;
|
||||
uint32_t i, md_size, sector_size, pi_offset, ref_tag;
|
||||
uint16_t crc16, guard, app_tag;
|
||||
const struct spdk_nvme_ns_data *nsdata;
|
||||
|
||||
if (spdk_nvme_ns_get_pi_type(entry->u.nvme.ns) ==
|
||||
SPDK_NVME_FMT_NVM_PROTECTION_DISABLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
sector_size = spdk_nvme_ns_get_sector_size(entry->u.nvme.ns);
|
||||
md_size = spdk_nvme_ns_get_md_size(entry->u.nvme.ns);
|
||||
nsdata = spdk_nvme_ns_get_data(entry->u.nvme.ns);
|
||||
|
||||
/* PI locates at the first 8 bytes of metadata,
|
||||
* doesn't support now
|
||||
*/
|
||||
if (nsdata->dps.md_start) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < lba_count; i++) {
|
||||
pi_offset = ((sector_size + md_size) * (i + 1)) - 8;
|
||||
pi = (struct spdk_nvme_protection_info *)(task->buf + pi_offset);
|
||||
|
||||
if (entry->io_flags & SPDK_NVME_IO_FLAGS_PRCHK_GUARD) {
|
||||
/* CRC buffer should not include last 8 bytes of PI */
|
||||
crc16 = spdk_crc16_t10dif(task->buf + (sector_size + md_size) * i,
|
||||
sector_size + md_size - 8);
|
||||
to_be16(&guard, crc16);
|
||||
if (pi->guard != guard) {
|
||||
fprintf(stdout, "Get Guard Error LBA 0x%16.16"PRIx64","
|
||||
" Preferred 0x%04x but returned with 0x%04x,"
|
||||
" may read the LBA without write it first\n",
|
||||
lba + i, guard, pi->guard);
|
||||
}
|
||||
|
||||
}
|
||||
if (entry->io_flags & SPDK_NVME_IO_FLAGS_PRCHK_APPTAG) {
|
||||
/* Previously we used the number of lbas as
|
||||
* application tag for writes
|
||||
*/
|
||||
to_be16(&app_tag, lba_count);
|
||||
if (pi->app_tag != app_tag) {
|
||||
fprintf(stdout, "Get Application Tag Error LBA 0x%16.16"PRIx64","
|
||||
" Preferred 0x%04x but returned with 0x%04x,"
|
||||
" may read the LBA without write it first\n",
|
||||
lba + i, app_tag, pi->app_tag);
|
||||
}
|
||||
}
|
||||
if (entry->io_flags & SPDK_NVME_IO_FLAGS_PRCHK_REFTAG) {
|
||||
to_be32(&ref_tag, (uint32_t)lba + i);
|
||||
if (pi->ref_tag != ref_tag) {
|
||||
fprintf(stdout, "Get Reference Tag Error LBA 0x%16.16"PRIx64","
|
||||
" Preferred 0x%08x but returned with 0x%08x,"
|
||||
" may read the LBA without write it first\n",
|
||||
lba + i, ref_tag, pi->ref_tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void io_complete(void *ctx, const struct spdk_nvme_cpl *completion);
|
||||
|
||||
static __thread unsigned int seed = 0;
|
||||
@ -560,7 +628,9 @@ submit_single_io(struct perf_task *task)
|
||||
}
|
||||
}
|
||||
|
||||
task->is_read = false;
|
||||
task->submit_tsc = spdk_get_ticks();
|
||||
task->lba = offset_in_ios * entry->io_size_blocks;
|
||||
|
||||
if ((g_rw_percentage == 100) ||
|
||||
(g_rw_percentage != 0 && ((rand_r(&seed) % 100) < g_rw_percentage))) {
|
||||
@ -571,12 +641,13 @@ submit_single_io(struct perf_task *task)
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
task_extended_lba_setup_pi(entry, task, offset_in_ios * entry->io_size_blocks,
|
||||
task_extended_lba_setup_pi(entry, task, task->lba,
|
||||
entry->io_size_blocks, false);
|
||||
task->is_read = true;
|
||||
|
||||
rc = spdk_nvme_ns_cmd_read_with_md(entry->u.nvme.ns, ns_ctx->u.nvme.qpair,
|
||||
task->buf, NULL,
|
||||
offset_in_ios * entry->io_size_blocks,
|
||||
task->lba,
|
||||
entry->io_size_blocks, io_complete,
|
||||
task, entry->io_flags,
|
||||
task->appmask, task->apptag);
|
||||
@ -589,12 +660,12 @@ submit_single_io(struct perf_task *task)
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
task_extended_lba_setup_pi(entry, task, offset_in_ios * entry->io_size_blocks,
|
||||
task_extended_lba_setup_pi(entry, task, task->lba,
|
||||
entry->io_size_blocks, true);
|
||||
|
||||
rc = spdk_nvme_ns_cmd_write_with_md(entry->u.nvme.ns, ns_ctx->u.nvme.qpair,
|
||||
task->buf, NULL,
|
||||
offset_in_ios * entry->io_size_blocks,
|
||||
task->lba,
|
||||
entry->io_size_blocks, io_complete,
|
||||
task, entry->io_flags,
|
||||
task->appmask, task->apptag);
|
||||
@ -613,8 +684,10 @@ task_complete(struct perf_task *task)
|
||||
{
|
||||
struct ns_worker_ctx *ns_ctx;
|
||||
uint64_t tsc_diff;
|
||||
struct ns_entry *entry;
|
||||
|
||||
ns_ctx = task->ns_ctx;
|
||||
entry = ns_ctx->entry;
|
||||
ns_ctx->current_queue_depth--;
|
||||
ns_ctx->io_completed++;
|
||||
tsc_diff = spdk_get_ticks() - task->submit_tsc;
|
||||
@ -629,6 +702,15 @@ task_complete(struct perf_task *task)
|
||||
spdk_histogram_data_tally(ns_ctx->histogram, tsc_diff);
|
||||
}
|
||||
|
||||
/* add application level verification for end-to-end data protection */
|
||||
if (entry->type == ENTRY_TYPE_NVME_NS) {
|
||||
if (spdk_nvme_ns_supports_extended_lba(entry->u.nvme.ns) &&
|
||||
task->is_read && !g_metacfg_pract_flag) {
|
||||
task_extended_lba_pi_verify(entry, task, task->lba,
|
||||
entry->io_size_blocks);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* is_draining indicates when time has expired for the test run
|
||||
* and we are just waiting for the previously submitted I/O
|
||||
|
Loading…
Reference in New Issue
Block a user