Commit beaab6a1 authored by Joel Cunningham's avatar Joel Cunningham Committed by Tomasz Zawadzki
Browse files

lib/nvmf: avoid aborting reservation commands



We don't have support to abort namespace persistent reservation
commands, so add handling to identify if the cid refers to a reservation
command and return early as not aborted before falling into the
transport level and bdev level abort logic.

Add unit test to coverage identifying a cid as a reservation command.

Change-Id: If929d87a65bce77fcb43924ec4ab9eba5e80acd1
Signed-off-by: default avatarJoel Cunningham <joel.cunningham@oracle.com>
Reviewed-on: https://review.spdk.io/c/spdk/spdk/+/26597


Reviewed-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
Tested-by: default avatarSPDK Automated Test System <spdkbot@gmail.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <jim.harris@nvidia.com>
Reviewed-by: default avatarChangpeng Liu <changpeliu@tencent.com>
parent bbbc1959
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -3644,6 +3644,31 @@ nvmf_qpair_abort_pending_zcopy_reqs(struct spdk_nvmf_qpair *qpair)
	}
}

static bool
nvmf_qpair_cid_is_reservation(const struct spdk_nvmf_qpair *qpair, uint16_t cid)
{
	struct spdk_nvmf_request *req;
	struct spdk_nvme_cmd *cmd;

	TAILQ_FOREACH(req, &qpair->outstanding, link) {
		cmd = &req->cmd->nvme_cmd;

		if (cmd->cid != cid) {
			continue;
		}
		switch (cmd->opc) {
		case SPDK_NVME_OPC_RESERVATION_REGISTER:
		case SPDK_NVME_OPC_RESERVATION_ACQUIRE:
		case SPDK_NVME_OPC_RESERVATION_RELEASE:
		case SPDK_NVME_OPC_RESERVATION_REPORT:
			return true;
		default:
			return false;
		}
	}
	return false;
}

static void
nvmf_qpair_abort_request(struct spdk_nvmf_qpair *qpair, struct spdk_nvmf_request *req)
{
@@ -3657,6 +3682,13 @@ nvmf_qpair_abort_request(struct spdk_nvmf_qpair *qpair, struct spdk_nvmf_request
		spdk_nvmf_request_complete(req);
		return;
	}
	if (nvmf_qpair_cid_is_reservation(qpair, cid)) {
		/* We don't support aborting reservation requests, leave completion as not-aborted */
		SPDK_DEBUGLOG(nvmf, "abort ctrlr=%p sqid=%u cid=%u for reservation not supported\n",
			      qpair->ctrlr, qpair->qid, cid);
		spdk_nvmf_request_complete(req);
		return;
	}

	nvmf_transport_qpair_abort_request(qpair, req);
}
+47 −0
Original line number Diff line number Diff line
@@ -3640,6 +3640,52 @@ test_nvmf_check_qpair_active(void)
	}
}

static void
test_nvmf_qpair_cid_is_reservation(void)
{
	struct spdk_nvmf_qpair qpair = { .outstanding = TAILQ_HEAD_INITIALIZER(qpair.outstanding) };
	enum {
		NUM_REQS_READS = 2,
		NUM_REQS_RESERVATIONS = 4,
		TOTAL_REQS = NUM_REQS_READS + NUM_REQS_RESERVATIONS,
	};
	struct spdk_nvmf_request reqs[TOTAL_REQS] = {};
	union nvmf_h2c_msg cmd[TOTAL_REQS] = {};
	enum spdk_nvme_nvm_opcode reservation_ops[NUM_REQS_RESERVATIONS] = {
		SPDK_NVME_OPC_RESERVATION_REGISTER,
		SPDK_NVME_OPC_RESERVATION_REPORT,
		SPDK_NVME_OPC_RESERVATION_ACQUIRE,
		SPDK_NVME_OPC_RESERVATION_RELEASE
	};
	size_t i;
	for (i = 0; i < NUM_REQS_READS; i++) {
		cmd[i].nvme_cmd.opc = SPDK_NVME_OPC_READ;
		cmd[i].nvme_cmd.cid = i;

		reqs[i].qpair = &qpair;
		reqs[i].cmd = &cmd[i];
		TAILQ_INSERT_TAIL(&qpair.outstanding, &reqs[i], link);
	}
	for (; i < TOTAL_REQS; i++) {
		cmd[i].nvme_cmd.opc = reservation_ops[i - NUM_REQS_READS];
		cmd[i].nvme_cmd.cid = i;

		reqs[i].qpair = &qpair;
		reqs[i].cmd = &cmd[i];
		TAILQ_INSERT_TAIL(&qpair.outstanding, &reqs[i], link);
	}
	/* None of the reads should be considered reservation */
	for (i = 0; i < NUM_REQS_READS; i++) {
		SPDK_CU_ASSERT_FATAL(nvmf_qpair_cid_is_reservation(&qpair, i) == false);
	}
	/* Validate each reservation type is flagged */
	for (; i < TOTAL_REQS; i++) {
		SPDK_CU_ASSERT_FATAL(nvmf_qpair_cid_is_reservation(&qpair, i) == true);
	}
	/* Non-existent cid */
	SPDK_CU_ASSERT_FATAL(nvmf_qpair_cid_is_reservation(&qpair, i * 2) == false);
}

int
main(int argc, char **argv)
{
@@ -3682,6 +3728,7 @@ main(int argc, char **argv)
	CU_ADD_TEST(suite, test_nvmf_ctrlr_set_features_host_behavior_support);
	CU_ADD_TEST(suite, test_nvmf_ctrlr_ns_attachment);
	CU_ADD_TEST(suite, test_nvmf_check_qpair_active);
	CU_ADD_TEST(suite, test_nvmf_qpair_cid_is_reservation);

	allocate_threads(1);
	set_thread(0);