Commit 4e9e220e authored by Changpeng Liu's avatar Changpeng Liu Committed by Jim Harris
Browse files

scsi: add persistent reservation in command with read keys action support



Change-Id: Ia8e4ad31e84a1a97c83d4f49680bb7090ee4e041
Signed-off-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/436093


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent a6edaa96
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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;
	}
+1 −0
Original line number Diff line number Diff line
@@ -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;
+56 −0
Original line number Diff line number Diff line
@@ -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;
}
+3 −0
Original line number Diff line number Diff line
@@ -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)
{