dif: Add seed value for guard to avoid 0 in case of all zero data.

Allow user to add seed value for guard compuation to DIF context.
This will avoid the guard being zero in case of all zero data.

NVMe controller doesn't support seed value for guard computation
explicitly, and hence if we want to use such a seed value in
NVMe controller, we have to format metadata more than 8 byte,
and add seed value into the reserved metadata field.

But some popular iSCSI/FC HBAs and SAS controllers have supported
seed value for guard computation, and so supporting seed value
in the SPDK DIF library is very helpful for some use cases.

Hence this patch makes the DIF library possible to specify seed
value for those use cases.

Change-Id: I7e9e87cb441bf263e64605c7820409fdc22dd977
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/444334
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: wuzhouhui <wuzhouhui@kingsoft.com>
This commit is contained in:
Shuhei Matsumoto 2019-02-13 15:17:49 +09:00 committed by Ben Walker
parent fda97cff8a
commit 8696cd4288
7 changed files with 100 additions and 32 deletions

View File

@ -545,7 +545,7 @@ fio_extended_lba_setup_pi(struct spdk_fio_qpair *fio_qpair, struct io_u *io_u)
rc = spdk_dif_ctx_init(&fio_req->dif_ctx, extended_lba_size, md_size,
true, false,
(enum spdk_dif_type)spdk_nvme_ns_get_pi_type(ns),
fio_qpair->io_flags, lba, 0xFFFF, FIO_NVME_PI_APPTAG);
fio_qpair->io_flags, lba, 0xFFFF, FIO_NVME_PI_APPTAG, 0);
if (rc != 0) {
fprintf(stderr, "Initialization of DIF context failed\n");
return;

View File

@ -469,7 +469,7 @@ nvme_submit_io(struct perf_task *task, struct ns_worker_ctx *ns_ctx,
rc = spdk_dif_ctx_init(&task->dif_ctx, entry->block_size, entry->md_size,
entry->md_interleave, entry->pi_loc,
(enum spdk_dif_type)entry->pi_type, entry->io_flags,
lba, 0xFFFF, (uint16_t)entry->io_size_blocks);
lba, 0xFFFF, (uint16_t)entry->io_size_blocks, 0);
if (rc != 0) {
fprintf(stderr, "Initialization of DIF context failed\n");
exit(1);

View File

@ -91,6 +91,9 @@ struct spdk_dif_ctx {
/* Application tag mask */
uint16_t apptag_mask;
/* Seed value for guard computation */
uint16_t guard_seed;
};
/** DIF error information */
@ -124,12 +127,14 @@ struct spdk_dif_error {
* starting block address.
* \param apptag_mask Application tag mask.
* \param app_tag Application tag.
* \param guard_seed Seed value for guard computation.
*
* \return 0 on success and negated errno otherwise.
*/
int spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_size,
bool md_interleave, bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag);
uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag,
uint16_t guard_seed);
/**
* Generate DIF for extended LBA payload.

View File

@ -1604,7 +1604,7 @@ bdev_nvme_verify_pi_error(struct spdk_bdev_io *bdev_io)
rc = spdk_dif_ctx_init(&dif_ctx,
bdev->blocklen, bdev->md_len, bdev->md_interleave,
bdev->dif_is_head_of_md, bdev->dif_type, bdev->dif_check_flags,
bdev_io->u.bdev.offset_blocks, 0, 0);
bdev_io->u.bdev.offset_blocks, 0, 0, 0);
if (rc != 0) {
SPDK_ERRLOG("Initialization of DIF context failed\n");
return;

View File

@ -184,7 +184,8 @@ _get_guard_interval(uint32_t block_size, uint32_t md_size, bool dif_loc, bool md
int
spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_size,
bool md_interleave, bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag)
uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag,
uint16_t guard_seed)
{
if (md_size < sizeof(struct spdk_dif)) {
SPDK_ERRLOG("Metadata size is smaller than DIF size.\n");
@ -216,6 +217,7 @@ spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_siz
ctx->init_ref_tag = init_ref_tag;
ctx->apptag_mask = apptag_mask;
ctx->app_tag = app_tag;
ctx->guard_seed = guard_seed;
return 0;
}
@ -266,7 +268,7 @@ dif_generate(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
_iov_iter_get_buf(&iter, &buf, NULL);
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
guard = spdk_crc16_t10dif(0, buf, ctx->guard_interval);
guard = spdk_crc16_t10dif(ctx->guard_seed, buf, ctx->guard_interval);
}
_dif_generate(buf + ctx->guard_interval, guard, offset_blocks, ctx);
@ -282,10 +284,12 @@ _dif_generate_split(struct _iov_iter *iter, uint32_t offset_blocks,
{
uint32_t offset_in_block, offset_in_dif, buf_len;
void *buf;
uint16_t guard;
uint16_t guard = 0;
struct spdk_dif dif = {};
guard = 0;
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
guard = ctx->guard_seed;
}
offset_in_block = 0;
while (offset_in_block < ctx->block_size) {
@ -491,7 +495,7 @@ dif_verify(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
_iov_iter_get_buf(&iter, &buf, NULL);
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
guard = spdk_crc16_t10dif(0, buf, ctx->guard_interval);
guard = spdk_crc16_t10dif(ctx->guard_seed, buf, ctx->guard_interval);
}
rc = _dif_verify(buf + ctx->guard_interval, guard, offset_blocks, ctx, err_blk);
@ -512,10 +516,12 @@ _dif_verify_split(struct _iov_iter *iter, uint32_t offset_blocks,
{
uint32_t offset_in_block, offset_in_dif, buf_len;
void *buf;
uint16_t guard;
uint16_t guard = 0;
struct spdk_dif dif = {};
guard = 0;
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
guard = ctx->guard_seed;
}
offset_in_block = 0;
while (offset_in_block < ctx->block_size) {
@ -610,7 +616,7 @@ dif_generate_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
guard = 0;
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
guard = spdk_crc16_t10dif_copy(0, dst, src, data_block_size);
guard = spdk_crc16_t10dif_copy(ctx->guard_seed, dst, src, data_block_size);
guard = spdk_crc16_t10dif(guard, dst + data_block_size,
ctx->guard_interval - data_block_size);
} else {
@ -630,14 +636,16 @@ _dif_generate_copy_split(struct _iov_iter *src_iter, struct _iov_iter *dst_iter,
uint32_t offset_blocks, const struct spdk_dif_ctx *ctx)
{
uint32_t offset_in_block, src_len, data_block_size;
uint16_t guard;
uint16_t guard = 0;
void *src, *dst;
_iov_iter_get_buf(dst_iter, &dst, NULL);
data_block_size = ctx->block_size - ctx->md_size;
guard = 0;
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
guard = ctx->guard_seed;
}
offset_in_block = 0;
while (offset_in_block < data_block_size) {
@ -736,7 +744,7 @@ dif_verify_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
guard = 0;
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
guard = spdk_crc16_t10dif_copy(0, dst, src, data_block_size);
guard = spdk_crc16_t10dif_copy(ctx->guard_seed, dst, src, data_block_size);
guard = spdk_crc16_t10dif(guard, src + data_block_size,
ctx->guard_interval - data_block_size);
} else {
@ -762,14 +770,16 @@ _dif_verify_copy_split(struct _iov_iter *src_iter, struct _iov_iter *dst_iter,
struct spdk_dif_error *err_blk)
{
uint32_t offset_in_block, dst_len, data_block_size;
uint16_t guard;
uint16_t guard = 0;
void *src, *dst;
_iov_iter_get_buf(src_iter, &src, NULL);
data_block_size = ctx->block_size - ctx->md_size;
guard = 0;
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
guard = ctx->guard_seed;
}
offset_in_block = 0;
while (offset_in_block < data_block_size) {
@ -1015,7 +1025,7 @@ dix_generate(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
guard = 0;
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
guard = spdk_crc16_t10dif(0, data_buf, ctx->block_size);
guard = spdk_crc16_t10dif(ctx->guard_seed, data_buf, ctx->block_size);
guard = spdk_crc16_t10dif(guard, md_buf, ctx->guard_interval);
}
@ -1032,12 +1042,14 @@ _dix_generate_split(struct _iov_iter *data_iter, struct _iov_iter *md_iter,
uint32_t offset_blocks, const struct spdk_dif_ctx *ctx)
{
uint32_t offset_in_block, data_buf_len;
uint16_t guard;
uint16_t guard = 0;
void *data_buf, *md_buf;
_iov_iter_get_buf(md_iter, &md_buf, NULL);
guard = 0;
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
guard = ctx->guard_seed;
}
offset_in_block = 0;
while (offset_in_block < ctx->block_size) {
@ -1123,7 +1135,7 @@ dix_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
guard = 0;
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
guard = spdk_crc16_t10dif(0, data_buf, ctx->block_size);
guard = spdk_crc16_t10dif(ctx->guard_seed, data_buf, ctx->block_size);
guard = spdk_crc16_t10dif(guard, md_buf, ctx->guard_interval);
}
@ -1146,12 +1158,14 @@ _dix_verify_split(struct _iov_iter *data_iter, struct _iov_iter *md_iter,
struct spdk_dif_error *err_blk)
{
uint32_t offset_in_block, data_buf_len;
uint16_t guard;
uint16_t guard = 0;
void *data_buf, *md_buf;
_iov_iter_get_buf(md_iter, &md_buf, NULL);
guard = 0;
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
guard = ctx->guard_seed;
}
offset_in_block = 0;
while (offset_in_block < ctx->block_size) {

View File

@ -506,7 +506,7 @@ bdevperf_generate_dif(struct bdevperf_task *task)
spdk_bdev_is_dif_head_of_md(bdev),
spdk_bdev_get_dif_type(bdev),
target->dif_check_flags,
task->offset_blocks, 0, 0);
task->offset_blocks, 0, 0, 0);
if (rc != 0) {
fprintf(stderr, "Initialization of DIF context failed\n");
return rc;

View File

@ -38,6 +38,7 @@
#include "util/dif.c"
#define DATA_PATTERN 0xAB
#define GUARD_SEED 0xCD
static int
ut_data_pattern_generate(struct iovec *iovs, int iovcnt,
@ -272,10 +273,57 @@ dif_sec_512_md_0_error_test(void)
int rc;
/* Metadata size is 0. */
rc = spdk_dif_ctx_init(&ctx, 512, 0, true, false, SPDK_DIF_TYPE1, 0, 0, 0, 0);
rc = spdk_dif_ctx_init(&ctx, 512, 0, true, false, SPDK_DIF_TYPE1, 0, 0, 0, 0, 0);
CU_ASSERT(rc != 0);
}
static void
dif_guard_seed_test(void)
{
struct iovec iov;
struct spdk_dif_ctx ctx = {};
struct spdk_dif_error err_blk = {};
struct spdk_dif *dif;
uint16_t guard;
int rc;
_iov_alloc_buf(&iov, 512 + 8);
memset(iov.iov_base, 0, 512 + 8);
dif = (struct spdk_dif *)(iov.iov_base + 512);
rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1,
SPDK_DIF_FLAGS_GUARD_CHECK, 0, 0, 0, 0);
CU_ASSERT(rc == 0);
rc = spdk_dif_generate(&iov, 1, 1, &ctx);
CU_ASSERT(rc == 0);
/* Guard should be zero if the block is all zero and seed is not added. */
guard = from_be16(&dif->guard);
CU_ASSERT(guard == 0);
rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk);
CU_ASSERT(rc == 0);
rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1,
SPDK_DIF_FLAGS_GUARD_CHECK, 0, 0, 0, GUARD_SEED);
CU_ASSERT(rc == 0);
rc = spdk_dif_generate(&iov, 1, 1, &ctx);
CU_ASSERT(rc == 0);
/* Guard should not be zero if the block is all zero but seed is added. */
guard = from_be16(&dif->guard);
CU_ASSERT(guard != 0);
rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk);
CU_ASSERT(rc == 0);
_iov_free_buf(&iov);
}
static void
dif_generate_and_verify(struct iovec *iovs, int iovcnt,
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
@ -289,7 +337,7 @@ dif_generate_and_verify(struct iovec *iovs, int iovcnt,
CU_ASSERT(rc == 0);
rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags,
init_ref_tag, apptag_mask, app_tag);
init_ref_tag, apptag_mask, app_tag, GUARD_SEED);
CU_ASSERT(rc == 0);
rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx);
@ -594,7 +642,7 @@ _dif_inject_error_and_verify(struct iovec *iovs, int iovcnt,
CU_ASSERT(rc == 0);
rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc,
SPDK_DIF_TYPE1, dif_flags, 88, 0xFFFF, 0x88);
SPDK_DIF_TYPE1, dif_flags, 88, 0xFFFF, 0x88, GUARD_SEED);
CU_ASSERT(rc == 0);
rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx);
@ -752,7 +800,7 @@ dif_copy_gen_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov
CU_ASSERT(rc == 0);
rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags,
init_ref_tag, apptag_mask, app_tag);
init_ref_tag, apptag_mask, app_tag, GUARD_SEED);
CU_ASSERT(rc == 0);
rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx);
@ -923,7 +971,7 @@ _dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *
CU_ASSERT(rc == 0);
rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, SPDK_DIF_TYPE1, dif_flags,
88, 0xFFFF, 0x88);
88, 0xFFFF, 0x88, GUARD_SEED);
SPDK_CU_ASSERT_FATAL(rc == 0);
rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx);
@ -1028,7 +1076,7 @@ dix_sec_512_md_0_error(void)
struct spdk_dif_ctx ctx;
int rc;
rc = spdk_dif_ctx_init(&ctx, 512, 0, false, false, SPDK_DIF_TYPE1, 0, 0, 0, 0);
rc = spdk_dif_ctx_init(&ctx, 512, 0, false, false, SPDK_DIF_TYPE1, 0, 0, 0, 0, 0);
CU_ASSERT(rc != 0);
}
@ -1045,7 +1093,7 @@ dix_generate_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
CU_ASSERT(rc == 0);
rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, dif_type, dif_flags,
init_ref_tag, apptag_mask, app_tag);
init_ref_tag, apptag_mask, app_tag, GUARD_SEED);
CU_ASSERT(rc == 0);
rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx);
@ -1211,7 +1259,7 @@ _dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_io
CU_ASSERT(rc == 0);
rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, SPDK_DIF_TYPE1, dif_flags,
88, 0xFFFF, 0x88);
88, 0xFFFF, 0x88, GUARD_SEED);
CU_ASSERT(rc == 0);
rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx);
@ -1315,6 +1363,7 @@ main(int argc, char **argv)
CU_add_test(suite, "dif_generate_and_verify_test", dif_generate_and_verify_test) == NULL ||
CU_add_test(suite, "dif_disable_check_test", dif_disable_check_test) == NULL ||
CU_add_test(suite, "dif_sec_512_md_0_error_test", dif_sec_512_md_0_error_test) == NULL ||
CU_add_test(suite, "dif_guard_seed_test", dif_guard_seed_test) == NULL ||
CU_add_test(suite, "dif_disable_sec_512_md_8_single_iov_test",
dif_disable_sec_512_md_8_single_iov_test) == NULL ||
CU_add_test(suite, "dif_sec_512_md_8_prchk_0_single_iov_test",