[PATCH 5/7] nvmet: implement namespace identify descriptor list
Max Gurtovoy
maxg at mellanox.com
Tue May 30 04:04:00 PDT 2017
Hi Johannes,
On 5/30/2017 11:08 AM, Johannes Thumshirn wrote:
> A NVMe Identify NS command with a CNS value of '3' is expecting a list
> of Namespace Identification Descriptor structures to be returned to
> the host for the namespace requested in the namespace identify
> command.
>
> This Namespace Identification Descriptor structure consists of the
> type of the namespace identifier, the length of the identifier and the
> actual identifier.
>
> Valid types are EUI-64, NGUID and UUID which we have saved in our
> nvme_ns structure if they have been configured via configfs. If no
> value has been assigened to one of these we return an "invalid opcode"
> back to the host to maintain backward compatibiliy with older
> implementations without Namespace Identify Descriptor list support.
>
> Signed-off-by: Johannes Thumshirn <jthumshirn at suse.de>
> ---
> drivers/nvme/target/admin-cmd.c | 75 +++++++++++++++++++++++++++++++++++++++++
> include/linux/nvme.h | 14 ++++++++
> 2 files changed, 89 insertions(+)
>
> diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
> index 60c9eec57986..2290301a6172 100644
> --- a/drivers/nvme/target/admin-cmd.c
> +++ b/drivers/nvme/target/admin-cmd.c
> @@ -368,6 +368,78 @@ static void nvmet_execute_identify_nslist(struct nvmet_req *req)
> nvmet_req_complete(req, status);
> }
>
> +static void nvmet_execute_identify_desclist(struct nvmet_req *req)
> +{
> + static const int buf_size = 4069;
Shouldn't it be 4096 ?
> + struct nvmet_ns *ns;
> + struct nvme_ns_nid *ns_nid;
> + u8 *nid_list;
> + u16 status = 0;
> + int pos = 0;
> + const u8 *p;
> +
> + ns = nvmet_find_namespace(req->sq->ctrl, req->cmd->identify.nsid);
> + if (!ns) {
> + status = NVME_SC_INVALID_NS | NVME_SC_DNR;
> + goto out;
> + }
> +
> + nid_list = kzalloc(buf_size, GFP_KERNEL);
> + if (!nid_list) {
> + status = NVME_SC_INTERNAL;
> + goto out_put_ns;
> + }
> +
> + p = nid_list;
> +
> + if (memchr_inv(ns->uuid, 0, sizeof(ns->uuid))) {
> + ns_nid = (struct nvme_ns_nid *)p;
> + ns_nid->nidt = NVME_NIDT_UUID;
> + ns_nid->nidl = 16;
maybe define NVME_NIDT_UUID_LEN instead of 16 ?
this way you can use it in the host side too.
> + memcpy(&ns_nid->nid, &ns->uuid, sizeof(ns->uuid));
> + pos += sizeof(struct nvme_ns_nid) + sizeof(ns->uuid);
> + if (pos > buf_size) {
> + status = NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
> + goto out_free_nid_list;
> + }
> + p += pos;
> + }
> + if (memchr_inv(ns->nguid, 0, sizeof(ns->nguid))) {
> + ns_nid = (struct nvme_ns_nid *)p;
> + ns_nid->nidt = NVME_NIDT_NGUID;
> + ns_nid->nidl = 16;
see above comment.
> + memcpy(&ns_nid->nid, &ns->nguid, sizeof(ns->nguid));
> + pos += sizeof(struct nvme_ns_nid) + sizeof(ns->nguid);
> + if (pos > buf_size) {
> + status = NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
> + goto out_free_nid_list;
> + }
> + p += pos;
> + }
> + if (memchr_inv(ns->eui64, 0, sizeof(ns->eui64))) {
> + ns_nid = (struct nvme_ns_nid *)p;
> + ns_nid->nidt = NVME_NIDT_EUI64;
> + ns_nid->nidl = 8;
see above.
> + memcpy(&ns_nid->nid, &ns->eui64, sizeof(ns->eui64));
> + pos += sizeof(struct nvme_ns_nid) + sizeof(ns->eui64);
> + if (pos > buf_size) {
> + status = NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
> + goto out_free_nid_list;
> + }
> + p += pos;
> + }
> +
> + status = nvmet_copy_to_sgl(req, 0, nid_list, buf_size);
> +
> +out_free_nid_list:
> + kfree(nid_list);
> +
> +out_put_ns:
> + nvmet_put_namespace(ns);
> +out:
> + nvmet_req_complete(req, status);
> +}
> +
> /*
> * A "mimimum viable" abort implementation: the command is mandatory in the
> * spec, but we are not required to do any useful work. We couldn't really
> @@ -516,6 +588,9 @@ u16 nvmet_parse_admin_cmd(struct nvmet_req *req)
> case NVME_ID_CNS_NS_ACTIVE_LIST:
> req->execute = nvmet_execute_identify_nslist;
> return 0;
> + case NVME_ID_CNS_NS_DESC_LIST:
> + req->execute = nvmet_execute_identify_desclist;
> + return 0;
> }
> break;
> case nvme_admin_abort_cmd:
> diff --git a/include/linux/nvme.h b/include/linux/nvme.h
> index b625bacf37ef..cad0e19f0bba 100644
> --- a/include/linux/nvme.h
> +++ b/include/linux/nvme.h
> @@ -288,6 +288,7 @@ enum {
> NVME_ID_CNS_NS = 0x00,
> NVME_ID_CNS_CTRL = 0x01,
> NVME_ID_CNS_NS_ACTIVE_LIST = 0x02,
> + NVME_ID_CNS_NS_DESC_LIST = 0x03,
> NVME_ID_CNS_NS_PRESENT_LIST = 0x10,
> NVME_ID_CNS_NS_PRESENT = 0x11,
> NVME_ID_CNS_CTRL_NS_LIST = 0x12,
> @@ -314,6 +315,19 @@ enum {
> NVME_NS_DPS_PI_TYPE3 = 3,
> };
>
> +struct nvme_ns_nid {
> + __u8 nidt;
> + __u8 nidl;
> + __le16 reserved;
> + __u8 nid[0];
> +};
> +
> +enum {
> + NVME_NIDT_EUI64 = 0x01,
> + NVME_NIDT_NGUID = 0x02,
> + NVME_NIDT_UUID = 0x03,
> +};
> +
> struct nvme_smart_log {
> __u8 critical_warning;
> __u8 temperature[2];
>
More information about the Linux-nvme
mailing list