dif: Clean-up APIs by introducing context data

This patch reduces the number of parameters of APIs by setting
necessary information to context struct and pass it to APIs.

This will simplify the code and will clarify the core logic.
Besides, by introducing context data, update of reference tag
is further consolidated.

Change-Id: I1b3eec596847eb4ef1cf43441035df21f746192a
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/438021
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: wuzhouhui <wuzhouhui@kingsoft.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Shuhei Matsumoto 2019-01-07 09:20:35 +09:00 committed by Jim Harris
parent c0839cc0c9
commit 18461cba7c
3 changed files with 234 additions and 250 deletions

View File

@ -60,68 +60,90 @@ struct spdk_dif {
};
SPDK_STATIC_ASSERT(sizeof(struct spdk_dif) == 8, "Incorrect size");
/** DIF context information */
struct spdk_dif_ctx {
/** Block size */
uint32_t block_size;
/** Metadata size */
uint32_t md_size;
/** Interval for guard computation */
uint32_t guard_interval;
/** DIF type */
enum spdk_dif_type dif_type;
/* Flags to specify the DIF action */
uint32_t dif_flags;
/* Initial reference tag */
uint32_t init_ref_tag;
/** Application tag */
uint16_t app_tag;
/* Application tag mask */
uint16_t apptag_mask;
};
/**
* Initialize DIF context.
*
* \param ctx DIF context.
* \param block_size Block size in a block.
* \param md_size Metadata size in a block.
* \param dif_loc DIF location. If true, DIF is set in the last 8 bytes of metadata.
* If false, DIF is in the first 8 bytes of metadata.
* \param dif_type Type of DIF.
* \param dif_flags Flag to specify the DIF action.
* \param init_ref_tag Initial reference tag. For type 1, this is the
* starting block address.
* \param apptag_mask Application tag mask.
* \param app_tag Application tag.
*
* \return 0 on success and negated errno otherwise.
*/
int spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_size,
bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag);
/**
* Generate DIF for extended LBA payload.
*
* \param iovs iovec array describing the extended LBA payload.
* \param iovcnt Number of elements in the iovec array.
* \param block_size Block size in a block.
* \param md_size Metadata size in a block.
* \param num_blocks Number of blocks of the payload.
* \param dif_loc DIF location. If true, DIF is set in the last 8 bytes of metadata.
* If false, DIF is in the first 8 bytes of metadata.
* \param dif_type Type of DIF.
* \param dif_flags Flag to specify the DIF action.
* \param init_ref_tag Initial Reference Tag. For type 1, this is the
* starting block address.
* \param app_tag Application Tag.
* \param ctx DIF context.
*
* \return 0 on success and negated errno otherwise.
*/
int spdk_dif_generate(struct iovec *iovs, int iovcnt,
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t init_ref_tag, uint16_t app_tag);
int spdk_dif_generate(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
const struct spdk_dif_ctx *ctx);
/**
* Verify DIF for extended LBA payload.
*
* \param iovs iovec array describing the extended LBA payload.
* \param iovcnt Number of elements in the iovec array.
* \param block_size Block size in a block.
* \param md_size Metadata size in a block.
* \param num_blocks Number of blocks of the payload.
* \param dif_loc DIF location. If true, DIF is set in the last 8 bytes of metadata.
* If false, DIF is set in the first 8 bytes of metadata.
* \param dif_type Type of DIF.
* \param dif_flags Flag to specify the DIF action.
* \param init_ref_tag Initial Reference Tag. For type 1, this is the
* starting block address.
* \param apptag_mask Application Tag Mask.
* \param app_tag Application Tag.
* \param ctx DIF context.
*
* \return 0 on success and negated errno otherwise.
*/
int spdk_dif_verify(struct iovec *iovs, int iovcnt,
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag);
int spdk_dif_verify(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
const struct spdk_dif_ctx *ctx);
/**
* Inject bit flip error to extended LBA payload.
*
* \param iovs iovec array describing the extended LBA payload.
* \param iovcnt Number of elements in the iovec array.
* \param block_size Block size in a block.
* \param md_size Metadata size in a block.
* \param num_blocks Number of blocks of the payload.
* \param dif_loc DIF location. If true, DIF is set in the last 8 bytes of metadata.
* If false, DIF is set in the first 8 bytes of metadata.
* \param inject_flags Flag to specify the action of error injection.
* \param ctx DIF context.
*
* \return 0 on success and negated errno otherwise including no metadata.
*/
int spdk_dif_inject_error(struct iovec *iovs, int iovcnt,
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
bool dif_loc, uint32_t inject_flags);
int spdk_dif_inject_error(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
const struct spdk_dif_ctx *ctx, uint32_t inject_flags);
#endif /* SPDK_DIF_H */

View File

@ -177,33 +177,74 @@ _get_dif_guard_interval(uint32_t block_size, uint32_t md_size, bool dif_loc)
}
}
int
spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_size,
bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag)
{
if (md_size < sizeof(struct spdk_dif)) {
SPDK_ERRLOG("Metadata size is smaller than DIF size.\n");
return -EINVAL;
}
if (block_size < md_size) {
SPDK_ERRLOG("Block size is smaller than DIF size.\n");
return -EINVAL;
}
if (!_dif_type_is_valid(dif_type, dif_flags)) {
SPDK_ERRLOG("DIF type is invalid.\n");
return -EINVAL;
}
ctx->block_size = block_size;
ctx->md_size = md_size;
ctx->guard_interval = _get_dif_guard_interval(block_size, md_size, dif_loc);
ctx->dif_type = dif_type;
ctx->dif_flags = dif_flags;
ctx->init_ref_tag = init_ref_tag;
ctx->apptag_mask = apptag_mask;
ctx->app_tag = app_tag;
return 0;
}
static void
_dif_generate(void *_dif, uint32_t dif_flags,
uint16_t guard, uint32_t ref_tag, uint16_t app_tag)
_dif_generate(void *_dif, uint16_t guard, uint32_t offset_blocks,
const struct spdk_dif_ctx *ctx)
{
struct spdk_dif *dif = _dif;
uint32_t ref_tag;
if (dif_flags & SPDK_DIF_GUARD_CHECK) {
if (ctx->dif_flags & SPDK_DIF_GUARD_CHECK) {
to_be16(&dif->guard, guard);
}
if (dif_flags & SPDK_DIF_APPTAG_CHECK) {
to_be16(&dif->app_tag, app_tag);
if (ctx->dif_flags & SPDK_DIF_APPTAG_CHECK) {
to_be16(&dif->app_tag, ctx->app_tag);
}
if (dif_flags & SPDK_DIF_REFTAG_CHECK) {
if (ctx->dif_flags & SPDK_DIF_REFTAG_CHECK) {
/* For type 1 and 2, the reference tag is incremented for each
* subsequent logical block. For type 3, the reference tag
* remains the same as the initial reference tag.
*/
if (ctx->dif_type != SPDK_DIF_TYPE3) {
ref_tag = ctx->init_ref_tag + offset_blocks;
} else {
ref_tag = ctx->init_ref_tag;
}
to_be32(&dif->ref_tag, ref_tag);
}
}
static void
dif_generate(struct iovec *iovs, int iovcnt,
uint32_t block_size, uint32_t guard_interval, uint32_t num_blocks,
enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t init_ref_tag, uint16_t app_tag)
dif_generate(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
const struct spdk_dif_ctx *ctx)
{
struct _iov_iter iter;
uint32_t offset_blocks, ref_tag;
uint32_t offset_blocks;
void *buf;
uint16_t guard = 0;
@ -211,35 +252,22 @@ dif_generate(struct iovec *iovs, int iovcnt,
_iov_iter_init(&iter, iovs, iovcnt);
while (offset_blocks < num_blocks && _iov_iter_cont(&iter)) {
/* For type 1 and 2, the reference tag is incremented for each
* subsequent logical block. For type 3, the reference tag
* remains the same as the initial reference tag.
*/
if (dif_type != SPDK_DIF_TYPE3) {
ref_tag = init_ref_tag + offset_blocks;
} else {
ref_tag = init_ref_tag;
}
_iov_iter_get_buf(&iter, &buf, NULL);
if (dif_flags & SPDK_DIF_GUARD_CHECK) {
guard = spdk_crc16_t10dif(0, buf, guard_interval);
if (ctx->dif_flags & SPDK_DIF_GUARD_CHECK) {
guard = spdk_crc16_t10dif(0, buf, ctx->guard_interval);
}
_dif_generate(buf + guard_interval, dif_flags, guard, ref_tag,
app_tag);
_dif_generate(buf + ctx->guard_interval, guard, offset_blocks, ctx);
_iov_iter_advance(&iter, block_size);
_iov_iter_advance(&iter, ctx->block_size);
offset_blocks++;
}
}
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)
_dif_generate_split(struct _iov_iter *iter, uint32_t offset_blocks,
const struct spdk_dif_ctx *ctx)
{
uint32_t offset_in_block, offset_in_dif, buf_len;
void *buf;
@ -249,32 +277,32 @@ _dif_generate_split(struct _iov_iter *iter,
guard = 0;
offset_in_block = 0;
while (offset_in_block < block_size && _iov_iter_cont(iter)) {
while (offset_in_block < ctx->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 (offset_in_block < ctx->guard_interval) {
buf_len = spdk_min(buf_len, ctx->guard_interval - offset_in_block);
if (dif_flags & SPDK_DIF_GUARD_CHECK) {
if (ctx->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 (offset_in_block + buf_len == ctx->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);
_dif_generate(&dif, guard, offset_blocks, ctx);
}
} else if (offset_in_block < guard_interval + sizeof(struct spdk_dif)) {
} else if (offset_in_block < ctx->guard_interval + sizeof(struct spdk_dif)) {
/* Copy generated DIF to the split DIF field. */
offset_in_dif = offset_in_block - guard_interval;
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, block_size - offset_in_block);
buf_len = spdk_min(buf_len, ctx->block_size - offset_in_block);
}
_iov_iter_advance(iter, buf_len);
@ -283,85 +311,53 @@ _dif_generate_split(struct _iov_iter *iter,
}
static void
dif_generate_split(struct iovec *iovs, int iovcnt,
uint32_t block_size, uint32_t guard_interval, uint32_t num_blocks,
enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t init_ref_tag, uint16_t app_tag)
dif_generate_split(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
const struct spdk_dif_ctx *ctx)
{
struct _iov_iter iter;
uint32_t offset_blocks, ref_tag;
uint32_t offset_blocks;
offset_blocks = 0;
_iov_iter_init(&iter, iovs, iovcnt);
while (offset_blocks < num_blocks && _iov_iter_cont(&iter)) {
/* For type 1 and 2, the reference tag is incremented for each
* subsequent logical block. For type 3, the reference tag
* remains the same as the initial reference tag.
*/
if (dif_type != SPDK_DIF_TYPE3) {
ref_tag = init_ref_tag + offset_blocks;
} else {
ref_tag = init_ref_tag;
}
_dif_generate_split(&iter, block_size, guard_interval,
dif_type, dif_flags, ref_tag, app_tag);
_dif_generate_split(&iter, offset_blocks, ctx);
offset_blocks++;
}
}
int
spdk_dif_generate(struct iovec *iovs, int iovcnt,
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t init_ref_tag, uint16_t app_tag)
spdk_dif_generate(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
const struct spdk_dif_ctx *ctx)
{
uint32_t guard_interval;
if (!_are_iovs_valid(iovs, iovcnt, block_size * num_blocks)) {
if (!_are_iovs_valid(iovs, iovcnt, ctx->block_size * num_blocks)) {
SPDK_ERRLOG("Size of iovec array is not valid.\n");
return -EINVAL;
}
if (md_size < sizeof(struct spdk_dif)) {
SPDK_ERRLOG("Metadata size is smaller than DIF size.\n");
return -EINVAL;
}
if (!_dif_type_is_valid(dif_type, dif_flags)) {
SPDK_ERRLOG("DIF type is invalid.\n");
return -EINVAL;
}
if (_dif_is_disabled(dif_type)) {
if (_dif_is_disabled(ctx->dif_type)) {
return 0;
}
guard_interval = _get_dif_guard_interval(block_size, md_size, dif_loc);
if (_are_iovs_bytes_multiple(iovs, iovcnt, block_size)) {
dif_generate(iovs, iovcnt, block_size, guard_interval, num_blocks,
dif_type, dif_flags, init_ref_tag, app_tag);
if (_are_iovs_bytes_multiple(iovs, iovcnt, ctx->block_size)) {
dif_generate(iovs, iovcnt, num_blocks, ctx);
} else {
dif_generate_split(iovs, iovcnt, block_size, guard_interval, num_blocks,
dif_type, dif_flags, init_ref_tag, app_tag);
dif_generate_split(iovs, iovcnt, num_blocks, ctx);
}
return 0;
}
static int
_dif_verify(void *_dif, enum spdk_dif_type dif_type, uint32_t dif_flags,
uint16_t guard, uint32_t ref_tag, uint16_t apptag_mask, uint16_t app_tag)
_dif_verify(void *_dif, uint16_t guard, uint32_t offset_blocks,
const struct spdk_dif_ctx *ctx)
{
struct spdk_dif *dif = _dif;
uint16_t _guard;
uint16_t _app_tag;
uint32_t _ref_tag;
uint32_t ref_tag, _ref_tag;
switch (dif_type) {
switch (ctx->dif_type) {
case SPDK_DIF_TYPE1:
case SPDK_DIF_TYPE2:
/* If Type 1 or 2 is used, then all DIF checks are disabled when
@ -383,7 +379,17 @@ _dif_verify(void *_dif, enum spdk_dif_type dif_type, uint32_t dif_flags,
break;
}
if (dif_flags & SPDK_DIF_GUARD_CHECK) {
/* For type 1 and 2, the reference tag is incremented for each
* subsequent logical block. For type 3, the reference tag
* remains the same as the initial reference tag.
*/
if (ctx->dif_type != SPDK_DIF_TYPE3) {
ref_tag = ctx->init_ref_tag + offset_blocks;
} else {
ref_tag = ctx->init_ref_tag;
}
if (ctx->dif_flags & SPDK_DIF_GUARD_CHECK) {
/* Compare the DIF Guard field to the CRC computed over the logical
* block data.
*/
@ -396,21 +402,21 @@ _dif_verify(void *_dif, enum spdk_dif_type dif_type, uint32_t dif_flags,
}
}
if (dif_flags & SPDK_DIF_APPTAG_CHECK) {
if (ctx->dif_flags & SPDK_DIF_APPTAG_CHECK) {
/* Compare unmasked bits in the DIF Application Tag field to the
* passed Application Tag.
*/
_app_tag = from_be16(&dif->app_tag);
if ((_app_tag & apptag_mask) != app_tag) {
if ((_app_tag & ctx->apptag_mask) != ctx->app_tag) {
SPDK_ERRLOG("Failed to compare App Tag: LBA=%" PRIu32 "," \
" Expected=%x, Actual=%x\n",
ref_tag, app_tag, (_app_tag & apptag_mask));
ref_tag, ctx->app_tag, (_app_tag & ctx->apptag_mask));
return -1;
}
}
if (dif_flags & SPDK_DIF_REFTAG_CHECK) {
switch (dif_type) {
if (ctx->dif_flags & SPDK_DIF_REFTAG_CHECK) {
switch (ctx->dif_type) {
case SPDK_DIF_TYPE1:
case SPDK_DIF_TYPE2:
/* Compare the DIF Reference Tag field to the passed Reference Tag.
@ -440,13 +446,11 @@ _dif_verify(void *_dif, enum spdk_dif_type dif_type, uint32_t dif_flags,
}
static int
dif_verify(struct iovec *iovs, int iovcnt,
uint32_t block_size, uint32_t guard_interval, uint32_t num_blocks,
enum spdk_dif_type dif_type, uint32_t dif_flags, uint32_t init_ref_tag,
uint16_t apptag_mask, uint16_t app_tag)
dif_verify(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
const struct spdk_dif_ctx *ctx)
{
struct _iov_iter iter;
uint32_t offset_blocks, ref_tag;
uint32_t offset_blocks;
int rc;
void *buf;
uint16_t guard = 0;
@ -455,29 +459,18 @@ dif_verify(struct iovec *iovs, int iovcnt,
_iov_iter_init(&iter, iovs, iovcnt);
while (offset_blocks < num_blocks && _iov_iter_cont(&iter)) {
/* For type 1 and 2, the reference tag is incremented for each
* subsequent logical block. For type 3, the reference tag
* remains the same as the initial reference tag.
*/
if (dif_type != SPDK_DIF_TYPE3) {
ref_tag = init_ref_tag + offset_blocks;
} else {
ref_tag = init_ref_tag;
}
_iov_iter_get_buf(&iter, &buf, NULL);
if (dif_flags & SPDK_DIF_GUARD_CHECK) {
guard = spdk_crc16_t10dif(0, buf, guard_interval);
if (ctx->dif_flags & SPDK_DIF_GUARD_CHECK) {
guard = spdk_crc16_t10dif(0, buf, ctx->guard_interval);
}
rc = _dif_verify(buf + guard_interval, dif_type, dif_flags,
guard, ref_tag, apptag_mask, app_tag);
rc = _dif_verify(buf + ctx->guard_interval, guard, offset_blocks, ctx);
if (rc != 0) {
return rc;
}
_iov_iter_advance(&iter, block_size);
_iov_iter_advance(&iter, ctx->block_size);
offset_blocks++;
}
@ -485,10 +478,8 @@ dif_verify(struct iovec *iovs, int iovcnt,
}
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)
_dif_verify_split(struct _iov_iter *iter, uint32_t offset_blocks,
const struct spdk_dif_ctx *ctx)
{
uint32_t offset_in_block, offset_in_dif, buf_len;
void *buf;
@ -498,65 +489,50 @@ _dif_verify_split(struct _iov_iter *iter,
guard = 0;
offset_in_block = 0;
while (offset_in_block < block_size && _iov_iter_cont(iter)) {
while (offset_in_block < ctx->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 (offset_in_block < ctx->guard_interval) {
buf_len = spdk_min(buf_len, ctx->guard_interval - offset_in_block);
if (dif_flags & SPDK_DIF_GUARD_CHECK) {
if (ctx->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)) {
} else if (offset_in_block < ctx->guard_interval + sizeof(struct spdk_dif)) {
/* Copy the split DIF field to the temporary DIF buffer. */
offset_in_dif = offset_in_block - guard_interval;
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, block_size - offset_in_block);
buf_len = spdk_min(buf_len, ctx->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);
return _dif_verify(&dif, guard, offset_blocks, ctx);
}
static int
dif_verify_split(struct iovec *iovs, int iovcnt,
uint32_t block_size, uint32_t guard_interval, uint32_t num_blocks,
enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag)
dif_verify_split(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
const struct spdk_dif_ctx *ctx)
{
struct _iov_iter iter;
uint32_t offset_blocks;
uint32_t ref_tag;
int rc;
offset_blocks = 0;
_iov_iter_init(&iter, iovs, iovcnt);
while (offset_blocks < num_blocks && _iov_iter_cont(&iter)) {
/* For type 1 and 2, the reference tag is incremented for each
* subsequent logical block. For type 3, the reference tag
* remains the same as the initial reference tag.
*/
if (dif_type != SPDK_DIF_TYPE3) {
ref_tag = init_ref_tag + offset_blocks;
} else {
ref_tag = init_ref_tag;
}
rc = _dif_verify_split(&iter, block_size, guard_interval, dif_type, dif_flags,
ref_tag, apptag_mask, app_tag);
rc = _dif_verify_split(&iter, offset_blocks, ctx);
if (rc != 0) {
return rc;
}
offset_blocks++;
}
@ -564,40 +540,22 @@ dif_verify_split(struct iovec *iovs, int iovcnt,
}
int
spdk_dif_verify(struct iovec *iovs, int iovcnt,
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag)
spdk_dif_verify(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
const struct spdk_dif_ctx *ctx)
{
uint32_t guard_interval;
if (!_are_iovs_valid(iovs, iovcnt, block_size * num_blocks)) {
if (!_are_iovs_valid(iovs, iovcnt, ctx->block_size * num_blocks)) {
SPDK_ERRLOG("Size of iovec array is not valid.\n");
return -EINVAL;
}
if (md_size < sizeof(struct spdk_dif)) {
SPDK_ERRLOG("Metadata size is smaller than DIF size\n");
return -EINVAL;
}
if (!_dif_type_is_valid(dif_type, dif_flags)) {
SPDK_ERRLOG("DIF type is invalid.\n");
return -EINVAL;
}
if (_dif_is_disabled(dif_type)) {
if (_dif_is_disabled(ctx->dif_type)) {
return 0;
}
guard_interval = _get_dif_guard_interval(block_size, md_size, dif_loc);
if (_are_iovs_bytes_multiple(iovs, iovcnt, block_size)) {
return dif_verify(iovs, iovcnt, block_size, guard_interval, num_blocks,
dif_type, dif_flags, init_ref_tag, apptag_mask, app_tag);
if (_are_iovs_bytes_multiple(iovs, iovcnt, ctx->block_size)) {
return dif_verify(iovs, iovcnt, num_blocks, ctx);
} else {
return dif_verify_split(iovs, iovcnt, block_size, guard_interval, num_blocks,
dif_type, dif_flags, init_ref_tag, apptag_mask, app_tag);
return dif_verify_split(iovs, iovcnt, num_blocks, ctx);
}
}
@ -675,27 +633,19 @@ dif_inject_error(struct iovec *iovs, int iovcnt,
#define _member_size(type, member) sizeof(((type *)0)->member)
int
spdk_dif_inject_error(struct iovec *iovs, int iovcnt,
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
bool dif_loc, uint32_t inject_flags)
spdk_dif_inject_error(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
const struct spdk_dif_ctx *ctx, uint32_t inject_flags)
{
uint32_t guard_interval;
int rc;
if (md_size < sizeof(struct spdk_dif)) {
return -EINVAL;
}
if (!_are_iovs_valid(iovs, iovcnt, block_size * num_blocks)) {
if (!_are_iovs_valid(iovs, iovcnt, ctx->block_size * num_blocks)) {
SPDK_ERRLOG("Size of iovec array is not valid.\n");
return -EINVAL;
}
guard_interval = _get_dif_guard_interval(block_size, md_size, dif_loc);
if (inject_flags & SPDK_DIF_REFTAG_ERROR) {
rc = dif_inject_error(iovs, iovcnt, block_size, num_blocks,
guard_interval + offsetof(struct spdk_dif, ref_tag),
rc = dif_inject_error(iovs, iovcnt, ctx->block_size, num_blocks,
ctx->guard_interval + offsetof(struct spdk_dif, ref_tag),
_member_size(struct spdk_dif, ref_tag));
if (rc != 0) {
SPDK_ERRLOG("Failed to inject error to Reference Tag.\n");
@ -704,8 +654,8 @@ spdk_dif_inject_error(struct iovec *iovs, int iovcnt,
}
if (inject_flags & SPDK_DIF_APPTAG_ERROR) {
rc = dif_inject_error(iovs, iovcnt, block_size, num_blocks,
guard_interval + offsetof(struct spdk_dif, app_tag),
rc = dif_inject_error(iovs, iovcnt, ctx->block_size, num_blocks,
ctx->guard_interval + offsetof(struct spdk_dif, app_tag),
_member_size(struct spdk_dif, app_tag));
if (rc != 0) {
SPDK_ERRLOG("Failed to inject error to Application Tag.\n");
@ -713,8 +663,8 @@ spdk_dif_inject_error(struct iovec *iovs, int iovcnt,
}
}
if (inject_flags & SPDK_DIF_GUARD_ERROR) {
rc = dif_inject_error(iovs, iovcnt, block_size, num_blocks,
guard_interval,
rc = dif_inject_error(iovs, iovcnt, ctx->block_size, num_blocks,
ctx->guard_interval,
_member_size(struct spdk_dif, guard));
if (rc != 0) {
SPDK_ERRLOG("Failed to inject error to Guard.\n");
@ -728,9 +678,9 @@ spdk_dif_inject_error(struct iovec *iovs, int iovcnt,
* the last 8 bytes. But error injection does not cover these metadata
* because classification is not determined yet.
*/
rc = dif_inject_error(iovs, iovcnt, block_size, num_blocks,
rc = dif_inject_error(iovs, iovcnt, ctx->block_size, num_blocks,
0,
block_size - md_size);
ctx->block_size - ctx->md_size);
if (rc != 0) {
SPDK_ERRLOG("Failed to inject error to data block.\n");
return rc;

View File

@ -131,26 +131,38 @@ _iov_free_buf(struct iovec *iov)
static void
_dif_generate_and_verify(struct iovec *iov,
uint32_t block_size, uint32_t md_size, uint32_t guard_interval,
uint32_t block_size, uint32_t md_size, bool dif_loc,
enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t ref_tag, uint32_t e_ref_tag,
uint16_t app_tag, uint16_t apptag_mask, uint16_t e_app_tag,
bool expect_pass)
{
int rc;
struct spdk_dif_ctx ctx = {};
uint32_t guard_interval;
uint16_t guard = 0;
int rc;
rc = ut_data_pattern_generate(iov, 1, block_size, md_size, 1);
CU_ASSERT(rc == 0);
guard_interval = _get_dif_guard_interval(block_size, md_size, dif_loc);
ctx.dif_type = dif_type;
ctx.dif_flags = dif_flags;
ctx.init_ref_tag = ref_tag;
ctx.app_tag = app_tag;
if (dif_flags & SPDK_DIF_GUARD_CHECK) {
guard = spdk_crc16_t10dif(0, iov->iov_base, guard_interval);
}
_dif_generate(iov->iov_base + guard_interval, dif_flags, guard, ref_tag, app_tag);
_dif_generate(iov->iov_base + guard_interval, guard, 0, &ctx);
rc = _dif_verify(iov->iov_base + guard_interval, dif_type, dif_flags,
guard, e_ref_tag, apptag_mask, e_app_tag);
ctx.init_ref_tag = e_ref_tag;
ctx.apptag_mask = apptag_mask;
ctx.app_tag = e_app_tag;
rc = _dif_verify(iov->iov_base + guard_interval, guard, 0, &ctx);
CU_ASSERT((expect_pass && rc == 0) || (!expect_pass && rc != 0));
rc = ut_data_pattern_verify(iov, 1, block_size, md_size, 1);
@ -171,7 +183,7 @@ dif_generate_and_verify_test(void)
/* The case that DIF is contained in the first 8 bytes of metadata. */
_dif_generate_and_verify(&iov,
4096 + 128, 128, 4096,
4096 + 128, 128, false,
SPDK_DIF_TYPE1, dif_flags,
22, 22,
0x22, 0xFFFF, 0x22,
@ -179,7 +191,7 @@ dif_generate_and_verify_test(void)
/* The case that DIF is contained in the last 8 bytes of metadata. */
_dif_generate_and_verify(&iov,
4096 + 128, 128, 4096 + 128 - 8,
4096 + 128, 128, true,
SPDK_DIF_TYPE1, dif_flags,
22, 22,
0x22, 0xFFFF, 0x22,
@ -189,7 +201,7 @@ dif_generate_and_verify_test(void)
/* Reference tag doesn't match. */
_dif_generate_and_verify(&iov,
4096 + 128, 128, 4096,
4096 + 128, 128, false,
SPDK_DIF_TYPE1, dif_flags,
22, 23,
0x22, 0xFFFF, 0x22,
@ -197,7 +209,7 @@ dif_generate_and_verify_test(void)
/* Application tag doesn't match. */
_dif_generate_and_verify(&iov,
4096 + 128, 128, 4096,
4096 + 128, 128, false,
SPDK_DIF_TYPE1, dif_flags,
22, 22,
0x22, 0xFFFF, 0x23,
@ -220,7 +232,7 @@ dif_disable_check_test(void)
* Type 1. DIF check is disabled and pass is expected.
*/
_dif_generate_and_verify(&iov,
4096 + 128, 128, 4096,
4096 + 128, 128, false,
SPDK_DIF_TYPE1, dif_flags,
22, 22,
0xFFFF, 0xFFFF, 0x22,
@ -231,7 +243,7 @@ dif_disable_check_test(void)
* fail is expected.
*/
_dif_generate_and_verify(&iov,
4096 + 128, 128, 4096,
4096 + 128, 128, false,
SPDK_DIF_TYPE3, dif_flags,
22, 22,
0xFFFF, 0xFFFF, 0x22,
@ -242,7 +254,7 @@ dif_disable_check_test(void)
* pass is expected.
*/
_dif_generate_and_verify(&iov,
4096 + 128, 128, 4096,
4096 + 128, 128, false,
SPDK_DIF_TYPE3, dif_flags,
0xFFFFFFFF, 22,
0xFFFF, 0xFFFF, 0x22,
@ -254,14 +266,11 @@ dif_disable_check_test(void)
static void
dif_sec_512_md_0_error_test(void)
{
struct iovec iov = {};
struct spdk_dif_ctx ctx = {};
int rc;
/* Metadata size is 0. */
rc = spdk_dif_generate(&iov, 1, 512, 0, 1, false, SPDK_DIF_TYPE1, 0, 0, 0);
CU_ASSERT(rc != 0);
rc = spdk_dif_verify(&iov, 1, 512, 0, 1, false, SPDK_DIF_TYPE1, 0, 0, 0, 0);
rc = spdk_dif_ctx_init(&ctx, 512, 0, false, SPDK_DIF_TYPE1, 0, 0, 0, 0);
CU_ASSERT(rc != 0);
}
@ -271,19 +280,20 @@ dif_generate_and_verify(struct iovec *iovs, int iovcnt,
bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag)
{
struct spdk_dif_ctx ctx = {};
int rc;
rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks);
CU_ASSERT(rc == 0);
rc = spdk_dif_generate(iovs, iovcnt, block_size, md_size, num_blocks,
dif_loc, dif_type, dif_flags,
init_ref_tag, app_tag);
rc = spdk_dif_ctx_init(&ctx, block_size, md_size, dif_loc, dif_type, dif_flags,
init_ref_tag, apptag_mask, app_tag);
CU_ASSERT(rc == 0);
rc = spdk_dif_verify(iovs, iovcnt, block_size, md_size, num_blocks,
dif_loc, dif_type, dif_flags,
init_ref_tag, apptag_mask, app_tag);
rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx);
CU_ASSERT(rc == 0);
rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx);
CU_ASSERT(rc == 0);
rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks);
@ -562,6 +572,7 @@ _dif_inject_error_and_verify(struct iovec *iovs, int iovcnt,
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
uint32_t inject_flags, bool dif_loc)
{
struct spdk_dif_ctx ctx = {};
uint32_t dif_flags;
int rc;
@ -570,16 +581,17 @@ _dif_inject_error_and_verify(struct iovec *iovs, int iovcnt,
rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks);
CU_ASSERT(rc == 0);
rc = spdk_dif_generate(iovs, iovcnt, block_size, md_size, num_blocks,
dif_loc, SPDK_DIF_TYPE1, dif_flags, 88, 0x88);
rc = spdk_dif_ctx_init(&ctx, block_size, md_size, dif_loc,
SPDK_DIF_TYPE1, dif_flags, 88, 0xFFFF, 0x88);
CU_ASSERT(rc == 0);
rc = spdk_dif_inject_error(iovs, iovcnt, block_size, md_size, num_blocks,
dif_loc, inject_flags);
rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx);
CU_ASSERT(rc == 0);
rc = spdk_dif_verify(iovs, iovcnt, block_size, md_size, num_blocks,
dif_loc, SPDK_DIF_TYPE1, dif_flags, 88, 0xFFFF, 0x88);
rc = spdk_dif_inject_error(iovs, iovcnt, num_blocks, &ctx, inject_flags);
CU_ASSERT(rc == 0);
rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx);
CU_ASSERT(rc != 0);
rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks);