Pmem FS-DAX registers the device range as ZONE_DEVICE memory, and the kernel normally allocates and initializes vmemmap storage for every advertised PFN up front. Sparse backing storage and workloads that only use the DAX direct-access path may never need writable per-PFN state for most of that range, but still pay the memory and initialization cost.
Opt pmem FS-DAX into the shared read-only vmemmap mode and materialize private metadata before inserting a PFN into a userspace mapping. PMD faults materialize the whole PMD-sized metadata range. PFNs that are never faulted continue to use the shared metadata. This shifts private vmemmap allocation from device registration to the first DAX fault for each metadata page, so the struct page overhead tracks the faulted DAX working set instead of the full advertised pmem device size. Signed-off-by: Muchun Song <[email protected]> --- drivers/nvdimm/pmem.c | 1 + fs/dax.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index b14f75daeda7..5530b32163d3 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -543,6 +543,7 @@ static int pmem_attach_disk(struct device *dev, pmem->pgmap.nr_range = 1; pmem->pgmap.type = MEMORY_DEVICE_FS_DAX; pmem->pgmap.ops = &fsdax_pagemap_ops; + pmem->pgmap.flags |= PGMAP_VMEMMAP_OPTIMIZATION; addr = devm_memremap_pages(dev, &pmem->pgmap); bb_range = pmem->pgmap.range; } else { diff --git a/fs/dax.c b/fs/dax.c index 1fbba0d21c13..89377301d51b 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -13,6 +13,7 @@ #include <linux/fs.h> #include <linux/highmem.h> #include <linux/memcontrol.h> +#include <linux/memremap.h> #include <linux/mm.h> #include <linux/mutex.h> #include <linux/sched.h> @@ -1877,6 +1878,10 @@ static vm_fault_t dax_fault_iter(struct vm_fault *vmf, if (err) return pmd ? VM_FAULT_FALLBACK : dax_fault_return(err); + err = vmemmap_materialize_page(pfn_to_page(pfn), pmd ? PMD_ORDER : 0); + if (err) + return dax_fault_return(err); + *entry = dax_insert_entry(xas, vmf, iter, *entry, pfn, entry_flags); if (write && iomap->flags & IOMAP_F_SHARED) { -- 2.54.0

