diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-06-19 02:27:58 +0300 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-06-19 02:27:58 +0300 |
| commit | cfd96ad1389cd6045a3af05bd34b2e52b291e365 (patch) | |
| tree | 3b1e544b7b0df919046e3d0aa6c96bca61673086 | |
| parent | 7849ce38717e64213bf9cbb166d1cda14e05143f (diff) | |
| parent | 86e411b6ec277dbb8ac1f1d855dc337181a62a29 (diff) | |
| download | linux-cfd96ad1389cd6045a3af05bd34b2e52b291e365.tar.xz | |
Merge tag 'libnvdimm-for-7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull nvdimm/dax updates from Alison Schofield:
- Fix a race condition and a couple of static analysis issues in BTT
- Use sysfs_emit() in preparation for removal of cpumap_print_to_pagebuf()
- Escalate a dev_dbg to dev_err in a resource conflict message
- MAINTAINER file updates
* tag 'libnvdimm-for-7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm:
MAINTAINERS: nvdimm: Include maintainer profile
MAINTAINERS: Update address for Ira Weiny
MAINTAINERS: Add maintainer info for libnvdimm and DAX
nvdimm: Use sysfs_emit() for cpumask show callback
dax/bus: Upgrade resource conflict message to dev_err() in alloc_dax_region()
nvdimm/btt: Free arenas on btt_init() error paths
nvdimm/btt: Free arena sub-allocations on discover_arenas() error path
nvdimm/btt: Handle preemption in BTT lane acquisition
| -rw-r--r-- | .mailmap | 1 | ||||
| -rw-r--r-- | Documentation/driver-api/nvdimm/btt.rst | 5 | ||||
| -rw-r--r-- | MAINTAINERS | 11 | ||||
| -rw-r--r-- | drivers/dax/bus.c | 2 | ||||
| -rw-r--r-- | drivers/nvdimm/btt.c | 14 | ||||
| -rw-r--r-- | drivers/nvdimm/nd.h | 11 | ||||
| -rw-r--r-- | drivers/nvdimm/nd_perf.c | 2 | ||||
| -rw-r--r-- | drivers/nvdimm/region_devs.c | 66 |
8 files changed, 50 insertions, 62 deletions
@@ -450,6 +450,7 @@ Juha Yrjola <juha.yrjola@nokia.com> Juha Yrjola <juha.yrjola@solidboot.com> Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com> Justin Iurman <justin.iurman@gmail.com> <justin.iurman@uliege.be> +Ira Weiny <iweiny@kernel.org> <ira.weiny@intel.com> Iskren Chernev <me@iskren.info> <iskren.chernev@gmail.com> Kalle Valo <kvalo@kernel.org> <kvalo@codeaurora.org> Kalle Valo <kvalo@kernel.org> <quic_kvalo@quicinc.com> diff --git a/Documentation/driver-api/nvdimm/btt.rst b/Documentation/driver-api/nvdimm/btt.rst index 2d8269f834bd..d29fab95f149 100644 --- a/Documentation/driver-api/nvdimm/btt.rst +++ b/Documentation/driver-api/nvdimm/btt.rst @@ -161,9 +161,8 @@ process:: nlanes = min(nfree, num_cpus) A lane number is obtained at the start of any IO, and is used for indexing into -all the on-disk and in-memory data structures for the duration of the IO. If -there are more CPUs than the max number of available lanes, than lanes are -protected by spinlocks. +all the on-disk and in-memory data structures for the duration of the IO. Lanes +are protected by mutexes. d. In-memory data structure: Read Tracking Table (RTT) diff --git a/MAINTAINERS b/MAINTAINERS index 3147a467d458..926a17df059e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4302,7 +4302,7 @@ M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> M: "Rafael J. Wysocki" <rafael@kernel.org> M: Danilo Krummrich <dakr@kernel.org> R: Dave Ertman <david.m.ertman@intel.com> -R: Ira Weiny <ira.weiny@intel.com> +R: Ira Weiny <iweiny@kernel.org> R: Leon Romanovsky <leon@kernel.org> L: driver-core@lists.linux.dev S: Supported @@ -6454,8 +6454,8 @@ M: Jonathan Cameron <jic23@kernel.org> M: Dave Jiang <dave.jiang@intel.com> M: Alison Schofield <alison.schofield@intel.com> M: Vishal Verma <vishal.l.verma@intel.com> -M: Ira Weiny <ira.weiny@intel.com> M: Dan Williams <djbw@kernel.org> +R: Ira Weiny <iweiny@kernel.org> L: linux-cxl@vger.kernel.org S: Maintained F: Documentation/driver-api/cxl @@ -7320,6 +7320,7 @@ DEVICE DIRECT ACCESS (DAX) M: Dan Williams <djbw@kernel.org> M: Vishal Verma <vishal.l.verma@intel.com> M: Dave Jiang <dave.jiang@intel.com> +M: Alison Schofield <alison.schofield@intel.com> L: nvdimm@lists.linux.dev L: linux-cxl@vger.kernel.org S: Supported @@ -14725,6 +14726,7 @@ LIBNVDIMM BTT: BLOCK TRANSLATION TABLE M: Vishal Verma <vishal.l.verma@intel.com> M: Dan Williams <djbw@kernel.org> M: Dave Jiang <dave.jiang@intel.com> +M: Alison Schofield <alison.schofield@intel.com> L: nvdimm@lists.linux.dev S: Supported Q: https://patchwork.kernel.org/project/linux-nvdimm/list/ @@ -14735,6 +14737,7 @@ LIBNVDIMM PMEM: PERSISTENT MEMORY DRIVER M: Dan Williams <djbw@kernel.org> M: Vishal Verma <vishal.l.verma@intel.com> M: Dave Jiang <dave.jiang@intel.com> +M: Alison Schofield <alison.schofield@intel.com> L: nvdimm@lists.linux.dev S: Supported Q: https://patchwork.kernel.org/project/linux-nvdimm/list/ @@ -14753,12 +14756,14 @@ LIBNVDIMM: NON-VOLATILE MEMORY DEVICE SUBSYSTEM M: Dan Williams <djbw@kernel.org> M: Vishal Verma <vishal.l.verma@intel.com> M: Dave Jiang <dave.jiang@intel.com> -M: Ira Weiny <ira.weiny@intel.com> +M: Alison Schofield <alison.schofield@intel.com> +R: Ira Weiny <iweiny@kernel.org> L: nvdimm@lists.linux.dev S: Supported Q: https://patchwork.kernel.org/project/linux-nvdimm/list/ P: Documentation/nvdimm/maintainer-entry-profile.rst T: git git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git +F: Documentation/nvdimm/maintainer-entry-profile.rst F: drivers/acpi/nfit/* F: drivers/nvdimm/* F: include/linux/libnvdimm.h diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c index ccfe65004888..b809e1a264af 100644 --- a/drivers/dax/bus.c +++ b/drivers/dax/bus.c @@ -670,7 +670,7 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id, rc = request_resource(&dax_regions, &dax_region->res); if (rc) { - dev_dbg(parent, "dax_region resource conflict for %pR\n", + dev_err(parent, "dax_region resource conflict for %pR\n", &dax_region->res); goto err_res; } diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c index fdcb080a4314..7e1112960d7f 100644 --- a/drivers/nvdimm/btt.c +++ b/drivers/nvdimm/btt.c @@ -919,6 +919,9 @@ static int discover_arenas(struct btt *btt) return ret; out: + kfree(arena->freelist); + kfree(arena->rtt); + kfree(arena->map_locks); kfree(arena); free_arenas(btt); return ret; @@ -1589,7 +1592,7 @@ static struct btt *btt_init(struct nd_btt *nd_btt, unsigned long long rawsize, if (btt->init_state != INIT_READY && nd_region->ro) { dev_warn(dev, "%s is read-only, unable to init btt metadata\n", dev_name(&nd_region->dev)); - return NULL; + goto err; } else if (btt->init_state != INIT_READY) { btt->num_arenas = (rawsize / ARENA_MAX_SIZE) + ((rawsize % ARENA_MAX_SIZE) ? 1 : 0); @@ -1599,25 +1602,28 @@ static struct btt *btt_init(struct nd_btt *nd_btt, unsigned long long rawsize, ret = create_arenas(btt); if (ret) { dev_info(dev, "init: create_arenas: %d\n", ret); - return NULL; + goto err; } ret = btt_meta_init(btt); if (ret) { dev_err(dev, "init: error in meta_init: %d\n", ret); - return NULL; + goto err; } } ret = btt_blk_init(btt); if (ret) { dev_err(dev, "init: error in blk_init: %d\n", ret); - return NULL; + goto err; } btt_debugfs_init(btt); return btt; +err: + free_arenas(btt); + return NULL; } /** diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index 18b64559664b..ed69dea5b75f 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -365,11 +365,6 @@ unsigned sizeof_namespace_label(struct nvdimm_drvdata *ndd); for (res = (ndd)->dpa.child, next = res ? res->sibling : NULL; \ res; res = next, next = next ? next->sibling : NULL) -struct nd_percpu_lane { - int count; - spinlock_t lock; -}; - enum nd_label_flags { ND_LABEL_REAP, }; @@ -400,6 +395,10 @@ struct nd_mapping { struct nvdimm_drvdata *ndd; }; +struct nd_lane { + struct mutex lock; /* serialize lane access */ +} ____cacheline_aligned_in_smp; + struct nd_region { struct device dev; struct ida ns_ida; @@ -420,7 +419,7 @@ struct nd_region { struct kernfs_node *bb_state; struct badblocks bb; struct nd_interleave_set *nd_set; - struct nd_percpu_lane __percpu *lane; + struct nd_lane *lane; int (*flush)(struct nd_region *nd_region, struct bio *bio); struct nd_mapping mapping[] __counted_by(ndr_mappings); }; diff --git a/drivers/nvdimm/nd_perf.c b/drivers/nvdimm/nd_perf.c index e0b51438dc9b..9e497cae65b3 100644 --- a/drivers/nvdimm/nd_perf.c +++ b/drivers/nvdimm/nd_perf.c @@ -123,7 +123,7 @@ static ssize_t nvdimm_pmu_cpumask_show(struct device *dev, nd_pmu = container_of(pmu, struct nvdimm_pmu, pmu); - return cpumap_print_to_pagebuf(true, buf, cpumask_of(nd_pmu->cpu)); + return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(nd_pmu->cpu))); } static int nvdimm_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node) diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index e35c2e18518f..5e079d61cbaa 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c @@ -192,7 +192,9 @@ static void nd_region_release(struct device *dev) put_device(&nvdimm->dev); } - free_percpu(nd_region->lane); + for (i = 0; i < nd_region->num_lanes; i++) + mutex_destroy(&nd_region->lane[i].lock); + kfree(nd_region->lane); if (!test_bit(ND_REGION_CXL, &nd_region->flags)) memregion_free(nd_region->id); kfree(nd_region); @@ -904,52 +906,30 @@ void nd_region_advance_seeds(struct nd_region *nd_region, struct device *dev) * nd_region_acquire_lane - allocate and lock a lane * @nd_region: region id and number of lanes possible * - * A lane correlates to a BLK-data-window and/or a log slot in the BTT. - * We optimize for the common case where there are 256 lanes, one - * per-cpu. For larger systems we need to lock to share lanes. For now - * this implementation assumes the cost of maintaining an allocator for - * free lanes is on the order of the lock hold time, so it implements a - * static lane = cpu % num_lanes mapping. + * A lane correlates to a log slot in the BTT. Lanes are shared across + * CPUs using a static lane = cpu % num_lanes mapping, with a per-lane + * mutex to serialize access. * - * In the case of a BTT instance on top of a BLK namespace a lane may be - * acquired recursively. We lock on the first instance. - * - * In the case of a BTT instance on top of PMEM, we only acquire a lane - * for the BTT metadata updates. + * Callers must be in sleepable context. The only in-tree caller is + * BTT's ->submit_bio handler (btt_read_pg / btt_write_pg). */ unsigned int nd_region_acquire_lane(struct nd_region *nd_region) + __acquires(&nd_region->lane[lane].lock) { - unsigned int cpu, lane; - - migrate_disable(); - cpu = smp_processor_id(); - if (nd_region->num_lanes < nr_cpu_ids) { - struct nd_percpu_lane *ndl_lock, *ndl_count; + unsigned int lane; - lane = cpu % nd_region->num_lanes; - ndl_count = per_cpu_ptr(nd_region->lane, cpu); - ndl_lock = per_cpu_ptr(nd_region->lane, lane); - if (ndl_count->count++ == 0) - spin_lock(&ndl_lock->lock); - } else - lane = cpu; + might_sleep(); + lane = raw_smp_processor_id() % nd_region->num_lanes; + mutex_lock(&nd_region->lane[lane].lock); return lane; } EXPORT_SYMBOL(nd_region_acquire_lane); void nd_region_release_lane(struct nd_region *nd_region, unsigned int lane) + __releases(&nd_region->lane[lane].lock) { - if (nd_region->num_lanes < nr_cpu_ids) { - unsigned int cpu = smp_processor_id(); - struct nd_percpu_lane *ndl_lock, *ndl_count; - - ndl_count = per_cpu_ptr(nd_region->lane, cpu); - ndl_lock = per_cpu_ptr(nd_region->lane, lane); - if (--ndl_count->count == 0) - spin_unlock(&ndl_lock->lock); - } - migrate_enable(); + mutex_unlock(&nd_region->lane[lane].lock); } EXPORT_SYMBOL(nd_region_release_lane); @@ -1019,17 +999,16 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus, goto err_id; } - nd_region->lane = alloc_percpu(struct nd_percpu_lane); + nd_region->num_lanes = ndr_desc->num_lanes; + if (!nd_region->num_lanes) + goto err_percpu; + nd_region->lane = kcalloc(nd_region->num_lanes, + sizeof(*nd_region->lane), GFP_KERNEL); if (!nd_region->lane) goto err_percpu; - for (i = 0; i < nr_cpu_ids; i++) { - struct nd_percpu_lane *ndl; - - ndl = per_cpu_ptr(nd_region->lane, i); - spin_lock_init(&ndl->lock); - ndl->count = 0; - } + for (i = 0; i < nd_region->num_lanes; i++) + mutex_init(&nd_region->lane[i].lock); for (i = 0; i < ndr_desc->num_mappings; i++) { struct nd_mapping_desc *mapping = &ndr_desc->mapping[i]; @@ -1046,7 +1025,6 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus, } nd_region->provider_data = ndr_desc->provider_data; nd_region->nd_set = ndr_desc->nd_set; - nd_region->num_lanes = ndr_desc->num_lanes; nd_region->flags = ndr_desc->flags; nd_region->ro = ro; nd_region->numa_node = ndr_desc->numa_node; |
