提交 614a0676 编写于 作者: K Keith Busch 提交者: Yang Yingliang

nvme: unlink head after removing last namespace

mainline inclusion
from mainline-v5.8-rc1
commit d5675729
category: bugfix
bugzilla: NA
CVE: NA
Link: https://gitee.com/openeuler/kernel/issues/I1WGZE

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

The driver had been unlinking the namespace head from the subsystem's
list only after the last reference was released, and outside of the
list's subsys->lock protection.

There is no reason to track an empty head, so unlink the entry from the
subsystem's list when the last namespace using that head is removed and
with the mutex lock protecting the list update. The next namespace to
attach reusing the previous NSID will allocate a new head rather than
find the old head with mismatched identifiers.
Signed-off-by: NKeith Busch <kbusch@kernel.org>
Reviewed-by: NSagi Grimberg <sagi@grimberg.me>
Signed-off-by: NChristoph Hellwig <hch@lst.de>
Signed-off-by: NJens Axboe <axboe@kernel.dk>
Reviewed-by: NChao Leng <lengchao@huawei.com>
Reviewed-by: NJike Cheng <chengjike.cheng@huawei.com>
Signed-off-by: NLijie <lijie34@huawei.com>
Acked-by: NHanjun Guo <guohanjun@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 c4b7246a
...@@ -397,7 +397,6 @@ static void nvme_free_ns_head(struct kref *ref) ...@@ -397,7 +397,6 @@ static void nvme_free_ns_head(struct kref *ref)
nvme_mpath_remove_disk(head); nvme_mpath_remove_disk(head);
ida_simple_remove(&head->subsys->ns_ida, head->instance); ida_simple_remove(&head->subsys->ns_ida, head->instance);
list_del_init(&head->entry);
cleanup_srcu_struct_quiesced(&head->srcu); cleanup_srcu_struct_quiesced(&head->srcu);
nvme_put_subsystem(head->subsys); nvme_put_subsystem(head->subsys);
kfree(head); kfree(head);
...@@ -3065,7 +3064,6 @@ static int __nvme_check_ids(struct nvme_subsystem *subsys, ...@@ -3065,7 +3064,6 @@ static int __nvme_check_ids(struct nvme_subsystem *subsys,
list_for_each_entry(h, &subsys->nsheads, entry) { list_for_each_entry(h, &subsys->nsheads, entry) {
if (nvme_ns_ids_valid(&new->ids) && if (nvme_ns_ids_valid(&new->ids) &&
!list_empty(&h->list) &&
nvme_ns_ids_equal(&new->ids, &h->ids)) nvme_ns_ids_equal(&new->ids, &h->ids))
return -EINVAL; return -EINVAL;
} }
...@@ -3293,6 +3291,8 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid) ...@@ -3293,6 +3291,8 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
out_unlink_ns: out_unlink_ns:
mutex_lock(&ctrl->subsys->lock); mutex_lock(&ctrl->subsys->lock);
list_del_rcu(&ns->siblings); list_del_rcu(&ns->siblings);
if (list_empty(&ns->head->list))
list_del_init(&ns->head->entry);
mutex_unlock(&ctrl->subsys->lock); mutex_unlock(&ctrl->subsys->lock);
nvme_put_ns_head(ns->head); nvme_put_ns_head(ns->head);
out_free_id: out_free_id:
...@@ -3312,7 +3312,10 @@ static void nvme_ns_remove(struct nvme_ns *ns) ...@@ -3312,7 +3312,10 @@ static void nvme_ns_remove(struct nvme_ns *ns)
mutex_lock(&ns->ctrl->subsys->lock); mutex_lock(&ns->ctrl->subsys->lock);
list_del_rcu(&ns->siblings); list_del_rcu(&ns->siblings);
if (list_empty(&ns->head->list))
list_del_init(&ns->head->entry);
mutex_unlock(&ns->ctrl->subsys->lock); mutex_unlock(&ns->ctrl->subsys->lock);
synchronize_rcu(); /* guarantee not available in head->list */ synchronize_rcu(); /* guarantee not available in head->list */
nvme_mpath_clear_current_path(ns); nvme_mpath_clear_current_path(ns);
synchronize_srcu(&ns->head->srcu); /* wait for concurrent submissions */ synchronize_srcu(&ns->head->srcu); /* wait for concurrent submissions */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册