Skip to content

Commit 8b7c0ff

Browse files
author
Christoph Hellwig
committed
nvme: query namespace identifiers before adding the namespace
Check the namespace identifier list first thing when scanning namespaces. This keeps the code to query the CSI common between the alloc and validate path, and helps to structure the code better for multiple command set support. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Keith Busch <kbusch@kernel.org> Reviewed-by: Damien Le Moal <damien.lemoal@wdc.com>
1 parent 3a9967b commit 8b7c0ff

1 file changed

Lines changed: 53 additions & 63 deletions

File tree

drivers/nvme/host/core.c

Lines changed: 53 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,8 @@ static int nvme_identify_ns_descs(struct nvme_ctrl *ctrl, unsigned nsid,
12811281
int status, pos, len;
12821282
void *data;
12831283

1284+
if (ctrl->vs < NVME_VS(1, 3, 0) && !nvme_multi_css(ctrl))
1285+
return 0;
12841286
if (ctrl->quirks & NVME_QUIRK_NO_NS_DESC_LIST)
12851287
return 0;
12861288

@@ -1335,8 +1337,8 @@ static int nvme_identify_ns_list(struct nvme_ctrl *dev, unsigned nsid, __le32 *n
13351337
NVME_IDENTIFY_DATA_SIZE);
13361338
}
13371339

1338-
static int nvme_identify_ns(struct nvme_ctrl *ctrl,
1339-
unsigned nsid, struct nvme_id_ns **id)
1340+
static int nvme_identify_ns(struct nvme_ctrl *ctrl, unsigned nsid,
1341+
struct nvme_ns_ids *ids, struct nvme_id_ns **id)
13401342
{
13411343
struct nvme_command c = { };
13421344
int error;
@@ -1359,6 +1361,14 @@ static int nvme_identify_ns(struct nvme_ctrl *ctrl,
13591361
error = -ENODEV;
13601362
if ((*id)->ncap == 0) /* namespace not allocated or attached */
13611363
goto out_free_id;
1364+
1365+
if (ctrl->vs >= NVME_VS(1, 1, 0) &&
1366+
!memchr_inv(ids->eui64, 0, sizeof(ids->eui64)))
1367+
memcpy(ids->eui64, (*id)->eui64, sizeof(ids->eui64));
1368+
if (ctrl->vs >= NVME_VS(1, 2, 0) &&
1369+
!memchr_inv(ids->nguid, 0, sizeof(ids->nguid)))
1370+
memcpy(ids->nguid, (*id)->nguid, sizeof(ids->nguid));
1371+
13621372
return 0;
13631373

13641374
out_free_id:
@@ -1884,20 +1894,6 @@ static void nvme_config_write_zeroes(struct gendisk *disk, struct nvme_ns *ns)
18841894
nvme_lba_to_sect(ns, max_blocks));
18851895
}
18861896

1887-
static int nvme_report_ns_ids(struct nvme_ctrl *ctrl, unsigned int nsid,
1888-
struct nvme_id_ns *id, struct nvme_ns_ids *ids)
1889-
{
1890-
memset(ids, 0, sizeof(*ids));
1891-
1892-
if (ctrl->vs >= NVME_VS(1, 1, 0))
1893-
memcpy(ids->eui64, id->eui64, sizeof(id->eui64));
1894-
if (ctrl->vs >= NVME_VS(1, 2, 0))
1895-
memcpy(ids->nguid, id->nguid, sizeof(id->nguid));
1896-
if (ctrl->vs >= NVME_VS(1, 3, 0) || nvme_multi_css(ctrl))
1897-
return nvme_identify_ns_descs(ctrl, nsid, ids);
1898-
return 0;
1899-
}
1900-
19011897
static bool nvme_ns_ids_valid(struct nvme_ns_ids *ids)
19021898
{
19031899
return !uuid_is_null(&ids->uuid) ||
@@ -2117,30 +2113,16 @@ static void nvme_set_chunk_sectors(struct nvme_ns *ns, struct nvme_id_ns *id)
21172113
static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id)
21182114
{
21192115
unsigned lbaf = id->flbas & NVME_NS_FLBAS_LBA_MASK;
2120-
struct nvme_ctrl *ctrl = ns->ctrl;
21212116
int ret;
21222117

21232118
blk_mq_freeze_queue(ns->disk->queue);
21242119
ns->lba_shift = id->lbaf[lbaf].ds;
2125-
nvme_set_queue_limits(ctrl, ns->queue);
2120+
nvme_set_queue_limits(ns->ctrl, ns->queue);
21262121

2127-
switch (ns->head->ids.csi) {
2128-
case NVME_CSI_NVM:
2129-
break;
2130-
case NVME_CSI_ZNS:
2122+
if (ns->head->ids.csi == NVME_CSI_ZNS) {
21312123
ret = nvme_update_zone_info(ns, lbaf);
2132-
if (ret) {
2133-
dev_warn(ctrl->device,
2134-
"failed to add zoned namespace:%u ret:%d\n",
2135-
ns->head->ns_id, ret);
2124+
if (ret)
21362125
goto out_unfreeze;
2137-
}
2138-
break;
2139-
default:
2140-
dev_warn(ctrl->device, "unknown csi:%u ns:%u\n",
2141-
ns->head->ids.csi, ns->head->ns_id);
2142-
ret = -ENODEV;
2143-
goto out_unfreeze;
21442126
}
21452127

21462128
ret = nvme_configure_metadata(ns, id);
@@ -2174,27 +2156,22 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id)
21742156
return ret;
21752157
}
21762158

2177-
static int nvme_validate_ns(struct nvme_ns *ns)
2159+
static int nvme_validate_ns(struct nvme_ns *ns, struct nvme_ns_ids *ids)
21782160
{
21792161
struct nvme_ctrl *ctrl = ns->ctrl;
21802162
struct nvme_id_ns *id;
2181-
struct nvme_ns_ids ids;
21822163
int ret = 0;
21832164

21842165
if (test_bit(NVME_NS_DEAD, &ns->flags)) {
21852166
set_capacity(ns->disk, 0);
21862167
return -ENODEV;
21872168
}
21882169

2189-
ret = nvme_identify_ns(ctrl, ns->head->ns_id, &id);
2170+
ret = nvme_identify_ns(ctrl, ns->head->ns_id, ids, &id);
21902171
if (ret)
21912172
goto out;
21922173

2193-
ret = nvme_report_ns_ids(ctrl, ns->head->ns_id, id, &ids);
2194-
if (ret)
2195-
goto free_id;
2196-
2197-
if (!nvme_ns_ids_equal(&ns->head->ids, &ids)) {
2174+
if (!nvme_ns_ids_equal(&ns->head->ids, ids)) {
21982175
dev_err(ctrl->device,
21992176
"identifiers changed for nsid %d\n", ns->head->ns_id);
22002177
ret = -ENODEV;
@@ -3794,25 +3771,16 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
37943771
}
37953772

37963773
static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid,
3797-
struct nvme_id_ns *id)
3774+
struct nvme_ns_ids *ids, bool is_shared)
37983775
{
37993776
struct nvme_ctrl *ctrl = ns->ctrl;
3800-
bool is_shared = id->nmic & NVME_NS_NMIC_SHARED;
38013777
struct nvme_ns_head *head = NULL;
3802-
struct nvme_ns_ids ids;
38033778
int ret = 0;
38043779

3805-
ret = nvme_report_ns_ids(ctrl, nsid, id, &ids);
3806-
if (ret) {
3807-
if (ret < 0)
3808-
return ret;
3809-
return blk_status_to_errno(nvme_error_status(ret));
3810-
}
3811-
38123780
mutex_lock(&ctrl->subsys->lock);
38133781
head = nvme_find_ns_head(ctrl->subsys, nsid);
38143782
if (!head) {
3815-
head = nvme_alloc_ns_head(ctrl, nsid, &ids);
3783+
head = nvme_alloc_ns_head(ctrl, nsid, ids);
38163784
if (IS_ERR(head)) {
38173785
ret = PTR_ERR(head);
38183786
goto out_unlock;
@@ -3825,7 +3793,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid,
38253793
"Duplicate unshared namespace %d\n", nsid);
38263794
goto out_put_ns_head;
38273795
}
3828-
if (!nvme_ns_ids_equal(&head->ids, &ids)) {
3796+
if (!nvme_ns_ids_equal(&head->ids, ids)) {
38293797
dev_err(ctrl->device,
38303798
"IDs don't match for shared namespace %d\n",
38313799
nsid);
@@ -3873,15 +3841,16 @@ struct nvme_ns *nvme_find_get_ns(struct nvme_ctrl *ctrl, unsigned nsid)
38733841
}
38743842
EXPORT_SYMBOL_NS_GPL(nvme_find_get_ns, NVME_TARGET_PASSTHRU);
38753843

3876-
static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
3844+
static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid,
3845+
struct nvme_ns_ids *ids)
38773846
{
38783847
struct nvme_ns *ns;
38793848
struct gendisk *disk;
38803849
struct nvme_id_ns *id;
38813850
char disk_name[DISK_NAME_LEN];
38823851
int node = ctrl->numa_node, flags = GENHD_FL_EXT_DEVT, ret;
38833852

3884-
if (nvme_identify_ns(ctrl, nsid, &id))
3853+
if (nvme_identify_ns(ctrl, nsid, ids, &id))
38853854
return;
38863855

38873856
ns = kzalloc_node(sizeof(*ns), GFP_KERNEL, node);
@@ -3903,7 +3872,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
39033872
ns->ctrl = ctrl;
39043873
kref_init(&ns->kref);
39053874

3906-
ret = nvme_init_ns_head(ns, nsid, id);
3875+
ret = nvme_init_ns_head(ns, nsid, ids, id->nmic & NVME_NS_NMIC_SHARED);
39073876
if (ret)
39083877
goto out_free_queue;
39093878
nvme_set_disk_name(disk_name, ns, ctrl, &flags);
@@ -4006,20 +3975,41 @@ static void nvme_ns_remove_by_nsid(struct nvme_ctrl *ctrl, u32 nsid)
40063975

40073976
static void nvme_validate_or_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
40083977
{
3978+
struct nvme_ns_ids ids = { };
40093979
struct nvme_ns *ns;
40103980
int ret;
40113981

3982+
if (nvme_identify_ns_descs(ctrl, nsid, &ids))
3983+
return;
3984+
40123985
ns = nvme_find_get_ns(ctrl, nsid);
4013-
if (!ns) {
4014-
nvme_alloc_ns(ctrl, nsid);
3986+
if (ns) {
3987+
ret = nvme_validate_ns(ns, &ids);
3988+
revalidate_disk_size(ns->disk, ret == 0);
3989+
if (ret)
3990+
nvme_ns_remove(ns);
3991+
nvme_put_ns(ns);
40153992
return;
40163993
}
40173994

4018-
ret = nvme_validate_ns(ns);
4019-
revalidate_disk_size(ns->disk, ret == 0);
4020-
if (ret)
4021-
nvme_ns_remove(ns);
4022-
nvme_put_ns(ns);
3995+
switch (ids.csi) {
3996+
case NVME_CSI_NVM:
3997+
nvme_alloc_ns(ctrl, nsid, &ids);
3998+
break;
3999+
case NVME_CSI_ZNS:
4000+
if (!IS_ENABLED(CONFIG_BLK_DEV_ZONED)) {
4001+
dev_warn(ctrl->device,
4002+
"nsid %u not supported without CONFIG_BLK_DEV_ZONED\n",
4003+
nsid);
4004+
break;
4005+
}
4006+
nvme_alloc_ns(ctrl, nsid, &ids);
4007+
break;
4008+
default:
4009+
dev_warn(ctrl->device, "unknown csi %u for nsid %u\n",
4010+
ids.csi, nsid);
4011+
break;
4012+
}
40234013
}
40244014

40254015
static void nvme_remove_invalid_namespaces(struct nvme_ctrl *ctrl,

0 commit comments

Comments
 (0)