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

scsi: add persistent reservation out command with clear service action support



Any application client can release the persistent reservation and remove all
registrations from a device server by issuing a PERSISTENT RESERVE OUT command
with CLEAR service action through a registered I_T nexus.

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


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 e8e791f7
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -340,6 +340,43 @@ check_condition:
	return -EINVAL;
}

static int
spdk_scsi_pr_out_clear(struct spdk_scsi_task *task, uint64_t rkey)
{
	struct spdk_scsi_lun *lun = task->lun;
	struct spdk_scsi_pr_registrant *reg, *tmp;
	int sc, sk, asc;

	SPDK_DEBUGLOG(SPDK_LOG_SCSI, "PR OUT CLEAR: rkey 0x%"PRIx64"\n", rkey);

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

	if (rkey != reg->rkey) {
		SPDK_ERRLOG("Reservation key 0x%"PRIx64" doesn't match "
			    "registrant's key 0x%"PRIx64"\n", rkey, reg->rkey);
		sc = SPDK_SCSI_STATUS_RESERVATION_CONFLICT;
		sk = SPDK_SCSI_SENSE_NO_SENSE;
		asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
		goto error_exit;
	}

	TAILQ_FOREACH_SAFE(reg, &lun->reg_head, link, tmp) {
		spdk_scsi_pr_unregister_registrant(lun, reg);
	}

	return 0;

error_exit:
	spdk_scsi_task_set_status(task, sc, sk, asc, SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
	return -EINVAL;
}

int
spdk_scsi_pr_out(struct spdk_scsi_task *task,
@@ -383,6 +420,9 @@ spdk_scsi_pr_out(struct spdk_scsi_task *task,
		}
		rc = spdk_scsi_pr_out_release(task, rtype, rkey);
		break;
	case SPDK_SCSI_PR_OUT_CLEAR:
		rc = spdk_scsi_pr_out_clear(task, rkey);
		break;
	default:
		SPDK_ERRLOG("Invalid service action code %u\n", action);
		goto invalid;