Skip to content

Commit 34ad615

Browse files
alanpeteradChristoph Hellwig
authored andcommitted
nvmet: add a clear_ids attribute for passthru targets
If the clear_ids attribute is set to true, the EUI/GUID/UUID is cleared for the passthru target. By default, loop targets will set clear_ids to true. This resolves an issue where a connect to a passthru target fails when using a trtype of 'loop' because EUI/GUID/UUID is not unique. Fixes: 2079f41 ("nvme: check that EUI/GUID/UUID are globally unique") Signed-off-by: Alan Adamson <alan.adamson@oracle.com> Reviewed-by: Keith Busch <kbusch@kernel.org> Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
1 parent f7f70f4 commit 34ad615

File tree

4 files changed

+82
-0
lines changed

4 files changed

+82
-0
lines changed

drivers/nvme/target/configfs.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,11 +773,31 @@ static ssize_t nvmet_passthru_io_timeout_store(struct config_item *item,
773773
}
774774
CONFIGFS_ATTR(nvmet_passthru_, io_timeout);
775775

776+
static ssize_t nvmet_passthru_clear_ids_show(struct config_item *item,
777+
char *page)
778+
{
779+
return sprintf(page, "%u\n", to_subsys(item->ci_parent)->clear_ids);
780+
}
781+
782+
static ssize_t nvmet_passthru_clear_ids_store(struct config_item *item,
783+
const char *page, size_t count)
784+
{
785+
struct nvmet_subsys *subsys = to_subsys(item->ci_parent);
786+
unsigned int clear_ids;
787+
788+
if (kstrtouint(page, 0, &clear_ids))
789+
return -EINVAL;
790+
subsys->clear_ids = clear_ids;
791+
return count;
792+
}
793+
CONFIGFS_ATTR(nvmet_passthru_, clear_ids);
794+
776795
static struct configfs_attribute *nvmet_passthru_attrs[] = {
777796
&nvmet_passthru_attr_device_path,
778797
&nvmet_passthru_attr_enable,
779798
&nvmet_passthru_attr_admin_timeout,
780799
&nvmet_passthru_attr_io_timeout,
800+
&nvmet_passthru_attr_clear_ids,
781801
NULL,
782802
};
783803

drivers/nvme/target/core.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,12 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
13741374
ctrl->port = req->port;
13751375
ctrl->ops = req->ops;
13761376

1377+
#ifdef CONFIG_NVME_TARGET_PASSTHRU
1378+
/* By default, set loop targets to clear IDS by default */
1379+
if (ctrl->port->disc_addr.trtype == NVMF_TRTYPE_LOOP)
1380+
subsys->clear_ids = 1;
1381+
#endif
1382+
13771383
INIT_WORK(&ctrl->async_event_work, nvmet_async_event_work);
13781384
INIT_LIST_HEAD(&ctrl->async_events);
13791385
INIT_RADIX_TREE(&ctrl->p2p_ns_map, GFP_KERNEL);

drivers/nvme/target/nvmet.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ struct nvmet_subsys {
249249
struct config_group passthru_group;
250250
unsigned int admin_timeout;
251251
unsigned int io_timeout;
252+
unsigned int clear_ids;
252253
#endif /* CONFIG_NVME_TARGET_PASSTHRU */
253254

254255
#ifdef CONFIG_BLK_DEV_ZONED

drivers/nvme/target/passthru.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,53 @@ void nvmet_passthrough_override_cap(struct nvmet_ctrl *ctrl)
3030
ctrl->cap &= ~(1ULL << 43);
3131
}
3232

33+
static u16 nvmet_passthru_override_id_descs(struct nvmet_req *req)
34+
{
35+
struct nvmet_ctrl *ctrl = req->sq->ctrl;
36+
u16 status = NVME_SC_SUCCESS;
37+
int pos, len;
38+
bool csi_seen = false;
39+
void *data;
40+
u8 csi;
41+
42+
if (!ctrl->subsys->clear_ids)
43+
return status;
44+
45+
data = kzalloc(NVME_IDENTIFY_DATA_SIZE, GFP_KERNEL);
46+
if (!data)
47+
return NVME_SC_INTERNAL;
48+
49+
status = nvmet_copy_from_sgl(req, 0, data, NVME_IDENTIFY_DATA_SIZE);
50+
if (status)
51+
goto out_free;
52+
53+
for (pos = 0; pos < NVME_IDENTIFY_DATA_SIZE; pos += len) {
54+
struct nvme_ns_id_desc *cur = data + pos;
55+
56+
if (cur->nidl == 0)
57+
break;
58+
if (cur->nidt == NVME_NIDT_CSI) {
59+
memcpy(&csi, cur + 1, NVME_NIDT_CSI_LEN);
60+
csi_seen = true;
61+
break;
62+
}
63+
len = sizeof(struct nvme_ns_id_desc) + cur->nidl;
64+
}
65+
66+
memset(data, 0, NVME_IDENTIFY_DATA_SIZE);
67+
if (csi_seen) {
68+
struct nvme_ns_id_desc *cur = data;
69+
70+
cur->nidt = NVME_NIDT_CSI;
71+
cur->nidl = NVME_NIDT_CSI_LEN;
72+
memcpy(cur + 1, &csi, NVME_NIDT_CSI_LEN);
73+
}
74+
status = nvmet_copy_to_sgl(req, 0, data, NVME_IDENTIFY_DATA_SIZE);
75+
out_free:
76+
kfree(data);
77+
return status;
78+
}
79+
3380
static u16 nvmet_passthru_override_id_ctrl(struct nvmet_req *req)
3481
{
3582
struct nvmet_ctrl *ctrl = req->sq->ctrl;
@@ -152,6 +199,11 @@ static u16 nvmet_passthru_override_id_ns(struct nvmet_req *req)
152199
*/
153200
id->mc = 0;
154201

202+
if (req->sq->ctrl->subsys->clear_ids) {
203+
memset(id->nguid, 0, NVME_NIDT_NGUID_LEN);
204+
memset(id->eui64, 0, NVME_NIDT_EUI64_LEN);
205+
}
206+
155207
status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id));
156208

157209
out_free:
@@ -176,6 +228,9 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w)
176228
case NVME_ID_CNS_NS:
177229
nvmet_passthru_override_id_ns(req);
178230
break;
231+
case NVME_ID_CNS_NS_DESC_LIST:
232+
nvmet_passthru_override_id_descs(req);
233+
break;
179234
}
180235
} else if (status < 0)
181236
status = NVME_SC_INTERNAL;

0 commit comments

Comments
 (0)