scsi: Add an API to return DIF context of bdev and CDB
This patch adds an API spdk_scsi_bdev_get_dif_ctx(). spdk_scsi_bdev_get_dif_ctx() decodes opcode in CDB, and if opcode is read or write block commands, it gets LBA and use the lower 32bits of LBA as Reference Tag. It gets DIF information from specified bdev next. Then it sets all to DIF context and return. spdk_scsi_bdev_get_dif_ctx() is exported to iSCSI through spdk_scsi_lun_get_dif_ctx(). Change-Id: Id8aac164c48e9e9d4ff7cfc9fa81bb5090f3e187 Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/446224 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
parent
e17851314e
commit
8697bce7af
@ -518,6 +518,18 @@ int spdk_scsi_lun_allocate_io_channel(struct spdk_scsi_desc *desc);
|
||||
*/
|
||||
void spdk_scsi_lun_free_io_channel(struct spdk_scsi_desc *desc);
|
||||
|
||||
/**
|
||||
* Get DIF context for SCSI LUN and SCSI command.
|
||||
*
|
||||
* \param lun Logical unit.
|
||||
* \param cdb SCSI CDB.
|
||||
* \param offset Offset in the payload.
|
||||
* \param dif_ctx Output parameter which will contain initialized DIF context.
|
||||
*
|
||||
* \return true on success or false otherwise.
|
||||
*/
|
||||
bool spdk_scsi_lun_get_dif_ctx(struct spdk_scsi_lun *lun, uint8_t *cdb, uint32_t offset,
|
||||
struct spdk_dif_ctx *dif_ctx);
|
||||
|
||||
/**
|
||||
* Set iSCSI Initiator port TransportID
|
||||
|
@ -494,3 +494,10 @@ spdk_scsi_lun_is_removing(const struct spdk_scsi_lun *lun)
|
||||
{
|
||||
return lun->removed;
|
||||
}
|
||||
|
||||
bool
|
||||
spdk_scsi_lun_get_dif_ctx(struct spdk_scsi_lun *lun, uint8_t *cdb,
|
||||
uint32_t offset, struct spdk_dif_ctx *dif_ctx)
|
||||
{
|
||||
return spdk_scsi_bdev_get_dif_ctx(lun->bdev, cdb, offset, dif_ctx);
|
||||
}
|
||||
|
@ -2093,3 +2093,58 @@ spdk_bdev_scsi_reset(struct spdk_scsi_task *task)
|
||||
spdk_bdev_scsi_queue_io(task, spdk_bdev_scsi_reset_resubmit, task);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
spdk_scsi_bdev_get_dif_ctx(struct spdk_bdev *bdev, uint8_t *cdb, uint32_t offset,
|
||||
struct spdk_dif_ctx *dif_ctx)
|
||||
{
|
||||
uint32_t ref_tag = 0, dif_check_flags = 0;
|
||||
int rc;
|
||||
|
||||
if (spdk_likely(spdk_bdev_get_md_size(bdev) == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* We use lower 32 bits of LBA as Reference. Tag */
|
||||
switch (cdb[0]) {
|
||||
case SPDK_SBC_READ_6:
|
||||
case SPDK_SBC_WRITE_6:
|
||||
ref_tag = (uint32_t)cdb[1] << 16;
|
||||
ref_tag |= (uint32_t)cdb[2] << 8;
|
||||
ref_tag |= (uint32_t)cdb[3];
|
||||
break;
|
||||
case SPDK_SBC_READ_10:
|
||||
case SPDK_SBC_WRITE_10:
|
||||
case SPDK_SBC_READ_12:
|
||||
case SPDK_SBC_WRITE_12:
|
||||
ref_tag = from_be32(&cdb[2]);
|
||||
break;
|
||||
case SPDK_SBC_READ_16:
|
||||
case SPDK_SBC_WRITE_16:
|
||||
ref_tag = (uint32_t)from_be64(&cdb[2]);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
ref_tag += offset / spdk_bdev_get_data_block_size(bdev);
|
||||
|
||||
if (spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_REFTAG)) {
|
||||
dif_check_flags |= SPDK_DIF_FLAGS_REFTAG_CHECK;
|
||||
}
|
||||
|
||||
if (spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_GUARD)) {
|
||||
dif_check_flags |= SPDK_DIF_FLAGS_GUARD_CHECK;
|
||||
}
|
||||
|
||||
rc = spdk_dif_ctx_init(dif_ctx,
|
||||
spdk_bdev_get_block_size(bdev),
|
||||
spdk_bdev_get_md_size(bdev),
|
||||
spdk_bdev_is_md_interleaved(bdev),
|
||||
spdk_bdev_is_dif_head_of_md(bdev),
|
||||
spdk_bdev_get_dif_type(bdev),
|
||||
dif_check_flags,
|
||||
ref_tag, 0, 0, 0);
|
||||
|
||||
return (rc == 0) ? true : false;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "spdk/scsi.h"
|
||||
#include "spdk/scsi_spec.h"
|
||||
#include "spdk/trace.h"
|
||||
#include "spdk/dif.h"
|
||||
|
||||
#include "spdk_internal/log.h"
|
||||
|
||||
@ -168,6 +169,9 @@ void spdk_scsi_port_destruct(struct spdk_scsi_port *port);
|
||||
int spdk_bdev_scsi_execute(struct spdk_scsi_task *task);
|
||||
void spdk_bdev_scsi_reset(struct spdk_scsi_task *task);
|
||||
|
||||
bool spdk_scsi_bdev_get_dif_ctx(struct spdk_bdev *bdev, uint8_t *cdb, uint32_t offset,
|
||||
struct spdk_dif_ctx *dif_ctx);
|
||||
|
||||
struct spdk_scsi_globals {
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
@ -72,6 +72,12 @@ DEFINE_STUB(spdk_bdev_get_name, const char *,
|
||||
DEFINE_STUB(spdk_bdev_get_block_size, uint32_t,
|
||||
(const struct spdk_bdev *bdev), 512);
|
||||
|
||||
DEFINE_STUB(spdk_bdev_get_md_size, uint32_t,
|
||||
(const struct spdk_bdev *bdev), 8);
|
||||
|
||||
DEFINE_STUB(spdk_bdev_is_md_interleaved, bool,
|
||||
(const struct spdk_bdev *bdev), false);
|
||||
|
||||
DEFINE_STUB(spdk_bdev_get_data_block_size, uint32_t,
|
||||
(const struct spdk_bdev *bdev), 512);
|
||||
|
||||
@ -87,6 +93,15 @@ DEFINE_STUB(spdk_bdev_get_product_name, const char *,
|
||||
DEFINE_STUB(spdk_bdev_has_write_cache, bool,
|
||||
(const struct spdk_bdev *bdev), false);
|
||||
|
||||
DEFINE_STUB(spdk_bdev_get_dif_type, enum spdk_dif_type,
|
||||
(const struct spdk_bdev *bdev), SPDK_DIF_DISABLE);
|
||||
|
||||
DEFINE_STUB(spdk_bdev_is_dif_head_of_md, bool,
|
||||
(const struct spdk_bdev *bdev), false);
|
||||
|
||||
DEFINE_STUB(spdk_bdev_is_dif_check_enabled, bool,
|
||||
(const struct spdk_bdev *bdev, enum spdk_dif_check_type check_type), false);
|
||||
|
||||
void
|
||||
spdk_scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
|
||||
{
|
||||
@ -245,6 +260,16 @@ spdk_bdev_queue_io_wait(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_size,
|
||||
bool md_interleave, 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,
|
||||
uint16_t guard_seed)
|
||||
{
|
||||
ctx->init_ref_tag = init_ref_tag;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This test specifically tests a mode select 6 command from the
|
||||
* Windows SCSI compliance test that caused SPDK to crash.
|
||||
@ -929,6 +954,42 @@ xfer_test(void)
|
||||
_xfer_test(true);
|
||||
}
|
||||
|
||||
static void
|
||||
get_dif_ctx_test(void)
|
||||
{
|
||||
struct spdk_bdev bdev = {};
|
||||
struct spdk_dif_ctx dif_ctx = {};
|
||||
uint8_t cdb[16];
|
||||
uint32_t offset;
|
||||
bool ret;
|
||||
|
||||
cdb[0] = SPDK_SBC_READ_6;
|
||||
cdb[1] = 0x12;
|
||||
cdb[2] = 0x34;
|
||||
cdb[3] = 0x50;
|
||||
offset = 0x6 * 512;
|
||||
|
||||
ret = spdk_scsi_bdev_get_dif_ctx(&bdev, cdb, offset, &dif_ctx);
|
||||
CU_ASSERT(ret == true);
|
||||
CU_ASSERT(dif_ctx.init_ref_tag == 0x123456);
|
||||
|
||||
cdb[0] = SPDK_SBC_WRITE_12;
|
||||
to_be32(&cdb[2], 0x12345670);
|
||||
offset = 0x8 * 512;
|
||||
|
||||
ret = spdk_scsi_bdev_get_dif_ctx(&bdev, cdb, offset, &dif_ctx);
|
||||
CU_ASSERT(ret == true);
|
||||
CU_ASSERT(dif_ctx.init_ref_tag == 0x12345678);
|
||||
|
||||
cdb[0] = SPDK_SBC_WRITE_16;
|
||||
to_be64(&cdb[2], 0x0000000012345670);
|
||||
offset = 0x8 * 512;
|
||||
|
||||
ret = spdk_scsi_bdev_get_dif_ctx(&bdev, cdb, offset, &dif_ctx);
|
||||
CU_ASSERT(ret == true);
|
||||
CU_ASSERT(dif_ctx.init_ref_tag == 0x12345678);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -961,6 +1022,7 @@ main(int argc, char **argv)
|
||||
|| CU_add_test(suite, "transfer length test", xfer_len_test) == NULL
|
||||
|| CU_add_test(suite, "transfer test", xfer_test) == NULL
|
||||
|| CU_add_test(suite, "scsi name padding test", scsi_name_padding_test) == NULL
|
||||
|| CU_add_test(suite, "get dif context test", get_dif_ctx_test) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
|
Loading…
Reference in New Issue
Block a user