From 8d79b4109f931aba25f188aa47b8945f49c79ce5 Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Tue, 14 May 2019 01:16:23 -0400 Subject: [PATCH] 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: Changpeng Liu Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/436091 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Jim Harris --- lib/scsi/scsi_pr.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/lib/scsi/scsi_pr.c b/lib/scsi/scsi_pr.c index 937ae49b5..d927c5ca4 100644 --- a/lib/scsi/scsi_pr.c +++ b/lib/scsi/scsi_pr.c @@ -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;