Skip to content

Commit c85c9ab

Browse files
Christoph Hellwigkeithbusch
authored andcommitted
nvme: split nvme_update_zone_info
nvme_update_zone_info does (admin queue) I/O to the device and can fail. We fail to abort the queue limits update if that happen, but really should avoid with the frozen I/O queue as much as possible anyway. Split the logic into a helper to query the information that can be called on an unfrozen queue and one to apply it to the queue limits. Fixes: 9b130d681443 ("nvme: use the atomic queue limits update API") Reported-by: Kanchan Joshi <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Kanchan Joshi <[email protected]> Signed-off-by: Keith Busch <[email protected]>
1 parent ac229a2 commit c85c9ab

File tree

3 files changed

+41
-23
lines changed

3 files changed

+41
-23
lines changed

drivers/nvme/host/core.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,6 +2076,7 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
20762076
bool vwc = ns->ctrl->vwc & NVME_CTRL_VWC_PRESENT;
20772077
struct queue_limits lim;
20782078
struct nvme_id_ns_nvm *nvm = NULL;
2079+
struct nvme_zone_info zi = {};
20792080
struct nvme_id_ns *id;
20802081
sector_t capacity;
20812082
unsigned lbaf;
@@ -2091,15 +2092,22 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
20912092
ret = -ENODEV;
20922093
goto out;
20932094
}
2095+
lbaf = nvme_lbaf_index(id->flbas);
20942096

20952097
if (ns->ctrl->ctratt & NVME_CTRL_ATTR_ELBAS) {
20962098
ret = nvme_identify_ns_nvm(ns->ctrl, info->nsid, &nvm);
20972099
if (ret < 0)
20982100
goto out;
20992101
}
21002102

2103+
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
2104+
ns->head->ids.csi == NVME_CSI_ZNS) {
2105+
ret = nvme_query_zone_info(ns, lbaf, &zi);
2106+
if (ret < 0)
2107+
goto out;
2108+
}
2109+
21012110
blk_mq_freeze_queue(ns->disk->queue);
2102-
lbaf = nvme_lbaf_index(id->flbas);
21032111
ns->head->lba_shift = id->lbaf[lbaf].ds;
21042112
ns->head->nuse = le64_to_cpu(id->nuse);
21052113
capacity = nvme_lba_to_sect(ns->head, le64_to_cpu(id->nsze));
@@ -2112,13 +2120,8 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
21122120
capacity = 0;
21132121
nvme_config_discard(ns, &lim);
21142122
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
2115-
ns->head->ids.csi == NVME_CSI_ZNS) {
2116-
ret = nvme_update_zone_info(ns, lbaf, &lim);
2117-
if (ret) {
2118-
blk_mq_unfreeze_queue(ns->disk->queue);
2119-
goto out;
2120-
}
2121-
}
2123+
ns->head->ids.csi == NVME_CSI_ZNS)
2124+
nvme_update_zone_info(ns, &lim, &zi);
21222125
ret = queue_limits_commit_update(ns->disk->queue, &lim);
21232126
if (ret) {
21242127
blk_mq_unfreeze_queue(ns->disk->queue);

drivers/nvme/host/nvme.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,10 +1036,18 @@ static inline bool nvme_disk_is_ns_head(struct gendisk *disk)
10361036
}
10371037
#endif /* CONFIG_NVME_MULTIPATH */
10381038

1039+
struct nvme_zone_info {
1040+
u64 zone_size;
1041+
unsigned int max_open_zones;
1042+
unsigned int max_active_zones;
1043+
};
1044+
10391045
int nvme_ns_report_zones(struct nvme_ns *ns, sector_t sector,
10401046
unsigned int nr_zones, report_zones_cb cb, void *data);
1041-
int nvme_update_zone_info(struct nvme_ns *ns, unsigned lbaf,
1042-
struct queue_limits *lim);
1047+
int nvme_query_zone_info(struct nvme_ns *ns, unsigned lbaf,
1048+
struct nvme_zone_info *zi);
1049+
void nvme_update_zone_info(struct nvme_ns *ns, struct queue_limits *lim,
1050+
struct nvme_zone_info *zi);
10431051
#ifdef CONFIG_BLK_DEV_ZONED
10441052
blk_status_t nvme_setup_zone_mgmt_send(struct nvme_ns *ns, struct request *req,
10451053
struct nvme_command *cmnd,

drivers/nvme/host/zns.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ static int nvme_set_max_append(struct nvme_ctrl *ctrl)
3535
return 0;
3636
}
3737

38-
int nvme_update_zone_info(struct nvme_ns *ns, unsigned lbaf,
39-
struct queue_limits *lim)
38+
int nvme_query_zone_info(struct nvme_ns *ns, unsigned lbaf,
39+
struct nvme_zone_info *zi)
4040
{
4141
struct nvme_effects_log *log = ns->head->effects;
4242
struct nvme_command c = { };
@@ -89,27 +89,34 @@ int nvme_update_zone_info(struct nvme_ns *ns, unsigned lbaf,
8989
goto free_data;
9090
}
9191

92-
ns->head->zsze =
93-
nvme_lba_to_sect(ns->head, le64_to_cpu(id->lbafe[lbaf].zsze));
94-
if (!is_power_of_2(ns->head->zsze)) {
92+
zi->zone_size = le64_to_cpu(id->lbafe[lbaf].zsze);
93+
if (!is_power_of_2(zi->zone_size)) {
9594
dev_warn(ns->ctrl->device,
96-
"invalid zone size:%llu for namespace:%u\n",
97-
ns->head->zsze, ns->head->ns_id);
95+
"invalid zone size: %llu for namespace: %u\n",
96+
zi->zone_size, ns->head->ns_id);
9897
status = -ENODEV;
9998
goto free_data;
10099
}
100+
zi->max_open_zones = le32_to_cpu(id->mor) + 1;
101+
zi->max_active_zones = le32_to_cpu(id->mar) + 1;
101102

102-
blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, ns->queue);
103-
lim->zoned = 1;
104-
lim->max_open_zones = le32_to_cpu(id->mor) + 1;
105-
lim->max_active_zones = le32_to_cpu(id->mar) + 1;
106-
lim->chunk_sectors = ns->head->zsze;
107-
lim->max_zone_append_sectors = ns->ctrl->max_zone_append;
108103
free_data:
109104
kfree(id);
110105
return status;
111106
}
112107

108+
void nvme_update_zone_info(struct nvme_ns *ns, struct queue_limits *lim,
109+
struct nvme_zone_info *zi)
110+
{
111+
lim->zoned = 1;
112+
lim->max_open_zones = zi->max_open_zones;
113+
lim->max_active_zones = zi->max_active_zones;
114+
lim->max_zone_append_sectors = ns->ctrl->max_zone_append;
115+
lim->chunk_sectors = ns->head->zsze =
116+
nvme_lba_to_sect(ns->head, zi->zone_size);
117+
blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, ns->queue);
118+
}
119+
113120
static void *nvme_zns_alloc_report_buffer(struct nvme_ns *ns,
114121
unsigned int nr_zones, size_t *buflen)
115122
{

0 commit comments

Comments
 (0)