diff options
author | Solganik Alexander <sashas@lightbitslabs.com> | 2016-10-30 10:35:15 +0200 |
---|---|---|
committer | Sagi Grimberg <sagi@grimberg.me> | 2016-12-06 10:17:03 +0200 |
commit | e4fcf07cca6a3b6c4be00df16f08be894325eaa3 (patch) | |
tree | fe89e5c2ba76c318026e6b708bc73060f9c4902f /drivers/nvme/target/configfs.c | |
parent | f3116d8f1e110a5eeaac94f5d1c490e9e466a223 (diff) | |
download | blackbird-op-linux-e4fcf07cca6a3b6c4be00df16f08be894325eaa3.tar.gz blackbird-op-linux-e4fcf07cca6a3b6c4be00df16f08be894325eaa3.zip |
nvmet: Fix possible infinite loop triggered on hot namespace removal
When removing a namespace we delete it from the subsystem namespaces
list with list_del_init which allows us to know if it is enabled or
not.
The problem is that list_del_init initialize the list next and does
not respect the RCU list-traversal we do on the IO path for locating
a namespace. Instead we need to use list_del_rcu which is allowed to
run concurrently with the _rcu list-traversal primitives (keeps list
next intact) and guarantees concurrent nvmet_find_naespace forward
progress.
By changing that, we cannot rely on ns->dev_link for knowing if the
namspace is enabled, so add enabled indicator entry to nvmet_ns for
that.
Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: Solganik Alexander <sashas@lightbitslabs.com>
Cc: <stable@vger.kernel.org> # v4.8+
Diffstat (limited to 'drivers/nvme/target/configfs.c')
-rw-r--r-- | drivers/nvme/target/configfs.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c index af5e2dc4a3d5..011f88e5663e 100644 --- a/drivers/nvme/target/configfs.c +++ b/drivers/nvme/target/configfs.c @@ -271,7 +271,7 @@ static ssize_t nvmet_ns_device_path_store(struct config_item *item, mutex_lock(&subsys->lock); ret = -EBUSY; - if (nvmet_ns_enabled(ns)) + if (ns->enabled) goto out_unlock; kfree(ns->device_path); @@ -307,7 +307,7 @@ static ssize_t nvmet_ns_device_nguid_store(struct config_item *item, int ret = 0; mutex_lock(&subsys->lock); - if (nvmet_ns_enabled(ns)) { + if (ns->enabled) { ret = -EBUSY; goto out_unlock; } @@ -339,7 +339,7 @@ CONFIGFS_ATTR(nvmet_ns_, device_nguid); static ssize_t nvmet_ns_enable_show(struct config_item *item, char *page) { - return sprintf(page, "%d\n", nvmet_ns_enabled(to_nvmet_ns(item))); + return sprintf(page, "%d\n", to_nvmet_ns(item)->enabled); } static ssize_t nvmet_ns_enable_store(struct config_item *item, |