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 <shuhei.matsumoto.xt@hitachi.com>
Change-Id: Ic4f1765e01507efa812dfaf7a8018666c6346f8e
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458328
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Shuhei Matsumoto 2019-06-17 15:48:27 +09:00 committed by Changpeng Liu
parent 42287a6954
commit d69dc28b00

View File

@ -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;
}