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:
parent
f9cbc493dc
commit
0a3cdcf3c3
170
lib/util/dif.c
170
lib/util/dif.c
@ -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++;
|
||||||
|
Loading…
Reference in New Issue
Block a user