Commit 27707953 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Changpeng Liu
Browse files

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: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: I0171d9021837b9a4b425370293cef45dbe7500e8
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458225


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarDarek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
parent f1344911
Loading
Loading
Loading
Loading
+21 −16
Original line number Diff line number Diff line
@@ -328,31 +328,36 @@ _dif_generate_split(struct _dif_sgl *sgl, uint32_t offset_blocks,
	}
	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);

		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) {
		_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);
			}
		} else if (offset_in_block < ctx->guard_interval + sizeof(struct spdk_dif)) {
			/* Copy generated DIF to the split DIF field. */

	/* 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 + 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);
		}