/*- * BSD LICENSE * * Copyright (c) Hewlett Packard Enterprise Development LP * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * This is an example handler for modifying parts of the NVMF identify * ctlr response based on the underlying NVMe device. */ #include "spdk/stdinc.h" #include "spdk/bdev.h" #include "spdk_internal/nvmf.h" #include "spdk_internal/log.h" static void fixup_identify_ctrlr(struct spdk_nvmf_request *req) { uint32_t length; int rc; struct spdk_nvme_ctrlr_data *nvme_cdata; struct spdk_nvme_ctrlr_data nvmf_cdata = {}; struct spdk_nvmf_ctrlr *ctrlr = spdk_nvmf_request_get_ctrlr(req); struct spdk_nvme_cpl *rsp = spdk_nvmf_request_get_response(req); /* This is the identify data from the NVMe drive */ spdk_nvmf_request_get_data(req, (void **)&nvme_cdata, &length); /* Get the NVMF identify data */ rc = spdk_nvmf_ctrlr_identify_ctrlr(ctrlr, &nvmf_cdata); if (rc != SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE) { rsp->status.sct = SPDK_NVME_SCT_GENERIC; rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; return; } /* Fixup NVMF identify data with NVMe identify data */ /* Serial Number (SN) */ memcpy(&nvmf_cdata.sn[0], &nvme_cdata->sn[0], sizeof(nvmf_cdata.sn)); /* Model Number (MN) */ memcpy(&nvmf_cdata.mn[0], &nvme_cdata->mn[0], sizeof(nvmf_cdata.mn)); /* Firmware Revision (FR) */ memcpy(&nvmf_cdata.fr[0], &nvme_cdata->fr[0], sizeof(nvmf_cdata.fr)); /* IEEE OUI Identifier (IEEE) */ memcpy(&nvmf_cdata.ieee[0], &nvme_cdata->ieee[0], sizeof(nvmf_cdata.ieee)); /* FRU Globally Unique Identifier (FGUID) */ /* Copy the fixed up data back to the response */ memcpy(nvme_cdata, &nvmf_cdata, length); } int spdk_nvmf_custom_identify_hdlr(struct spdk_nvmf_request *req) { struct spdk_nvme_cmd *cmd = spdk_nvmf_request_get_cmd(req); struct spdk_bdev *bdev; struct spdk_bdev_desc *desc; struct spdk_io_channel *ch; struct spdk_nvmf_subsystem *subsys; int rc; if (cmd->cdw10_bits.identify.cns != SPDK_NVME_IDENTIFY_CTRLR) { return -1; /* continue */ } subsys = spdk_nvmf_request_get_subsystem(req); if (subsys == NULL) { return -1; } /* Only procss this request if it has exactly one namespace */ if (spdk_nvmf_subsystem_get_max_nsid(subsys) != 1) { return -1; } /* Forward to first namespace if it supports NVME admin commands */ rc = spdk_nvmf_request_get_bdev(1, req, &bdev, &desc, &ch); if (rc) { /* No bdev found for this namespace. Continue. */ return -1; } if (!spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_NVME_ADMIN)) { return -1; } return spdk_nvmf_bdev_ctrlr_nvme_passthru_admin(bdev, desc, ch, req, fixup_identify_ctrlr); }