diff options
author | Jens Axboe <axboe@kernel.dk> | 2020-11-19 09:23:27 -0700 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2020-11-19 09:23:27 -0700 |
commit | 45f703a0d4b87f940ea150367dc4f4a9c06fa868 (patch) | |
tree | 30cf530de2fc22e59cb08fd3907627a2f28894f5 | |
parent | 6f117cb854a44a79898d844e6ae3fd23bd94e786 (diff) | |
parent | 8168d23fbcee4f9f6c5a1ce8650417f09aef70eb (diff) |
Merge tag 'nvme-5.10-2020-11-19' of git://git.infradead.org/nvme into block-5.10
Pull NVMe fixes from Christoph:
"nvme fixes for 5.10
- Doorbell Buffer freeing fix (Minwoo Im)
- CSE log leak fix (Keith Busch)"
* tag 'nvme-5.10-2020-11-19' of git://git.infradead.org/nvme:
nvme: fix memory leak freeing command effects
nvme: directly cache command effects log
nvme: free sq/cq dbbuf pointers when dbbuf set fails
-rw-r--r-- | drivers/nvme/host/core.c | 25 | ||||
-rw-r--r-- | drivers/nvme/host/nvme.h | 6 | ||||
-rw-r--r-- | drivers/nvme/host/pci.c | 15 |
3 files changed, 33 insertions, 13 deletions
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 9b01afcb7777..9a270e49df17 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2929,7 +2929,7 @@ int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp, u8 csi, static int nvme_get_effects_log(struct nvme_ctrl *ctrl, u8 csi, struct nvme_effects_log **log) { - struct nvme_cel *cel = xa_load(&ctrl->cels, csi); + struct nvme_effects_log *cel = xa_load(&ctrl->cels, csi); int ret; if (cel) @@ -2940,16 +2940,15 @@ static int nvme_get_effects_log(struct nvme_ctrl *ctrl, u8 csi, return -ENOMEM; ret = nvme_get_log(ctrl, 0x00, NVME_LOG_CMD_EFFECTS, 0, csi, - &cel->log, sizeof(cel->log), 0); + cel, sizeof(*cel), 0); if (ret) { kfree(cel); return ret; } - cel->csi = csi; - xa_store(&ctrl->cels, cel->csi, cel, GFP_KERNEL); + xa_store(&ctrl->cels, csi, cel, GFP_KERNEL); out: - *log = &cel->log; + *log = cel; return 0; } @@ -4374,6 +4373,19 @@ void nvme_uninit_ctrl(struct nvme_ctrl *ctrl) } EXPORT_SYMBOL_GPL(nvme_uninit_ctrl); +static void nvme_free_cels(struct nvme_ctrl *ctrl) +{ + struct nvme_effects_log *cel; + unsigned long i; + + xa_for_each (&ctrl->cels, i, cel) { + xa_erase(&ctrl->cels, i); + kfree(cel); + } + + xa_destroy(&ctrl->cels); +} + static void nvme_free_ctrl(struct device *dev) { struct nvme_ctrl *ctrl = @@ -4383,8 +4395,7 @@ static void nvme_free_ctrl(struct device *dev) if (!subsys || ctrl->instance != subsys->instance) ida_simple_remove(&nvme_instance_ida, ctrl->instance); - xa_destroy(&ctrl->cels); - + nvme_free_cels(ctrl); nvme_mpath_uninit(ctrl); __free_page(ctrl->discard_page); diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index bc330bf0d3bd..567f7ad18a91 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -226,12 +226,6 @@ struct nvme_fault_inject { #endif }; -struct nvme_cel { - struct list_head entry; - struct nvme_effects_log log; - u8 csi; -}; - struct nvme_ctrl { bool comp_seen; enum nvme_ctrl_state state; diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 0578ff253c47..3be352403839 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -292,9 +292,21 @@ static void nvme_dbbuf_init(struct nvme_dev *dev, nvmeq->dbbuf_cq_ei = &dev->dbbuf_eis[cq_idx(qid, dev->db_stride)]; } +static void nvme_dbbuf_free(struct nvme_queue *nvmeq) +{ + if (!nvmeq->qid) + return; + + nvmeq->dbbuf_sq_db = NULL; + nvmeq->dbbuf_cq_db = NULL; + nvmeq->dbbuf_sq_ei = NULL; + nvmeq->dbbuf_cq_ei = NULL; +} + static void nvme_dbbuf_set(struct nvme_dev *dev) { struct nvme_command c; + unsigned int i; if (!dev->dbbuf_dbs) return; @@ -308,6 +320,9 @@ static void nvme_dbbuf_set(struct nvme_dev *dev) dev_warn(dev->ctrl.device, "unable to set dbbuf\n"); /* Free memory and continue on */ nvme_dbbuf_dma_free(dev); + + for (i = 1; i <= dev->online_queues; i++) + nvme_dbbuf_free(&dev->queues[i]); } } |