From 27707953ec83f5ec255d38ad92c5a9bd0ae2a688 Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Mon, 17 Jun 2019 13:47:19 +0900 Subject: [PATCH] dif: Separate _dif_generate_split into three parts For NVMe/TCP target, data segments which correspond to H2C or C2H PDU will have any alignment, and _dif_generate_split will have to process partial data 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_generate_split had assumed that passed block is always a complete block. To process the above types, separating guard computation, DIF generation, and DIF copy into three parts will be helpful and is done in this patch. Signed-off-by: Shuhei Matsumoto Change-Id: I0171d9021837b9a4b425370293cef45dbe7500e8 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458225 Tested-by: SPDK CI Jenkins Reviewed-by: Darek Stojaczyk Reviewed-by: Changpeng Liu --- lib/util/dif.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/lib/util/dif.c b/lib/util/dif.c index 9a000cda4..671262ae5 100644 --- a/lib/util/dif.c +++ b/lib/util/dif.c @@ -328,31 +328,36 @@ _dif_generate_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; + } + + /* If a whole logical block data is parsed, generate DIF + * and save it to the temporary DIF area. + */ + _dif_generate(&dif, guard, offset_blocks, ctx); + + /* Copy generated DIF field to the split DIF field, 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); - } - - if (offset_in_block + buf_len == ctx->guard_interval) { - /* If a whole logical block data is parsed, generate DIF - * and save it to the temporary DIF area. - */ - _dif_generate(&dif, guard, offset_blocks, ctx); - } - } else if (offset_in_block < ctx->guard_interval + sizeof(struct spdk_dif)) { - /* Copy generated DIF to the split DIF field. */ + 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(buf, ((uint8_t *)&dif) + offset_in_dif, buf_len); } else { - /* Skip metadata field after DIF field. */ buf_len = spdk_min(buf_len, ctx->block_size - offset_in_block); }