]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 24 May 2021 12:22:19 +0000 (14:22 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 24 May 2021 12:22:19 +0000 (14:22 +0200)
added patches:
nvme-multipath-fix-double-initialization-of-ana-state.patch

queue-5.10/nvme-multipath-fix-double-initialization-of-ana-state.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/nvme-multipath-fix-double-initialization-of-ana-state.patch b/queue-5.10/nvme-multipath-fix-double-initialization-of-ana-state.patch
new file mode 100644 (file)
index 0000000..9292ed6
--- /dev/null
@@ -0,0 +1,150 @@
+From 5e1f689913a4498e3081093670ef9d85b2c60920 Mon Sep 17 00:00:00 2001
+From: Christoph Hellwig <hch@lst.de>
+Date: Thu, 29 Apr 2021 14:18:53 +0200
+Subject: nvme-multipath: fix double initialization of ANA state
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit 5e1f689913a4498e3081093670ef9d85b2c60920 upstream.
+
+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: 0d0b660f214d ("nvme: add ANA support")
+Reported-by: Martin Wilck <mwilck@suse.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Keith Busch <kbusch@kernel.org>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvme/host/core.c      |    3 +-
+ drivers/nvme/host/multipath.c |   55 ++++++++++++++++++++++--------------------
+ drivers/nvme/host/nvme.h      |    8 ++++--
+ 3 files changed, 37 insertions(+), 29 deletions(-)
+
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -3131,7 +3131,7 @@ int nvme_init_identify(struct nvme_ctrl
+               ctrl->hmmaxd = le16_to_cpu(id->hmmaxd);
+       }
+-      ret = nvme_mpath_init(ctrl, id);
++      ret = nvme_mpath_init_identify(ctrl, id);
+       kfree(id);
+       if (ret < 0)
+@@ -4517,6 +4517,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctr
+               min(default_ps_max_latency_us, (unsigned long)S32_MAX));
+       nvme_fault_inject_init(&ctrl->fault_inject, dev_name(ctrl->device));
++      nvme_mpath_init_ctrl(ctrl);
+       return 0;
+ out_free_name:
+--- a/drivers/nvme/host/multipath.c
++++ b/drivers/nvme/host/multipath.c
+@@ -708,9 +708,18 @@ void nvme_mpath_remove_disk(struct nvme_
+       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 */
+       if (!multipath || !ctrl->subsys ||
+@@ -722,37 +731,31 @@ int nvme_mpath_init(struct nvme_ctrl *ct
+       ctrl->nanagrpid = le32_to_cpu(id->nanagrpid);
+       ctrl->anagrpmax = le32_to_cpu(id->anagrpmax);
+-      mutex_init(&ctrl->ana_lock);
+-      timer_setup(&ctrl->anatt_timer, nvme_anatt_timeout, 0);
+-      ctrl->ana_log_size = sizeof(struct nvme_ana_rsp_hdr) +
+-              ctrl->nanagrpid * sizeof(struct nvme_ana_group_desc);
+-      ctrl->ana_log_size += ctrl->max_namespaces * sizeof(__le32);
+-
+-      if (ctrl->ana_log_size > ctrl->max_hw_sectors << SECTOR_SHIFT) {
++      ana_log_size = sizeof(struct nvme_ana_rsp_hdr) +
++              ctrl->nanagrpid * sizeof(struct nvme_ana_group_desc) +
++              ctrl->max_namespaces * sizeof(__le32);
++      if (ana_log_size > max_transfer_size) {
+               dev_err(ctrl->device,
+-                      "ANA log page size (%zd) larger than MDTS (%d).\n",
+-                      ctrl->ana_log_size,
+-                      ctrl->max_hw_sectors << SECTOR_SHIFT);
++                      "ANA log page size (%zd) larger than MDTS (%zd).\n",
++                      ana_log_size, max_transfer_size);
+               dev_err(ctrl->device, "disabling ANA support.\n");
+-              return 0;
++              goto out_uninit;
+       }
+-
+-      INIT_WORK(&ctrl->ana_work, nvme_ana_work);
+-      kfree(ctrl->ana_log_buf);
+-      ctrl->ana_log_buf = kmalloc(ctrl->ana_log_size, GFP_KERNEL);
+-      if (!ctrl->ana_log_buf) {
+-              error = -ENOMEM;
+-              goto out;
++      if (ana_log_size > ctrl->ana_log_size) {
++              nvme_mpath_stop(ctrl);
++              kfree(ctrl->ana_log_buf);
++              ctrl->ana_log_buf = kmalloc(ctrl->ana_log_size, GFP_KERNEL);
++              if (!ctrl->ana_log_buf)
++                      return -ENOMEM;
+       }
+-
++      ctrl->ana_log_size = ana_log_size;
+       error = nvme_read_ana_log(ctrl);
+       if (error)
+-              goto out_free_ana_log_buf;
++              goto out_uninit;
+       return 0;
+-out_free_ana_log_buf:
+-      kfree(ctrl->ana_log_buf);
+-      ctrl->ana_log_buf = NULL;
+-out:
++
++out_uninit:
++      nvme_mpath_uninit(ctrl);
+       return error;
+ }
+--- a/drivers/nvme/host/nvme.h
++++ b/drivers/nvme/host/nvme.h
+@@ -654,7 +654,8 @@ void nvme_kick_requeue_lists(struct nvme
+ 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_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_stop(struct nvme_ctrl *ctrl);
+ bool nvme_mpath_clear_current_path(struct nvme_ns *ns);
+@@ -730,7 +731,10 @@ static inline void nvme_trace_bio_comple
+         blk_status_t status)
+ {
+ }
+-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)
+ {
+       if (ctrl->subsys->cmic & (1 << 3))
index a34abfe8af5daa205a93476c6f3d0e58a30c2b35..4a227683989315580a08a4ea42c2477d8aa6261d 100644 (file)
@@ -99,3 +99,4 @@ tty-vt-always-invoke-vc-vc_sw-con_resize-callback.patch
 drm-i915-gt-disable-hiz-raw-stall-optimization-on-broken-gen7.patch
 openrisc-mm-init.c-remove-unused-memblock_region-variable-in-map_ram.patch
 x86-xen-swap-nx-determination-and-gdt-setup-on-bsp.patch
+nvme-multipath-fix-double-initialization-of-ana-state.patch