From 43510e12923814ce65ef35209d6b09ffa281da8b Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Mon, 18 Jul 2016 10:52:09 -0700 Subject: [PATCH] nvmf: fail attempts to modify reserved bits in CC Track each individual bit in the Set Property handler for CC, and fail the request if any unhandled bits are modified. Also add handlers for IOSQES and IOCQES (I/O submission and completion queue entry size). Change-Id: I374dc3c15197e029ba07fd9ee1cff0e38a0a884d Signed-off-by: Daniel Verkamp --- lib/nvmf/session.c | 59 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/lib/nvmf/session.c b/lib/nvmf/session.c index ca8c3e7da..66de516a9 100644 --- a/lib/nvmf/session.c +++ b/lib/nvmf/session.c @@ -319,30 +319,69 @@ nvmf_prop_get_cc(struct nvmf_session *session) static bool nvmf_prop_set_cc(struct nvmf_session *session, uint64_t value) { - union spdk_nvme_cc_register cc; + union spdk_nvme_cc_register cc, diff; cc.raw = (uint32_t)value; - if (cc.bits.en ^ session->vcprop.cc.bits.en) { + SPDK_TRACELOG(SPDK_TRACE_NVMF, "cur CC: 0x%08x\n", session->vcprop.cc.raw); + SPDK_TRACELOG(SPDK_TRACE_NVMF, "new CC: 0x%08x\n", cc.raw); + + /* + * Calculate which bits changed between the current and new CC. + * Mark each bit as 0 once it is handled to determine if any unhandled bits were changed. + */ + diff.raw = cc.raw ^ session->vcprop.cc.raw; + + if (diff.bits.en) { if (cc.bits.en) { SPDK_TRACELOG(SPDK_TRACE_NVMF, "Property Set CC Enable!\n"); + session->vcprop.cc.bits.en = 1; session->vcprop.csts.bits.rdy = 1; } else { SPDK_ERRLOG("CC.EN transition from 1 to 0 (reset) not implemented!\n"); /* TODO: reset */ } + diff.bits.en = 0; } - if (cc.bits.shn == SPDK_NVME_SHN_NORMAL || - cc.bits.shn == SPDK_NVME_SHN_ABRUPT) { - SPDK_TRACELOG(SPDK_TRACE_NVMF, "Property Set CC Shutdown %u%ub!\n", - cc.bits.shn >> 1, cc.bits.shn & 1); - session->vcprop.cc.bits.en = 0; - session->vcprop.csts.bits.rdy = 0; - session->vcprop.csts.bits.shst = SPDK_NVME_SHST_COMPLETE; + if (diff.bits.shn) { + if (cc.bits.shn == SPDK_NVME_SHN_NORMAL || + cc.bits.shn == SPDK_NVME_SHN_ABRUPT) { + SPDK_TRACELOG(SPDK_TRACE_NVMF, "Property Set CC Shutdown %u%ub!\n", + cc.bits.shn >> 1, cc.bits.shn & 1); + session->vcprop.cc.bits.shn = cc.bits.shn; + session->vcprop.cc.bits.en = 0; + session->vcprop.csts.bits.rdy = 0; + session->vcprop.csts.bits.shst = SPDK_NVME_SHST_COMPLETE; + } else if (cc.bits.shn == 0) { + session->vcprop.cc.bits.shn = 0; + } else { + SPDK_ERRLOG("Prop Set CC: Invalid SHN value %u%ub\n", + cc.bits.shn >> 1, cc.bits.shn & 1); + return false; + } + diff.bits.shn = 0; + } + + if (diff.bits.iosqes) { + SPDK_TRACELOG(SPDK_TRACE_NVMF, "Prop Set IOSQES = %u (%u bytes)\n", + cc.bits.iosqes, 1u << cc.bits.iosqes); + session->vcprop.cc.bits.iosqes = cc.bits.iosqes; + diff.bits.iosqes = 0; + } + + if (diff.bits.iocqes) { + SPDK_TRACELOG(SPDK_TRACE_NVMF, "Prop Set IOCQES = %u (%u bytes)\n", + cc.bits.iocqes, 1u << cc.bits.iocqes); + session->vcprop.cc.bits.iocqes = cc.bits.iocqes; + diff.bits.iocqes = 0; + } + + if (diff.raw != 0) { + SPDK_ERRLOG("Prop Set CC toggled reserved bits 0x%x!\n", diff.raw); + return false; } - session->vcprop.cc.raw = cc.raw; return true; }