From d69dc28b00142e365cceb3e45bb825a710e429d3 Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Mon, 17 Jun 2019 15:48:27 +0900 Subject: [PATCH] dif: Separate _dif_verify_split into three parts For NVMe/TCP target, data segments which correspond to H2C or C2H PDU will have any alignment, and _dif_verify_split will have to process partial data block, particularly the following types: - start and end are both within a data block. - start is within a data block, and end is at the end of a block On the other hand, _dif_verify_split had assumed that passed block is always a complete block. To process the above types, separating guard computation, DIF copy and skipping metadata field, and DIF verification into three parts will be helpful and is done in this patch. Signed-off-by: Shuhei Matsumoto Change-Id: Ic4f1765e01507efa812dfaf7a8018666c6346f8e Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458328 Reviewed-by: Changpeng Liu Reviewed-by: Darek Stojaczyk Tested-by: SPDK CI Jenkins --- lib/util/dif.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/util/dif.c b/lib/util/dif.c index e6df100e4d..4a8e15f4b4 100644 --- a/lib/util/dif.c +++ b/lib/util/dif.c @@ -592,27 +592,32 @@ _dif_verify_split(struct _dif_sgl *sgl, uint32_t offset_blocks, } offset_in_block = 0; + /* Compute CRC over split logical block data. */ + while (offset_in_block < ctx->guard_interval) { + _dif_sgl_get_buf(sgl, &buf, &buf_len); + buf_len = spdk_min(buf_len, ctx->guard_interval - offset_in_block); + + if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { + guard = spdk_crc16_t10dif(guard, buf, buf_len); + } + + _dif_sgl_advance(sgl, buf_len); + offset_in_block += buf_len; + } + + /* Copy the split DIF field to the temporary DIF buffer, and then + * skip metadata field after DIF field (if any). */ while (offset_in_block < ctx->block_size) { _dif_sgl_get_buf(sgl, &buf, &buf_len); - if (offset_in_block < ctx->guard_interval) { - buf_len = spdk_min(buf_len, ctx->guard_interval - offset_in_block); - - if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { - /* Compute CRC over split logical block data. */ - guard = spdk_crc16_t10dif(guard, buf, buf_len); - } - } else if (offset_in_block < ctx->guard_interval + sizeof(struct spdk_dif)) { - /* Copy the split DIF field to the temporary DIF buffer. */ + if (offset_in_block < ctx->guard_interval + sizeof(struct spdk_dif)) { offset_in_dif = offset_in_block - ctx->guard_interval; buf_len = spdk_min(buf_len, sizeof(struct spdk_dif) - offset_in_dif); memcpy((uint8_t *)&dif + offset_in_dif, buf, buf_len); } else { - /* Skip metadata field after DIF field. */ buf_len = spdk_min(buf_len, ctx->block_size - offset_in_block); } - _dif_sgl_advance(sgl, buf_len); offset_in_block += buf_len; }