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

scsi: add persistent reservation out with release service action support



An application client releases the persistent reservation by issuing a
PERSISTENT RESERVE OUT command with RELEASE service action through an
I_T nexus that is a persistent reservation holder.  The RELEASE service
action will release the persistent reservation and do noting to
existing registrants.  Unit Attention isn't supported by SPDK so here
we will not establish any unit attention condition.

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


Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 601fbbf9
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
@@ -293,6 +293,54 @@ error_exit:
	return -EINVAL;
}

static int
spdk_scsi_pr_out_release(struct spdk_scsi_task *task,
			 enum spdk_scsi_pr_type_code rtype, uint64_t rkey)
{
	struct spdk_scsi_lun *lun = task->lun;
	struct spdk_scsi_pr_registrant *reg;
	int sk, asc;

	SPDK_DEBUGLOG(SPDK_LOG_SCSI, "PR OUT RELEASE: rkey 0x%"PRIx64", "
		      "reservation type %u\n", rkey, rtype);

	reg = spdk_scsi_pr_get_registrant(lun, task->initiator_port, task->target_port);
	if (!reg) {
		SPDK_ERRLOG("No registration\n");
		sk = SPDK_SCSI_SENSE_NOT_READY;
		asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
		goto check_condition;
	}

	/* no reservation holder */
	if (!lun->reservation.holder) {
		SPDK_DEBUGLOG(SPDK_LOG_SCSI, "RELEASE: no reservation holder\n");
		return 0;
	}

	if (lun->reservation.rtype != rtype || rkey != lun->reservation.crkey) {
		sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
		asc = SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB;
		goto check_condition;
	}

	/* I_T nexus is not a persistent reservation holder */
	if (!spdk_scsi_pr_registrant_is_holder(lun, reg)) {
		SPDK_DEBUGLOG(SPDK_LOG_SCSI, "RELEASE: current I_T nexus is not holder\n");
		return 0;
	}

	spdk_scsi_pr_release_reservation(lun, reg);

	return 0;

check_condition:
	spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, sk, asc,
				  SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
	return -EINVAL;
}


int
spdk_scsi_pr_out(struct spdk_scsi_task *task,
		 uint8_t *cdb, uint8_t *data,
@@ -329,6 +377,12 @@ spdk_scsi_pr_out(struct spdk_scsi_task *task,
		rc = spdk_scsi_pr_out_reserve(task, rtype, rkey,
					      spec_i_pt, all_tg_pt, aptpl);
		break;
	case SPDK_SCSI_PR_OUT_RELEASE:
		if (scope != SPDK_SCSI_PR_LU_SCOPE) {
			goto invalid;
		}
		rc = spdk_scsi_pr_out_release(task, rtype, rkey);
		break;
	default:
		SPDK_ERRLOG("Invalid service action code %u\n", action);
		goto invalid;