dif: Factor out core logic to generate and verify DIF for each split block

This patch factors out the core logic to generate and verify DIF
for each split extended logical block.

This patch reduces nesting and clarify the core logic.

Change-Id: I6adf36fb86fafef8a4235021f77a1d99a0d63c8a
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/437795
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Shuhei Matsumoto 2018-12-19 10:26:36 +09:00 committed by Jim Harris
parent f9cbc493dc
commit 0a3cdcf3c3

View File

@ -209,6 +209,53 @@ dif_generate(struct iovec *iovs, int iovcnt,
} }
} }
static void
_dif_generate_split(struct _iov_iter *iter,
uint32_t block_size, uint32_t guard_interval,
enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t ref_tag, uint16_t app_tag)
{
uint32_t offset_in_block, offset_in_dif, buf_len;
void *buf;
uint16_t guard;
struct spdk_dif dif = {};
guard = 0;
offset_in_block = 0;
while (offset_in_block < block_size && _iov_iter_cont(iter)) {
_iov_iter_get_buf(iter, &buf, &buf_len);
if (offset_in_block < guard_interval) {
buf_len = spdk_min(buf_len, guard_interval - offset_in_block);
if (dif_flags & SPDK_DIF_GUARD_CHECK) {
/* Compute CRC over split logical block data. */
guard = spdk_crc16_t10dif(guard, buf, buf_len);
}
if (offset_in_block + buf_len == guard_interval) {
/* If a whole logical block data is parsed, generate DIF
* and save it to the temporary DIF area.
*/
_dif_generate(&dif, dif_flags, guard, ref_tag, app_tag);
}
} else if (offset_in_block < guard_interval + sizeof(struct spdk_dif)) {
/* Copy generated DIF to the split DIF field. */
offset_in_dif = offset_in_block - 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, block_size - offset_in_block);
}
_iov_iter_advance(iter, buf_len);
offset_in_block += buf_len;
}
}
static void static void
dif_generate_split(struct iovec *iovs, int iovcnt, dif_generate_split(struct iovec *iovs, int iovcnt,
uint32_t block_size, uint32_t guard_interval, uint32_t num_blocks, uint32_t block_size, uint32_t guard_interval, uint32_t num_blocks,
@ -216,11 +263,7 @@ dif_generate_split(struct iovec *iovs, int iovcnt,
uint32_t init_ref_tag, uint16_t app_tag) uint32_t init_ref_tag, uint16_t app_tag)
{ {
struct _iov_iter iter; struct _iov_iter iter;
uint32_t offset_blocks, offset_in_block, offset_in_dif; uint32_t offset_blocks, ref_tag;
uint32_t buf_len, ref_tag;
void *buf;
uint16_t guard;
struct spdk_dif dif = {};
offset_blocks = 0; offset_blocks = 0;
_iov_iter_init(&iter, iovs, iovcnt); _iov_iter_init(&iter, iovs, iovcnt);
@ -236,40 +279,9 @@ dif_generate_split(struct iovec *iovs, int iovcnt,
ref_tag = init_ref_tag; ref_tag = init_ref_tag;
} }
guard = 0; _dif_generate_split(&iter, block_size, guard_interval,
offset_in_block = 0; dif_type, dif_flags, ref_tag, app_tag);
while (offset_in_block < block_size && _iov_iter_cont(&iter)) {
_iov_iter_get_buf(&iter, &buf, &buf_len);
if (offset_in_block < guard_interval) {
buf_len = spdk_min(buf_len, guard_interval - offset_in_block);
if (dif_flags & SPDK_DIF_GUARD_CHECK) {
/* Compute CRC over split logical block data. */
guard = spdk_crc16_t10dif(guard, buf, buf_len);
}
if (offset_in_block + buf_len == guard_interval) {
/* If a whole logical block data is parsed, generate DIF
* and save it to the temporary DIF area.
*/
_dif_generate(&dif, dif_flags, guard, ref_tag, app_tag);
}
} else if (offset_in_block < guard_interval + sizeof(struct spdk_dif)) {
/* Copy generated DIF to the split DIF field. */
offset_in_dif = offset_in_block - 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, block_size - offset_in_block);
}
_iov_iter_advance(&iter, buf_len);
offset_in_block += buf_len;
}
offset_blocks++; offset_blocks++;
} }
} }
@ -436,6 +448,48 @@ dif_verify(struct iovec *iovs, int iovcnt,
return 0; return 0;
} }
static int
_dif_verify_split(struct _iov_iter *iter,
uint32_t block_size, uint32_t guard_interval,
enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t ref_tag, uint16_t apptag_mask, uint16_t app_tag)
{
uint32_t offset_in_block, offset_in_dif, buf_len;
void *buf;
uint16_t guard;
struct spdk_dif dif = {};
guard = 0;
offset_in_block = 0;
while (offset_in_block < block_size && _iov_iter_cont(iter)) {
_iov_iter_get_buf(iter, &buf, &buf_len);
if (offset_in_block < guard_interval) {
buf_len = spdk_min(buf_len, guard_interval - offset_in_block);
if (dif_flags & SPDK_DIF_GUARD_CHECK) {
/* Compute CRC over split logical block data. */
guard = spdk_crc16_t10dif(guard, buf, buf_len);
}
} else if (offset_in_block < guard_interval + sizeof(struct spdk_dif)) {
/* Copy the split DIF field to the temporary DIF buffer. */
offset_in_dif = offset_in_block - 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, block_size - offset_in_block);
}
_iov_iter_advance(iter, buf_len);
offset_in_block += buf_len;
}
return _dif_verify(&dif, dif_type, dif_flags, guard, ref_tag, apptag_mask, app_tag);
}
static int static int
dif_verify_split(struct iovec *iovs, int iovcnt, dif_verify_split(struct iovec *iovs, int iovcnt,
uint32_t block_size, uint32_t guard_interval, uint32_t num_blocks, uint32_t block_size, uint32_t guard_interval, uint32_t num_blocks,
@ -443,12 +497,9 @@ dif_verify_split(struct iovec *iovs, int iovcnt,
uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag) uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag)
{ {
struct _iov_iter iter; struct _iov_iter iter;
uint32_t offset_blocks, offset_in_block, offset_in_dif; uint32_t offset_blocks;
uint32_t buf_len, ref_tag = 0; uint32_t ref_tag;
int rc; int rc;
void *buf;
uint16_t guard;
struct spdk_dif dif = {};
offset_blocks = 0; offset_blocks = 0;
_iov_iter_init(&iter, iovs, iovcnt); _iov_iter_init(&iter, iovs, iovcnt);
@ -464,37 +515,10 @@ dif_verify_split(struct iovec *iovs, int iovcnt,
ref_tag = init_ref_tag; ref_tag = init_ref_tag;
} }
guard = 0; rc = _dif_verify_split(&iter, block_size, guard_interval, dif_type, dif_flags,
offset_in_block = 0; ref_tag, apptag_mask, app_tag);
while (offset_in_block < block_size && _iov_iter_cont(&iter)) {
_iov_iter_get_buf(&iter, &buf, &buf_len);
if (offset_in_block < guard_interval) {
buf_len = spdk_min(buf_len, guard_interval - offset_in_block);
if (dif_flags & SPDK_DIF_GUARD_CHECK) {
/* Compute CRC over split logical block data. */
guard = spdk_crc16_t10dif(guard, buf, buf_len);
}
} else if (offset_in_block < guard_interval + sizeof(struct spdk_dif)) {
/* Copy the split DIF field to the temporary DIF buffer. */
offset_in_dif = offset_in_block - 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, block_size - offset_in_block);
}
_iov_iter_advance(&iter, buf_len);
offset_in_block += buf_len;
}
rc = _dif_verify(&dif, dif_type, dif_flags, guard, ref_tag, apptag_mask, app_tag);
if (rc != 0) { if (rc != 0) {
return 0; return rc;
} }
offset_blocks++; offset_blocks++;