Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nvme: read the subsystem NQN from Identify Controller

NVMe 1.2.1 or later requires controllers to provide a subsystem NQN in the
Identify controller data structures. Use this NQN for the subsysnqn
sysfs attribute by storing it in the nvme_ctrl structure after verifying
it. For older controllers we generate a "fake" NQN per non-normative
text in the NVMe 1.3 spec.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Keith Busch <keith.busch@intel.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Christoph Hellwig and committed by
Jens Axboe
180de007 942fbab4

+29 -18
+28 -3
drivers/nvme/host/core.c
··· 1705 1705 string_matches(id->fr, q->fr, sizeof(id->fr)); 1706 1706 } 1707 1707 1708 + static void nvme_init_subnqn(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) 1709 + { 1710 + size_t nqnlen; 1711 + int off; 1712 + 1713 + nqnlen = strnlen(id->subnqn, NVMF_NQN_SIZE); 1714 + if (nqnlen > 0 && nqnlen < NVMF_NQN_SIZE) { 1715 + strcpy(ctrl->subnqn, id->subnqn); 1716 + return; 1717 + } 1718 + 1719 + if (ctrl->vs >= NVME_VS(1, 2, 1)) 1720 + dev_warn(ctrl->device, "missing or invalid SUBNQN field.\n"); 1721 + 1722 + /* Generate a "fake" NQN per Figure 254 in NVMe 1.3 + ECN 001 */ 1723 + off = snprintf(ctrl->subnqn, NVMF_NQN_SIZE, 1724 + "nqn.2014.08.org.nvmexpress:%4x%4x", 1725 + le16_to_cpu(id->vid), le16_to_cpu(id->ssvid)); 1726 + memcpy(ctrl->subnqn + off, id->sn, sizeof(id->sn)); 1727 + off += sizeof(id->sn); 1728 + memcpy(ctrl->subnqn + off, id->mn, sizeof(id->mn)); 1729 + off += sizeof(id->mn); 1730 + memset(ctrl->subnqn + off, 0, sizeof(ctrl->subnqn) - off); 1731 + } 1732 + 1708 1733 /* 1709 1734 * Initialize the cached copies of the Identify data and various controller 1710 1735 * register in our nvme_ctrl structure. This should be called as soon as ··· 1764 1739 dev_err(ctrl->device, "Identify Controller failed (%d)\n", ret); 1765 1740 return -EIO; 1766 1741 } 1742 + 1743 + nvme_init_subnqn(ctrl, id); 1767 1744 1768 1745 if (!ctrl->identified) { 1769 1746 /* ··· 2162 2135 { 2163 2136 struct nvme_ctrl *ctrl = dev_get_drvdata(dev); 2164 2137 2165 - return snprintf(buf, PAGE_SIZE, "%s\n", 2166 - ctrl->ops->get_subsysnqn(ctrl)); 2138 + return snprintf(buf, PAGE_SIZE, "%s\n", ctrl->subnqn); 2167 2139 } 2168 2140 static DEVICE_ATTR(subsysnqn, S_IRUGO, nvme_sysfs_show_subsysnqn, NULL); 2169 2141 ··· 2207 2181 return 0; 2208 2182 } 2209 2183 2210 - CHECK_ATTR(ctrl, a, subsysnqn); 2211 2184 CHECK_ATTR(ctrl, a, address); 2212 2185 2213 2186 return a->mode;
-10
drivers/nvme/host/fabrics.c
··· 126 126 EXPORT_SYMBOL_GPL(nvmf_get_address); 127 127 128 128 /** 129 - * nvmf_get_subsysnqn() - Get subsystem NQN 130 - * @ctrl: Host NVMe controller instance which we got the NQN 131 - */ 132 - const char *nvmf_get_subsysnqn(struct nvme_ctrl *ctrl) 133 - { 134 - return ctrl->opts->subsysnqn; 135 - } 136 - EXPORT_SYMBOL_GPL(nvmf_get_subsysnqn); 137 - 138 - /** 139 129 * nvmf_reg_read32() - NVMe Fabrics "Property Get" API function. 140 130 * @ctrl: Host NVMe controller instance maintaining the admin 141 131 * queue used to submit the property read command to
-1
drivers/nvme/host/fabrics.h
··· 139 139 int nvmf_register_transport(struct nvmf_transport_ops *ops); 140 140 void nvmf_unregister_transport(struct nvmf_transport_ops *ops); 141 141 void nvmf_free_options(struct nvmf_ctrl_options *opts); 142 - const char *nvmf_get_subsysnqn(struct nvme_ctrl *ctrl); 143 142 int nvmf_get_address(struct nvme_ctrl *ctrl, char *buf, int size); 144 143 bool nvmf_should_reconnect(struct nvme_ctrl *ctrl); 145 144
-1
drivers/nvme/host/fc.c
··· 2631 2631 .free_ctrl = nvme_fc_nvme_ctrl_freed, 2632 2632 .submit_async_event = nvme_fc_submit_async_event, 2633 2633 .delete_ctrl = nvme_fc_del_nvme_ctrl, 2634 - .get_subsysnqn = nvmf_get_subsysnqn, 2635 2634 .get_address = nvmf_get_address, 2636 2635 }; 2637 2636
+1 -1
drivers/nvme/host/nvme.h
··· 138 138 char serial[20]; 139 139 char model[40]; 140 140 char firmware_rev[8]; 141 + char subnqn[NVMF_NQN_SIZE]; 141 142 u16 cntlid; 142 143 143 144 u32 ctrl_config; ··· 226 225 void (*free_ctrl)(struct nvme_ctrl *ctrl); 227 226 void (*submit_async_event)(struct nvme_ctrl *ctrl, int aer_idx); 228 227 int (*delete_ctrl)(struct nvme_ctrl *ctrl); 229 - const char *(*get_subsysnqn)(struct nvme_ctrl *ctrl); 230 228 int (*get_address)(struct nvme_ctrl *ctrl, char *buf, int size); 231 229 }; 232 230
-1
drivers/nvme/host/rdma.c
··· 1757 1757 .free_ctrl = nvme_rdma_free_ctrl, 1758 1758 .submit_async_event = nvme_rdma_submit_async_event, 1759 1759 .delete_ctrl = nvme_rdma_del_ctrl, 1760 - .get_subsysnqn = nvmf_get_subsysnqn, 1761 1760 .get_address = nvmf_get_address, 1762 1761 }; 1763 1762
-1
drivers/nvme/target/loop.c
··· 540 540 .free_ctrl = nvme_loop_free_ctrl, 541 541 .submit_async_event = nvme_loop_submit_async_event, 542 542 .delete_ctrl = nvme_loop_del_ctrl, 543 - .get_subsysnqn = nvmf_get_subsysnqn, 544 543 }; 545 544 546 545 static int nvme_loop_create_io_queues(struct nvme_loop_ctrl *ctrl)