[PATCH v4] nvmet: add missing lock around nvmet_ns_changed in nvmet_ns_revalidate

Niels Dossche dossche.niels at gmail.com
Sun Mar 13 16:41:15 PDT 2022


nvmet_ns_changed states via lockdep that the ns->subsys->lock must be
held. The only caller of nvmet_ns_changed which does not acquire that
lock is nvmet_ns_revalidate. nvmet_ns_revalidate has 3 callers,
of which 2 do not acquire that lock: nvmet_execute_identify_cns_cs_ns
and nvmet_execute_identify_ns. The other caller
nvmet_ns_revalidate_size_store does acquire the lock.

The solution is to remove the locking from the one callsite that
acquires the lock, and place all the locking necessary for
the call to nvmet_ns_changed inside the check in nvmet_ns_revalidate.

Both of those identify functions are called from a common function
nvmet_execute_identify, which itself is called indirectly via the
req->execute function pointer.

This issue was found using a static type-based analyser and manually
verified.

Signed-off-by: Niels Dossche <dossche.niels at gmail.com>
---

Changes in v4:
 - do the locking locally unconditionally

Changes in v3:
 - improve commit description
 - do the locking locally

Changes in v2:
 - added sentence about how the issue was found.
 - added missing &

 drivers/nvme/target/configfs.c | 3 ---
 drivers/nvme/target/core.c     | 5 ++++-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index 091a0ca16361..b67ea5772d99 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -580,14 +580,11 @@ static ssize_t nvmet_ns_revalidate_size_store(struct config_item *item,
 	if (!val)
 		return -EINVAL;
 
-	mutex_lock(&ns->subsys->lock);
 	if (!ns->enabled) {
 		pr_err("enable ns before revalidate.\n");
-		mutex_unlock(&ns->subsys->lock);
 		return -EINVAL;
 	}
 	nvmet_ns_revalidate(ns);
-	mutex_unlock(&ns->subsys->lock);
 	return count;
 }
 
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index 5119c687de68..a9a2d2b02dee 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -540,8 +540,11 @@ void nvmet_ns_revalidate(struct nvmet_ns *ns)
 	else
 		nvmet_file_ns_revalidate(ns);
 
-	if (oldsize != ns->size)
+	if (oldsize != ns->size) {
+		mutex_lock(&ns->subsys->lock);
 		nvmet_ns_changed(ns->subsys, ns->nsid);
+		mutex_unlock(&ns->subsys->lock);
+	}
 }
 
 int nvmet_ns_enable(struct nvmet_ns *ns)
-- 
2.35.1




More information about the Linux-nvme mailing list