提交 4d4a72b3 编写于 作者: C Christoph Hellwig 提交者: Yang Yingliang

nvme-multipath: fix double initialization of ANA state

mainline inclusion
from mainline-v5.13-rc2
commit 5e1f6899
category: bugfix
bugzilla: NA
CVE: NA
Link: https://gitee.com/openeuler/kernel/issues/I4JFBE?from=project-issue

-------------------------------------------------

nvme_init_identify and thus nvme_mpath_init can be called multiple
times and thus must not overwrite potentially initialized or in-use
fields.  Split out a helper for the basic initialization when the
controller is initialized and make sure the init_identify path does
not blindly change in-use data structures.

Fixes: 0d0b660f ("nvme: add ANA support")
Reported-by: NMartin Wilck <mwilck@suse.com>
Signed-off-by: NChristoph Hellwig <hch@lst.de>
Reviewed-by: NKeith Busch <kbusch@kernel.org>
Reviewed-by: NSagi Grimberg <sagi@grimberg.me>
Reviewed-by: NHannes Reinecke <hare@suse.de>

conflicts:
drivers/nvme/host/core.c
drivers/nvme/host/multipath.c
[adjust context]
Signed-off-by: Nchengjike <chengjike.cheng@huawei.com>
Reviewed-by: NAo Sun <sunao.sun@huawei.com>
Reviewed-by: NZhenwei Yang <yangzhenwei@huawei.com>
Reviewed-by: NHou Tao <houtao1@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 d8d45e68
...@@ -2674,7 +2674,7 @@ int nvme_init_identify(struct nvme_ctrl *ctrl) ...@@ -2674,7 +2674,7 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
ctrl->hmmaxd = le16_to_cpu(id->hmmaxd); ctrl->hmmaxd = le16_to_cpu(id->hmmaxd);
} }
ret = nvme_mpath_init(ctrl, id); ret = nvme_mpath_init_identify(ctrl, id);
kfree(id); kfree(id);
if (ret < 0) if (ret < 0)
...@@ -3834,6 +3834,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, ...@@ -3834,6 +3834,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
ctrl->device->power.set_latency_tolerance = nvme_set_latency_tolerance; ctrl->device->power.set_latency_tolerance = nvme_set_latency_tolerance;
dev_pm_qos_update_user_latency_tolerance(ctrl->device, dev_pm_qos_update_user_latency_tolerance(ctrl->device,
min(default_ps_max_latency_us, (unsigned long)S32_MAX)); min(default_ps_max_latency_us, (unsigned long)S32_MAX));
nvme_mpath_init_ctrl(ctrl);
return 0; return 0;
out_free_name: out_free_name:
......
...@@ -586,9 +586,18 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head) ...@@ -586,9 +586,18 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head)
put_disk(head->disk); put_disk(head->disk);
} }
int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) void nvme_mpath_init_ctrl(struct nvme_ctrl *ctrl)
{ {
int error; mutex_init(&ctrl->ana_lock);
timer_setup(&ctrl->anatt_timer, nvme_anatt_timeout, 0);
INIT_WORK(&ctrl->ana_work, nvme_ana_work);
}
int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
{
size_t max_transfer_size = ctrl->max_hw_sectors << SECTOR_SHIFT;
size_t ana_log_size;
int error = 0;
/* check if multipath is enabled and we have the capability */ /* check if multipath is enabled and we have the capability */
if (!multipath || !ctrl->subsys || !(ctrl->subsys->cmic & (1 << 3))) if (!multipath || !ctrl->subsys || !(ctrl->subsys->cmic & (1 << 3)))
...@@ -599,37 +608,33 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) ...@@ -599,37 +608,33 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
ctrl->nanagrpid = le32_to_cpu(id->nanagrpid); ctrl->nanagrpid = le32_to_cpu(id->nanagrpid);
ctrl->anagrpmax = le32_to_cpu(id->anagrpmax); ctrl->anagrpmax = le32_to_cpu(id->anagrpmax);
mutex_init(&ctrl->ana_lock); ana_log_size = sizeof(struct nvme_ana_rsp_hdr) +
timer_setup(&ctrl->anatt_timer, nvme_anatt_timeout, 0); ctrl->nanagrpid * sizeof(struct nvme_ana_group_desc) +
ctrl->ana_log_size = sizeof(struct nvme_ana_rsp_hdr) + ctrl->max_namespaces * sizeof(__le32);
ctrl->nanagrpid * sizeof(struct nvme_ana_group_desc); if (ana_log_size > max_transfer_size) {
ctrl->ana_log_size += ctrl->max_namespaces * sizeof(__le32);
if (ctrl->ana_log_size > ctrl->max_hw_sectors << SECTOR_SHIFT) {
dev_err(ctrl->device, dev_err(ctrl->device,
"ANA log page size (%zd) larger than MDTS (%d).\n", "ANA log page size (%zd) larger than MDTS (%zd).\n",
ctrl->ana_log_size, ana_log_size, max_transfer_size);
ctrl->max_hw_sectors << SECTOR_SHIFT);
dev_err(ctrl->device, "disabling ANA support.\n"); dev_err(ctrl->device, "disabling ANA support.\n");
return 0; goto out_uninit;
} }
INIT_WORK(&ctrl->ana_work, nvme_ana_work); if (ana_log_size > ctrl->ana_log_size) {
kfree(ctrl->ana_log_buf); nvme_mpath_stop(ctrl);
ctrl->ana_log_buf = kmalloc(ctrl->ana_log_size, GFP_KERNEL); kfree(ctrl->ana_log_buf);
if (!ctrl->ana_log_buf) { ctrl->ana_log_buf = kmalloc(ctrl->ana_log_size, GFP_KERNEL);
error = -ENOMEM; if (!ctrl->ana_log_buf)
goto out; return -ENOMEM;
} }
ctrl->ana_log_size = ana_log_size;
error = nvme_read_ana_log(ctrl, false); error = nvme_read_ana_log(ctrl, false);
if (error) if (error)
goto out_free_ana_log_buf; goto out_uninit;
return 0; return 0;
out_free_ana_log_buf:
kfree(ctrl->ana_log_buf); out_uninit:
ctrl->ana_log_buf = NULL; nvme_mpath_uninit(ctrl);
out:
return error; return error;
} }
......
...@@ -486,7 +486,8 @@ void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl); ...@@ -486,7 +486,8 @@ void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl);
int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl,struct nvme_ns_head *head); int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl,struct nvme_ns_head *head);
void nvme_mpath_add_disk(struct nvme_ns *ns, struct nvme_id_ns *id); void nvme_mpath_add_disk(struct nvme_ns *ns, struct nvme_id_ns *id);
void nvme_mpath_remove_disk(struct nvme_ns_head *head); void nvme_mpath_remove_disk(struct nvme_ns_head *head);
int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id); int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id);
void nvme_mpath_init_ctrl(struct nvme_ctrl *ctrl);
void nvme_mpath_uninit(struct nvme_ctrl *ctrl); void nvme_mpath_uninit(struct nvme_ctrl *ctrl);
void nvme_mpath_stop(struct nvme_ctrl *ctrl); void nvme_mpath_stop(struct nvme_ctrl *ctrl);
...@@ -568,7 +569,10 @@ static inline void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl) ...@@ -568,7 +569,10 @@ static inline void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
static inline void nvme_mpath_check_last_path(struct nvme_ns *ns) static inline void nvme_mpath_check_last_path(struct nvme_ns *ns)
{ {
} }
static inline int nvme_mpath_init(struct nvme_ctrl *ctrl, static inline void nvme_mpath_init_ctrl(struct nvme_ctrl *ctrl)
{
}
static inline int nvme_mpath_init_identify(struct nvme_ctrl *ctrl,
struct nvme_id_ctrl *id) struct nvme_id_ctrl *id)
{ {
if (ctrl->subsys->cmic & (1 << 3)) if (ctrl->subsys->cmic & (1 << 3))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册