mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-25 02:09:42 +00:00
nvmet: implement namespace identify descriptor list
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 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. Also as the Namespace Identify Descriptor list is the only mandatory feature change between 1.2.1 and 1.3 we can bump the advertised version as well. Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de> Reviewed-by: Hannes Reinecke <hare@suse.com> Reviewed-by: Max Gurtovoy <maxg@mellanox.com> Reviewed-by: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
d934f9848a
commit
637dc0f38a
3 changed files with 64 additions and 1 deletions
|
@ -367,6 +367,64 @@ static void nvmet_execute_identify_nslist(struct nvmet_req *req)
|
|||
nvmet_req_complete(req, status);
|
||||
}
|
||||
|
||||
static u16 nvmet_copy_ns_identifier(struct nvmet_req *req, u8 type, u8 len,
|
||||
void *id, off_t *off)
|
||||
{
|
||||
struct nvme_ns_id_desc desc = {
|
||||
.nidt = type,
|
||||
.nidl = len,
|
||||
};
|
||||
u16 status;
|
||||
|
||||
status = nvmet_copy_to_sgl(req, *off, &desc, sizeof(desc));
|
||||
if (status)
|
||||
return status;
|
||||
*off += sizeof(desc);
|
||||
|
||||
status = nvmet_copy_to_sgl(req, *off, id, len);
|
||||
if (status)
|
||||
return status;
|
||||
*off += len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nvmet_execute_identify_desclist(struct nvmet_req *req)
|
||||
{
|
||||
struct nvmet_ns *ns;
|
||||
u16 status = 0;
|
||||
off_t off = 0;
|
||||
|
||||
ns = nvmet_find_namespace(req->sq->ctrl, req->cmd->identify.nsid);
|
||||
if (!ns) {
|
||||
status = NVME_SC_INVALID_NS | NVME_SC_DNR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memchr_inv(&ns->uuid, 0, sizeof(ns->uuid))) {
|
||||
status = nvmet_copy_ns_identifier(req, NVME_NIDT_UUID,
|
||||
NVME_NIDT_UUID_LEN,
|
||||
&ns->uuid, &off);
|
||||
if (status)
|
||||
goto out_put_ns;
|
||||
}
|
||||
if (memchr_inv(ns->nguid, 0, sizeof(ns->nguid))) {
|
||||
status = nvmet_copy_ns_identifier(req, NVME_NIDT_NGUID,
|
||||
NVME_NIDT_NGUID_LEN,
|
||||
&ns->nguid, &off);
|
||||
if (status)
|
||||
goto out_put_ns;
|
||||
}
|
||||
|
||||
if (sg_zero_buffer(req->sg, req->sg_cnt, NVME_IDENTIFY_DATA_SIZE - off,
|
||||
off) != NVME_IDENTIFY_DATA_SIZE - off)
|
||||
status = NVME_SC_INTERNAL | NVME_SC_DNR;
|
||||
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
|
||||
|
@ -515,6 +573,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:
|
||||
|
|
|
@ -380,6 +380,7 @@ struct nvmet_ns *nvmet_ns_alloc(struct nvmet_subsys *subsys, u32 nsid)
|
|||
|
||||
ns->nsid = nsid;
|
||||
ns->subsys = subsys;
|
||||
uuid_gen(&ns->uuid);
|
||||
|
||||
return ns;
|
||||
}
|
||||
|
@ -926,7 +927,7 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
|
|||
if (!subsys)
|
||||
return NULL;
|
||||
|
||||
subsys->ver = NVME_VS(1, 2, 1); /* NVMe 1.2.1 */
|
||||
subsys->ver = NVME_VS(1, 3, 0); /* NVMe 1.3.0 */
|
||||
|
||||
switch (type) {
|
||||
case NVME_NQN_NVME:
|
||||
|
|
|
@ -47,6 +47,7 @@ struct nvmet_ns {
|
|||
u32 blksize_shift;
|
||||
loff_t size;
|
||||
u8 nguid[16];
|
||||
uuid_t uuid;
|
||||
|
||||
bool enabled;
|
||||
struct nvmet_subsys *subsys;
|
||||
|
|
Loading…
Reference in a new issue