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 <shuhei.matsumoto.xt@hitachi.com>
Change-Id: I0171d9021837b9a4b425370293cef45dbe7500e8
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458225
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Shuhei Matsumoto 2019-06-17 13:47:19 +09:00 committed by Changpeng Liu
parent f1344911ea
commit 27707953ec

View File

@ -328,31 +328,36 @@ _dif_generate_split(struct _dif_sgl *sgl, uint32_t offset_blocks,
} }
offset_in_block = 0; offset_in_block = 0;
while (offset_in_block < ctx->block_size) { /* Compute CRC over split logical block data. */
while (offset_in_block < ctx->guard_interval) {
_dif_sgl_get_buf(sgl, &buf, &buf_len); _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); buf_len = spdk_min(buf_len, ctx->guard_interval - offset_in_block);
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
/* Compute CRC over split logical block data. */
guard = spdk_crc16_t10dif(guard, buf, buf_len); guard = spdk_crc16_t10dif(guard, buf, buf_len);
} }
if (offset_in_block + buf_len == ctx->guard_interval) { _dif_sgl_advance(sgl, buf_len);
offset_in_block += buf_len;
}
/* If a whole logical block data is parsed, generate DIF /* If a whole logical block data is parsed, generate DIF
* and save it to the temporary DIF area. * and save it to the temporary DIF area.
*/ */
_dif_generate(&dif, guard, offset_blocks, ctx); _dif_generate(&dif, guard, offset_blocks, ctx);
}
} else if (offset_in_block < ctx->guard_interval + sizeof(struct spdk_dif)) { /* Copy generated DIF field to the split DIF field, and then
/* Copy generated DIF to the split DIF field. */ * 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 + sizeof(struct spdk_dif)) {
offset_in_dif = offset_in_block - ctx->guard_interval; offset_in_dif = offset_in_block - ctx->guard_interval;
buf_len = spdk_min(buf_len, sizeof(struct spdk_dif) - offset_in_dif); buf_len = spdk_min(buf_len, sizeof(struct spdk_dif) - offset_in_dif);
memcpy(buf, ((uint8_t *)&dif) + offset_in_dif, buf_len); memcpy(buf, ((uint8_t *)&dif) + offset_in_dif, buf_len);
} else { } else {
/* Skip metadata field after DIF field. */
buf_len = spdk_min(buf_len, ctx->block_size - offset_in_block); buf_len = spdk_min(buf_len, ctx->block_size - offset_in_block);
} }