From 4e9e220e7c74f8e69c428f13485d198ea5428220 Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Tue, 14 May 2019 01:34:34 -0400 Subject: [PATCH] scsi: add persistent reservation in command with read keys action support Change-Id: Ia8e4ad31e84a1a97c83d4f49680bb7090ee4e041 Signed-off-by: Changpeng Liu Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/436093 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Jim Harris --- lib/scsi/scsi_bdev.c | 8 +++ lib/scsi/scsi_internal.h | 1 + lib/scsi/scsi_pr.c | 56 +++++++++++++++++++ test/unit/lib/scsi/scsi_bdev.c/scsi_bdev_ut.c | 3 + 4 files changed, 68 insertions(+) diff --git a/lib/scsi/scsi_bdev.c b/lib/scsi/scsi_bdev.c index 974127d76..90b401b6f 100644 --- a/lib/scsi/scsi_bdev.c +++ b/lib/scsi/scsi_bdev.c @@ -2043,6 +2043,14 @@ bdev_scsi_process_primary(struct spdk_scsi_task *task) data_len = 0; break; + case SPDK_SPC_PERSISTENT_RESERVE_IN: + alloc_len = from_be16(&cdb[7]); + data_len = alloc_len; + data = calloc(1, data_len); + assert(data != NULL); + rc = spdk_scsi_pr_in(task, cdb, data, data_len); + break; + default: return SPDK_SCSI_TASK_UNKNOWN; } diff --git a/lib/scsi/scsi_internal.h b/lib/scsi/scsi_internal.h index f558e6bfa..789e74381 100644 --- a/lib/scsi/scsi_internal.h +++ b/lib/scsi/scsi_internal.h @@ -202,6 +202,7 @@ bool spdk_scsi_bdev_get_dif_ctx(struct spdk_bdev *bdev, uint8_t *cdb, uint32_t o struct spdk_dif_ctx *dif_ctx); int spdk_scsi_pr_out(struct spdk_scsi_task *task, uint8_t *cdb, uint8_t *data, uint16_t data_len); +int spdk_scsi_pr_in(struct spdk_scsi_task *task, uint8_t *cdb, uint8_t *data, uint16_t data_len); struct spdk_scsi_globals { pthread_mutex_t mutex; diff --git a/lib/scsi/scsi_pr.c b/lib/scsi/scsi_pr.c index 820ae4a1e..d49572995 100644 --- a/lib/scsi/scsi_pr.c +++ b/lib/scsi/scsi_pr.c @@ -560,3 +560,59 @@ invalid: SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); return -EINVAL; } + +static int +spdk_scsi_pr_in_read_keys(struct spdk_scsi_task *task, uint8_t *data, + uint16_t data_len) +{ + struct spdk_scsi_lun *lun = task->lun; + struct spdk_scsi_pr_in_read_keys_data *keys; + struct spdk_scsi_pr_registrant *reg, *tmp; + uint16_t count = 0; + + SPDK_DEBUGLOG(SPDK_LOG_SCSI, "PR IN READ KEYS\n"); + keys = (struct spdk_scsi_pr_in_read_keys_data *)data; + + to_be32(&keys->header.pr_generation, lun->pr_generation); + TAILQ_FOREACH_SAFE(reg, &lun->reg_head, link, tmp) { + if (((count + 1) * 8 + sizeof(keys->header)) > data_len) { + break; + } + to_be64(&keys->rkeys[count], reg->rkey); + count++; + } + to_be32(&keys->header.addiontal_len, count * 8); + + return (sizeof(keys->header) + count * 8); +} + +int +spdk_scsi_pr_in(struct spdk_scsi_task *task, + uint8_t *cdb, uint8_t *data, + uint16_t data_len) +{ + enum spdk_scsi_pr_in_action_code action; + int rc = 0; + + action = cdb[1] & 0x1f; + if (data_len < sizeof(struct spdk_scsi_pr_in_read_header)) { + goto invalid; + } + + switch (action) { + case SPDK_SCSI_PR_IN_READ_KEYS: + rc = spdk_scsi_pr_in_read_keys(task, data, data_len); + break; + default: + goto invalid; + } + + return rc; + +invalid: + spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, + SPDK_SCSI_SENSE_ILLEGAL_REQUEST, + SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB, + SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); + return -EINVAL; +} diff --git a/test/unit/lib/scsi/scsi_bdev.c/scsi_bdev_ut.c b/test/unit/lib/scsi/scsi_bdev.c/scsi_bdev_ut.c index 14812b6d0..70b229ffc 100644 --- a/test/unit/lib/scsi/scsi_bdev.c/scsi_bdev_ut.c +++ b/test/unit/lib/scsi/scsi_bdev.c/scsi_bdev_ut.c @@ -105,6 +105,9 @@ DEFINE_STUB(spdk_bdev_is_dif_check_enabled, bool, DEFINE_STUB(spdk_scsi_pr_out, int, (struct spdk_scsi_task *task, uint8_t *cdb, uint8_t *data, uint16_t data_len), 0); +DEFINE_STUB(spdk_scsi_pr_in, int, (struct spdk_scsi_task *task, uint8_t *cdb, + uint8_t *data, uint16_t data_len), 0); + void spdk_scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task) {