* [PATCH] nvdimm: Introduce guard() for nvdimm_bus_lock
@ 2025-09-22 21:13 Dave Jiang
2025-09-22 22:50 ` dan.j.williams
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Dave Jiang @ 2025-09-22 21:13 UTC (permalink / raw)
To: nvdimm
Cc: ira.weiny, vishal.l.verma, dan.j.williams, jonathan.cameron,
s.neeraj
Converting nvdimm_bus_lock/unlock to guard() to clean up usage
of gotos for error handling and avoid future mistakes of missed
unlock on error paths.
Link: https://lore.kernel.org/linux-cxl/20250917163623.00004a3c@huawei.com/
Suggested-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
Ira, up to you if you want to take this cleanup.
---
drivers/nvdimm/badrange.c | 3 +-
drivers/nvdimm/btt_devs.c | 20 +++-----
drivers/nvdimm/bus.c | 17 +++----
drivers/nvdimm/claim.c | 5 +-
drivers/nvdimm/core.c | 17 ++++---
drivers/nvdimm/dax_devs.c | 8 ++--
drivers/nvdimm/dimm.c | 17 ++++---
drivers/nvdimm/dimm_devs.c | 43 ++++++++---------
drivers/nvdimm/namespace_devs.c | 81 +++++++++++++++------------------
drivers/nvdimm/nd.h | 2 +
drivers/nvdimm/pfn_devs.c | 29 +++++-------
drivers/nvdimm/region.c | 14 +++---
drivers/nvdimm/region_devs.c | 72 ++++++++++++++---------------
drivers/nvdimm/security.c | 6 +--
14 files changed, 149 insertions(+), 185 deletions(-)
diff --git a/drivers/nvdimm/badrange.c b/drivers/nvdimm/badrange.c
index ee478ccde7c6..36c626db459a 100644
--- a/drivers/nvdimm/badrange.c
+++ b/drivers/nvdimm/badrange.c
@@ -278,8 +278,7 @@ void nvdimm_badblocks_populate(struct nd_region *nd_region,
}
nvdimm_bus = walk_to_nvdimm_bus(&nd_region->dev);
- nvdimm_bus_lock(&nvdimm_bus->dev);
+ guard(nvdimm_bus)(&nvdimm_bus->dev);
badblocks_populate(&nvdimm_bus->badrange, bb, range);
- nvdimm_bus_unlock(&nvdimm_bus->dev);
}
EXPORT_SYMBOL_GPL(nvdimm_badblocks_populate);
diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c
index 497fd434a6a1..b35bcbe5db7f 100644
--- a/drivers/nvdimm/btt_devs.c
+++ b/drivers/nvdimm/btt_devs.c
@@ -50,14 +50,12 @@ static ssize_t sector_size_store(struct device *dev,
struct nd_btt *nd_btt = to_nd_btt(dev);
ssize_t rc;
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
rc = nd_size_select_store(dev, buf, &nd_btt->lbasize,
btt_lbasize_supported);
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
buf[len - 1] == '\n' ? "" : "\n");
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
return rc ? rc : len;
}
@@ -95,10 +93,9 @@ static ssize_t namespace_show(struct device *dev,
struct nd_btt *nd_btt = to_nd_btt(dev);
ssize_t rc;
- nvdimm_bus_lock(dev);
+ guard(nvdimm_bus)(dev);
rc = sprintf(buf, "%s\n", nd_btt->ndns
? dev_name(&nd_btt->ndns->dev) : "");
- nvdimm_bus_unlock(dev);
return rc;
}
@@ -108,13 +105,11 @@ static ssize_t namespace_store(struct device *dev,
struct nd_btt *nd_btt = to_nd_btt(dev);
ssize_t rc;
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
rc = nd_namespace_store(dev, &nd_btt->ndns, buf, len);
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
buf[len - 1] == '\n' ? "" : "\n");
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
return rc;
}
@@ -351,9 +346,8 @@ int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns)
return -ENODEV;
}
- nvdimm_bus_lock(&ndns->dev);
- btt_dev = __nd_btt_create(nd_region, 0, NULL, ndns);
- nvdimm_bus_unlock(&ndns->dev);
+ scoped_guard(nvdimm_bus, &ndns->dev)
+ btt_dev = __nd_btt_create(nd_region, 0, NULL, ndns);
if (!btt_dev)
return -ENOMEM;
btt_sb = devm_kzalloc(dev, sizeof(*btt_sb), GFP_KERNEL);
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 0ccf4a9e523a..d2c2d71e7fe0 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -64,17 +64,15 @@ static struct module *to_bus_provider(struct device *dev)
static void nvdimm_bus_probe_start(struct nvdimm_bus *nvdimm_bus)
{
- nvdimm_bus_lock(&nvdimm_bus->dev);
+ guard(nvdimm_bus)(&nvdimm_bus->dev);
nvdimm_bus->probe_active++;
- nvdimm_bus_unlock(&nvdimm_bus->dev);
}
static void nvdimm_bus_probe_end(struct nvdimm_bus *nvdimm_bus)
{
- nvdimm_bus_lock(&nvdimm_bus->dev);
+ guard(nvdimm_bus)(&nvdimm_bus->dev);
if (--nvdimm_bus->probe_active == 0)
wake_up(&nvdimm_bus->wait);
- nvdimm_bus_unlock(&nvdimm_bus->dev);
}
static int nvdimm_bus_probe(struct device *dev)
@@ -1177,15 +1175,15 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
goto out;
}
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
rc = nd_cmd_clear_to_send(nvdimm_bus, nvdimm, func, buf);
if (rc)
- goto out_unlock;
+ goto out;
rc = nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, &cmd_rc);
if (rc < 0)
- goto out_unlock;
+ goto out;
if (!nvdimm && cmd == ND_CMD_CLEAR_ERROR && cmd_rc >= 0) {
struct nd_cmd_clear_error *clear_err = buf;
@@ -1197,9 +1195,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
if (copy_to_user(p, buf, buf_len))
rc = -EFAULT;
-out_unlock:
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
out:
kfree(in_env);
kfree(out_env);
diff --git a/drivers/nvdimm/claim.c b/drivers/nvdimm/claim.c
index 51614651d2e7..e53a2cc04695 100644
--- a/drivers/nvdimm/claim.c
+++ b/drivers/nvdimm/claim.c
@@ -35,9 +35,8 @@ void nd_detach_ndns(struct device *dev,
if (!ndns)
return;
get_device(&ndns->dev);
- nvdimm_bus_lock(&ndns->dev);
- __nd_detach_ndns(dev, _ndns);
- nvdimm_bus_unlock(&ndns->dev);
+ scoped_guard(nvdimm_bus, &ndns->dev)
+ __nd_detach_ndns(dev, _ndns);
put_device(&ndns->dev);
}
diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c
index eaa796629c27..5ba204113fe1 100644
--- a/drivers/nvdimm/core.c
+++ b/drivers/nvdimm/core.c
@@ -141,9 +141,8 @@ static void nvdimm_map_put(void *data)
struct nvdimm_map *nvdimm_map = data;
struct nvdimm_bus *nvdimm_bus = nvdimm_map->nvdimm_bus;
- nvdimm_bus_lock(&nvdimm_bus->dev);
+ guard(nvdimm_bus)(&nvdimm_bus->dev);
kref_put(&nvdimm_map->kref, nvdimm_map_release);
- nvdimm_bus_unlock(&nvdimm_bus->dev);
}
/**
@@ -158,13 +157,13 @@ void *devm_nvdimm_memremap(struct device *dev, resource_size_t offset,
{
struct nvdimm_map *nvdimm_map;
- nvdimm_bus_lock(dev);
- nvdimm_map = find_nvdimm_map(dev, offset);
- if (!nvdimm_map)
- nvdimm_map = alloc_nvdimm_map(dev, offset, size, flags);
- else
- kref_get(&nvdimm_map->kref);
- nvdimm_bus_unlock(dev);
+ scoped_guard(nvdimm_bus, dev) {
+ nvdimm_map = find_nvdimm_map(dev, offset);
+ if (!nvdimm_map)
+ nvdimm_map = alloc_nvdimm_map(dev, offset, size, flags);
+ else
+ kref_get(&nvdimm_map->kref);
+ }
if (!nvdimm_map)
return NULL;
diff --git a/drivers/nvdimm/dax_devs.c b/drivers/nvdimm/dax_devs.c
index 37b743acbb7b..a5d44b5c9452 100644
--- a/drivers/nvdimm/dax_devs.c
+++ b/drivers/nvdimm/dax_devs.c
@@ -104,10 +104,10 @@ int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns)
return -ENODEV;
}
- nvdimm_bus_lock(&ndns->dev);
- nd_dax = nd_dax_alloc(nd_region);
- dax_dev = nd_dax_devinit(nd_dax, ndns);
- nvdimm_bus_unlock(&ndns->dev);
+ scoped_guard(nvdimm_bus, &ndns->dev) {
+ nd_dax = nd_dax_alloc(nd_region);
+ dax_dev = nd_dax_devinit(nd_dax, ndns);
+ }
if (!dax_dev)
return -ENOMEM;
pfn_sb = devm_kmalloc(dev, sizeof(*pfn_sb), GFP_KERNEL);
diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c
index 91d9163ee303..2018458a3dba 100644
--- a/drivers/nvdimm/dimm.c
+++ b/drivers/nvdimm/dimm.c
@@ -95,13 +95,13 @@ static int nvdimm_probe(struct device *dev)
dev_dbg(dev, "config data size: %d\n", ndd->nsarea.config_size);
- nvdimm_bus_lock(dev);
- if (ndd->ns_current >= 0) {
- rc = nd_label_reserve_dpa(ndd);
- if (rc == 0)
- nvdimm_set_labeling(dev);
+ scoped_guard(nvdimm_bus, dev) {
+ if (ndd->ns_current >= 0) {
+ rc = nd_label_reserve_dpa(ndd);
+ if (rc == 0)
+ nvdimm_set_labeling(dev);
+ }
}
- nvdimm_bus_unlock(dev);
if (rc)
goto err;
@@ -117,9 +117,8 @@ static void nvdimm_remove(struct device *dev)
{
struct nvdimm_drvdata *ndd = dev_get_drvdata(dev);
- nvdimm_bus_lock(dev);
- dev_set_drvdata(dev, NULL);
- nvdimm_bus_unlock(dev);
+ scoped_guard(nvdimm_bus, dev)
+ dev_set_drvdata(dev, NULL);
put_ndd(ndd);
}
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index 21498d461fde..4b293c4ad15c 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -226,10 +226,10 @@ void nvdimm_drvdata_release(struct kref *kref)
struct resource *res, *_r;
dev_dbg(dev, "trace\n");
- nvdimm_bus_lock(dev);
- for_each_dpa_resource_safe(ndd, res, _r)
- nvdimm_free_dpa(ndd, res);
- nvdimm_bus_unlock(dev);
+ scoped_guard(nvdimm_bus, dev) {
+ for_each_dpa_resource_safe(ndd, res, _r)
+ nvdimm_free_dpa(ndd, res);
+ }
kvfree(ndd->data);
kfree(ndd);
@@ -326,7 +326,7 @@ static ssize_t __available_slots_show(struct nvdimm_drvdata *ndd, char *buf)
return -ENXIO;
dev = ndd->dev;
- nvdimm_bus_lock(dev);
+ guard(nvdimm_bus)(dev);
nfree = nd_label_nfree(ndd);
if (nfree - 1 > nfree) {
dev_WARN_ONCE(dev, 1, "we ate our last label?\n");
@@ -334,7 +334,6 @@ static ssize_t __available_slots_show(struct nvdimm_drvdata *ndd, char *buf)
} else
nfree--;
rc = sprintf(buf, "%d\n", nfree);
- nvdimm_bus_unlock(dev);
return rc;
}
@@ -395,12 +394,10 @@ static ssize_t security_store(struct device *dev,
* done while probing is idle and the DIMM is not in active use
* in any region.
*/
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
wait_nvdimm_bus_probe_idle(dev);
rc = nvdimm_security_store(dev, buf, len);
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
return rc;
}
@@ -454,9 +451,8 @@ static ssize_t result_show(struct device *dev, struct device_attribute *attr, ch
if (!nvdimm->fw_ops)
return -EOPNOTSUPP;
- nvdimm_bus_lock(dev);
- result = nvdimm->fw_ops->activate_result(nvdimm);
- nvdimm_bus_unlock(dev);
+ scoped_guard(nvdimm_bus, dev)
+ result = nvdimm->fw_ops->activate_result(nvdimm);
switch (result) {
case NVDIMM_FWA_RESULT_NONE:
@@ -483,9 +479,8 @@ static ssize_t activate_show(struct device *dev, struct device_attribute *attr,
if (!nvdimm->fw_ops)
return -EOPNOTSUPP;
- nvdimm_bus_lock(dev);
- state = nvdimm->fw_ops->activate_state(nvdimm);
- nvdimm_bus_unlock(dev);
+ scoped_guard(nvdimm_bus, dev)
+ state = nvdimm->fw_ops->activate_state(nvdimm);
switch (state) {
case NVDIMM_FWA_IDLE:
@@ -516,9 +511,8 @@ static ssize_t activate_store(struct device *dev, struct device_attribute *attr,
else
return -EINVAL;
- nvdimm_bus_lock(dev);
+ guard(nvdimm_bus)(dev);
rc = nvdimm->fw_ops->arm(nvdimm, arg);
- nvdimm_bus_unlock(dev);
if (rc < 0)
return rc;
@@ -545,9 +539,8 @@ static umode_t nvdimm_firmware_visible(struct kobject *kobj, struct attribute *a
if (!nvdimm->fw_ops)
return 0;
- nvdimm_bus_lock(dev);
+ guard(nvdimm_bus)(dev);
cap = nd_desc->fw_ops->capability(nd_desc);
- nvdimm_bus_unlock(dev);
if (cap < NVDIMM_FWA_CAP_QUIESCE)
return 0;
@@ -641,11 +634,11 @@ void nvdimm_delete(struct nvdimm *nvdimm)
bool dev_put = false;
/* We are shutting down. Make state frozen artificially. */
- nvdimm_bus_lock(dev);
- set_bit(NVDIMM_SECURITY_FROZEN, &nvdimm->sec.flags);
- if (test_and_clear_bit(NDD_WORK_PENDING, &nvdimm->flags))
- dev_put = true;
- nvdimm_bus_unlock(dev);
+ scoped_guard(nvdimm_bus, dev) {
+ set_bit(NVDIMM_SECURITY_FROZEN, &nvdimm->sec.flags);
+ if (test_and_clear_bit(NDD_WORK_PENDING, &nvdimm->flags))
+ dev_put = true;
+ }
cancel_delayed_work_sync(&nvdimm->dwork);
if (dev_put)
put_device(dev);
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index 55cfbf1e0a95..38933abfb2a6 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -264,15 +264,13 @@ static ssize_t alt_name_store(struct device *dev,
struct nd_region *nd_region = to_nd_region(dev->parent);
ssize_t rc;
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
wait_nvdimm_bus_probe_idle(dev);
rc = __alt_name_store(dev, buf, len);
if (rc >= 0)
rc = nd_namespace_label_update(nd_region, dev);
dev_dbg(dev, "%s(%zd)\n", rc < 0 ? "fail " : "", rc);
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
return rc < 0 ? rc : len;
}
@@ -849,8 +847,8 @@ static ssize_t size_store(struct device *dev,
if (rc)
return rc;
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
wait_nvdimm_bus_probe_idle(dev);
rc = __size_store(dev, val);
if (rc >= 0)
@@ -866,9 +864,6 @@ static ssize_t size_store(struct device *dev,
dev_dbg(dev, "%llx %s (%d)\n", val, rc < 0 ? "fail" : "success", rc);
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
-
return rc < 0 ? rc : len;
}
@@ -893,9 +888,8 @@ resource_size_t nvdimm_namespace_capacity(struct nd_namespace_common *ndns)
{
resource_size_t size;
- nvdimm_bus_lock(&ndns->dev);
+ guard(nvdimm_bus)(&ndns->dev);
size = __nvdimm_namespace_capacity(ndns);
- nvdimm_bus_unlock(&ndns->dev);
return size;
}
@@ -1044,8 +1038,8 @@ static ssize_t uuid_store(struct device *dev,
} else
return -ENXIO;
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
wait_nvdimm_bus_probe_idle(dev);
if (to_ndns(dev)->claim)
rc = -EBUSY;
@@ -1059,8 +1053,6 @@ static ssize_t uuid_store(struct device *dev,
kfree(uuid);
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
buf[len - 1] == '\n' ? "" : "\n");
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
return rc < 0 ? rc : len;
}
@@ -1119,8 +1111,8 @@ static ssize_t sector_size_store(struct device *dev,
} else
return -ENXIO;
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
if (to_ndns(dev)->claim)
rc = -EBUSY;
if (rc >= 0)
@@ -1129,8 +1121,6 @@ static ssize_t sector_size_store(struct device *dev,
rc = nd_namespace_label_update(nd_region, dev);
dev_dbg(dev, "result: %zd %s: %s%s", rc, rc < 0 ? "tried" : "wrote",
buf, buf[len - 1] == '\n' ? "" : "\n");
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
return rc ? rc : len;
}
@@ -1145,7 +1135,7 @@ static ssize_t dpa_extents_show(struct device *dev,
int count = 0, i;
u32 flags = 0;
- nvdimm_bus_lock(dev);
+ guard(nvdimm_bus)(dev);
if (is_namespace_pmem(dev)) {
struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev);
@@ -1167,8 +1157,6 @@ static ssize_t dpa_extents_show(struct device *dev,
count++;
}
out:
- nvdimm_bus_unlock(dev);
-
return sprintf(buf, "%d\n", count);
}
static DEVICE_ATTR_RO(dpa_extents);
@@ -1279,15 +1267,13 @@ static ssize_t holder_class_store(struct device *dev,
struct nd_region *nd_region = to_nd_region(dev->parent);
int rc;
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
wait_nvdimm_bus_probe_idle(dev);
rc = __holder_class_store(dev, buf);
if (rc >= 0)
rc = nd_namespace_label_update(nd_region, dev);
dev_dbg(dev, "%s(%d)\n", rc < 0 ? "fail " : "", rc);
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
return rc < 0 ? rc : len;
}
@@ -2152,31 +2138,38 @@ static int init_active_labels(struct nd_region *nd_region)
nd_region);
}
+static int __create_namespaces(struct nd_region *nd_region, int *type,
+ struct device ***devs)
+{
+ int rc;
+
+ guard(nvdimm_bus)(&nd_region->dev);
+ rc = init_active_labels(nd_region);
+ if (rc)
+ return rc;
+
+ *type = nd_region_to_nstype(nd_region);
+ switch (*type) {
+ case ND_DEVICE_NAMESPACE_IO:
+ *devs = create_namespace_io(nd_region);
+ break;
+ case ND_DEVICE_NAMESPACE_PMEM:
+ *devs = create_namespaces(nd_region);
+ break;
+ }
+
+ return 0;
+}
+
int nd_region_register_namespaces(struct nd_region *nd_region, int *err)
{
struct device **devs = NULL;
int i, rc = 0, type;
*err = 0;
- nvdimm_bus_lock(&nd_region->dev);
- rc = init_active_labels(nd_region);
- if (rc) {
- nvdimm_bus_unlock(&nd_region->dev);
+ rc = __create_namespaces(nd_region, &type, &devs);
+ if (rc)
return rc;
- }
-
- type = nd_region_to_nstype(nd_region);
- switch (type) {
- case ND_DEVICE_NAMESPACE_IO:
- devs = create_namespace_io(nd_region);
- break;
- case ND_DEVICE_NAMESPACE_PMEM:
- devs = create_namespaces(nd_region);
- break;
- default:
- break;
- }
- nvdimm_bus_unlock(&nd_region->dev);
if (!devs)
return -ENODEV;
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index cc5c8f3f81e8..a8013033509c 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -632,6 +632,8 @@ u64 nd_region_interleave_set_cookie(struct nd_region *nd_region,
u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region);
void nvdimm_bus_lock(struct device *dev);
void nvdimm_bus_unlock(struct device *dev);
+DEFINE_GUARD(nvdimm_bus, struct device *, nvdimm_bus_lock(_T), nvdimm_bus_unlock(_T));
+
bool is_nvdimm_bus_locked(struct device *dev);
void nvdimm_check_and_set_ro(struct gendisk *disk);
void nvdimm_drvdata_release(struct kref *kref);
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index 8f3e816e805d..f2a44d1f62be 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -57,8 +57,8 @@ static ssize_t mode_store(struct device *dev,
struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
ssize_t rc = 0;
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
if (dev->driver)
rc = -EBUSY;
else {
@@ -78,8 +78,6 @@ static ssize_t mode_store(struct device *dev,
}
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
buf[len - 1] == '\n' ? "" : "\n");
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
return rc ? rc : len;
}
@@ -125,14 +123,12 @@ static ssize_t align_store(struct device *dev,
unsigned long aligns[MAX_NVDIMM_ALIGN] = { [0] = 0, };
ssize_t rc;
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
rc = nd_size_select_store(dev, buf, &nd_pfn->align,
nd_pfn_supported_alignments(aligns));
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
buf[len - 1] == '\n' ? "" : "\n");
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
return rc ? rc : len;
}
@@ -170,10 +166,9 @@ static ssize_t namespace_show(struct device *dev,
struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
ssize_t rc;
- nvdimm_bus_lock(dev);
+ guard(nvdimm_bus)(dev);
rc = sprintf(buf, "%s\n", nd_pfn->ndns
? dev_name(&nd_pfn->ndns->dev) : "");
- nvdimm_bus_unlock(dev);
return rc;
}
@@ -183,13 +178,11 @@ static ssize_t namespace_store(struct device *dev,
struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
ssize_t rc;
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
rc = nd_namespace_store(dev, &nd_pfn->ndns, buf, len);
dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
buf[len - 1] == '\n' ? "" : "\n");
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
return rc;
}
@@ -639,10 +632,10 @@ int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns)
return -ENODEV;
}
- nvdimm_bus_lock(&ndns->dev);
- nd_pfn = nd_pfn_alloc(nd_region);
- pfn_dev = nd_pfn_devinit(nd_pfn, ndns);
- nvdimm_bus_unlock(&ndns->dev);
+ scoped_guard(nvdimm_bus, &ndns->dev) {
+ nd_pfn = nd_pfn_alloc(nd_region);
+ pfn_dev = nd_pfn_devinit(nd_pfn, ndns);
+ }
if (!pfn_dev)
return -ENOMEM;
pfn_sb = devm_kmalloc(dev, sizeof(*pfn_sb), GFP_KERNEL);
diff --git a/drivers/nvdimm/region.c b/drivers/nvdimm/region.c
index 88dc062af5f8..2abbdcef8d33 100644
--- a/drivers/nvdimm/region.c
+++ b/drivers/nvdimm/region.c
@@ -87,13 +87,13 @@ static void nd_region_remove(struct device *dev)
device_for_each_child(dev, NULL, child_unregister);
/* flush attribute readers and disable */
- nvdimm_bus_lock(dev);
- nd_region->ns_seed = NULL;
- nd_region->btt_seed = NULL;
- nd_region->pfn_seed = NULL;
- nd_region->dax_seed = NULL;
- dev_set_drvdata(dev, NULL);
- nvdimm_bus_unlock(dev);
+ scoped_guard(nvdimm_bus, dev) {
+ nd_region->ns_seed = NULL;
+ nd_region->btt_seed = NULL;
+ nd_region->pfn_seed = NULL;
+ nd_region->dax_seed = NULL;
+ dev_set_drvdata(dev, NULL);
+ }
/*
* Note, this assumes device_lock() context to not race
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index de1ee5ebc851..b2b4519e9f4c 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -102,31 +102,44 @@ static int nd_region_invalidate_memregion(struct nd_region *nd_region)
return 0;
}
-int nd_region_activate(struct nd_region *nd_region)
+static int get_flush_data(struct nd_region *nd_region, size_t *size, int *num_flush)
{
- int i, j, rc, num_flush = 0;
- struct nd_region_data *ndrd;
- struct device *dev = &nd_region->dev;
size_t flush_data_size = sizeof(void *);
+ int _num_flush = 0;
+ int i;
- nvdimm_bus_lock(&nd_region->dev);
+ guard(nvdimm_bus)(&nd_region->dev);
for (i = 0; i < nd_region->ndr_mappings; i++) {
struct nd_mapping *nd_mapping = &nd_region->mapping[i];
struct nvdimm *nvdimm = nd_mapping->nvdimm;
- if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) {
- nvdimm_bus_unlock(&nd_region->dev);
+ if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags))
return -EBUSY;
- }
/* at least one null hint slot per-dimm for the "no-hint" case */
flush_data_size += sizeof(void *);
- num_flush = min_not_zero(num_flush, nvdimm->num_flush);
+ _num_flush = min_not_zero(_num_flush, nvdimm->num_flush);
if (!nvdimm->num_flush)
continue;
flush_data_size += nvdimm->num_flush * sizeof(void *);
}
- nvdimm_bus_unlock(&nd_region->dev);
+
+ *size = flush_data_size;
+ *num_flush = _num_flush;
+
+ return 0;
+}
+
+int nd_region_activate(struct nd_region *nd_region)
+{
+ int i, j, rc, num_flush;
+ struct nd_region_data *ndrd;
+ struct device *dev = &nd_region->dev;
+ size_t flush_data_size;
+
+ rc = get_flush_data(nd_region, &flush_data_size, &num_flush);
+ if (rc)
+ return rc;
rc = nd_region_invalidate_memregion(nd_region);
if (rc)
@@ -327,8 +340,8 @@ static ssize_t set_cookie_show(struct device *dev,
* the v1.1 namespace label cookie definition. To read all this
* data we need to wait for probing to settle.
*/
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
wait_nvdimm_bus_probe_idle(dev);
if (nd_region->ndr_mappings) {
struct nd_mapping *nd_mapping = &nd_region->mapping[0];
@@ -343,8 +356,6 @@ static ssize_t set_cookie_show(struct device *dev,
nsindex));
}
}
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
if (rc)
return rc;
@@ -401,12 +412,10 @@ static ssize_t available_size_show(struct device *dev,
* memory nvdimm_bus_lock() is dropped, but that's userspace's
* problem to not race itself.
*/
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
wait_nvdimm_bus_probe_idle(dev);
available = nd_region_available_dpa(nd_region);
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
return sprintf(buf, "%llu\n", available);
}
@@ -418,12 +427,10 @@ static ssize_t max_available_extent_show(struct device *dev,
struct nd_region *nd_region = to_nd_region(dev);
unsigned long long available = 0;
- device_lock(dev);
- nvdimm_bus_lock(dev);
+ guard(device)(dev);
+ guard(nvdimm_bus)(dev);
wait_nvdimm_bus_probe_idle(dev);
available = nd_region_allocatable_dpa(nd_region);
- nvdimm_bus_unlock(dev);
- device_unlock(dev);
return sprintf(buf, "%llu\n", available);
}
@@ -435,12 +442,11 @@ static ssize_t init_namespaces_show(struct device *dev,
struct nd_region_data *ndrd = dev_get_drvdata(dev);
ssize_t rc;
- nvdimm_bus_lock(dev);
+ guard(nvdimm_bus)(dev);
if (ndrd)
rc = sprintf(buf, "%d/%d\n", ndrd->ns_active, ndrd->ns_count);
else
rc = -ENXIO;
- nvdimm_bus_unlock(dev);
return rc;
}
@@ -452,12 +458,11 @@ static ssize_t namespace_seed_show(struct device *dev,
struct nd_region *nd_region = to_nd_region(dev);
ssize_t rc;
- nvdimm_bus_lock(dev);
+ guard(nvdimm_bus)(dev);
if (nd_region->ns_seed)
rc = sprintf(buf, "%s\n", dev_name(nd_region->ns_seed));
else
rc = sprintf(buf, "\n");
- nvdimm_bus_unlock(dev);
return rc;
}
static DEVICE_ATTR_RO(namespace_seed);
@@ -468,12 +473,11 @@ static ssize_t btt_seed_show(struct device *dev,
struct nd_region *nd_region = to_nd_region(dev);
ssize_t rc;
- nvdimm_bus_lock(dev);
+ guard(nvdimm_bus)(dev);
if (nd_region->btt_seed)
rc = sprintf(buf, "%s\n", dev_name(nd_region->btt_seed));
else
rc = sprintf(buf, "\n");
- nvdimm_bus_unlock(dev);
return rc;
}
@@ -485,12 +489,11 @@ static ssize_t pfn_seed_show(struct device *dev,
struct nd_region *nd_region = to_nd_region(dev);
ssize_t rc;
- nvdimm_bus_lock(dev);
+ guard(nvdimm_bus)(dev);
if (nd_region->pfn_seed)
rc = sprintf(buf, "%s\n", dev_name(nd_region->pfn_seed));
else
rc = sprintf(buf, "\n");
- nvdimm_bus_unlock(dev);
return rc;
}
@@ -502,12 +505,11 @@ static ssize_t dax_seed_show(struct device *dev,
struct nd_region *nd_region = to_nd_region(dev);
ssize_t rc;
- nvdimm_bus_lock(dev);
+ guard(nvdimm_bus)(dev);
if (nd_region->dax_seed)
rc = sprintf(buf, "%s\n", dev_name(nd_region->dax_seed));
else
rc = sprintf(buf, "\n");
- nvdimm_bus_unlock(dev);
return rc;
}
@@ -581,9 +583,8 @@ static ssize_t align_store(struct device *dev,
* times ensure it does not change for the duration of the
* allocation.
*/
- nvdimm_bus_lock(dev);
+ guard(nvdimm_bus)(dev);
nd_region->align = val;
- nvdimm_bus_unlock(dev);
return len;
}
@@ -890,7 +891,7 @@ void nd_mapping_free_labels(struct nd_mapping *nd_mapping)
*/
void nd_region_advance_seeds(struct nd_region *nd_region, struct device *dev)
{
- nvdimm_bus_lock(dev);
+ guard(nvdimm_bus)(dev);
if (nd_region->ns_seed == dev) {
nd_region_create_ns_seed(nd_region);
} else if (is_nd_btt(dev)) {
@@ -915,7 +916,6 @@ void nd_region_advance_seeds(struct nd_region *nd_region, struct device *dev)
if (nd_region->ns_seed == &nd_dax->nd_pfn.ndns->dev)
nd_region_create_ns_seed(nd_region);
}
- nvdimm_bus_unlock(dev);
}
/**
diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c
index a03e3c45f297..e70dc3b08458 100644
--- a/drivers/nvdimm/security.c
+++ b/drivers/nvdimm/security.c
@@ -221,9 +221,8 @@ int nvdimm_security_unlock(struct device *dev)
struct nvdimm *nvdimm = to_nvdimm(dev);
int rc;
- nvdimm_bus_lock(dev);
+ guard(nvdimm_bus)(dev);
rc = __nvdimm_security_unlock(nvdimm);
- nvdimm_bus_unlock(dev);
return rc;
}
@@ -490,9 +489,8 @@ void nvdimm_security_overwrite_query(struct work_struct *work)
struct nvdimm *nvdimm =
container_of(work, typeof(*nvdimm), dwork.work);
- nvdimm_bus_lock(&nvdimm->dev);
+ guard(nvdimm_bus)(&nvdimm->dev);
__nvdimm_security_overwrite_query(nvdimm);
- nvdimm_bus_unlock(&nvdimm->dev);
}
#define OPS \
base-commit: 07e27ad16399afcd693be20211b0dfae63e0615f
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH] nvdimm: Introduce guard() for nvdimm_bus_lock
2025-09-22 21:13 [PATCH] nvdimm: Introduce guard() for nvdimm_bus_lock Dave Jiang
@ 2025-09-22 22:50 ` dan.j.williams
2025-09-22 23:00 ` Dave Jiang
2025-09-23 1:58 ` kernel test robot
2025-09-23 10:18 ` Jonathan Cameron
2 siblings, 1 reply; 7+ messages in thread
From: dan.j.williams @ 2025-09-22 22:50 UTC (permalink / raw)
To: Dave Jiang, nvdimm
Cc: ira.weiny, vishal.l.verma, dan.j.williams, jonathan.cameron,
s.neeraj
Dave Jiang wrote:
> Converting nvdimm_bus_lock/unlock to guard() to clean up usage
> of gotos for error handling and avoid future mistakes of missed
> unlock on error paths.
>
> Link: https://lore.kernel.org/linux-cxl/20250917163623.00004a3c@huawei.com/
> Suggested-by: Jonathan Cameron <jonathan.cameron@huawei.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> ---
> Ira, up to you if you want to take this cleanup.
> ---
[..]
> diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
> index 0ccf4a9e523a..d2c2d71e7fe0 100644
> --- a/drivers/nvdimm/bus.c
> +++ b/drivers/nvdimm/bus.c
> @@ -1177,15 +1175,15 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
> goto out;
> }
>
> - device_lock(dev);
> - nvdimm_bus_lock(dev);
> + guard(device)(dev);
> + guard(nvdimm_bus)(dev);
> rc = nd_cmd_clear_to_send(nvdimm_bus, nvdimm, func, buf);
> if (rc)
> - goto out_unlock;
> + goto out;
>
> rc = nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, &cmd_rc);
> if (rc < 0)
> - goto out_unlock;
> + goto out;
>
> if (!nvdimm && cmd == ND_CMD_CLEAR_ERROR && cmd_rc >= 0) {
> struct nd_cmd_clear_error *clear_err = buf;
[..]
> diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c
> index 91d9163ee303..2018458a3dba 100644
> --- a/drivers/nvdimm/dimm.c
> +++ b/drivers/nvdimm/dimm.c
> @@ -95,13 +95,13 @@ static int nvdimm_probe(struct device *dev)
>
> dev_dbg(dev, "config data size: %d\n", ndd->nsarea.config_size);
>
> - nvdimm_bus_lock(dev);
> - if (ndd->ns_current >= 0) {
> - rc = nd_label_reserve_dpa(ndd);
> - if (rc == 0)
> - nvdimm_set_labeling(dev);
> + scoped_guard(nvdimm_bus, dev) {
> + if (ndd->ns_current >= 0) {
> + rc = nd_label_reserve_dpa(ndd);
> + if (rc == 0)
> + nvdimm_set_labeling(dev);
> + }
> }
> - nvdimm_bus_unlock(dev);
>
> if (rc)
> goto err;
[.. trim the hunks that successfully eliminated goto ..]
My litmus test for scoped-based-cleanup conversions is whether *all* of
the gotos are removed in a converted function. So either fully convert
all error unwind in a function to scope-based, or none of it. Do not
leave people to reason about potentially jumping through scopes with
goto.
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH] nvdimm: Introduce guard() for nvdimm_bus_lock
2025-09-22 22:50 ` dan.j.williams
@ 2025-09-22 23:00 ` Dave Jiang
2025-09-22 23:23 ` dan.j.williams
0 siblings, 1 reply; 7+ messages in thread
From: Dave Jiang @ 2025-09-22 23:00 UTC (permalink / raw)
To: dan.j.williams, nvdimm
Cc: ira.weiny, vishal.l.verma, jonathan.cameron, s.neeraj
On 9/22/25 3:50 PM, dan.j.williams@intel.com wrote:
> Dave Jiang wrote:
>> Converting nvdimm_bus_lock/unlock to guard() to clean up usage
>> of gotos for error handling and avoid future mistakes of missed
>> unlock on error paths.
>>
>> Link: https://lore.kernel.org/linux-cxl/20250917163623.00004a3c@huawei.com/
>> Suggested-by: Jonathan Cameron <jonathan.cameron@huawei.com>
>> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
>> ---
>> Ira, up to you if you want to take this cleanup.
>> ---
> [..]
>> diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
>> index 0ccf4a9e523a..d2c2d71e7fe0 100644
>> --- a/drivers/nvdimm/bus.c
>> +++ b/drivers/nvdimm/bus.c
>> @@ -1177,15 +1175,15 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
>> goto out;
>> }
>>
>> - device_lock(dev);
>> - nvdimm_bus_lock(dev);
>> + guard(device)(dev);
>> + guard(nvdimm_bus)(dev);
>> rc = nd_cmd_clear_to_send(nvdimm_bus, nvdimm, func, buf);
>> if (rc)
>> - goto out_unlock;
>> + goto out;
>>
>> rc = nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, &cmd_rc);
>> if (rc < 0)
>> - goto out_unlock;
>> + goto out;
>>
>> if (!nvdimm && cmd == ND_CMD_CLEAR_ERROR && cmd_rc >= 0) {
>> struct nd_cmd_clear_error *clear_err = buf;
> [..]
>> diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c
>> index 91d9163ee303..2018458a3dba 100644
>> --- a/drivers/nvdimm/dimm.c
>> +++ b/drivers/nvdimm/dimm.c
>> @@ -95,13 +95,13 @@ static int nvdimm_probe(struct device *dev)
>>
>> dev_dbg(dev, "config data size: %d\n", ndd->nsarea.config_size);
>>
>> - nvdimm_bus_lock(dev);
>> - if (ndd->ns_current >= 0) {
>> - rc = nd_label_reserve_dpa(ndd);
>> - if (rc == 0)
>> - nvdimm_set_labeling(dev);
>> + scoped_guard(nvdimm_bus, dev) {
>> + if (ndd->ns_current >= 0) {
>> + rc = nd_label_reserve_dpa(ndd);
>> + if (rc == 0)
>> + nvdimm_set_labeling(dev);
>> + }
>> }
>> - nvdimm_bus_unlock(dev);
>>
>> if (rc)
>> goto err;
> [.. trim the hunks that successfully eliminated goto ..]
>
> My litmus test for scoped-based-cleanup conversions is whether *all* of
> the gotos are removed in a converted function. So either fully convert
> all error unwind in a function to scope-based, or none of it. Do not
> leave people to reason about potentially jumping through scopes with
> goto.
This needs a bit more changes. I was undecided if I should include those changes in this patch or if they push out of scope. But it sounds like I should include them.
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH] nvdimm: Introduce guard() for nvdimm_bus_lock
2025-09-22 23:00 ` Dave Jiang
@ 2025-09-22 23:23 ` dan.j.williams
0 siblings, 0 replies; 7+ messages in thread
From: dan.j.williams @ 2025-09-22 23:23 UTC (permalink / raw)
To: Dave Jiang, dan.j.williams, nvdimm
Cc: ira.weiny, vishal.l.verma, jonathan.cameron, s.neeraj
Dave Jiang wrote:
[..]
> This needs a bit more changes. I was undecided if I should include
> those changes in this patch or if they push out of scope. But it
> sounds like I should include them.
You can do them in their own patches, but I would keep those patches
together in a series.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] nvdimm: Introduce guard() for nvdimm_bus_lock
2025-09-22 21:13 [PATCH] nvdimm: Introduce guard() for nvdimm_bus_lock Dave Jiang
2025-09-22 22:50 ` dan.j.williams
@ 2025-09-23 1:58 ` kernel test robot
2025-09-23 10:18 ` Jonathan Cameron
2 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2025-09-23 1:58 UTC (permalink / raw)
To: Dave Jiang, nvdimm
Cc: llvm, oe-kbuild-all, ira.weiny, vishal.l.verma, dan.j.williams,
jonathan.cameron, s.neeraj
Hi Dave,
kernel test robot noticed the following build errors:
[auto build test ERROR on 07e27ad16399afcd693be20211b0dfae63e0615f]
url: https://github.com/intel-lab-lkp/linux/commits/Dave-Jiang/nvdimm-Introduce-guard-for-nvdimm_bus_lock/20250923-051440
base: 07e27ad16399afcd693be20211b0dfae63e0615f
patch link: https://lore.kernel.org/r/20250922211330.1433044-1-dave.jiang%40intel.com
patch subject: [PATCH] nvdimm: Introduce guard() for nvdimm_bus_lock
config: x86_64-buildonly-randconfig-006-20250923 (https://download.01.org/0day-ci/archive/20250923/202509230941.jMdKMPL8-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250923/202509230941.jMdKMPL8-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202509230941.jMdKMPL8-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/nvdimm/bus.c:1175:3: error: cannot jump from this goto statement to its label
1175 | goto out;
| ^
drivers/nvdimm/bus.c:1179:2: note: jump bypasses initialization of variable with __attribute__((cleanup))
1179 | guard(nvdimm_bus)(dev);
| ^
include/linux/cleanup.h:401:15: note: expanded from macro 'guard'
401 | CLASS(_name, __UNIQUE_ID(guard))
| ^
include/linux/compiler.h:166:29: note: expanded from macro '__UNIQUE_ID'
166 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
| ^
include/linux/compiler_types.h:84:22: note: expanded from macro '__PASTE'
84 | #define __PASTE(a,b) ___PASTE(a,b)
| ^
include/linux/compiler_types.h:83:23: note: expanded from macro '___PASTE'
83 | #define ___PASTE(a,b) a##b
| ^
<scratch space>:93:1: note: expanded from here
93 | __UNIQUE_ID_guard458
| ^
drivers/nvdimm/bus.c:1178:2: note: jump bypasses initialization of variable with __attribute__((cleanup))
1178 | guard(device)(dev);
| ^
include/linux/cleanup.h:401:15: note: expanded from macro 'guard'
401 | CLASS(_name, __UNIQUE_ID(guard))
| ^
include/linux/compiler.h:166:29: note: expanded from macro '__UNIQUE_ID'
166 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
| ^
include/linux/compiler_types.h:84:22: note: expanded from macro '__PASTE'
84 | #define __PASTE(a,b) ___PASTE(a,b)
| ^
include/linux/compiler_types.h:83:23: note: expanded from macro '___PASTE'
83 | #define ___PASTE(a,b) a##b
| ^
<scratch space>:84:1: note: expanded from here
84 | __UNIQUE_ID_guard457
| ^
drivers/nvdimm/bus.c:1170:3: error: cannot jump from this goto statement to its label
1170 | goto out;
| ^
drivers/nvdimm/bus.c:1179:2: note: jump bypasses initialization of variable with __attribute__((cleanup))
1179 | guard(nvdimm_bus)(dev);
| ^
include/linux/cleanup.h:401:15: note: expanded from macro 'guard'
401 | CLASS(_name, __UNIQUE_ID(guard))
| ^
include/linux/compiler.h:166:29: note: expanded from macro '__UNIQUE_ID'
166 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
| ^
include/linux/compiler_types.h:84:22: note: expanded from macro '__PASTE'
84 | #define __PASTE(a,b) ___PASTE(a,b)
| ^
include/linux/compiler_types.h:83:23: note: expanded from macro '___PASTE'
83 | #define ___PASTE(a,b) a##b
| ^
<scratch space>:93:1: note: expanded from here
93 | __UNIQUE_ID_guard458
| ^
drivers/nvdimm/bus.c:1178:2: note: jump bypasses initialization of variable with __attribute__((cleanup))
1178 | guard(device)(dev);
| ^
include/linux/cleanup.h:401:15: note: expanded from macro 'guard'
401 | CLASS(_name, __UNIQUE_ID(guard))
| ^
include/linux/compiler.h:166:29: note: expanded from macro '__UNIQUE_ID'
166 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
| ^
include/linux/compiler_types.h:84:22: note: expanded from macro '__PASTE'
84 | #define __PASTE(a,b) ___PASTE(a,b)
| ^
include/linux/compiler_types.h:83:23: note: expanded from macro '___PASTE'
83 | #define ___PASTE(a,b) a##b
| ^
<scratch space>:84:1: note: expanded from here
84 | __UNIQUE_ID_guard457
| ^
drivers/nvdimm/bus.c:1164:3: error: cannot jump from this goto statement to its label
1164 | goto out;
| ^
drivers/nvdimm/bus.c:1179:2: note: jump bypasses initialization of variable with __attribute__((cleanup))
1179 | guard(nvdimm_bus)(dev);
| ^
include/linux/cleanup.h:401:15: note: expanded from macro 'guard'
401 | CLASS(_name, __UNIQUE_ID(guard))
| ^
include/linux/compiler.h:166:29: note: expanded from macro '__UNIQUE_ID'
166 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
| ^
include/linux/compiler_types.h:84:22: note: expanded from macro '__PASTE'
84 | #define __PASTE(a,b) ___PASTE(a,b)
| ^
include/linux/compiler_types.h:83:23: note: expanded from macro '___PASTE'
83 | #define ___PASTE(a,b) a##b
| ^
<scratch space>:93:1: note: expanded from here
93 | __UNIQUE_ID_guard458
| ^
drivers/nvdimm/bus.c:1178:2: note: jump bypasses initialization of variable with __attribute__((cleanup))
1178 | guard(device)(dev);
vim +1175 drivers/nvdimm/bus.c
eaf961536e1622 Dan Williams 2015-05-01 1023
62232e45f4a265 Dan Williams 2015-06-08 1024 static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
62232e45f4a265 Dan Williams 2015-06-08 1025 int read_only, unsigned int ioctl_cmd, unsigned long arg)
62232e45f4a265 Dan Williams 2015-06-08 1026 {
62232e45f4a265 Dan Williams 2015-06-08 1027 struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc;
62232e45f4a265 Dan Williams 2015-06-08 1028 const struct nd_cmd_desc *desc = NULL;
62232e45f4a265 Dan Williams 2015-06-08 1029 unsigned int cmd = _IOC_NR(ioctl_cmd);
62232e45f4a265 Dan Williams 2015-06-08 1030 struct device *dev = &nvdimm_bus->dev;
58738c495e15ba Dan Williams 2017-08-31 1031 void __user *p = (void __user *) arg;
6de5d06e657acd Dan Williams 2019-07-17 1032 char *out_env = NULL, *in_env = NULL;
62232e45f4a265 Dan Williams 2015-06-08 1033 const char *cmd_name, *dimm_name;
58738c495e15ba Dan Williams 2017-08-31 1034 u32 in_len = 0, out_len = 0;
58738c495e15ba Dan Williams 2017-08-31 1035 unsigned int func = cmd;
e3654eca70d637 Dan Williams 2016-04-28 1036 unsigned long cmd_mask;
58738c495e15ba Dan Williams 2017-08-31 1037 struct nd_cmd_pkg pkg;
006358b35c73ab Dave Jiang 2017-04-07 1038 int rc, i, cmd_rc;
6de5d06e657acd Dan Williams 2019-07-17 1039 void *buf = NULL;
58738c495e15ba Dan Williams 2017-08-31 1040 u64 buf_len = 0;
62232e45f4a265 Dan Williams 2015-06-08 1041
62232e45f4a265 Dan Williams 2015-06-08 1042 if (nvdimm) {
62232e45f4a265 Dan Williams 2015-06-08 1043 desc = nd_cmd_dimm_desc(cmd);
62232e45f4a265 Dan Williams 2015-06-08 1044 cmd_name = nvdimm_cmd_name(cmd);
e3654eca70d637 Dan Williams 2016-04-28 1045 cmd_mask = nvdimm->cmd_mask;
62232e45f4a265 Dan Williams 2015-06-08 1046 dimm_name = dev_name(&nvdimm->dev);
62232e45f4a265 Dan Williams 2015-06-08 1047 } else {
62232e45f4a265 Dan Williams 2015-06-08 1048 desc = nd_cmd_bus_desc(cmd);
62232e45f4a265 Dan Williams 2015-06-08 1049 cmd_name = nvdimm_bus_cmd_name(cmd);
e3654eca70d637 Dan Williams 2016-04-28 1050 cmd_mask = nd_desc->cmd_mask;
62232e45f4a265 Dan Williams 2015-06-08 1051 dimm_name = "bus";
62232e45f4a265 Dan Williams 2015-06-08 1052 }
62232e45f4a265 Dan Williams 2015-06-08 1053
92fe2aa859f52c Dan Williams 2020-07-20 1054 /* Validate command family support against bus declared support */
31eca76ba2fc98 Dan Williams 2016-04-28 1055 if (cmd == ND_CMD_CALL) {
92fe2aa859f52c Dan Williams 2020-07-20 1056 unsigned long *mask;
92fe2aa859f52c Dan Williams 2020-07-20 1057
31eca76ba2fc98 Dan Williams 2016-04-28 1058 if (copy_from_user(&pkg, p, sizeof(pkg)))
31eca76ba2fc98 Dan Williams 2016-04-28 1059 return -EFAULT;
92fe2aa859f52c Dan Williams 2020-07-20 1060
92fe2aa859f52c Dan Williams 2020-07-20 1061 if (nvdimm) {
92fe2aa859f52c Dan Williams 2020-07-20 1062 if (pkg.nd_family > NVDIMM_FAMILY_MAX)
92fe2aa859f52c Dan Williams 2020-07-20 1063 return -EINVAL;
92fe2aa859f52c Dan Williams 2020-07-20 1064 mask = &nd_desc->dimm_family_mask;
92fe2aa859f52c Dan Williams 2020-07-20 1065 } else {
92fe2aa859f52c Dan Williams 2020-07-20 1066 if (pkg.nd_family > NVDIMM_BUS_FAMILY_MAX)
92fe2aa859f52c Dan Williams 2020-07-20 1067 return -EINVAL;
92fe2aa859f52c Dan Williams 2020-07-20 1068 mask = &nd_desc->bus_family_mask;
92fe2aa859f52c Dan Williams 2020-07-20 1069 }
92fe2aa859f52c Dan Williams 2020-07-20 1070
92fe2aa859f52c Dan Williams 2020-07-20 1071 if (!test_bit(pkg.nd_family, mask))
92fe2aa859f52c Dan Williams 2020-07-20 1072 return -EINVAL;
31eca76ba2fc98 Dan Williams 2016-04-28 1073 }
31eca76ba2fc98 Dan Williams 2016-04-28 1074
f84afbdd3a9e5e Dan Carpenter 2020-02-25 1075 if (!desc ||
f84afbdd3a9e5e Dan Carpenter 2020-02-25 1076 (desc->out_num + desc->in_num == 0) ||
f84afbdd3a9e5e Dan Carpenter 2020-02-25 1077 cmd > ND_CMD_CALL ||
e3654eca70d637 Dan Williams 2016-04-28 1078 !test_bit(cmd, &cmd_mask))
62232e45f4a265 Dan Williams 2015-06-08 1079 return -ENOTTY;
62232e45f4a265 Dan Williams 2015-06-08 1080
62232e45f4a265 Dan Williams 2015-06-08 1081 /* fail write commands (when read-only) */
62232e45f4a265 Dan Williams 2015-06-08 1082 if (read_only)
07accfa9d1a8ba Jerry Hoemann 2016-01-06 1083 switch (cmd) {
07accfa9d1a8ba Jerry Hoemann 2016-01-06 1084 case ND_CMD_VENDOR:
07accfa9d1a8ba Jerry Hoemann 2016-01-06 1085 case ND_CMD_SET_CONFIG_DATA:
07accfa9d1a8ba Jerry Hoemann 2016-01-06 1086 case ND_CMD_ARS_START:
d4f323672aa637 Dan Williams 2016-03-03 1087 case ND_CMD_CLEAR_ERROR:
31eca76ba2fc98 Dan Williams 2016-04-28 1088 case ND_CMD_CALL:
ca6bf264f6d856 Dan Williams 2019-07-17 1089 dev_dbg(dev, "'%s' command while read-only.\n",
62232e45f4a265 Dan Williams 2015-06-08 1090 nvdimm ? nvdimm_cmd_name(cmd)
62232e45f4a265 Dan Williams 2015-06-08 1091 : nvdimm_bus_cmd_name(cmd));
62232e45f4a265 Dan Williams 2015-06-08 1092 return -EPERM;
62232e45f4a265 Dan Williams 2015-06-08 1093 default:
62232e45f4a265 Dan Williams 2015-06-08 1094 break;
62232e45f4a265 Dan Williams 2015-06-08 1095 }
62232e45f4a265 Dan Williams 2015-06-08 1096
62232e45f4a265 Dan Williams 2015-06-08 1097 /* process an input envelope */
6de5d06e657acd Dan Williams 2019-07-17 1098 in_env = kzalloc(ND_CMD_MAX_ENVELOPE, GFP_KERNEL);
6de5d06e657acd Dan Williams 2019-07-17 1099 if (!in_env)
6de5d06e657acd Dan Williams 2019-07-17 1100 return -ENOMEM;
62232e45f4a265 Dan Williams 2015-06-08 1101 for (i = 0; i < desc->in_num; i++) {
62232e45f4a265 Dan Williams 2015-06-08 1102 u32 in_size, copy;
62232e45f4a265 Dan Williams 2015-06-08 1103
62232e45f4a265 Dan Williams 2015-06-08 1104 in_size = nd_cmd_in_size(nvdimm, cmd, desc, i, in_env);
62232e45f4a265 Dan Williams 2015-06-08 1105 if (in_size == UINT_MAX) {
62232e45f4a265 Dan Williams 2015-06-08 1106 dev_err(dev, "%s:%s unknown input size cmd: %s field: %d\n",
62232e45f4a265 Dan Williams 2015-06-08 1107 __func__, dimm_name, cmd_name, i);
6de5d06e657acd Dan Williams 2019-07-17 1108 rc = -ENXIO;
6de5d06e657acd Dan Williams 2019-07-17 1109 goto out;
45def22c1fab85 Dan Williams 2015-04-26 1110 }
6de5d06e657acd Dan Williams 2019-07-17 1111 if (in_len < ND_CMD_MAX_ENVELOPE)
6de5d06e657acd Dan Williams 2019-07-17 1112 copy = min_t(u32, ND_CMD_MAX_ENVELOPE - in_len, in_size);
62232e45f4a265 Dan Williams 2015-06-08 1113 else
62232e45f4a265 Dan Williams 2015-06-08 1114 copy = 0;
6de5d06e657acd Dan Williams 2019-07-17 1115 if (copy && copy_from_user(&in_env[in_len], p + in_len, copy)) {
6de5d06e657acd Dan Williams 2019-07-17 1116 rc = -EFAULT;
6de5d06e657acd Dan Williams 2019-07-17 1117 goto out;
6de5d06e657acd Dan Williams 2019-07-17 1118 }
62232e45f4a265 Dan Williams 2015-06-08 1119 in_len += in_size;
62232e45f4a265 Dan Williams 2015-06-08 1120 }
62232e45f4a265 Dan Williams 2015-06-08 1121
31eca76ba2fc98 Dan Williams 2016-04-28 1122 if (cmd == ND_CMD_CALL) {
53b85a449b15e0 Jerry Hoemann 2017-06-30 1123 func = pkg.nd_command;
426824d63b77bd Dan Williams 2018-03-05 1124 dev_dbg(dev, "%s, idx: %llu, in: %u, out: %u, len %llu\n",
426824d63b77bd Dan Williams 2018-03-05 1125 dimm_name, pkg.nd_command,
31eca76ba2fc98 Dan Williams 2016-04-28 1126 in_len, out_len, buf_len);
31eca76ba2fc98 Dan Williams 2016-04-28 1127 }
31eca76ba2fc98 Dan Williams 2016-04-28 1128
62232e45f4a265 Dan Williams 2015-06-08 1129 /* process an output envelope */
6de5d06e657acd Dan Williams 2019-07-17 1130 out_env = kzalloc(ND_CMD_MAX_ENVELOPE, GFP_KERNEL);
6de5d06e657acd Dan Williams 2019-07-17 1131 if (!out_env) {
6de5d06e657acd Dan Williams 2019-07-17 1132 rc = -ENOMEM;
6de5d06e657acd Dan Williams 2019-07-17 1133 goto out;
6de5d06e657acd Dan Williams 2019-07-17 1134 }
6de5d06e657acd Dan Williams 2019-07-17 1135
62232e45f4a265 Dan Williams 2015-06-08 1136 for (i = 0; i < desc->out_num; i++) {
62232e45f4a265 Dan Williams 2015-06-08 1137 u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i,
efda1b5d87cbc3 Dan Williams 2016-12-06 1138 (u32 *) in_env, (u32 *) out_env, 0);
62232e45f4a265 Dan Williams 2015-06-08 1139 u32 copy;
62232e45f4a265 Dan Williams 2015-06-08 1140
62232e45f4a265 Dan Williams 2015-06-08 1141 if (out_size == UINT_MAX) {
426824d63b77bd Dan Williams 2018-03-05 1142 dev_dbg(dev, "%s unknown output size cmd: %s field: %d\n",
426824d63b77bd Dan Williams 2018-03-05 1143 dimm_name, cmd_name, i);
6de5d06e657acd Dan Williams 2019-07-17 1144 rc = -EFAULT;
6de5d06e657acd Dan Williams 2019-07-17 1145 goto out;
62232e45f4a265 Dan Williams 2015-06-08 1146 }
6de5d06e657acd Dan Williams 2019-07-17 1147 if (out_len < ND_CMD_MAX_ENVELOPE)
6de5d06e657acd Dan Williams 2019-07-17 1148 copy = min_t(u32, ND_CMD_MAX_ENVELOPE - out_len, out_size);
62232e45f4a265 Dan Williams 2015-06-08 1149 else
62232e45f4a265 Dan Williams 2015-06-08 1150 copy = 0;
62232e45f4a265 Dan Williams 2015-06-08 1151 if (copy && copy_from_user(&out_env[out_len],
6de5d06e657acd Dan Williams 2019-07-17 1152 p + in_len + out_len, copy)) {
6de5d06e657acd Dan Williams 2019-07-17 1153 rc = -EFAULT;
6de5d06e657acd Dan Williams 2019-07-17 1154 goto out;
6de5d06e657acd Dan Williams 2019-07-17 1155 }
62232e45f4a265 Dan Williams 2015-06-08 1156 out_len += out_size;
62232e45f4a265 Dan Williams 2015-06-08 1157 }
62232e45f4a265 Dan Williams 2015-06-08 1158
58738c495e15ba Dan Williams 2017-08-31 1159 buf_len = (u64) out_len + (u64) in_len;
62232e45f4a265 Dan Williams 2015-06-08 1160 if (buf_len > ND_IOCTL_MAX_BUFLEN) {
426824d63b77bd Dan Williams 2018-03-05 1161 dev_dbg(dev, "%s cmd: %s buf_len: %llu > %d\n", dimm_name,
426824d63b77bd Dan Williams 2018-03-05 1162 cmd_name, buf_len, ND_IOCTL_MAX_BUFLEN);
6de5d06e657acd Dan Williams 2019-07-17 1163 rc = -EINVAL;
6de5d06e657acd Dan Williams 2019-07-17 1164 goto out;
62232e45f4a265 Dan Williams 2015-06-08 1165 }
62232e45f4a265 Dan Williams 2015-06-08 1166
62232e45f4a265 Dan Williams 2015-06-08 1167 buf = vmalloc(buf_len);
6de5d06e657acd Dan Williams 2019-07-17 1168 if (!buf) {
6de5d06e657acd Dan Williams 2019-07-17 1169 rc = -ENOMEM;
6de5d06e657acd Dan Williams 2019-07-17 1170 goto out;
6de5d06e657acd Dan Williams 2019-07-17 1171 }
62232e45f4a265 Dan Williams 2015-06-08 1172
62232e45f4a265 Dan Williams 2015-06-08 1173 if (copy_from_user(buf, p, buf_len)) {
62232e45f4a265 Dan Williams 2015-06-08 1174 rc = -EFAULT;
62232e45f4a265 Dan Williams 2015-06-08 @1175 goto out;
62232e45f4a265 Dan Williams 2015-06-08 1176 }
62232e45f4a265 Dan Williams 2015-06-08 1177
eb0e82bc5f69da Dave Jiang 2025-09-22 1178 guard(device)(dev);
eb0e82bc5f69da Dave Jiang 2025-09-22 1179 guard(nvdimm_bus)(dev);
53b85a449b15e0 Jerry Hoemann 2017-06-30 1180 rc = nd_cmd_clear_to_send(nvdimm_bus, nvdimm, func, buf);
eaf961536e1622 Dan Williams 2015-05-01 1181 if (rc)
eb0e82bc5f69da Dave Jiang 2025-09-22 1182 goto out;
eaf961536e1622 Dan Williams 2015-05-01 1183
006358b35c73ab Dave Jiang 2017-04-07 1184 rc = nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, &cmd_rc);
62232e45f4a265 Dan Williams 2015-06-08 1185 if (rc < 0)
eb0e82bc5f69da Dave Jiang 2025-09-22 1186 goto out;
006358b35c73ab Dave Jiang 2017-04-07 1187
006358b35c73ab Dave Jiang 2017-04-07 1188 if (!nvdimm && cmd == ND_CMD_CLEAR_ERROR && cmd_rc >= 0) {
006358b35c73ab Dave Jiang 2017-04-07 1189 struct nd_cmd_clear_error *clear_err = buf;
006358b35c73ab Dave Jiang 2017-04-07 1190
23f4984483623c Dan Williams 2017-04-29 1191 nvdimm_account_cleared_poison(nvdimm_bus, clear_err->address,
006358b35c73ab Dave Jiang 2017-04-07 1192 clear_err->cleared);
006358b35c73ab Dave Jiang 2017-04-07 1193 }
0beb2012a17226 Dan Williams 2017-04-07 1194
62232e45f4a265 Dan Williams 2015-06-08 1195 if (copy_to_user(p, buf, buf_len))
62232e45f4a265 Dan Williams 2015-06-08 1196 rc = -EFAULT;
0beb2012a17226 Dan Williams 2017-04-07 1197
62232e45f4a265 Dan Williams 2015-06-08 1198 out:
6de5d06e657acd Dan Williams 2019-07-17 1199 kfree(in_env);
6de5d06e657acd Dan Williams 2019-07-17 1200 kfree(out_env);
62232e45f4a265 Dan Williams 2015-06-08 1201 vfree(buf);
62232e45f4a265 Dan Williams 2015-06-08 1202 return rc;
62232e45f4a265 Dan Williams 2015-06-08 1203 }
62232e45f4a265 Dan Williams 2015-06-08 1204
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH] nvdimm: Introduce guard() for nvdimm_bus_lock
2025-09-22 21:13 [PATCH] nvdimm: Introduce guard() for nvdimm_bus_lock Dave Jiang
2025-09-22 22:50 ` dan.j.williams
2025-09-23 1:58 ` kernel test robot
@ 2025-09-23 10:18 ` Jonathan Cameron
2025-09-23 16:36 ` Dave Jiang
2 siblings, 1 reply; 7+ messages in thread
From: Jonathan Cameron @ 2025-09-23 10:18 UTC (permalink / raw)
To: Dave Jiang; +Cc: nvdimm, ira.weiny, vishal.l.verma, dan.j.williams, s.neeraj
On Mon, 22 Sep 2025 14:13:30 -0700
Dave Jiang <dave.jiang@intel.com> wrote:
> Converting nvdimm_bus_lock/unlock to guard() to clean up usage
> of gotos for error handling and avoid future mistakes of missed
> unlock on error paths.
>
> Link: https://lore.kernel.org/linux-cxl/20250917163623.00004a3c@huawei.com/
> Suggested-by: Jonathan Cameron <jonathan.cameron@huawei.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Hi Dave,
Thanks for looking at this.
Fully agree with Dan about the getting rid of all gotos by end of series.
A few other things inline. Mostly places where the use of guard()
opens up low hanging fruit that improves readability (+ shortens code).
This code has a lot of dev_dbg() and some of them are so generic I'm not
sure they are actually useful (cover a whole set of error paths). Perhaps
it is worth splitting some of those up, or reducing the paths that trigger
them as part of this refactor.
Jonathan
> EXPORT_SYMBOL_GPL(nvdimm_badblocks_populate);
> diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c
> index 497fd434a6a1..b35bcbe5db7f 100644
> --- a/drivers/nvdimm/btt_devs.c
> +++ b/drivers/nvdimm/btt_devs.c
...
> @@ -95,10 +93,9 @@ static ssize_t namespace_show(struct device *dev,
> struct nd_btt *nd_btt = to_nd_btt(dev);
> ssize_t rc;
>
> - nvdimm_bus_lock(dev);
> + guard(nvdimm_bus)(dev);
> rc = sprintf(buf, "%s\n", nd_btt->ndns
> ? dev_name(&nd_btt->ndns->dev) : "");
return sprintf();
and drop the local variable.
> - nvdimm_bus_unlock(dev);
> return rc;
> }
>
> diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
> index 0ccf4a9e523a..d2c2d71e7fe0 100644
> --- a/drivers/nvdimm/bus.c
> +++ b/drivers/nvdimm/bus.c
> static int nvdimm_bus_probe(struct device *dev)
> @@ -1177,15 +1175,15 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
> goto out;
> }
>
> - device_lock(dev);
> - nvdimm_bus_lock(dev);
> + guard(device)(dev);
> + guard(nvdimm_bus)(dev);
> rc = nd_cmd_clear_to_send(nvdimm_bus, nvdimm, func, buf);
> if (rc)
> - goto out_unlock;
> + goto out;
>
> rc = nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, &cmd_rc);
> if (rc < 0)
> - goto out_unlock;
> + goto out;
>
> if (!nvdimm && cmd == ND_CMD_CLEAR_ERROR && cmd_rc >= 0) {
> struct nd_cmd_clear_error *clear_err = buf;
> @@ -1197,9 +1195,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
> if (copy_to_user(p, buf, buf_len))
> rc = -EFAULT;
>
> -out_unlock:
> - nvdimm_bus_unlock(dev);
> - device_unlock(dev);
> out:
Hmm. I'm not a fan of gotos that rely on initializing a bunch of pointers to NULL
so fewer labels are used. Will be nice to replace that as well via __free
Going to need a DEFINE_FREE for the vfree that follow these but that looks standard to me.
> kfree(in_env);
> kfree(out_env);
> diff --git a/drivers/nvdimm/claim.c b/drivers/nvdimm/claim.c
> index 51614651d2e7..e53a2cc04695 100644
> --- a/drivers/nvdimm/claim.c
> +++ b/drivers/nvdimm/claim.c
> @@ -35,9 +35,8 @@ void nd_detach_ndns(struct device *dev,
> if (!ndns)
> return;
> get_device(&ndns->dev);
> - nvdimm_bus_lock(&ndns->dev);
> - __nd_detach_ndns(dev, _ndns);
> - nvdimm_bus_unlock(&ndns->dev);
> + scoped_guard(nvdimm_bus, &ndns->dev)
> + __nd_detach_ndns(dev, _ndns);
> put_device(&ndns->dev);
maybe a guard for this as well? Then you could just use
guards for both rather than needing the scoped guard.
> }
> diff --git a/drivers/nvdimm/dax_devs.c b/drivers/nvdimm/dax_devs.c
> index 37b743acbb7b..a5d44b5c9452 100644
> --- a/drivers/nvdimm/dax_devs.c
> +++ b/drivers/nvdimm/dax_devs.c
> @@ -104,10 +104,10 @@ int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns)
> return -ENODEV;
> }
>
> - nvdimm_bus_lock(&ndns->dev);
> - nd_dax = nd_dax_alloc(nd_region);
> - dax_dev = nd_dax_devinit(nd_dax, ndns);
> - nvdimm_bus_unlock(&ndns->dev);
> + scoped_guard(nvdimm_bus, &ndns->dev) {
> + nd_dax = nd_dax_alloc(nd_region);
> + dax_dev = nd_dax_devinit(nd_dax, ndns);
> + }
> if (!dax_dev)
> return -ENOMEM;
Maybe move this check under the lock? For me that would be a little more obvious
as right next to where it is set.
> pfn_sb = devm_kmalloc(dev, sizeof(*pfn_sb), GFP_KERNEL);
> diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c
> index 91d9163ee303..2018458a3dba 100644
> --- a/drivers/nvdimm/dimm.c
> +++ b/drivers/nvdimm/dimm.c
> @@ -95,13 +95,13 @@ static int nvdimm_probe(struct device *dev)
>
> dev_dbg(dev, "config data size: %d\n", ndd->nsarea.config_size);
>
> - nvdimm_bus_lock(dev);
> - if (ndd->ns_current >= 0) {
> - rc = nd_label_reserve_dpa(ndd);
> - if (rc == 0)
> - nvdimm_set_labeling(dev);
> + scoped_guard(nvdimm_bus, dev) {
> + if (ndd->ns_current >= 0) {
> + rc = nd_label_reserve_dpa(ndd);
> + if (rc == 0)
> + nvdimm_set_labeling(dev);
> + }
> }
> - nvdimm_bus_unlock(dev);
This one looks awkward wrt to the goto and put_ndd().
Might not be worth the bother. I tend to take the view that it is
fine to use guard() for a lock where it helps but not force it to be
used universally if there are places where it doesn't.
>
> if (rc)
> goto err;
> @@ -117,9 +117,8 @@ static void nvdimm_remove(struct device *dev)
> {
> struct nvdimm_drvdata *ndd = dev_get_drvdata(dev);
>
> - nvdimm_bus_lock(dev);
> - dev_set_drvdata(dev, NULL);
> - nvdimm_bus_unlock(dev);
> + scoped_guard(nvdimm_bus, dev)
> + dev_set_drvdata(dev, NULL);
> put_ndd(ndd);
> }
>
> diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
> index 21498d461fde..4b293c4ad15c 100644
> --- a/drivers/nvdimm/dimm_devs.c
> +++ b/drivers/nvdimm/dimm_devs.c
> @@ -326,7 +326,7 @@ static ssize_t __available_slots_show(struct nvdimm_drvdata *ndd, char *buf)
> return -ENXIO;
>
> dev = ndd->dev;
> - nvdimm_bus_lock(dev);
> + guard(nvdimm_bus)(dev);
> nfree = nd_label_nfree(ndd);
> if (nfree - 1 > nfree) {
> dev_WARN_ONCE(dev, 1, "we ate our last label?\n");
> @@ -334,7 +334,6 @@ static ssize_t __available_slots_show(struct nvdimm_drvdata *ndd, char *buf)
> } else
> nfree--;
> rc = sprintf(buf, "%d\n", nfree);
> - nvdimm_bus_unlock(dev);
> return rc;
return sprintf() nad drop then then unused rc.
> }
>
> @@ -395,12 +394,10 @@ static ssize_t security_store(struct device *dev,
> * done while probing is idle and the DIMM is not in active use
> * in any region.
> */
> - device_lock(dev);
> - nvdimm_bus_lock(dev);
> + guard(device)(dev);
> + guard(nvdimm_bus)(dev);
> wait_nvdimm_bus_probe_idle(dev);
> rc = nvdimm_security_store(dev, buf, len);
return nvdimm_security_store()
> - nvdimm_bus_unlock(dev);
> - device_unlock(dev);
>
> return rc;
> }
> @@ -454,9 +451,8 @@ static ssize_t result_show(struct device *dev, struct device_attribute *attr, ch
> if (!nvdimm->fw_ops)
> return -EOPNOTSUPP;
>
> - nvdimm_bus_lock(dev);
> - result = nvdimm->fw_ops->activate_result(nvdimm);
> - nvdimm_bus_unlock(dev);
> + scoped_guard(nvdimm_bus, dev)
Maybe just guard? Seems unlikely to matter if we do the prints under the lock.
> + result = nvdimm->fw_ops->activate_result(nvdimm);
>
> switch (result) {
> case NVDIMM_FWA_RESULT_NONE:
> @@ -483,9 +479,8 @@ static ssize_t activate_show(struct device *dev, struct device_attribute *attr,
> if (!nvdimm->fw_ops)
> return -EOPNOTSUPP;
>
> - nvdimm_bus_lock(dev);
> - state = nvdimm->fw_ops->activate_state(nvdimm);
> - nvdimm_bus_unlock(dev);
> + scoped_guard(nvdimm_bus, dev)
Similar to above. I'd just hold it to function exit to simplify the code a little.
> + state = nvdimm->fw_ops->activate_state(nvdimm);
>
> switch (state) {
> case NVDIMM_FWA_IDLE:
..
> @@ -641,11 +634,11 @@ void nvdimm_delete(struct nvdimm *nvdimm)
> bool dev_put = false;
>
> /* We are shutting down. Make state frozen artificially. */
> - nvdimm_bus_lock(dev);
> - set_bit(NVDIMM_SECURITY_FROZEN, &nvdimm->sec.flags);
> - if (test_and_clear_bit(NDD_WORK_PENDING, &nvdimm->flags))
> - dev_put = true;
> - nvdimm_bus_unlock(dev);
> + scoped_guard(nvdimm_bus, dev) {
> + set_bit(NVDIMM_SECURITY_FROZEN, &nvdimm->sec.flags);
> + if (test_and_clear_bit(NDD_WORK_PENDING, &nvdimm->flags))
> + dev_put = true;
Not sure why this isn't
dev_put = test_and_clear_bit();
Maybe some earlier refactoring left this somewhat odd bit of code or
> + }
> cancel_delayed_work_sync(&nvdimm->dwork);
> if (dev_put)
> put_device(dev);
> diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
> index 55cfbf1e0a95..38933abfb2a6 100644
> --- a/drivers/nvdimm/namespace_devs.c
> +++ b/drivers/nvdimm/namespace_devs.c
...
> @@ -893,9 +888,8 @@ resource_size_t nvdimm_namespace_capacity(struct nd_namespace_common *ndns)
> {
> resource_size_t size;
>
> - nvdimm_bus_lock(&ndns->dev);
> + guard(nvdimm_bus)(&ndns->dev);
> size = __nvdimm_namespace_capacity(ndns);
> - nvdimm_bus_unlock(&ndns->dev);
>
> return size;
return __nvdimm_namespace_capacity(ndns);
> }
> @@ -1119,8 +1111,8 @@ static ssize_t sector_size_store(struct device *dev,
> } else
> return -ENXIO;
>
> - device_lock(dev);
> - nvdimm_bus_lock(dev);
> + guard(device)(dev);
> + guard(nvdimm_bus)(dev);
> if (to_ndns(dev)->claim)
> rc = -EBUSY;
> if (rc >= 0)
There is a bit mess of if (rc >= 0)
stuff in here that could just become early exits and generally result I think
in more readable code flow (enabled by the guard() usage) The side effect
being the dev_dbg() might need to be replicated but it could ten say what actually
happened rather than current case of one of 3 things failed.
if (to_ndns(dev)->claim) {
dev_dbg(dev...)
return -EBUSY;
}
rc = nd_size_select_store();
if (rc < 0) {
dev_dbg()
return rc;
}
rc = nd_namespace_label_update(nd_region, dev);
if (rc < 0) {
dev_dbg(); // if all these are actually useful given we know what we wrote and what failed.
return rc;
}
> @@ -1145,7 +1135,7 @@ static ssize_t dpa_extents_show(struct device *dev,
> int count = 0, i;
> u32 flags = 0;
>
> - nvdimm_bus_lock(dev);
> + guard(nvdimm_bus)(dev);
> if (is_namespace_pmem(dev)) {
> struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev);
>
> @@ -1167,8 +1157,6 @@ static ssize_t dpa_extents_show(struct device *dev,
> count++;
> }
> out:
Can drop this and return early particularly as it's just
return sprintf(buf, "0\n");
in that one path.
> - nvdimm_bus_unlock(dev);
> -
> return sprintf(buf, "%d\n", count);
> }
> static DEVICE_ATTR_RO(dpa_extents);
> @@ -2152,31 +2138,38 @@ static int init_active_labels(struct nd_region *nd_region)
> nd_region);
> }
>
> +static int __create_namespaces(struct nd_region *nd_region, int *type,
naming is a little odd given it calls create_namespaces internally.
Maybe
create_relevant_namespace() or something along those lines.
Or rename the create_namespaces() to be PMEM specific and reuse
that name for the wrapper.
> + struct device ***devs)
> +{
> + int rc;
> +
> + guard(nvdimm_bus)(&nd_region->dev);
> + rc = init_active_labels(nd_region);
> + if (rc)
> + return rc;
> +
> + *type = nd_region_to_nstype(nd_region);
> + switch (*type) {
> + case ND_DEVICE_NAMESPACE_IO:
> + *devs = create_namespace_io(nd_region);
> + break;
> + case ND_DEVICE_NAMESPACE_PMEM:
> + *devs = create_namespaces(nd_region);
> + break;
> + }
> +
> + return 0;
> +}
> +
> int nd_region_register_namespaces(struct nd_region *nd_region, int *err)
> {
> struct device **devs = NULL;
> int i, rc = 0, type;
>
> *err = 0;
> - nvdimm_bus_lock(&nd_region->dev);
> - rc = init_active_labels(nd_region);
> - if (rc) {
> - nvdimm_bus_unlock(&nd_region->dev);
> + rc = __create_namespaces(nd_region, &type, &devs);
> + if (rc)
> return rc;
> - }
> -
> - type = nd_region_to_nstype(nd_region);
> - switch (type) {
> - case ND_DEVICE_NAMESPACE_IO:
> - devs = create_namespace_io(nd_region);
> - break;
> - case ND_DEVICE_NAMESPACE_PMEM:
> - devs = create_namespaces(nd_region);
> - break;
> - default:
> - break;
> - }
> - nvdimm_bus_unlock(&nd_region->dev);
>
> if (!devs)
> return -ENODEV;
> diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
> index cc5c8f3f81e8..a8013033509c 100644
> --- a/drivers/nvdimm/nd.h
> +++ b/drivers/nvdimm/nd.h
> @@ -632,6 +632,8 @@ u64 nd_region_interleave_set_cookie(struct nd_region *nd_region,
> u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region);
> void nvdimm_bus_lock(struct device *dev);
> void nvdimm_bus_unlock(struct device *dev);
> +DEFINE_GUARD(nvdimm_bus, struct device *, nvdimm_bus_lock(_T), nvdimm_bus_unlock(_T));
You want that if (_T) or the IS_ERR_OR_NULL variant if appropriate.
Technically not needed, but as Peter Z pointed out in a similar case, sometimes the compiler
might spot that _T is always NULL in a path and optimize out the call. So he was
very keen to keep that guard in the definition unless the the cleanup was also visible
(As an inline in the header for instance).
> +
> bool is_nvdimm_bus_locked(struct device *dev);
> void nvdimm_check_and_set_ro(struct gendisk *disk);
> void nvdimm_drvdata_release(struct kref *kref);
> diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
> index 8f3e816e805d..f2a44d1f62be 100644
> --- a/drivers/nvdimm/pfn_devs.c
> +++ b/drivers/nvdimm/pfn_devs.c
> @@ -57,8 +57,8 @@ static ssize_t mode_store(struct device *dev,
> struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
> ssize_t rc = 0;
>
> - device_lock(dev);
> - nvdimm_bus_lock(dev);
> + guard(device)(dev);
> + guard(nvdimm_bus)(dev);
> if (dev->driver)
> rc = -EBUSY;
Maybe just do an early return here. Is it really that useful to
see anything other than -EBUSY? If so maybe have a new dev_dbg()
for this path. Nice to reduce the indent on the rest.
> else {
> @@ -78,8 +78,6 @@ static ssize_t mode_store(struct device *dev,
> }
> dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
> buf[len - 1] == '\n' ? "" : "\n");
> - nvdimm_bus_unlock(dev);
> - device_unlock(dev);
>
> return rc ? rc : len;
> }
> @@ -170,10 +166,9 @@ static ssize_t namespace_show(struct device *dev,
> struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
> ssize_t rc;
>
> - nvdimm_bus_lock(dev);
> + guard(nvdimm_bus)(dev);
> rc = sprintf(buf, "%s\n", nd_pfn->ndns
> ? dev_name(&nd_pfn->ndns->dev) : "");
> - nvdimm_bus_unlock(dev);
> return rc;
return sprintf()
> }
...
> diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
> index de1ee5ebc851..b2b4519e9f4c 100644
> --- a/drivers/nvdimm/region_devs.c
> +++ b/drivers/nvdimm/region_devs.c
> +int nd_region_activate(struct nd_region *nd_region)
> +{
> + int i, j, rc, num_flush;
> + struct nd_region_data *ndrd;
> + struct device *dev = &nd_region->dev;
> + size_t flush_data_size;
> +
> + rc = get_flush_data(nd_region, &flush_data_size, &num_flush);
> + if (rc)
> + return rc;
>
> rc = nd_region_invalidate_memregion(nd_region);
> if (rc)
> @@ -327,8 +340,8 @@ static ssize_t set_cookie_show(struct device *dev,
> * the v1.1 namespace label cookie definition. To read all this
> * data we need to wait for probing to settle.
> */
> - device_lock(dev);
> - nvdimm_bus_lock(dev);
> + guard(device)(dev);
> + guard(nvdimm_bus)(dev);
> wait_nvdimm_bus_probe_idle(dev);
> if (nd_region->ndr_mappings) {
> struct nd_mapping *nd_mapping = &nd_region->mapping[0];
> @@ -343,8 +356,6 @@ static ssize_t set_cookie_show(struct device *dev,
> nsindex));
> }
> }
> - nvdimm_bus_unlock(dev);
> - device_unlock(dev);
>
> if (rc)
> return rc;
> @@ -401,12 +412,10 @@ static ssize_t available_size_show(struct device *dev,
> * memory nvdimm_bus_lock() is dropped, but that's userspace's
> * problem to not race itself.
> */
> - device_lock(dev);
> - nvdimm_bus_lock(dev);
> + guard(device)(dev);
> + guard(nvdimm_bus)(dev);
> wait_nvdimm_bus_probe_idle(dev);
> available = nd_region_available_dpa(nd_region);
> - nvdimm_bus_unlock(dev);
> - device_unlock(dev);
>
> return sprintf(buf, "%llu\n", available);
Could role this together without I think any real loss of readability.
return sprintf(buf, "%llu\n", nd_region_available_dpa(nd_region));
> }
> @@ -418,12 +427,10 @@ static ssize_t max_available_extent_show(struct device *dev,
> struct nd_region *nd_region = to_nd_region(dev);
> unsigned long long available = 0;
>
> - device_lock(dev);
> - nvdimm_bus_lock(dev);
> + guard(device)(dev);
> + guard(nvdimm_bus)(dev);
> wait_nvdimm_bus_probe_idle(dev);
> available = nd_region_allocatable_dpa(nd_region);
> - nvdimm_bus_unlock(dev);
> - device_unlock(dev);
>
> return sprintf(buf, "%llu\n", available);
Similarly.
> }
> @@ -435,12 +442,11 @@ static ssize_t init_namespaces_show(struct device *dev,
> struct nd_region_data *ndrd = dev_get_drvdata(dev);
> ssize_t rc;
>
> - nvdimm_bus_lock(dev);
> + guard(nvdimm_bus)(dev);
> if (ndrd)
> rc = sprintf(buf, "%d/%d\n", ndrd->ns_active, ndrd->ns_count);
> else
> rc = -ENXIO;
> - nvdimm_bus_unlock(dev);
>
> return rc;
I'd do
if (!ndrd)
return -ENXIO;
return sprintf();
> }
> @@ -452,12 +458,11 @@ static ssize_t namespace_seed_show(struct device *dev,
> struct nd_region *nd_region = to_nd_region(dev);
> ssize_t rc;
>
> - nvdimm_bus_lock(dev);
> + guard(nvdimm_bus)(dev);
> if (nd_region->ns_seed)
> rc = sprintf(buf, "%s\n", dev_name(nd_region->ns_seed));
> else
> rc = sprintf(buf, "\n");
> - nvdimm_bus_unlock(dev);
> return rc;
likewise, I'd just return directly in each of the legs
> }
> static DEVICE_ATTR_RO(namespace_seed);
> @@ -468,12 +473,11 @@ static ssize_t btt_seed_show(struct device *dev,
> struct nd_region *nd_region = to_nd_region(dev);
> ssize_t rc;
>
> - nvdimm_bus_lock(dev);
> + guard(nvdimm_bus)(dev);
> if (nd_region->btt_seed)
> rc = sprintf(buf, "%s\n", dev_name(nd_region->btt_seed));
> else
> rc = sprintf(buf, "\n");
> - nvdimm_bus_unlock(dev);
>
> return rc;
Here as well.
> }
> @@ -485,12 +489,11 @@ static ssize_t pfn_seed_show(struct device *dev,
> struct nd_region *nd_region = to_nd_region(dev);
> ssize_t rc;
>
> - nvdimm_bus_lock(dev);
> + guard(nvdimm_bus)(dev);
> if (nd_region->pfn_seed)
> rc = sprintf(buf, "%s\n", dev_name(nd_region->pfn_seed));
> else
> rc = sprintf(buf, "\n");
> - nvdimm_bus_unlock(dev);
>
> return rc;
A common theme is emerging ;)
> }
> @@ -502,12 +505,11 @@ static ssize_t dax_seed_show(struct device *dev,
> struct nd_region *nd_region = to_nd_region(dev);
> ssize_t rc;
>
> - nvdimm_bus_lock(dev);
> + guard(nvdimm_bus)(dev);
> if (nd_region->dax_seed)
> rc = sprintf(buf, "%s\n", dev_name(nd_region->dax_seed));
> else
> rc = sprintf(buf, "\n");
> - nvdimm_bus_unlock(dev);
And again.
>
> return rc;
> }
> diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c
> index a03e3c45f297..e70dc3b08458 100644
> --- a/drivers/nvdimm/security.c
> +++ b/drivers/nvdimm/security.c
> @@ -221,9 +221,8 @@ int nvdimm_security_unlock(struct device *dev)
> struct nvdimm *nvdimm = to_nvdimm(dev);
> int rc;
>
> - nvdimm_bus_lock(dev);
> + guard(nvdimm_bus)(dev);
> rc = __nvdimm_security_unlock(nvdimm);
> - nvdimm_bus_unlock(dev);
> return rc;
return __nvdimm_se...
> }
>
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH] nvdimm: Introduce guard() for nvdimm_bus_lock
2025-09-23 10:18 ` Jonathan Cameron
@ 2025-09-23 16:36 ` Dave Jiang
0 siblings, 0 replies; 7+ messages in thread
From: Dave Jiang @ 2025-09-23 16:36 UTC (permalink / raw)
To: Jonathan Cameron
Cc: nvdimm, ira.weiny, vishal.l.verma, dan.j.williams, s.neeraj
On 9/23/25 3:18 AM, Jonathan Cameron wrote:
> On Mon, 22 Sep 2025 14:13:30 -0700
> Dave Jiang <dave.jiang@intel.com> wrote:
>
>> Converting nvdimm_bus_lock/unlock to guard() to clean up usage
>> of gotos for error handling and avoid future mistakes of missed
>> unlock on error paths.
>>
>> Link: https://lore.kernel.org/linux-cxl/20250917163623.00004a3c@huawei.com/
>> Suggested-by: Jonathan Cameron <jonathan.cameron@huawei.com>
>> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> Hi Dave,
>
> Thanks for looking at this.
>
> Fully agree with Dan about the getting rid of all gotos by end of series.
I'll do that in a different patch for that particular chunk.
>
> A few other things inline. Mostly places where the use of guard()
> opens up low hanging fruit that improves readability (+ shortens code).
>
> This code has a lot of dev_dbg() and some of them are so generic I'm not
> sure they are actually useful (cover a whole set of error paths). Perhaps
> it is worth splitting some of those up, or reducing the paths that trigger
> them as part of this refactor.
> > Jonathan
>
>
<snip>
>
>> diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
>> index 0ccf4a9e523a..d2c2d71e7fe0 100644
>> --- a/drivers/nvdimm/bus.c
>> +++ b/drivers/nvdimm/bus.c
>> static int nvdimm_bus_probe(struct device *dev)
>> @@ -1177,15 +1175,15 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
>> goto out;
>> }
>>
>> - device_lock(dev);
>> - nvdimm_bus_lock(dev);
>> + guard(device)(dev);
>> + guard(nvdimm_bus)(dev);
>> rc = nd_cmd_clear_to_send(nvdimm_bus, nvdimm, func, buf);
>> if (rc)
>> - goto out_unlock;
>> + goto out;
>>
>> rc = nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, &cmd_rc);
>> if (rc < 0)
>> - goto out_unlock;
>> + goto out;
>>
>> if (!nvdimm && cmd == ND_CMD_CLEAR_ERROR && cmd_rc >= 0) {
>> struct nd_cmd_clear_error *clear_err = buf;
>> @@ -1197,9 +1195,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
>> if (copy_to_user(p, buf, buf_len))
>> rc = -EFAULT;
>>
>> -out_unlock:
>> - nvdimm_bus_unlock(dev);
>> - device_unlock(dev);
>> out:
> Hmm. I'm not a fan of gotos that rely on initializing a bunch of pointers to NULL
> so fewer labels are used. Will be nice to replace that as well via __free
>
> Going to need a DEFINE_FREE for the vfree that follow these but that looks standard to me.
I ended up moving it to kvzalloc() instead. Seems reasonable and give us zeroing of the buffer as well.
DJ
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-09-23 16:36 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-22 21:13 [PATCH] nvdimm: Introduce guard() for nvdimm_bus_lock Dave Jiang
2025-09-22 22:50 ` dan.j.williams
2025-09-22 23:00 ` Dave Jiang
2025-09-22 23:23 ` dan.j.williams
2025-09-23 1:58 ` kernel test robot
2025-09-23 10:18 ` Jonathan Cameron
2025-09-23 16:36 ` Dave Jiang
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.