[PATCHv4] nvme: allow to re-attach namespaces after all paths are down
Keith Busch
kbusch at kernel.org
Mon May 17 08:26:01 PDT 2021
On Mon, May 17, 2021 at 10:18:09AM +0200, Hannes Reinecke wrote:
> We should only remove the ns head from the list of heads per
> subsystem if the reference count drops to zero. Removing it
> at the start of nvme_ns_remove() will prevent us from reattaching
> the namespace to the correct ns head once a path becomes available
> again.
This looks fine to me
Reviewed-by: Keith Busch <kbusch at kernel.org>
There are potential corner cases associated with namespace management
that can cause problems here, but it would certainly be a user error
that needs manual intervention anyway. I suspect those scenarios are
very uncommon too, so I think we can deal with that later if it becomes
a problem.
> Signed-off-by: Hannes Reinecke <hare at suse.de>
> ---
> drivers/nvme/host/core.c | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
> index 522c9b229f80..a60144a4054a 100644
> --- a/drivers/nvme/host/core.c
> +++ b/drivers/nvme/host/core.c
> @@ -546,6 +546,9 @@ static void nvme_free_ns_head(struct kref *ref)
> struct nvme_ns_head *head =
> container_of(ref, struct nvme_ns_head, ref);
>
> + mutex_lock(&head->subsys->lock);
> + list_del_init(&head->entry);
> + mutex_unlock(&head->subsys->lock);
> nvme_mpath_remove_disk(head);
> ida_simple_remove(&head->subsys->ns_ida, head->instance);
> cleanup_srcu_struct(&head->srcu);
> @@ -3605,7 +3608,11 @@ static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid,
> head->shared = is_shared;
> } else {
> ret = -EINVAL;
> - if (!is_shared || !head->shared) {
> + /*
> + * If multipath is enabled we might hit an ns head with no
> + * paths, but that doesn't indicate it's a shared namespace.
> + */
> + if (!list_empty(&head->list) && (!is_shared || !head->shared)) {
> dev_err(ctrl->device,
> "Duplicate unshared namespace %d\n", nsid);
> goto out_put_ns_head;
> @@ -3764,8 +3771,6 @@ static void nvme_ns_remove(struct nvme_ns *ns)
>
> mutex_lock(&ns->ctrl->subsys->lock);
> list_del_rcu(&ns->siblings);
> - if (list_empty(&ns->head->list))
> - list_del_init(&ns->head->entry);
> mutex_unlock(&ns->ctrl->subsys->lock);
>
> synchronize_rcu(); /* guarantee not available in head->list */
> --
More information about the Linux-nvme
mailing list