Commit 95232dd9 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'libnvdimm-fixes-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm

Pull libnvdimm fixes from Dan Williams:
 "A fix for an issue that could causes users to inadvertantly reserve
  too much capacity when debugging the KMSAN and persistent memory
  namespace, a lockdep fix, and a kernel-doc build warning:

   - Resolve the conflict between KMSAN and NVDIMM with respect to
     reserving pmem namespace / volume capacity for larger sizeof(struct
     page)

   - Fix a lockdep warning in the the NFIT code

   - Fix a kernel-doc build warning"

* tag 'libnvdimm-fixes-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm:
  nvdimm: Support sizeof(struct page) > MAX_STRUCT_PAGE_SIZE
  ACPI: NFIT: fix a potential deadlock during NFIT teardown
  dax: super.c: fix kernel-doc bad line warning
parents 230809c1 c91d7136
...@@ -3297,8 +3297,8 @@ void acpi_nfit_shutdown(void *data) ...@@ -3297,8 +3297,8 @@ void acpi_nfit_shutdown(void *data)
mutex_lock(&acpi_desc->init_mutex); mutex_lock(&acpi_desc->init_mutex);
set_bit(ARS_CANCEL, &acpi_desc->scrub_flags); set_bit(ARS_CANCEL, &acpi_desc->scrub_flags);
cancel_delayed_work_sync(&acpi_desc->dwork);
mutex_unlock(&acpi_desc->init_mutex); mutex_unlock(&acpi_desc->init_mutex);
cancel_delayed_work_sync(&acpi_desc->dwork);
/* /*
* Bounce the nvdimm bus lock to make sure any in-flight * Bounce the nvdimm bus lock to make sure any in-flight
......
...@@ -475,7 +475,7 @@ EXPORT_SYMBOL_GPL(put_dax); ...@@ -475,7 +475,7 @@ EXPORT_SYMBOL_GPL(put_dax);
/** /**
* dax_holder() - obtain the holder of a dax device * dax_holder() - obtain the holder of a dax device
* @dax_dev: a dax_device instance * @dax_dev: a dax_device instance
*
* Return: the holder's data which represents the holder if registered, * Return: the holder's data which represents the holder if registered,
* otherwize NULL. * otherwize NULL.
*/ */
......
...@@ -102,6 +102,25 @@ config NVDIMM_KEYS ...@@ -102,6 +102,25 @@ config NVDIMM_KEYS
depends on ENCRYPTED_KEYS depends on ENCRYPTED_KEYS
depends on (LIBNVDIMM=ENCRYPTED_KEYS) || LIBNVDIMM=m depends on (LIBNVDIMM=ENCRYPTED_KEYS) || LIBNVDIMM=m
config NVDIMM_KMSAN
bool
depends on KMSAN
help
KMSAN, and other memory debug facilities, increase the size of
'struct page' to contain extra metadata. This collides with
the NVDIMM capability to store a potentially
larger-than-"System RAM" size 'struct page' array in a
reservation of persistent memory rather than limited /
precious DRAM. However, that reservation needs to persist for
the life of the given NVDIMM namespace. If you are using KMSAN
to debug an issue unrelated to NVDIMMs or DAX then say N to this
option. Otherwise, say Y but understand that any namespaces
(with the page array stored pmem) created with this build of
the kernel will permanently reserve and strand excess
capacity compared to the CONFIG_KMSAN=n case.
Select N if unsure.
config NVDIMM_TEST_BUILD config NVDIMM_TEST_BUILD
tristate "Build the unit test core" tristate "Build the unit test core"
depends on m depends on m
......
...@@ -652,7 +652,7 @@ void devm_namespace_disable(struct device *dev, ...@@ -652,7 +652,7 @@ void devm_namespace_disable(struct device *dev,
struct nd_namespace_common *ndns); struct nd_namespace_common *ndns);
#if IS_ENABLED(CONFIG_ND_CLAIM) #if IS_ENABLED(CONFIG_ND_CLAIM)
/* max struct page size independent of kernel config */ /* max struct page size independent of kernel config */
#define MAX_STRUCT_PAGE_SIZE 128 #define MAX_STRUCT_PAGE_SIZE 64
int nvdimm_setup_pfn(struct nd_pfn *nd_pfn, struct dev_pagemap *pgmap); int nvdimm_setup_pfn(struct nd_pfn *nd_pfn, struct dev_pagemap *pgmap);
#else #else
static inline int nvdimm_setup_pfn(struct nd_pfn *nd_pfn, static inline int nvdimm_setup_pfn(struct nd_pfn *nd_pfn,
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include "pfn.h" #include "pfn.h"
#include "nd.h" #include "nd.h"
static const bool page_struct_override = IS_ENABLED(CONFIG_NVDIMM_KMSAN);
static void nd_pfn_release(struct device *dev) static void nd_pfn_release(struct device *dev)
{ {
struct nd_region *nd_region = to_nd_region(dev->parent); struct nd_region *nd_region = to_nd_region(dev->parent);
...@@ -758,12 +760,6 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) ...@@ -758,12 +760,6 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
return -ENXIO; return -ENXIO;
} }
/*
* Note, we use 64 here for the standard size of struct page,
* debugging options may cause it to be larger in which case the
* implementation will limit the pfns advertised through
* ->direct_access() to those that are included in the memmap.
*/
start = nsio->res.start; start = nsio->res.start;
size = resource_size(&nsio->res); size = resource_size(&nsio->res);
npfns = PHYS_PFN(size - SZ_8K); npfns = PHYS_PFN(size - SZ_8K);
...@@ -782,20 +778,33 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) ...@@ -782,20 +778,33 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
} }
end_trunc = start + size - ALIGN_DOWN(start + size, align); end_trunc = start + size - ALIGN_DOWN(start + size, align);
if (nd_pfn->mode == PFN_MODE_PMEM) { if (nd_pfn->mode == PFN_MODE_PMEM) {
unsigned long page_map_size = MAX_STRUCT_PAGE_SIZE * npfns;
/* /*
* The altmap should be padded out to the block size used * The altmap should be padded out to the block size used
* when populating the vmemmap. This *should* be equal to * when populating the vmemmap. This *should* be equal to
* PMD_SIZE for most architectures. * PMD_SIZE for most architectures.
* *
* Also make sure size of struct page is less than 128. We * Also make sure size of struct page is less than
* want to make sure we use large enough size here so that * MAX_STRUCT_PAGE_SIZE. The goal here is compatibility in the
* we don't have a dynamic reserve space depending on * face of production kernel configurations that reduce the
* struct page size. But we also want to make sure we notice * 'struct page' size below MAX_STRUCT_PAGE_SIZE. For debug
* when we end up adding new elements to struct page. * kernel configurations that increase the 'struct page' size
* above MAX_STRUCT_PAGE_SIZE, the page_struct_override allows
* for continuing with the capacity that will be wasted when
* reverting to a production kernel configuration. Otherwise,
* those configurations are blocked by default.
*/ */
BUILD_BUG_ON(sizeof(struct page) > MAX_STRUCT_PAGE_SIZE); if (sizeof(struct page) > MAX_STRUCT_PAGE_SIZE) {
offset = ALIGN(start + SZ_8K + MAX_STRUCT_PAGE_SIZE * npfns, align) if (page_struct_override)
- start; page_map_size = sizeof(struct page) * npfns;
else {
dev_err(&nd_pfn->dev,
"Memory debug options prevent using pmem for the page map\n");
return -EINVAL;
}
}
offset = ALIGN(start + SZ_8K + page_map_size, align) - start;
} else if (nd_pfn->mode == PFN_MODE_RAM) } else if (nd_pfn->mode == PFN_MODE_RAM)
offset = ALIGN(start + SZ_8K, align) - start; offset = ALIGN(start + SZ_8K, align) - start;
else else
...@@ -818,7 +827,10 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) ...@@ -818,7 +827,10 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
pfn_sb->version_minor = cpu_to_le16(4); pfn_sb->version_minor = cpu_to_le16(4);
pfn_sb->end_trunc = cpu_to_le32(end_trunc); pfn_sb->end_trunc = cpu_to_le32(end_trunc);
pfn_sb->align = cpu_to_le32(nd_pfn->align); pfn_sb->align = cpu_to_le32(nd_pfn->align);
pfn_sb->page_struct_size = cpu_to_le16(MAX_STRUCT_PAGE_SIZE); if (sizeof(struct page) > MAX_STRUCT_PAGE_SIZE && page_struct_override)
pfn_sb->page_struct_size = cpu_to_le16(sizeof(struct page));
else
pfn_sb->page_struct_size = cpu_to_le16(MAX_STRUCT_PAGE_SIZE);
pfn_sb->page_size = cpu_to_le32(PAGE_SIZE); pfn_sb->page_size = cpu_to_le32(PAGE_SIZE);
checksum = nd_sb_checksum((struct nd_gen_sb *) pfn_sb); checksum = nd_sb_checksum((struct nd_gen_sb *) pfn_sb);
pfn_sb->checksum = cpu_to_le64(checksum); pfn_sb->checksum = cpu_to_le64(checksum);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment