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

Configure Feed

Select the types of activity you want to include in your feed.

nvmet: Implement host identifier set feature support

The NVMe specifications mandate support for the host identifier
set_features for controllers that also supports reservations. Satisfy
this requirement by implementing handling of the NVME_FEAT_HOST_ID
feature for the nvme_set_features command. This implementation is for
now effective only for PCI target controllers. For other controller
types, the set features command is failed with a NVME_SC_CMD_SEQ_ERROR
status as before.

As noted in the code, 128 bits host identifiers are supported since the
NVMe base specifications version 2.1 indicate in section 5.1.25.1.28.1
that "The controller may support a 64-bit Host Identifier...".

The RHII (Reservations and Host Identifier Interaction) bit of the
controller attribute (ctratt) field of the identify controller data is
also set to indicate that a host ID of "0" is supported but that the
host ID must be a non-zero value to use reservations.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Tested-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Keith Busch <kbusch@kernel.org>

authored by

Damien Le Moal and committed by
Keith Busch
2f2b20fa 08461535

+32 -4
+31 -4
drivers/nvme/target/admin-cmd.c
··· 659 659 struct nvmet_ctrl *ctrl = req->sq->ctrl; 660 660 struct nvmet_subsys *subsys = ctrl->subsys; 661 661 struct nvme_id_ctrl *id; 662 - u32 cmd_capsule_size; 662 + u32 cmd_capsule_size, ctratt; 663 663 u16 status = 0; 664 664 665 665 if (!subsys->subsys_discovered) { ··· 707 707 708 708 /* XXX: figure out what to do about RTD3R/RTD3 */ 709 709 id->oaes = cpu_to_le32(NVMET_AEN_CFG_OPTIONAL); 710 - id->ctratt = cpu_to_le32(NVME_CTRL_ATTR_HID_128_BIT | 711 - NVME_CTRL_ATTR_TBKAS); 710 + ctratt = NVME_CTRL_ATTR_HID_128_BIT | NVME_CTRL_ATTR_TBKAS; 711 + if (nvmet_is_pci_ctrl(ctrl)) 712 + ctratt |= NVME_CTRL_ATTR_RHII; 713 + id->ctratt = cpu_to_le32(ctratt); 712 714 713 715 id->oacs = 0; 714 716 ··· 1257 1255 return 0; 1258 1256 } 1259 1257 1258 + static u16 nvmet_set_feat_host_id(struct nvmet_req *req) 1259 + { 1260 + struct nvmet_ctrl *ctrl = req->sq->ctrl; 1261 + 1262 + if (!nvmet_is_pci_ctrl(ctrl)) 1263 + return NVME_SC_CMD_SEQ_ERROR | NVME_STATUS_DNR; 1264 + 1265 + /* 1266 + * The NVMe base specifications v2.1 recommends supporting 128-bits host 1267 + * IDs (section 5.1.25.1.28.1). However, that same section also says 1268 + * that "The controller may support a 64-bit Host Identifier and/or an 1269 + * extended 128-bit Host Identifier". So simplify this support and do 1270 + * not support 64-bits host IDs to avoid needing to check that all 1271 + * controllers associated with the same subsystem all use the same host 1272 + * ID size. 1273 + */ 1274 + if (!(req->cmd->common.cdw11 & cpu_to_le32(1 << 0))) { 1275 + req->error_loc = offsetof(struct nvme_common_command, cdw11); 1276 + return NVME_SC_INVALID_FIELD | NVME_STATUS_DNR; 1277 + } 1278 + 1279 + return nvmet_copy_from_sgl(req, 0, &req->sq->ctrl->hostid, 1280 + sizeof(req->sq->ctrl->hostid)); 1281 + } 1282 + 1260 1283 void nvmet_execute_set_features(struct nvmet_req *req) 1261 1284 { 1262 1285 struct nvmet_subsys *subsys = nvmet_req_subsys(req); ··· 1312 1285 status = nvmet_set_feat_async_event(req, NVMET_AEN_CFG_ALL); 1313 1286 break; 1314 1287 case NVME_FEAT_HOST_ID: 1315 - status = NVME_SC_CMD_SEQ_ERROR | NVME_STATUS_DNR; 1288 + status = nvmet_set_feat_host_id(req); 1316 1289 break; 1317 1290 case NVME_FEAT_WRITE_PROTECT: 1318 1291 status = nvmet_set_feat_write_protect(req);
+1
include/linux/nvme.h
··· 276 276 NVME_CTRL_ATTR_HID_128_BIT = (1 << 0), 277 277 NVME_CTRL_ATTR_TBKAS = (1 << 6), 278 278 NVME_CTRL_ATTR_ELBAS = (1 << 15), 279 + NVME_CTRL_ATTR_RHII = (1 << 18), 279 280 }; 280 281 281 282 struct nvme_id_ctrl {