* [PATCH V10 0/8] dax: prepare for famfs
[not found] <20260327210311.79099-1-john@jagalactic.com>
@ 2026-03-27 21:03 ` John Groves
2026-03-27 21:04 ` [PATCH V10 1/8] dax: move dax_pgoff_to_phys from [drivers/dax/] device.c to bus.c John Groves
` (8 more replies)
0 siblings, 9 replies; 16+ messages in thread
From: John Groves @ 2026-03-27 21:03 UTC (permalink / raw)
To: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
Alison Schofield
Cc: John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org,
John Groves
From: John Groves <john@groves.net>
This patch series along with the bundled patches to fuse are available
as a git tag at [0].
Dropped the "bundle" thread. If this submission goes smoothly, I'll update
the fuse patches to v10 (very little change there as yet).
Changes v9 -> v10
- Minor modernizations per comments from (mostly) Jonathan
- Minor Kconfig simplification
- bus.c:dax_match_type(): don't make fsdev_dax eligible for automatic binding
where devdax would otherwise bind
- dax-private.h: add missing kerneldoc comment for field cached_size in
struct dev_dax_range (thanks Dave)
- fsdev_write_dax(): s/pmem_addr/addr/ (thanks Dave)
- include/linux/dax.h: remove a spuriously-added declaration of inode_dax()
(thanks Jonathan)
Description:
This patch series introduces the required dax support for famfs.
Previous versions of the famfs series included both dax and fuse patches.
This series separates them into separate patch series' (and the fuse
series dependends on this dax series).
The famfs user space code can be found at [1]
Dax Overview:
This series introduces a new "famfs mode" of devdax, whose driver is
drivers/dax/fsdev.c. This driver supports dax_iomap_rw() and
dax_iomap_fault() calls against a character dax instance. A dax device
now can be converted among three modes: 'system-ram', 'devdax' and
'famfs' via daxctl or sysfs (e.g. unbind devdax and bind famfs instead).
In famfs mode, a dax device initializes its pages consistent with the
fsdaxmode of pmem. Raw read/write/mmap are not supported in this mode,
but famfs is happy in this mode - using dax_iomap_rw() for read/write and
dax_iomap_fault() for mmap faults.
Changes v8 -> v9
- Big clarifying comments in fs/dax.c:dax_folio_reset_order() in response
to Jonathan's comments/questions
- Added drivers/dax/Kconfig:CONFIG_DEV_DAX_FSDEV to control inclusion of the
new famfs dax mode (which is in drivers/dax/fsdev.c - bind that to a daxdev
and you have famfs mode)
- Some trivial refactoring, mostly per Jonathan's comments
Changes v7 -> v8
- dax: Added a devm action to clear folio state when unbinding fsdev.c
(thanks Allison)
- Added a missing device_lock() in fs_dax_get() (thanks Dave)
- Re-factored some __free blocks for inline declaration
- Used FIELD_PREP where appropriate
- Minor doc edits
Changes v6 -> v7
- Fixed a regression in famfs_interleave_fileofs_to_daxofs() that
was reported by Intel's kernel test robot
- Added a check in __fsdev_dax_direct_access() for negative return
from pgoff_to_phys(), which would indicate an out-of-range offset
- Fixed a bug in __famfs_meta_free(), where not all interleaved
extents were freed
- Added chunksize alignment checks in famfs_fuse_meta_alloc() and
famfs_interleave_fileofs_to_daxofs() as interleaved chunks must
be PTE or PMD aligned
- Simplified famfs_file_init_dax() a bit
- Re-ran CM's kernel code review prompts on the entire series and
fixed several minor issues
Changes v4 -> v5 -> v6
- None. Re-sending due to technical difficulties
Changes v3 [9] -> v4
- The patch "dax: prevent driver unbind while filesystem holds device"
has been dropped. Dan Williams indicated that the favored behavior is
for a file system to stop working if an underlying driver is unbound,
rather than preventing the unbind.
- The patch "famfs_fuse: Famfs mount opt: -o shadow=<shadowpath>" has
been dropped. Found a way for the famfs user space to do without the
-o opt (via getxattr).
- Squashed the fs/fuse/Kconfig patch into the first subsequent patch
that needed the change
("famfs_fuse: Basic fuse kernel ABI enablement for famfs")
- Many review comments addressed.
- Addressed minor kerneldoc infractions reported by test robot.
Changes v2 [7] -> v3
- Dax: Completely new fsdev driver (drivers/dax/fsdev.c) replaces the
dev_dax_iomap modifications to bus.c/device.c. Devdax devices can now
be switched among 'devdax', 'famfs' and 'system-ram' modes via daxctl
or sysfs.
- Dax: fsdev uses MEMORY_DEVICE_FS_DAX type and leaves folios at order-0
(no vmemmap_shift), allowing fs-dax to manage folio lifecycles
dynamically like pmem does.
- Dax: The "poisoned page" problem is properly fixed via
fsdev_clear_folio_state(), which clears stale mapping/compound state
when fsdev binds. The temporary WARN_ON_ONCE workaround in fs/dax.c
has been removed.
- Dax: Added dax_set_ops() so fsdev can set dax_operations at bind time
(and clear them on unbind), since the dax_device is created before we
know which driver will bind.
- Dax: Added custom bind/unbind sysfs handlers; unbind return -EBUSY if a
filesystem holds the device, preventing unbind while famfs is mounted.
- Fuse: Famfs mounts now require that the fuse server/daemon has
CAP_SYS_RAWIO because they expose raw memory devices.
- Fuse: Added DAX address_space_operations with noop_dirty_folio since
famfs is memory-backed with no writeback required.
- Rebased to latest kernels, fully compatible with Alistair Popple
et. al's recent dax refactoring.
- Ran this series through Chris Mason's code review AI prompts to check
for issues - several subtle problems found and fixed.
- Dropped RFC status - this version is intended to be mergeable.
Changes v1 [8] -> v2:
- The GET_FMAP message/response has been moved from LOOKUP to OPEN, as
was the pretty much unanimous consensus.
- Made the response payload to GET_FMAP variable sized (patch 12)
- Dodgy kerneldoc comments cleaned up or removed.
- Fixed memory leak of fc->shadow in patch 11 (thanks Joanne)
- Dropped many pr_debug and pr_notice calls
References
[0] - https://github.com/jagalactic/linux/tree/famfs-v10 (this patch set)
[1] - https://famfs.org (famfs user space)
[2] - https://lore.kernel.org/linux-cxl/cover.1708709155.git.john@groves.net/
[3] - https://lore.kernel.org/linux-cxl/cover.1714409084.git.john@groves.net/
[4] - https://lwn.net/Articles/983105/ (lsfmm 2024)
[5] - https://lwn.net/Articles/1020170/ (lsfmm 2025)
[6] - https://lore.kernel.org/linux-cxl/cover.8068ad144a7eea4a813670301f4d2a86a8e68ec4.1740713401.git-series.apopple@nvidia.com/
[7] - https://lore.kernel.org/linux-fsdevel/20250703185032.46568-1-john@groves.net/ (famfs fuse v2)
[8] - https://lore.kernel.org/linux-fsdevel/20250421013346.32530-1-john@groves.net/ (famfs fuse v1)
[9] - https://lore.kernel.org/linux-fsdevel/20260107153244.64703-1-john@groves.net/T/#mb2c868801be16eca82dab239a1d201628534aea7 (famfs fuse v3)
John Groves (8):
dax: move dax_pgoff_to_phys from [drivers/dax/] device.c to bus.c
dax: Factor out dax_folio_reset_order() helper
dax: add fsdev.c driver for fs-dax on character dax
dax: Save the kva from memremap
dax: Add dax_operations for use by fs-dax on fsdev dax
dax: Add dax_set_ops() for setting dax_operations at bind time
dax: Add fs_dax_get() func to prepare dax for fs-dax usage
dax: export dax_dev_get()
MAINTAINERS | 8 +
drivers/dax/Kconfig | 5 +
drivers/dax/Makefile | 2 +
drivers/dax/bus.c | 22 ++-
drivers/dax/bus.h | 3 +
drivers/dax/dax-private.h | 4 +
drivers/dax/device.c | 23 ---
drivers/dax/fsdev.c | 346 ++++++++++++++++++++++++++++++++++++++
drivers/dax/super.c | 107 +++++++++++-
fs/dax.c | 74 ++++++--
include/linux/dax.h | 19 ++-
11 files changed, 563 insertions(+), 50 deletions(-)
create mode 100644 drivers/dax/fsdev.c
base-commit: c369299895a591d96745d6492d4888259b004a9e
--
2.53.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH V10 1/8] dax: move dax_pgoff_to_phys from [drivers/dax/] device.c to bus.c
2026-03-27 21:03 ` [PATCH V10 0/8] dax: prepare for famfs John Groves
@ 2026-03-27 21:04 ` John Groves
2026-03-27 21:04 ` [PATCH V10 2/8] dax: Factor out dax_folio_reset_order() helper John Groves
` (7 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: John Groves @ 2026-03-27 21:04 UTC (permalink / raw)
To: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
Alison Schofield
Cc: John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org,
John Groves, Ira Weiny, Jonathan Cameron
From: John Groves <john@groves.net>
This function will be used by both device.c and fsdev.c, but both are
loadable modules. Moving to bus.c puts it in core and makes it available
to both.
No code changes - just relocated.
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Signed-off-by: John Groves <john@groves.net>
---
drivers/dax/bus.c | 20 ++++++++++++++++++++
drivers/dax/device.c | 23 -----------------------
2 files changed, 20 insertions(+), 23 deletions(-)
diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
index c94c09622516..1b412264bb36 100644
--- a/drivers/dax/bus.c
+++ b/drivers/dax/bus.c
@@ -1417,6 +1417,26 @@ static const struct device_type dev_dax_type = {
.groups = dax_attribute_groups,
};
+/* see "strong" declaration in tools/testing/nvdimm/dax-dev.c */
+__weak phys_addr_t dax_pgoff_to_phys(struct dev_dax *dev_dax, pgoff_t pgoff,
+ unsigned long size)
+{
+ for (int i = 0; i < dev_dax->nr_range; i++) {
+ struct dev_dax_range *dax_range = &dev_dax->ranges[i];
+ struct range *range = &dax_range->range;
+ phys_addr_t phys;
+
+ if (!in_range(pgoff, dax_range->pgoff, PHYS_PFN(range_len(range))))
+ continue;
+ phys = PFN_PHYS(pgoff - dax_range->pgoff) + range->start;
+ if (phys + size - 1 <= range->end)
+ return phys;
+ break;
+ }
+ return -1;
+}
+EXPORT_SYMBOL_GPL(dax_pgoff_to_phys);
+
static struct dev_dax *__devm_create_dev_dax(struct dev_dax_data *data)
{
struct dax_region *dax_region = data->dax_region;
diff --git a/drivers/dax/device.c b/drivers/dax/device.c
index 528e81240c4d..2d2dbfd35e94 100644
--- a/drivers/dax/device.c
+++ b/drivers/dax/device.c
@@ -57,29 +57,6 @@ static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma,
vma->vm_file, func);
}
-/* see "strong" declaration in tools/testing/nvdimm/dax-dev.c */
-__weak phys_addr_t dax_pgoff_to_phys(struct dev_dax *dev_dax, pgoff_t pgoff,
- unsigned long size)
-{
- int i;
-
- for (i = 0; i < dev_dax->nr_range; i++) {
- struct dev_dax_range *dax_range = &dev_dax->ranges[i];
- struct range *range = &dax_range->range;
- unsigned long long pgoff_end;
- phys_addr_t phys;
-
- pgoff_end = dax_range->pgoff + PHYS_PFN(range_len(range)) - 1;
- if (pgoff < dax_range->pgoff || pgoff > pgoff_end)
- continue;
- phys = PFN_PHYS(pgoff - dax_range->pgoff) + range->start;
- if (phys + size - 1 <= range->end)
- return phys;
- break;
- }
- return -1;
-}
-
static void dax_set_mapping(struct vm_fault *vmf, unsigned long pfn,
unsigned long fault_size)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V10 2/8] dax: Factor out dax_folio_reset_order() helper
2026-03-27 21:03 ` [PATCH V10 0/8] dax: prepare for famfs John Groves
2026-03-27 21:04 ` [PATCH V10 1/8] dax: move dax_pgoff_to_phys from [drivers/dax/] device.c to bus.c John Groves
@ 2026-03-27 21:04 ` John Groves
2026-03-27 21:04 ` [PATCH V10 3/8] dax: add fsdev.c driver for fs-dax on character dax John Groves
` (6 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: John Groves @ 2026-03-27 21:04 UTC (permalink / raw)
To: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
Alison Schofield
Cc: John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org,
Jonathan Cameron, Ira Weiny, John Groves
From: John Groves <John@Groves.net>
Both fs/dax.c:dax_folio_put() and drivers/dax/fsdev.c:
fsdev_clear_folio_state() (the latter coming in the next commit after this
one) contain nearly identical code to reset a compound DAX folio back to
order-0 pages. Factor this out into a shared helper function.
The new dax_folio_reset_order() function:
- Clears the folio's mapping and share count
- Resets compound folio state via folio_reset_order()
- Clears PageHead and compound_head for each sub-page
- Restores the pgmap pointer for each resulting order-0 folio
- Returns the original folio order (for callers that need to advance by
that many pages)
Two intentional differences from the original dax_folio_put() logic:
1. folio->share is cleared unconditionally. This is correct because the DAX
subsystem maintains the invariant that share != 0 only when
mapping == NULL (enforced by dax_folio_make_shared()). dax_folio_put()
ensures share has reached zero before calling this helper, so the
unconditional clear is safe.
2. folio->pgmap is now explicitly restored for order-0 folios. For the
dax_folio_put() caller this is a no-op (reads and writes back the same
field). It is intentional for the upcoming fsdev_clear_folio_state()
caller, which converts previously-compound folios and needs pgmap
re-established for all pages regardless of order.
This simplifies fsdev_clear_folio_state() from ~50 lines to ~15 lines.
Suggested-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Signed-off-by: John Groves <john@groves.net>
---
fs/dax.c | 73 ++++++++++++++++++++++++++++++++++-----------
include/linux/dax.h | 1 +
2 files changed, 56 insertions(+), 18 deletions(-)
diff --git a/fs/dax.c b/fs/dax.c
index 289e6254aa30..87bed6de920d 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -378,6 +378,58 @@ static void dax_folio_make_shared(struct folio *folio)
folio->share = 1;
}
+/**
+ * dax_folio_reset_order - Reset a compound DAX folio to order-0 pages
+ * @folio: The folio to reset
+ *
+ * Splits a compound folio back into individual order-0 pages,
+ * clearing compound state and restoring pgmap pointers.
+ *
+ * Returns: the original folio order (0 if already order-0)
+ */
+int dax_folio_reset_order(struct folio *folio)
+{
+ struct dev_pagemap *pgmap = page_pgmap(&folio->page);
+ int order = folio_order(folio);
+
+ /*
+ * DAX maintains the invariant that folio->share != 0 only when
+ * folio->mapping == NULL (enforced by dax_folio_make_shared()).
+ * Equivalently: folio->mapping != NULL implies folio->share == 0.
+ * Callers ensure share has been decremented to zero before
+ * calling here, so unconditionally clearing both fields is
+ * correct.
+ */
+ folio->mapping = NULL;
+ folio->share = 0;
+
+ if (!order) {
+ /*
+ * Restore pgmap explicitly even for order-0 folios. For the
+ * dax_folio_put() caller this is a no-op (same value), but
+ * fsdev_clear_folio_state() may call this on folios that
+ * were previously compound and need pgmap re-established.
+ */
+ folio->pgmap = pgmap;
+ return 0;
+ }
+
+ folio_reset_order(folio);
+
+ for (int i = 0; i < (1UL << order); i++) {
+ struct page *page = folio_page(folio, i);
+ struct folio *f = (struct folio *)page;
+
+ ClearPageHead(page);
+ clear_compound_head(page);
+ f->mapping = NULL;
+ f->share = 0;
+ f->pgmap = pgmap;
+ }
+
+ return order;
+}
+
static inline unsigned long dax_folio_put(struct folio *folio)
{
unsigned long ref;
@@ -391,28 +443,13 @@ static inline unsigned long dax_folio_put(struct folio *folio)
if (ref)
return ref;
- folio->mapping = NULL;
- order = folio_order(folio);
- if (!order)
- return 0;
- folio_reset_order(folio);
+ order = dax_folio_reset_order(folio);
+ /* Debug check: verify refcounts are zero for all sub-folios */
for (i = 0; i < (1UL << order); i++) {
- struct dev_pagemap *pgmap = page_pgmap(&folio->page);
struct page *page = folio_page(folio, i);
- struct folio *new_folio = (struct folio *)page;
-
- ClearPageHead(page);
- clear_compound_head(page);
- new_folio->mapping = NULL;
- /*
- * Reset pgmap which was over-written by
- * prep_compound_page().
- */
- new_folio->pgmap = pgmap;
- new_folio->share = 0;
- WARN_ON_ONCE(folio_ref_count(new_folio));
+ WARN_ON_ONCE(folio_ref_count((struct folio *)page));
}
return ref;
diff --git a/include/linux/dax.h b/include/linux/dax.h
index bf103f317cac..73cfc1a7c8f1 100644
--- a/include/linux/dax.h
+++ b/include/linux/dax.h
@@ -153,6 +153,7 @@ static inline void fs_put_dax(struct dax_device *dax_dev, void *holder)
#if IS_ENABLED(CONFIG_FS_DAX)
int dax_writeback_mapping_range(struct address_space *mapping,
struct dax_device *dax_dev, struct writeback_control *wbc);
+int dax_folio_reset_order(struct folio *folio);
struct page *dax_layout_busy_page(struct address_space *mapping);
struct page *dax_layout_busy_page_range(struct address_space *mapping, loff_t start, loff_t end);
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V10 3/8] dax: add fsdev.c driver for fs-dax on character dax
2026-03-27 21:03 ` [PATCH V10 0/8] dax: prepare for famfs John Groves
2026-03-27 21:04 ` [PATCH V10 1/8] dax: move dax_pgoff_to_phys from [drivers/dax/] device.c to bus.c John Groves
2026-03-27 21:04 ` [PATCH V10 2/8] dax: Factor out dax_folio_reset_order() helper John Groves
@ 2026-03-27 21:04 ` John Groves
2026-03-27 21:04 ` [PATCH V10 4/8] dax: Save the kva from memremap John Groves
` (5 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: John Groves @ 2026-03-27 21:04 UTC (permalink / raw)
To: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
Alison Schofield
Cc: John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org,
John Groves, Jonathan Cameron
From: John Groves <john@groves.net>
The new fsdev driver provides pages/folios initialized compatibly with
fsdax - normal rather than devdax-style refcounting, and starting out
with order-0 folios.
When fsdev binds to a daxdev, it is usually (always?) switching from the
devdax mode (device.c), which pre-initializes compound folios according
to its alignment. Fsdev uses fsdev_clear_folio_state() to switch the
folios into a fsdax-compatible state.
A side effect of this is that raw mmap doesn't (can't?) work on an fsdev
dax instance. Accordingly, The fsdev driver does not provide raw mmap -
devices must be put in 'devdax' mode (drivers/dax/device.c) to get raw
mmap capability.
In this commit is just the framework, which remaps pages/folios compatibly
with fsdax.
Enabling dax changes:
- bus.h: add DAXDRV_FSDEV_TYPE driver type
- bus.c: allow DAXDRV_FSDEV_TYPE drivers to bind to daxdevs
- dax.h: prototype inode_dax(), which fsdev needs
Suggested-by: Dan Williams <dan.j.williams@intel.com>
Suggested-by: Gregory Price <gourry@gourry.net>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Signed-off-by: John Groves <john@groves.net>
---
MAINTAINERS | 8 ++
drivers/dax/Kconfig | 5 +
drivers/dax/Makefile | 2 +
drivers/dax/bus.h | 1 +
drivers/dax/fsdev.c | 245 +++++++++++++++++++++++++++++++++++++++++++
fs/dax.c | 1 +
6 files changed, 262 insertions(+)
create mode 100644 drivers/dax/fsdev.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 7d10988cbc62..eedf4cce56ed 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7298,6 +7298,14 @@ L: linux-cxl@vger.kernel.org
S: Supported
F: drivers/dax/
+DEVICE DIRECT ACCESS (DAX) [fsdev_dax]
+M: John Groves <jgroves@micron.com>
+M: John Groves <John@Groves.net>
+L: nvdimm@lists.linux.dev
+L: linux-cxl@vger.kernel.org
+S: Supported
+F: drivers/dax/fsdev.c
+
DEVICE FREQUENCY (DEVFREQ)
M: MyungJoo Ham <myungjoo.ham@samsung.com>
M: Kyungmin Park <kyungmin.park@samsung.com>
diff --git a/drivers/dax/Kconfig b/drivers/dax/Kconfig
index d656e4c0eb84..6d8493cc540c 100644
--- a/drivers/dax/Kconfig
+++ b/drivers/dax/Kconfig
@@ -61,6 +61,11 @@ config DEV_DAX_HMEM_DEVICES
depends on DEV_DAX_HMEM && DAX
def_bool y
+config DEV_DAX_FSDEV
+ tristate
+ depends on DEV_DAX && FS_DAX
+ default DEV_DAX
+
config DEV_DAX_KMEM
tristate "KMEM DAX: map dax-devices as System-RAM"
default DEV_DAX
diff --git a/drivers/dax/Makefile b/drivers/dax/Makefile
index 5ed5c39857c8..ba35bda7abef 100644
--- a/drivers/dax/Makefile
+++ b/drivers/dax/Makefile
@@ -4,11 +4,13 @@ obj-$(CONFIG_DEV_DAX) += device_dax.o
obj-$(CONFIG_DEV_DAX_KMEM) += kmem.o
obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
obj-$(CONFIG_DEV_DAX_CXL) += dax_cxl.o
+obj-$(CONFIG_DEV_DAX_FSDEV) += fsdev_dax.o
dax-y := super.o
dax-y += bus.o
device_dax-y := device.o
dax_pmem-y := pmem.o
dax_cxl-y := cxl.o
+fsdev_dax-y := fsdev.o
obj-y += hmem/
diff --git a/drivers/dax/bus.h b/drivers/dax/bus.h
index cbbf64443098..880bdf7e72d7 100644
--- a/drivers/dax/bus.h
+++ b/drivers/dax/bus.h
@@ -31,6 +31,7 @@ struct dev_dax *devm_create_dev_dax(struct dev_dax_data *data);
enum dax_driver_type {
DAXDRV_KMEM_TYPE,
DAXDRV_DEVICE_TYPE,
+ DAXDRV_FSDEV_TYPE,
};
struct dax_device_driver {
diff --git a/drivers/dax/fsdev.c b/drivers/dax/fsdev.c
new file mode 100644
index 000000000000..8b5c6976ad17
--- /dev/null
+++ b/drivers/dax/fsdev.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2026 Micron Technology, Inc. */
+#include <linux/memremap.h>
+#include <linux/pagemap.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/slab.h>
+#include <linux/dax.h>
+#include <linux/uio.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include "dax-private.h"
+#include "bus.h"
+
+/*
+ * FS-DAX compatible devdax driver
+ *
+ * Unlike drivers/dax/device.c which pre-initializes compound folios based
+ * on device alignment (via vmemmap_shift), this driver leaves folios
+ * uninitialized similar to pmem. This allows fs-dax filesystems like famfs
+ * to work without needing special handling for pre-initialized folios.
+ *
+ * Key differences from device.c:
+ * - pgmap type is MEMORY_DEVICE_FS_DAX (not MEMORY_DEVICE_GENERIC)
+ * - vmemmap_shift is NOT set (folios remain order-0)
+ * - fs-dax can dynamically create compound folios as needed
+ * - No mmap support - all access is through fs-dax/iomap
+ */
+
+static void fsdev_cdev_del(void *cdev)
+{
+ cdev_del(cdev);
+}
+
+static void fsdev_kill(void *dev_dax)
+{
+ kill_dev_dax(dev_dax);
+}
+
+/*
+ * Page map operations for FS-DAX mode
+ * Similar to fsdax_pagemap_ops in drivers/nvdimm/pmem.c
+ *
+ * Note: folio_free callback is not needed for MEMORY_DEVICE_FS_DAX.
+ * The core mm code in free_zone_device_folio() handles the wake_up_var()
+ * directly for this memory type.
+ */
+static int fsdev_pagemap_memory_failure(struct dev_pagemap *pgmap,
+ unsigned long pfn, unsigned long nr_pages, int mf_flags)
+{
+ struct dev_dax *dev_dax = pgmap->owner;
+ u64 offset = PFN_PHYS(pfn) - dev_dax->ranges[0].range.start;
+ u64 len = nr_pages << PAGE_SHIFT;
+
+ return dax_holder_notify_failure(dev_dax->dax_dev, offset,
+ len, mf_flags);
+}
+
+static const struct dev_pagemap_ops fsdev_pagemap_ops = {
+ .memory_failure = fsdev_pagemap_memory_failure,
+};
+
+/*
+ * Clear any stale folio state from pages in the given range.
+ * This is necessary because device_dax pre-initializes compound folios
+ * based on vmemmap_shift, and that state may persist after driver unbind.
+ * Since fsdev_dax uses MEMORY_DEVICE_FS_DAX without vmemmap_shift, fs-dax
+ * expects to find clean order-0 folios that it can build into compound
+ * folios on demand.
+ *
+ * At probe time, no filesystem should be mounted yet, so all mappings
+ * are stale and must be cleared along with compound state.
+ */
+static void fsdev_clear_folio_state(struct dev_dax *dev_dax)
+{
+ for (int i = 0; i < dev_dax->nr_range; i++) {
+ struct range *range = &dev_dax->ranges[i].range;
+ unsigned long pfn = PHYS_PFN(range->start);
+ unsigned long end_pfn = PHYS_PFN(range->end) + 1;
+
+ while (pfn < end_pfn) {
+ struct folio *folio = pfn_folio(pfn);
+ int order = dax_folio_reset_order(folio);
+
+ pfn += 1UL << order;
+ }
+ }
+}
+
+static void fsdev_clear_folio_state_action(void *data)
+{
+ fsdev_clear_folio_state(data);
+}
+
+static int fsdev_open(struct inode *inode, struct file *filp)
+{
+ struct dax_device *dax_dev = inode_dax(inode);
+ struct dev_dax *dev_dax = dax_get_private(dax_dev);
+
+ filp->private_data = dev_dax;
+
+ return 0;
+}
+
+static int fsdev_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static const struct file_operations fsdev_fops = {
+ .llseek = noop_llseek,
+ .owner = THIS_MODULE,
+ .open = fsdev_open,
+ .release = fsdev_release,
+};
+
+static int fsdev_dax_probe(struct dev_dax *dev_dax)
+{
+ struct dax_device *dax_dev = dev_dax->dax_dev;
+ struct device *dev = &dev_dax->dev;
+ struct dev_pagemap *pgmap;
+ struct inode *inode;
+ struct cdev *cdev;
+ void *addr;
+ int rc, i;
+
+ if (static_dev_dax(dev_dax)) {
+ if (dev_dax->nr_range > 1) {
+ dev_warn(dev, "static pgmap / multi-range device conflict\n");
+ return -EINVAL;
+ }
+
+ pgmap = dev_dax->pgmap;
+ } else {
+ size_t pgmap_size;
+
+ if (dev_dax->pgmap) {
+ dev_warn(dev, "dynamic-dax with pre-populated page map\n");
+ return -EINVAL;
+ }
+
+ pgmap_size = struct_size(pgmap, ranges, dev_dax->nr_range - 1);
+ pgmap = devm_kzalloc(dev, pgmap_size, GFP_KERNEL);
+ if (!pgmap)
+ return -ENOMEM;
+
+ pgmap->nr_range = dev_dax->nr_range;
+ dev_dax->pgmap = pgmap;
+
+ for (i = 0; i < dev_dax->nr_range; i++) {
+ struct range *range = &dev_dax->ranges[i].range;
+
+ pgmap->ranges[i] = *range;
+ }
+ }
+
+ for (i = 0; i < dev_dax->nr_range; i++) {
+ struct range *range = &dev_dax->ranges[i].range;
+
+ if (!devm_request_mem_region(dev, range->start,
+ range_len(range), dev_name(dev))) {
+ dev_warn(dev, "mapping%d: %#llx-%#llx could not reserve range\n",
+ i, range->start, range->end);
+ return -EBUSY;
+ }
+ }
+
+ /*
+ * Use MEMORY_DEVICE_FS_DAX without setting vmemmap_shift, leaving
+ * folios at order-0. Unlike device.c (MEMORY_DEVICE_GENERIC), this
+ * lets fs-dax dynamically build compound folios as needed, similar
+ * to pmem behavior.
+ */
+ pgmap->type = MEMORY_DEVICE_FS_DAX;
+ pgmap->ops = &fsdev_pagemap_ops;
+ pgmap->owner = dev_dax;
+
+ addr = devm_memremap_pages(dev, pgmap);
+ if (IS_ERR(addr))
+ return PTR_ERR(addr);
+
+ /*
+ * Clear any stale compound folio state left over from a previous
+ * driver (e.g., device_dax with vmemmap_shift). Also register this
+ * as a devm action so folio state is cleared on unbind, ensuring
+ * clean pages for subsequent drivers (e.g., kmem for system-ram).
+ */
+ fsdev_clear_folio_state(dev_dax);
+ rc = devm_add_action_or_reset(dev, fsdev_clear_folio_state_action,
+ dev_dax);
+ if (rc)
+ return rc;
+
+ /* Detect whether the data is at a non-zero offset into the memory */
+ if (pgmap->range.start != dev_dax->ranges[0].range.start) {
+ u64 phys = dev_dax->ranges[0].range.start;
+ u64 pgmap_phys = dev_dax->pgmap[0].range.start;
+ u64 data_offset = 0;
+
+ if (!WARN_ON(pgmap_phys > phys))
+ data_offset = phys - pgmap_phys;
+
+ pr_debug("%s: offset detected phys=%llx pgmap_phys=%llx offset=%llx\n",
+ __func__, phys, pgmap_phys, data_offset);
+ }
+
+ inode = dax_inode(dax_dev);
+ cdev = inode->i_cdev;
+ cdev_init(cdev, &fsdev_fops);
+ cdev->owner = dev->driver->owner;
+ cdev_set_parent(cdev, &dev->kobj);
+ rc = cdev_add(cdev, dev->devt, 1);
+ if (rc)
+ return rc;
+
+ rc = devm_add_action_or_reset(dev, fsdev_cdev_del, cdev);
+ if (rc)
+ return rc;
+
+ run_dax(dax_dev);
+ return devm_add_action_or_reset(dev, fsdev_kill, dev_dax);
+}
+
+static struct dax_device_driver fsdev_dax_driver = {
+ .probe = fsdev_dax_probe,
+ .type = DAXDRV_FSDEV_TYPE,
+};
+
+static int __init dax_init(void)
+{
+ return dax_driver_register(&fsdev_dax_driver);
+}
+
+static void __exit dax_exit(void)
+{
+ dax_driver_unregister(&fsdev_dax_driver);
+}
+
+MODULE_AUTHOR("John Groves");
+MODULE_DESCRIPTION("FS-DAX Device: fs-dax compatible devdax driver");
+MODULE_LICENSE("GPL");
+module_init(dax_init);
+module_exit(dax_exit);
+MODULE_ALIAS_DAX_DEVICE(0);
diff --git a/fs/dax.c b/fs/dax.c
index 87bed6de920d..cb5c87e43bc3 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -429,6 +429,7 @@ int dax_folio_reset_order(struct folio *folio)
return order;
}
+EXPORT_SYMBOL_GPL(dax_folio_reset_order);
static inline unsigned long dax_folio_put(struct folio *folio)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V10 4/8] dax: Save the kva from memremap
2026-03-27 21:03 ` [PATCH V10 0/8] dax: prepare for famfs John Groves
` (2 preceding siblings ...)
2026-03-27 21:04 ` [PATCH V10 3/8] dax: add fsdev.c driver for fs-dax on character dax John Groves
@ 2026-03-27 21:04 ` John Groves
2026-03-27 21:04 ` [PATCH V10 5/8] dax: Add dax_operations for use by fs-dax on fsdev dax John Groves
` (4 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: John Groves @ 2026-03-27 21:04 UTC (permalink / raw)
To: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
Alison Schofield
Cc: John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org,
John Groves, Ira Weiny, Jonathan Cameron
From: John Groves <john@groves.net>
Save the kva from memremap because we need it for iomap rw support.
Prior to famfs, there were no iomap users of /dev/dax - so the virtual
address from memremap was not needed.
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Signed-off-by: John Groves <john@groves.net>
---
drivers/dax/dax-private.h | 2 ++
drivers/dax/fsdev.c | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/dax/dax-private.h b/drivers/dax/dax-private.h
index c6ae27c982f4..7a3727d76a68 100644
--- a/drivers/dax/dax-private.h
+++ b/drivers/dax/dax-private.h
@@ -69,6 +69,7 @@ struct dev_dax_range {
* data while the device is activated in the driver.
* @region: parent region
* @dax_dev: core dax functionality
+ * @virt_addr: kva from memremap; used by fsdev_dax
* @align: alignment of this instance
* @target_node: effective numa node if dev_dax memory range is onlined
* @dyn_id: is this a dynamic or statically created instance
@@ -83,6 +84,7 @@ struct dev_dax_range {
struct dev_dax {
struct dax_region *region;
struct dax_device *dax_dev;
+ void *virt_addr;
unsigned int align;
int target_node;
bool dyn_id;
diff --git a/drivers/dax/fsdev.c b/drivers/dax/fsdev.c
index 8b5c6976ad17..c75478d3d548 100644
--- a/drivers/dax/fsdev.c
+++ b/drivers/dax/fsdev.c
@@ -121,6 +121,7 @@ static int fsdev_dax_probe(struct dev_dax *dev_dax)
struct device *dev = &dev_dax->dev;
struct dev_pagemap *pgmap;
struct inode *inode;
+ u64 data_offset = 0;
struct cdev *cdev;
void *addr;
int rc, i;
@@ -196,7 +197,6 @@ static int fsdev_dax_probe(struct dev_dax *dev_dax)
if (pgmap->range.start != dev_dax->ranges[0].range.start) {
u64 phys = dev_dax->ranges[0].range.start;
u64 pgmap_phys = dev_dax->pgmap[0].range.start;
- u64 data_offset = 0;
if (!WARN_ON(pgmap_phys > phys))
data_offset = phys - pgmap_phys;
@@ -204,6 +204,7 @@ static int fsdev_dax_probe(struct dev_dax *dev_dax)
pr_debug("%s: offset detected phys=%llx pgmap_phys=%llx offset=%llx\n",
__func__, phys, pgmap_phys, data_offset);
}
+ dev_dax->virt_addr = addr + data_offset;
inode = dax_inode(dax_dev);
cdev = inode->i_cdev;
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V10 5/8] dax: Add dax_operations for use by fs-dax on fsdev dax
2026-03-27 21:03 ` [PATCH V10 0/8] dax: prepare for famfs John Groves
` (3 preceding siblings ...)
2026-03-27 21:04 ` [PATCH V10 4/8] dax: Save the kva from memremap John Groves
@ 2026-03-27 21:04 ` John Groves
2026-03-27 21:05 ` [PATCH V10 6/8] dax: Add dax_set_ops() for setting dax_operations at bind time John Groves
` (3 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: John Groves @ 2026-03-27 21:04 UTC (permalink / raw)
To: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
Alison Schofield
Cc: John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org,
John Groves
From: John Groves <John@Groves.net>
fsdev: Add dax_operations for use by famfs.
This replicates the functionality from drivers/nvdimm/pmem.c that
conventional fs-dax file systems (e.g. xfs) use to support dax
read/write/mmap to a daxdev - without which famfs can't sit atop a
daxdev.
- These methods are based on pmem_dax_ops from drivers/nvdimm/pmem.c
- fsdev_dax_direct_access() returns the hpa, pfn and kva. The kva was
newly stored as dev_dax->virt_addr by dev_dax_probe().
- The hpa/pfn are used for mmap (dax_iomap_fault()), and the kva is used
for read/write (dax_iomap_rw())
- fsdev_dax_recovery_write() and dev_dax_zero_page_range() have not been
tested yet. I'm looking for suggestions as to how to test those.
- dax-private.h: add dev_dax->cached_size, which fsdev needs to
remember. The dev_dax size cannot change while a driver is bound
(dev_dax_resize returns -EBUSY if dev->driver is set). Caching the size
at probe time allows fsdev's direct_access path can use it without
acquiring dax_dev_rwsem (which isn't exported anyway).
Signed-off-by: John Groves <john@groves.net>
---
drivers/dax/dax-private.h | 2 +
drivers/dax/fsdev.c | 84 +++++++++++++++++++++++++++++++++++++++
2 files changed, 86 insertions(+)
diff --git a/drivers/dax/dax-private.h b/drivers/dax/dax-private.h
index 7a3727d76a68..81e4af49e39c 100644
--- a/drivers/dax/dax-private.h
+++ b/drivers/dax/dax-private.h
@@ -70,6 +70,7 @@ struct dev_dax_range {
* @region: parent region
* @dax_dev: core dax functionality
* @virt_addr: kva from memremap; used by fsdev_dax
+ * @cached_size: size of daxdev cached by fsdev_dax
* @align: alignment of this instance
* @target_node: effective numa node if dev_dax memory range is onlined
* @dyn_id: is this a dynamic or statically created instance
@@ -85,6 +86,7 @@ struct dev_dax {
struct dax_region *region;
struct dax_device *dax_dev;
void *virt_addr;
+ u64 cached_size;
unsigned int align;
int target_node;
bool dyn_id;
diff --git a/drivers/dax/fsdev.c b/drivers/dax/fsdev.c
index c75478d3d548..30f57c74c979 100644
--- a/drivers/dax/fsdev.c
+++ b/drivers/dax/fsdev.c
@@ -28,6 +28,85 @@
* - No mmap support - all access is through fs-dax/iomap
*/
+static void fsdev_write_dax(void *addr, struct page *page,
+ unsigned int off, unsigned int len)
+{
+ while (len) {
+ void *mem = kmap_local_page(page);
+ unsigned int chunk = min_t(unsigned int, len, PAGE_SIZE - off);
+
+ memcpy_flushcache(addr, mem + off, chunk);
+ kunmap_local(mem);
+ len -= chunk;
+ off = 0;
+ page++;
+ addr += chunk;
+ }
+}
+
+static long __fsdev_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff,
+ long nr_pages, enum dax_access_mode mode, void **kaddr,
+ unsigned long *pfn)
+{
+ struct dev_dax *dev_dax = dax_get_private(dax_dev);
+ size_t size = nr_pages << PAGE_SHIFT;
+ size_t offset = pgoff << PAGE_SHIFT;
+ void *virt_addr = dev_dax->virt_addr + offset;
+ phys_addr_t phys;
+ unsigned long local_pfn;
+
+ phys = dax_pgoff_to_phys(dev_dax, pgoff, size);
+ if (phys == -1) {
+ dev_dbg(&dev_dax->dev,
+ "pgoff (%#lx) out of range\n", pgoff);
+ return -EFAULT;
+ }
+
+ if (kaddr)
+ *kaddr = virt_addr;
+
+ local_pfn = PHYS_PFN(phys);
+ if (pfn)
+ *pfn = local_pfn;
+
+ /*
+ * Use cached_size which was computed at probe time. The size cannot
+ * change while the driver is bound (resize returns -EBUSY).
+ */
+ return PHYS_PFN(min(size, dev_dax->cached_size - offset));
+}
+
+static int fsdev_dax_zero_page_range(struct dax_device *dax_dev,
+ pgoff_t pgoff, size_t nr_pages)
+{
+ void *kaddr;
+
+ WARN_ONCE(nr_pages > 1, "%s: nr_pages > 1\n", __func__);
+ __fsdev_dax_direct_access(dax_dev, pgoff, 1, DAX_ACCESS, &kaddr, NULL);
+ fsdev_write_dax(kaddr, ZERO_PAGE(0), 0, PAGE_SIZE);
+ return 0;
+}
+
+static long fsdev_dax_direct_access(struct dax_device *dax_dev,
+ pgoff_t pgoff, long nr_pages, enum dax_access_mode mode,
+ void **kaddr, unsigned long *pfn)
+{
+ return __fsdev_dax_direct_access(dax_dev, pgoff, nr_pages, mode,
+ kaddr, pfn);
+}
+
+static size_t fsdev_dax_recovery_write(struct dax_device *dax_dev, pgoff_t pgoff,
+ void *addr, size_t bytes, struct iov_iter *i)
+{
+ return _copy_from_iter_flushcache(addr, bytes, i);
+}
+
+static const struct dax_operations dev_dax_ops = {
+ .direct_access = fsdev_dax_direct_access,
+ .zero_page_range = fsdev_dax_zero_page_range,
+ .recovery_write = fsdev_dax_recovery_write,
+};
+
static void fsdev_cdev_del(void *cdev)
{
cdev_del(cdev);
@@ -167,6 +246,11 @@ static int fsdev_dax_probe(struct dev_dax *dev_dax)
}
}
+ /* Cache size now; it cannot change while driver is bound */
+ dev_dax->cached_size = 0;
+ for (i = 0; i < dev_dax->nr_range; i++)
+ dev_dax->cached_size += range_len(&dev_dax->ranges[i].range);
+
/*
* Use MEMORY_DEVICE_FS_DAX without setting vmemmap_shift, leaving
* folios at order-0. Unlike device.c (MEMORY_DEVICE_GENERIC), this
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V10 6/8] dax: Add dax_set_ops() for setting dax_operations at bind time
2026-03-27 21:03 ` [PATCH V10 0/8] dax: prepare for famfs John Groves
` (4 preceding siblings ...)
2026-03-27 21:04 ` [PATCH V10 5/8] dax: Add dax_operations for use by fs-dax on fsdev dax John Groves
@ 2026-03-27 21:05 ` John Groves
2026-03-27 21:05 ` [PATCH V10 7/8] dax: Add fs_dax_get() func to prepare dax for fs-dax usage John Groves
` (2 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: John Groves @ 2026-03-27 21:05 UTC (permalink / raw)
To: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
Alison Schofield
Cc: John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org,
Jonathan Cameron, John Groves
From: John Groves <John@Groves.net>
Add a new dax_set_ops() function that allows drivers to set the
dax_operations after the dax_device has been allocated. This is needed
for fsdev_dax where the operations need to be set during probe and
cleared during unbind.
The fsdev driver uses devm_add_action_or_reset() for cleanup consistency,
avoiding the complexity of mixing devm-managed resources with manual
cleanup in a remove() callback. This ensures cleanup happens automatically
in the correct reverse order when the device is unbound.
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Signed-off-by: John Groves <john@groves.net>
---
drivers/dax/fsdev.c | 16 ++++++++++++++++
drivers/dax/super.c | 38 +++++++++++++++++++++++++++++++++++++-
include/linux/dax.h | 1 +
3 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/drivers/dax/fsdev.c b/drivers/dax/fsdev.c
index 30f57c74c979..4499d9621f33 100644
--- a/drivers/dax/fsdev.c
+++ b/drivers/dax/fsdev.c
@@ -117,6 +117,13 @@ static void fsdev_kill(void *dev_dax)
kill_dev_dax(dev_dax);
}
+static void fsdev_clear_ops(void *data)
+{
+ struct dev_dax *dev_dax = data;
+
+ dax_set_ops(dev_dax->dax_dev, NULL);
+}
+
/*
* Page map operations for FS-DAX mode
* Similar to fsdax_pagemap_ops in drivers/nvdimm/pmem.c
@@ -303,6 +310,15 @@ static int fsdev_dax_probe(struct dev_dax *dev_dax)
if (rc)
return rc;
+ /* Set the dax operations for fs-dax access path */
+ rc = dax_set_ops(dax_dev, &dev_dax_ops);
+ if (rc)
+ return rc;
+
+ rc = devm_add_action_or_reset(dev, fsdev_clear_ops, dev_dax);
+ if (rc)
+ return rc;
+
run_dax(dax_dev);
return devm_add_action_or_reset(dev, fsdev_kill, dev_dax);
}
diff --git a/drivers/dax/super.c b/drivers/dax/super.c
index c00b9dff4a06..ba0b4cd18a77 100644
--- a/drivers/dax/super.c
+++ b/drivers/dax/super.c
@@ -157,6 +157,9 @@ long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
if (!dax_alive(dax_dev))
return -ENXIO;
+ if (!dax_dev->ops)
+ return -EOPNOTSUPP;
+
if (nr_pages < 0)
return -EINVAL;
@@ -207,6 +210,10 @@ int dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff,
if (!dax_alive(dax_dev))
return -ENXIO;
+
+ if (!dax_dev->ops)
+ return -EOPNOTSUPP;
+
/*
* There are no callers that want to zero more than one page as of now.
* Once users are there, this check can be removed after the
@@ -223,7 +230,7 @@ EXPORT_SYMBOL_GPL(dax_zero_page_range);
size_t dax_recovery_write(struct dax_device *dax_dev, pgoff_t pgoff,
void *addr, size_t bytes, struct iov_iter *iter)
{
- if (!dax_dev->ops->recovery_write)
+ if (!dax_dev->ops || !dax_dev->ops->recovery_write)
return 0;
return dax_dev->ops->recovery_write(dax_dev, pgoff, addr, bytes, iter);
}
@@ -307,6 +314,35 @@ void set_dax_nomc(struct dax_device *dax_dev)
}
EXPORT_SYMBOL_GPL(set_dax_nomc);
+/**
+ * dax_set_ops - set the dax_operations for a dax_device
+ * @dax_dev: the dax_device to configure
+ * @ops: the operations to set (may be NULL to clear)
+ *
+ * This allows drivers to set the dax_operations after the dax_device
+ * has been allocated. This is needed when the device is created before
+ * the driver that needs specific ops is bound (e.g., fsdev_dax binding
+ * to a dev_dax created by hmem).
+ *
+ * When setting non-NULL ops, fails if ops are already set (returns -EBUSY).
+ * When clearing ops (NULL), always succeeds.
+ *
+ * Return: 0 on success, -EBUSY if ops already set
+ */
+int dax_set_ops(struct dax_device *dax_dev, const struct dax_operations *ops)
+{
+ if (ops) {
+ /* Setting ops: fail if already set */
+ if (cmpxchg(&dax_dev->ops, NULL, ops) != NULL)
+ return -EBUSY;
+ } else {
+ /* Clearing ops: always allowed */
+ dax_dev->ops = NULL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dax_set_ops);
+
bool dax_alive(struct dax_device *dax_dev)
{
lockdep_assert_held(&dax_srcu);
diff --git a/include/linux/dax.h b/include/linux/dax.h
index 73cfc1a7c8f1..b19bfe0c2fd1 100644
--- a/include/linux/dax.h
+++ b/include/linux/dax.h
@@ -243,6 +243,7 @@ static inline void dax_break_layout_final(struct inode *inode)
bool dax_alive(struct dax_device *dax_dev);
void *dax_get_private(struct dax_device *dax_dev);
+int dax_set_ops(struct dax_device *dax_dev, const struct dax_operations *ops);
long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
enum dax_access_mode mode, void **kaddr, unsigned long *pfn);
size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V10 7/8] dax: Add fs_dax_get() func to prepare dax for fs-dax usage
2026-03-27 21:03 ` [PATCH V10 0/8] dax: prepare for famfs John Groves
` (5 preceding siblings ...)
2026-03-27 21:05 ` [PATCH V10 6/8] dax: Add dax_set_ops() for setting dax_operations at bind time John Groves
@ 2026-03-27 21:05 ` John Groves
2026-03-27 21:05 ` [PATCH V10 8/8] dax: export dax_dev_get() John Groves
2026-03-30 21:21 ` [PATCH V10 0/8] dax: prepare for famfs Alison Schofield
8 siblings, 0 replies; 16+ messages in thread
From: John Groves @ 2026-03-27 21:05 UTC (permalink / raw)
To: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
Alison Schofield
Cc: John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org,
John Groves, Jonathan Cameron
From: John Groves <john@groves.net>
The fs_dax_get() function should be called by fs-dax file systems after
opening a fsdev dax device. This adds holder_operations, which provides
a memory failure callback path and effects exclusivity between callers
of fs_dax_get().
fs_dax_get() is specific to fsdev_dax, so it checks the driver type
(which required touching bus.[ch]). fs_dax_get() fails if fsdev_dax is
not bound to the memory.
This function serves the same role as fs_dax_get_by_bdev(), which dax
file systems call after opening the pmem block device.
This can't be located in fsdev.c because struct dax_device is opaque
there.
This will be called by fs/fuse/famfs.c in a subsequent commit.
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: John Groves <john@groves.net>
---
drivers/dax/bus.c | 2 --
drivers/dax/bus.h | 2 ++
drivers/dax/super.c | 66 ++++++++++++++++++++++++++++++++++++++++++++-
include/linux/dax.h | 16 ++++++++---
4 files changed, 79 insertions(+), 7 deletions(-)
diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
index 1b412264bb36..32f7b7702c28 100644
--- a/drivers/dax/bus.c
+++ b/drivers/dax/bus.c
@@ -39,8 +39,6 @@ static int dax_bus_uevent(const struct device *dev, struct kobj_uevent_env *env)
return add_uevent_var(env, "MODALIAS=" DAX_DEVICE_MODALIAS_FMT, 0);
}
-#define to_dax_drv(__drv) container_of_const(__drv, struct dax_device_driver, drv)
-
static struct dax_id *__dax_match_id(const struct dax_device_driver *dax_drv,
const char *dev_name)
{
diff --git a/drivers/dax/bus.h b/drivers/dax/bus.h
index 880bdf7e72d7..dc6f112ac4a4 100644
--- a/drivers/dax/bus.h
+++ b/drivers/dax/bus.h
@@ -42,6 +42,8 @@ struct dax_device_driver {
void (*remove)(struct dev_dax *dev);
};
+#define to_dax_drv(__drv) container_of_const(__drv, struct dax_device_driver, drv)
+
int __dax_driver_register(struct dax_device_driver *dax_drv,
struct module *module, const char *mod_name);
#define dax_driver_register(driver) \
diff --git a/drivers/dax/super.c b/drivers/dax/super.c
index ba0b4cd18a77..d4ab60c406bf 100644
--- a/drivers/dax/super.c
+++ b/drivers/dax/super.c
@@ -14,6 +14,7 @@
#include <linux/fs.h>
#include <linux/cacheinfo.h>
#include "dax-private.h"
+#include "bus.h"
/**
* struct dax_device - anchor object for dax services
@@ -111,6 +112,10 @@ struct dax_device *fs_dax_get_by_bdev(struct block_device *bdev, u64 *start_off,
}
EXPORT_SYMBOL_GPL(fs_dax_get_by_bdev);
+#endif /* CONFIG_BLOCK && CONFIG_FS_DAX */
+
+#if IS_ENABLED(CONFIG_FS_DAX)
+
void fs_put_dax(struct dax_device *dax_dev, void *holder)
{
if (dax_dev && holder &&
@@ -119,7 +124,66 @@ void fs_put_dax(struct dax_device *dax_dev, void *holder)
put_dax(dax_dev);
}
EXPORT_SYMBOL_GPL(fs_put_dax);
-#endif /* CONFIG_BLOCK && CONFIG_FS_DAX */
+
+/**
+ * fs_dax_get() - get ownership of a devdax via holder/holder_ops
+ *
+ * fs-dax file systems call this function to prepare to use a devdax device for
+ * fsdax. This is like fs_dax_get_by_bdev(), but the caller already has struct
+ * dev_dax (and there is no bdev). The holder makes this exclusive.
+ *
+ * @dax_dev: dev to be prepared for fs-dax usage
+ * @holder: filesystem or mapped device inside the dax_device
+ * @hops: operations for the inner holder
+ *
+ * Returns: 0 on success, <0 on failure
+ */
+int fs_dax_get(struct dax_device *dax_dev, void *holder,
+ const struct dax_holder_operations *hops)
+{
+ struct dev_dax *dev_dax;
+ struct dax_device_driver *dax_drv;
+ int id;
+
+ id = dax_read_lock();
+ if (!dax_dev || !dax_alive(dax_dev) || !igrab(&dax_dev->inode)) {
+ dax_read_unlock(id);
+ return -ENODEV;
+ }
+ dax_read_unlock(id);
+
+ /* Verify the device is bound to fsdev_dax driver */
+ dev_dax = dax_get_private(dax_dev);
+ if (!dev_dax) {
+ iput(&dax_dev->inode);
+ return -ENODEV;
+ }
+
+ device_lock(&dev_dax->dev);
+ if (!dev_dax->dev.driver) {
+ device_unlock(&dev_dax->dev);
+ iput(&dax_dev->inode);
+ return -ENODEV;
+ }
+ dax_drv = to_dax_drv(dev_dax->dev.driver);
+ if (dax_drv->type != DAXDRV_FSDEV_TYPE) {
+ device_unlock(&dev_dax->dev);
+ iput(&dax_dev->inode);
+ return -EOPNOTSUPP;
+ }
+ device_unlock(&dev_dax->dev);
+
+ if (cmpxchg(&dax_dev->holder_data, NULL, holder)) {
+ iput(&dax_dev->inode);
+ return -EBUSY;
+ }
+
+ dax_dev->holder_ops = hops;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fs_dax_get);
+#endif /* CONFIG_FS_DAX */
enum dax_device_flags {
/* !alive + rcu grace period == no new operations / mappings */
diff --git a/include/linux/dax.h b/include/linux/dax.h
index b19bfe0c2fd1..a85e270bfb3c 100644
--- a/include/linux/dax.h
+++ b/include/linux/dax.h
@@ -130,7 +130,6 @@ int dax_add_host(struct dax_device *dax_dev, struct gendisk *disk);
void dax_remove_host(struct gendisk *disk);
struct dax_device *fs_dax_get_by_bdev(struct block_device *bdev, u64 *start_off,
void *holder, const struct dax_holder_operations *ops);
-void fs_put_dax(struct dax_device *dax_dev, void *holder);
#else
static inline int dax_add_host(struct dax_device *dax_dev, struct gendisk *disk)
{
@@ -145,12 +144,12 @@ static inline struct dax_device *fs_dax_get_by_bdev(struct block_device *bdev,
{
return NULL;
}
-static inline void fs_put_dax(struct dax_device *dax_dev, void *holder)
-{
-}
#endif /* CONFIG_BLOCK && CONFIG_FS_DAX */
#if IS_ENABLED(CONFIG_FS_DAX)
+void fs_put_dax(struct dax_device *dax_dev, void *holder);
+int fs_dax_get(struct dax_device *dax_dev, void *holder,
+ const struct dax_holder_operations *hops);
int dax_writeback_mapping_range(struct address_space *mapping,
struct dax_device *dax_dev, struct writeback_control *wbc);
int dax_folio_reset_order(struct folio *folio);
@@ -164,6 +163,15 @@ dax_entry_t dax_lock_mapping_entry(struct address_space *mapping,
void dax_unlock_mapping_entry(struct address_space *mapping,
unsigned long index, dax_entry_t cookie);
#else
+static inline void fs_put_dax(struct dax_device *dax_dev, void *holder)
+{
+}
+
+static inline int fs_dax_get(struct dax_device *dax_dev, void *holder,
+ const struct dax_holder_operations *hops)
+{
+ return -EOPNOTSUPP;
+}
static inline struct page *dax_layout_busy_page(struct address_space *mapping)
{
return NULL;
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH V10 8/8] dax: export dax_dev_get()
2026-03-27 21:03 ` [PATCH V10 0/8] dax: prepare for famfs John Groves
` (6 preceding siblings ...)
2026-03-27 21:05 ` [PATCH V10 7/8] dax: Add fs_dax_get() func to prepare dax for fs-dax usage John Groves
@ 2026-03-27 21:05 ` John Groves
2026-03-30 21:21 ` [PATCH V10 0/8] dax: prepare for famfs Alison Schofield
8 siblings, 0 replies; 16+ messages in thread
From: John Groves @ 2026-03-27 21:05 UTC (permalink / raw)
To: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
Alison Schofield
Cc: John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org,
John Groves, Jonathan Cameron
From: John Groves <john@groves.net>
famfs needs to look up a dax_device by dev_t when resolving fmap
entries that reference character dax devices.
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Signed-off-by: John Groves <john@groves.net>
---
drivers/dax/super.c | 3 ++-
include/linux/dax.h | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/dax/super.c b/drivers/dax/super.c
index d4ab60c406bf..25cf99dd9360 100644
--- a/drivers/dax/super.c
+++ b/drivers/dax/super.c
@@ -521,7 +521,7 @@ static int dax_set(struct inode *inode, void *data)
return 0;
}
-static struct dax_device *dax_dev_get(dev_t devt)
+struct dax_device *dax_dev_get(dev_t devt)
{
struct dax_device *dax_dev;
struct inode *inode;
@@ -544,6 +544,7 @@ static struct dax_device *dax_dev_get(dev_t devt)
return dax_dev;
}
+EXPORT_SYMBOL_GPL(dax_dev_get);
struct dax_device *alloc_dax(void *private, const struct dax_operations *ops)
{
diff --git a/include/linux/dax.h b/include/linux/dax.h
index a85e270bfb3c..9ef95b136bb8 100644
--- a/include/linux/dax.h
+++ b/include/linux/dax.h
@@ -54,6 +54,7 @@ struct dax_device *alloc_dax(void *private, const struct dax_operations *ops);
void *dax_holder(struct dax_device *dax_dev);
void put_dax(struct dax_device *dax_dev);
void kill_dax(struct dax_device *dax_dev);
+struct dax_device *dax_dev_get(dev_t devt);
void dax_write_cache(struct dax_device *dax_dev, bool wc);
bool dax_write_cache_enabled(struct dax_device *dax_dev);
bool dax_synchronous(struct dax_device *dax_dev);
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH V10 0/8] dax: prepare for famfs
2026-03-27 21:03 ` [PATCH V10 0/8] dax: prepare for famfs John Groves
` (7 preceding siblings ...)
2026-03-27 21:05 ` [PATCH V10 8/8] dax: export dax_dev_get() John Groves
@ 2026-03-30 21:21 ` Alison Schofield
2026-04-13 20:51 ` Ira Weiny
2026-04-13 22:41 ` Alison Schofield
8 siblings, 2 replies; 16+ messages in thread
From: Alison Schofield @ 2026-03-30 21:21 UTC (permalink / raw)
To: John Groves
Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org
On Fri, Mar 27, 2026 at 09:03:26PM +0000, John Groves wrote:
> From: John Groves <john@groves.net>
>
> This patch series along with the bundled patches to fuse are available
> as a git tag at [0].
>
> Dropped the "bundle" thread. If this submission goes smoothly, I'll update
> the fuse patches to v10 (very little change there as yet).
>
> Changes v9 -> v10
> - Minor modernizations per comments from (mostly) Jonathan
> - Minor Kconfig simplification
> - bus.c:dax_match_type(): don't make fsdev_dax eligible for automatic binding
> where devdax would otherwise bind
> - dax-private.h: add missing kerneldoc comment for field cached_size in
> struct dev_dax_range (thanks Dave)
> - fsdev_write_dax(): s/pmem_addr/addr/ (thanks Dave)
> - include/linux/dax.h: remove a spuriously-added declaration of inode_dax()
> (thanks Jonathan)
>
> Description:
>
> This patch series introduces the required dax support for famfs.
> Previous versions of the famfs series included both dax and fuse patches.
> This series separates them into separate patch series' (and the fuse
> series dependends on this dax series).
>
> The famfs user space code can be found at [1]
>
> Dax Overview:
>
> This series introduces a new "famfs mode" of devdax, whose driver is
> drivers/dax/fsdev.c. This driver supports dax_iomap_rw() and
> dax_iomap_fault() calls against a character dax instance. A dax device
> now can be converted among three modes: 'system-ram', 'devdax' and
> 'famfs' via daxctl or sysfs (e.g. unbind devdax and bind famfs instead).
>
> In famfs mode, a dax device initializes its pages consistent with the
> fsdaxmode of pmem. Raw read/write/mmap are not supported in this mode,
> but famfs is happy in this mode - using dax_iomap_rw() for read/write and
> dax_iomap_fault() for mmap faults.
>
Here's what I found:
famfs-v10 on 7.0-rc5 + ndctl v84:
dax suite all pass 13/13, so no regression appears
famfs-v10 on 7.0-rc5 +
(ndctl v84 w https://github.com/jagalactic/ndctl/tree/famfs
top 3 patches + edit daxctl-famfs.sh to use cxl-test:
existing dax suite keeps passing
daxctl-famfs.sh oops w the new test at # Restore original mode"
seems easy to repoduce, maybe cannot go back to system-ram???
Let me know if you need more info.
-- Alison
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V10 0/8] dax: prepare for famfs
2026-03-30 21:21 ` [PATCH V10 0/8] dax: prepare for famfs Alison Schofield
@ 2026-04-13 20:51 ` Ira Weiny
2026-04-13 21:37 ` Ira Weiny
` (2 more replies)
2026-04-13 22:41 ` Alison Schofield
1 sibling, 3 replies; 16+ messages in thread
From: Ira Weiny @ 2026-04-13 20:51 UTC (permalink / raw)
To: Alison Schofield, John Groves
Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org
Alison Schofield wrote:
> On Fri, Mar 27, 2026 at 09:03:26PM +0000, John Groves wrote:
> > From: John Groves <john@groves.net>
> >
> > This patch series along with the bundled patches to fuse are available
> > as a git tag at [0].
> >
> > Dropped the "bundle" thread. If this submission goes smoothly, I'll update
> > the fuse patches to v10 (very little change there as yet).
> >
> > Changes v9 -> v10
> > - Minor modernizations per comments from (mostly) Jonathan
> > - Minor Kconfig simplification
> > - bus.c:dax_match_type(): don't make fsdev_dax eligible for automatic binding
> > where devdax would otherwise bind
> > - dax-private.h: add missing kerneldoc comment for field cached_size in
> > struct dev_dax_range (thanks Dave)
> > - fsdev_write_dax(): s/pmem_addr/addr/ (thanks Dave)
> > - include/linux/dax.h: remove a spuriously-added declaration of inode_dax()
> > (thanks Jonathan)
> >
> > Description:
> >
> > This patch series introduces the required dax support for famfs.
> > Previous versions of the famfs series included both dax and fuse patches.
> > This series separates them into separate patch series' (and the fuse
> > series dependends on this dax series).
> >
> > The famfs user space code can be found at [1]
> >
> > Dax Overview:
> >
> > This series introduces a new "famfs mode" of devdax, whose driver is
> > drivers/dax/fsdev.c. This driver supports dax_iomap_rw() and
> > dax_iomap_fault() calls against a character dax instance. A dax device
> > now can be converted among three modes: 'system-ram', 'devdax' and
> > 'famfs' via daxctl or sysfs (e.g. unbind devdax and bind famfs instead).
> >
> > In famfs mode, a dax device initializes its pages consistent with the
> > fsdaxmode of pmem. Raw read/write/mmap are not supported in this mode,
> > but famfs is happy in this mode - using dax_iomap_rw() for read/write and
> > dax_iomap_fault() for mmap faults.
> >
>
> Here's what I found:
>
> famfs-v10 on 7.0-rc5 + ndctl v84:
> dax suite all pass 13/13, so no regression appears
>
> famfs-v10 on 7.0-rc5 +
> (ndctl v84 w https://github.com/jagalactic/ndctl/tree/famfs
> top 3 patches + edit daxctl-famfs.sh to use cxl-test:
>
> existing dax suite keeps passing
> daxctl-famfs.sh oops w the new test at # Restore original mode"
> seems easy to repoduce, maybe cannot go back to system-ram???
John have you been able to reproduce this?
Ira
>
> Let me know if you need more info.
>
> -- Alison
>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V10 0/8] dax: prepare for famfs
2026-04-13 20:51 ` Ira Weiny
@ 2026-04-13 21:37 ` Ira Weiny
2026-04-13 21:40 ` Ira Weiny
2026-04-13 22:22 ` John Groves
2 siblings, 0 replies; 16+ messages in thread
From: Ira Weiny @ 2026-04-13 21:37 UTC (permalink / raw)
To: Ira Weiny, Alison Schofield, John Groves
Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org
Ira Weiny wrote:
> Alison Schofield wrote:
> > On Fri, Mar 27, 2026 at 09:03:26PM +0000, John Groves wrote:
> > > From: John Groves <john@groves.net>
> > >
[snip]
> > >
> > > Description:
> > >
> > > This patch series introduces the required dax support for famfs.
> > > Previous versions of the famfs series included both dax and fuse patches.
> > > This series separates them into separate patch series' (and the fuse
> > > series dependends on this dax series).
> > >
> > > The famfs user space code can be found at [1]
> > >
> > > Dax Overview:
> > >
> > > This series introduces a new "famfs mode" of devdax, whose driver is
> > > drivers/dax/fsdev.c. This driver supports dax_iomap_rw() and
> > > dax_iomap_fault() calls against a character dax instance. A dax device
> > > now can be converted among three modes: 'system-ram', 'devdax' and
> > > 'famfs' via daxctl or sysfs (e.g. unbind devdax and bind famfs instead).
> > >
> > > In famfs mode, a dax device initializes its pages consistent with the
> > > fsdaxmode of pmem. Raw read/write/mmap are not supported in this mode,
> > > but famfs is happy in this mode - using dax_iomap_rw() for read/write and
> > > dax_iomap_fault() for mmap faults.
> > >
> >
> > Here's what I found:
> >
> > famfs-v10 on 7.0-rc5 + ndctl v84:
> > dax suite all pass 13/13, so no regression appears
> >
> > famfs-v10 on 7.0-rc5 +
> > (ndctl v84 w https://github.com/jagalactic/ndctl/tree/famfs
> > top 3 patches + edit daxctl-famfs.sh to use cxl-test:
> >
> > existing dax suite keeps passing
> > daxctl-famfs.sh oops w the new test at # Restore original mode"
> > seems easy to repoduce, maybe cannot go back to system-ram???
>
> John have you been able to reproduce this?
>
> Ira
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V10 0/8] dax: prepare for famfs
2026-04-13 20:51 ` Ira Weiny
2026-04-13 21:37 ` Ira Weiny
@ 2026-04-13 21:40 ` Ira Weiny
2026-04-13 22:26 ` John Groves
2026-04-13 22:22 ` John Groves
2 siblings, 1 reply; 16+ messages in thread
From: Ira Weiny @ 2026-04-13 21:40 UTC (permalink / raw)
To: Ira Weiny, Alison Schofield, John Groves
Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org
Ira Weiny wrote:
> Alison Schofield wrote:
> > On Fri, Mar 27, 2026 at 09:03:26PM +0000, John Groves wrote:
> > > From: John Groves <john@groves.net>
> > >
[snip]
> > >
> > > Description:
> > >
> > > This patch series introduces the required dax support for famfs.
> > > Previous versions of the famfs series included both dax and fuse patches.
> > > This series separates them into separate patch series' (and the fuse
> > > series dependends on this dax series).
> > >
> > > The famfs user space code can be found at [1]
> > >
> > > Dax Overview:
> > >
> > > This series introduces a new "famfs mode" of devdax, whose driver is
> > > drivers/dax/fsdev.c. This driver supports dax_iomap_rw() and
> > > dax_iomap_fault() calls against a character dax instance. A dax device
> > > now can be converted among three modes: 'system-ram', 'devdax' and
> > > 'famfs' via daxctl or sysfs (e.g. unbind devdax and bind famfs instead).
> > >
> > > In famfs mode, a dax device initializes its pages consistent with the
> > > fsdaxmode of pmem. Raw read/write/mmap are not supported in this mode,
> > > but famfs is happy in this mode - using dax_iomap_rw() for read/write and
> > > dax_iomap_fault() for mmap faults.
> > >
> >
> > Here's what I found:
> >
> > famfs-v10 on 7.0-rc5 + ndctl v84:
> > dax suite all pass 13/13, so no regression appears
> >
> > famfs-v10 on 7.0-rc5 +
> > (ndctl v84 w https://github.com/jagalactic/ndctl/tree/famfs
> > top 3 patches + edit daxctl-famfs.sh to use cxl-test:
> >
> > existing dax suite keeps passing
> > daxctl-famfs.sh oops w the new test at # Restore original mode"
> > seems easy to repoduce, maybe cannot go back to system-ram???
>
> John have you been able to reproduce this?
>
> Ira
John I've found a different crash with the daxctl-famfs.sh test. See
below.
I got the ndctl repo with the test from Alison.
I'm not at all clear what is happening at this point...
Ira
<crash>
[ 519.007691] BUG: TASK stack guard page was hit at ffffc90001767fc8 (stack is ffffc90001768000..ffffc9000176c000)
[ 519.007694] Oops: stack guard page: 0000 [#1] SMP NOPTI
[ 519.007697] CPU: 0 UID: 0 PID: 1465 Comm: daxctl Tainted: G O 7.0.0-rc6ira+ #68 PREEMPT(full)
[ 519.007699] Tainted: [O]=OOT_MODULE
[ 519.007700] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS edk2-20250812-19.fc42 08/12/2025
[ 519.007701] RIP: 0010:sprintf+0xc/0x50
[ 519.007709] Code: 24 10 e8 37 f8 ff ff c9 c3 cc cc cc cc 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 55 48 89 e5 48 83 ec 48 48 8d 45 10 <48>
89 54 24 28 48 89 f2 be ff ff ff 7f 48 89 4c 24 30 48 89 e1 48
[ 519.007710] RSP: 0018:ffffc90001767fd0 EFLAGS: 00010282
[ 519.007712] RAX: ffffc90001768028 RBX: ffffc90001768068 RCX: 0000000000001e08
[ 519.007712] RDX: 0000000000000207 RSI: ffffffff82abab1c RDI: ffffc90001768068
[ 519.007713] RBP: ffffc90001768018 R08: 0000000000000000 R09: 0000000000000001
[ 519.007713] R10: ffffc90001768110 R11: 0000000000000002 R12: 0000000000000800
[ 519.007714] R13: ffffc90001768068 R14: 0000000000000000 R15: ffffffff839c71c0
[ 519.007715] FS: 00007fb94b807c80(0000) GS:ffff8880f9e9c000(0000) knlGS:0000000000000000
[ 519.007717] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 519.007717] CR2: ffffc90001767fc8 CR3: 0000000077d2e005 CR4: 0000000000770ef0
[ 519.007720] PKRU: 55555554
[ 519.007721] Call Trace:
[ 519.007722] <TASK>
[ 519.007723] info_print_prefix+0xc0/0xe0
[ 519.007728] record_print_text+0x58/0x2d0
[ 519.007730] printk_get_next_message+0xd8/0x220
[ 519.007733] console_flush_one_record+0x1a5/0x390
[ 519.007735] console_unlock+0x5a/0xe0
[ 519.007737] vprintk_emit+0x2e8/0x340
[ 519.007738] _printk+0x48/0x50
[ 519.007741] ? printk_get_next_message+0x70/0x220
[ 519.007743] __dump_page.cold+0x3c/0x331
[ 519.007746] ? dump_page+0x1b/0x30
[ 519.007748] dump_page+0x1b/0x30
[ 519.007749] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007751] get_pfnblock_migratetype+0xa/0x20
[ 519.007753] __dump_page.cold+0x1c6/0x331
[ 519.007755] ? dump_page+0x1b/0x30
[ 519.007756] dump_page+0x1b/0x30
[ 519.007756] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007757] get_pfnblock_migratetype+0xa/0x20
[ 519.007758] __dump_page.cold+0x1c6/0x331
[ 519.007760] ? dump_page+0x1b/0x30
[ 519.007761] dump_page+0x1b/0x30
[ 519.007761] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007762] get_pfnblock_migratetype+0xa/0x20
[ 519.007763] __dump_page.cold+0x1c6/0x331
[ 519.007765] ? dump_page+0x1b/0x30
[ 519.007765] dump_page+0x1b/0x30
[ 519.007766] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007767] get_pfnblock_migratetype+0xa/0x20
[ 519.007772] __dump_page.cold+0x1c6/0x331
[ 519.007774] ? dump_page+0x1b/0x30
[ 519.007775] dump_page+0x1b/0x30
[ 519.007775] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007776] get_pfnblock_migratetype+0xa/0x20
[ 519.007777] __dump_page.cold+0x1c6/0x331
[ 519.007779] ? dump_page+0x1b/0x30
[ 519.007780] dump_page+0x1b/0x30
[ 519.007780] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007781] get_pfnblock_migratetype+0xa/0x20
[ 519.007782] __dump_page.cold+0x1c6/0x331
[ 519.007784] ? dump_page+0x1b/0x30
[ 519.007785] dump_page+0x1b/0x30
[ 519.007785] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007786] get_pfnblock_migratetype+0xa/0x20
[ 519.007787] __dump_page.cold+0x1c6/0x331
[ 519.007789] ? dump_page+0x1b/0x30
[ 519.007790] dump_page+0x1b/0x30
[ 519.007790] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007791] get_pfnblock_migratetype+0xa/0x20
[ 519.007792] __dump_page.cold+0x1c6/0x331
[ 519.007794] ? dump_page+0x1b/0x30
[ 519.007795] dump_page+0x1b/0x30
[ 519.007795] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007796] get_pfnblock_migratetype+0xa/0x20
[ 519.007797] __dump_page.cold+0x1c6/0x331
[ 519.007799] ? dump_page+0x1b/0x30
[ 519.007800] dump_page+0x1b/0x30
[ 519.007800] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007801] get_pfnblock_migratetype+0xa/0x20
[ 519.007802] __dump_page.cold+0x1c6/0x331
[ 519.007804] ? dump_page+0x1b/0x30
[ 519.007805] dump_page+0x1b/0x30
[ 519.007808] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007809] get_pfnblock_migratetype+0xa/0x20
[ 519.007810] __dump_page.cold+0x1c6/0x331
[ 519.007812] ? dump_page+0x1b/0x30
[ 519.007813] dump_page+0x1b/0x30
[ 519.007813] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007814] get_pfnblock_migratetype+0xa/0x20
[ 519.007815] __dump_page.cold+0x1c6/0x331
[ 519.007817] ? dump_page+0x1b/0x30
[ 519.007818] dump_page+0x1b/0x30
[ 519.007818] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007819] get_pfnblock_migratetype+0xa/0x20
[ 519.007820] __dump_page.cold+0x1c6/0x331
[ 519.007822] ? dump_page+0x1b/0x30
[ 519.007823] dump_page+0x1b/0x30
[ 519.007824] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007824] get_pfnblock_migratetype+0xa/0x20
[ 519.007825] __dump_page.cold+0x1c6/0x331
[ 519.007827] ? dump_page+0x1b/0x30
[ 519.007828] dump_page+0x1b/0x30
[ 519.007829] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007829] get_pfnblock_migratetype+0xa/0x20
[ 519.007830] __dump_page.cold+0x1c6/0x331
[ 519.007833] ? dump_page+0x1b/0x30
[ 519.007833] dump_page+0x1b/0x30
[ 519.007834] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007834] get_pfnblock_migratetype+0xa/0x20
[ 519.007835] __dump_page.cold+0x1c6/0x331
[ 519.007838] ? dump_page+0x1b/0x30
[ 519.007838] dump_page+0x1b/0x30
[ 519.007839] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007840] get_pfnblock_migratetype+0xa/0x20
[ 519.007841] __dump_page.cold+0x1c6/0x331
[ 519.007843] ? dump_page+0x1b/0x30
[ 519.007843] dump_page+0x1b/0x30
[ 519.007844] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007845] get_pfnblock_migratetype+0xa/0x20
[ 519.007846] __dump_page.cold+0x1c6/0x331
[ 519.007848] ? dump_page+0x1b/0x30
[ 519.007849] dump_page+0x1b/0x30
[ 519.007849] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007850] get_pfnblock_migratetype+0xa/0x20
[ 519.007851] __dump_page.cold+0x1c6/0x331
[ 519.007853] ? dump_page+0x1b/0x30
[ 519.007854] dump_page+0x1b/0x30
[ 519.007854] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007855] get_pfnblock_migratetype+0xa/0x20
[ 519.007856] __dump_page.cold+0x1c6/0x331
[ 519.007858] ? dump_page+0x1b/0x30
[ 519.007859] dump_page+0x1b/0x30
[ 519.007859] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007860] get_pfnblock_migratetype+0xa/0x20
[ 519.007861] __dump_page.cold+0x1c6/0x331
[ 519.007863] ? dump_page+0x1b/0x30
[ 519.007864] dump_page+0x1b/0x30
[ 519.007864] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007865] get_pfnblock_migratetype+0xa/0x20
[ 519.007866] __dump_page.cold+0x1c6/0x331
[ 519.007868] ? dump_page+0x1b/0x30
[ 519.007869] dump_page+0x1b/0x30
[ 519.007869] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007870] get_pfnblock_migratetype+0xa/0x20
[ 519.007871] __dump_page.cold+0x1c6/0x331
[ 519.007873] ? dump_page+0x1b/0x30
[ 519.007874] dump_page+0x1b/0x30
[ 519.007874] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007875] get_pfnblock_migratetype+0xa/0x20
[ 519.007876] __dump_page.cold+0x1c6/0x331
[ 519.007878] ? dump_page+0x1b/0x30
[ 519.007879] dump_page+0x1b/0x30
[ 519.007880] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007880] get_pfnblock_migratetype+0xa/0x20
[ 519.007881] __dump_page.cold+0x1c6/0x331
[ 519.007883] ? dump_page+0x1b/0x30
[ 519.007884] dump_page+0x1b/0x30
[ 519.007885] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007885] get_pfnblock_migratetype+0xa/0x20
[ 519.007886] __dump_page.cold+0x1c6/0x331
[ 519.007889] ? dump_page+0x1b/0x30
[ 519.007889] dump_page+0x1b/0x30
[ 519.007890] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007890] get_pfnblock_migratetype+0xa/0x20
[ 519.007891] __dump_page.cold+0x1c6/0x331
[ 519.007894] ? dump_page+0x1b/0x30
[ 519.007894] dump_page+0x1b/0x30
[ 519.007895] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007895] get_pfnblock_migratetype+0xa/0x20
[ 519.007896] __dump_page.cold+0x1c6/0x331
[ 519.007899] ? dump_page+0x1b/0x30
[ 519.007899] dump_page+0x1b/0x30
[ 519.007900] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007900] get_pfnblock_migratetype+0xa/0x20
[ 519.007901] __dump_page.cold+0x1c6/0x331
[ 519.007904] ? dump_page+0x1b/0x30
[ 519.007904] dump_page+0x1b/0x30
[ 519.007905] __get_pfnblock_flags_mask+0x6c/0xe0
[ 519.007905] get_pfnblock_migratetype+0xa/0x20
[ 519.007906] __dump_page.cold+0x1c6/0x331
[ 519.007907] ? do_file_open+0xbe/0x150
[ 519.007910] ? stack_depot_save_flags+0x24/0x910
[ 519.007918] ? dump_page+0x1b/0x30
[ 519.007919] dump_page+0x1b/0x30
[ 519.007920] memmap_init_range+0x2f6/0x310
[ 519.007922] move_pfn_range_to_zone+0xee/0x220
[ 519.007924] mhp_init_memmap_on_memory+0x23/0xb0
[ 519.007926] memory_subsys_online+0x122/0x1a0
[ 519.007929] device_online+0x49/0x80
[ 519.007931] state_store+0x8e/0xa0
[ 519.007932] kernfs_fop_write_iter+0x136/0x1f0
[ 519.007935] vfs_write+0x205/0x460
[ 519.007937] ksys_write+0x57/0xd0
[ 519.007938] do_syscall_64+0x106/0x5f0
[ 519.007940] ? irqentry_exit+0x6c/0x520
[ 519.007941] ? exc_page_fault+0x66/0x180
[ 519.007942] entry_SYSCALL_64_after_hwframe+0x76/0x7e
[ 519.007944] RIP: 0033:0x7fb94ba3473e
[ 519.007946] Code: 4d 89 d8 e8 d4 bc 00 00 4c 8b 5d f8 41 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 11 c9 c3 0f 1f 80 00 00 00 00 48 8b 45 10 0f 05 <c9>
c3 83 e2 39 83 fa 08 75 e7 e8 13 ff ff ff 0f 1f 00 f3 0f 1e fa
[ 519.007946] RSP: 002b:00007fff47c8ddd0 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
[ 519.007948] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fb94ba3473e
[ 519.007948] RDX: 000000000000000f RSI: 00007fb94bc21a3e RDI: 0000000000000004
[ 519.007949] RBP: 00007fff47c8dde0 R08: 0000000000000000 R09: 0000000000000000
[ 519.007949] R10: 0000000000000000 R11: 0000000000000202 R12: 00007fff47c8e3f8
[ 519.007950] R13: 0000000000000006 R14: 00007fb94bc67000 R15: 0000000000413d88
[ 519.007951] </TASK>
[ 519.007951] Modules linked in: cxl_test(O) cxl_acpi(O) device_dax(O) fsdev_dax kmem nd_pmem(O) nd_btt(O) cxl_pmu dax_cxl dax_pmem(O) cxl_pci nd_e820
(O) nfit(O) cxl_mock_mem(O) cxl_pmem(O) cxl_mem(O) cxl_port(O) cxl_mock(O) libnvdimm(O) nfit_test_iomap(O) cxl_core(O) fwctl [last unloaded: cxl_acpi(O
)]
[ 519.007962] ---[ end trace 0000000000000000 ]---
[ 519.007963] RIP: 0010:sprintf+0xc/0x50
[ 519.007964] Code: 24 10 e8 37 f8 ff ff c9 c3 cc cc cc cc 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 55 48 89 e5 48 83 ec 48 48 8d 45 10 <48>
89 54 24 28 48 89 f2 be ff ff ff 7f 48 89 4c 24 30 48 89 e1 48
[ 519.007965] RSP: 0018:ffffc90001767fd0 EFLAGS: 00010282
[ 519.007966] RAX: ffffc90001768028 RBX: ffffc90001768068 RCX: 0000000000001e08
[ 519.007966] RDX: 0000000000000207 RSI: ffffffff82abab1c RDI: ffffc90001768068
[ 519.007967] RBP: ffffc90001768018 R08: 0000000000000000 R09: 0000000000000001
[ 519.007967] R10: ffffc90001768110 R11: 0000000000000002 R12: 0000000000000800
[ 519.007967] R13: ffffc90001768068 R14: 0000000000000000 R15: ffffffff839c71c0
[ 519.007968] FS: 00007fb94b807c80(0000) GS:ffff8880f9e9c000(0000) knlGS:0000000000000000
[ 519.007969] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 519.007969] CR2: ffffc90001767fc8 CR3: 0000000077d2e005 CR4: 0000000000770ef0
[ 519.007971] PKRU: 55555554
[ 519.007972] Kernel panic - not syncing: Fatal exception in interrupt
[ 519.008404] Kernel Offset: disabled
[ 519.083400] ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]---
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V10 0/8] dax: prepare for famfs
2026-04-13 20:51 ` Ira Weiny
2026-04-13 21:37 ` Ira Weiny
2026-04-13 21:40 ` Ira Weiny
@ 2026-04-13 22:22 ` John Groves
2 siblings, 0 replies; 16+ messages in thread
From: John Groves @ 2026-04-13 22:22 UTC (permalink / raw)
To: Ira Weiny
Cc: Alison Schofield, John Groves, Miklos Szeredi, Dan Williams,
Bernd Schubert, John Groves, Jonathan Corbet, Shuah Khan,
Vishal Verma, Dave Jiang, Matthew Wilcox, Jan Kara,
Alexander Viro, David Hildenbrand, Christian Brauner,
Darrick J . Wong, Randy Dunlap, Jeff Layton, Amir Goldstein,
Jonathan Cameron, Stefan Hajnoczi, Joanne Koong, Josef Bacik,
Bagas Sanjaya, Chen Linxuan, James Morse, Fuad Tabba,
Sean Christopherson, Shivank Garg, Ackerley Tng, Gregory Price,
Aravind Ramesh, Ajay Joshi, venkataravis@micron.com,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
nvdimm@lists.linux.dev, linux-cxl@vger.kernel.org,
linux-fsdevel@vger.kernel.org
On 26/04/13 03:51PM, Ira Weiny wrote:
> Alison Schofield wrote:
> > On Fri, Mar 27, 2026 at 09:03:26PM +0000, John Groves wrote:
> > > From: John Groves <john@groves.net>
> > >
> > > This patch series along with the bundled patches to fuse are available
> > > as a git tag at [0].
> > >
> > > Dropped the "bundle" thread. If this submission goes smoothly, I'll update
> > > the fuse patches to v10 (very little change there as yet).
> > >
> > > Changes v9 -> v10
> > > - Minor modernizations per comments from (mostly) Jonathan
> > > - Minor Kconfig simplification
> > > - bus.c:dax_match_type(): don't make fsdev_dax eligible for automatic binding
> > > where devdax would otherwise bind
> > > - dax-private.h: add missing kerneldoc comment for field cached_size in
> > > struct dev_dax_range (thanks Dave)
> > > - fsdev_write_dax(): s/pmem_addr/addr/ (thanks Dave)
> > > - include/linux/dax.h: remove a spuriously-added declaration of inode_dax()
> > > (thanks Jonathan)
> > >
> > > Description:
> > >
> > > This patch series introduces the required dax support for famfs.
> > > Previous versions of the famfs series included both dax and fuse patches.
> > > This series separates them into separate patch series' (and the fuse
> > > series dependends on this dax series).
> > >
> > > The famfs user space code can be found at [1]
> > >
> > > Dax Overview:
> > >
> > > This series introduces a new "famfs mode" of devdax, whose driver is
> > > drivers/dax/fsdev.c. This driver supports dax_iomap_rw() and
> > > dax_iomap_fault() calls against a character dax instance. A dax device
> > > now can be converted among three modes: 'system-ram', 'devdax' and
> > > 'famfs' via daxctl or sysfs (e.g. unbind devdax and bind famfs instead).
> > >
> > > In famfs mode, a dax device initializes its pages consistent with the
> > > fsdaxmode of pmem. Raw read/write/mmap are not supported in this mode,
> > > but famfs is happy in this mode - using dax_iomap_rw() for read/write and
> > > dax_iomap_fault() for mmap faults.
> > >
> >
> > Here's what I found:
> >
> > famfs-v10 on 7.0-rc5 + ndctl v84:
> > dax suite all pass 13/13, so no regression appears
> >
> > famfs-v10 on 7.0-rc5 +
> > (ndctl v84 w https://github.com/jagalactic/ndctl/tree/famfs
> > top 3 patches + edit daxctl-famfs.sh to use cxl-test:
> >
> > existing dax suite keeps passing
> > daxctl-famfs.sh oops w the new test at # Restore original mode"
> > seems easy to repoduce, maybe cannot go back to system-ram???
>
> John have you been able to reproduce this?
>
> Ira
>
Not yet, but I'm getting ready to try again.
John
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V10 0/8] dax: prepare for famfs
2026-04-13 21:40 ` Ira Weiny
@ 2026-04-13 22:26 ` John Groves
0 siblings, 0 replies; 16+ messages in thread
From: John Groves @ 2026-04-13 22:26 UTC (permalink / raw)
To: Ira Weiny
Cc: Alison Schofield, John Groves, Miklos Szeredi, Dan Williams,
Bernd Schubert, John Groves, Jonathan Corbet, Shuah Khan,
Vishal Verma, Dave Jiang, Matthew Wilcox, Jan Kara,
Alexander Viro, David Hildenbrand, Christian Brauner,
Darrick J . Wong, Randy Dunlap, Jeff Layton, Amir Goldstein,
Jonathan Cameron, Stefan Hajnoczi, Joanne Koong, Josef Bacik,
Bagas Sanjaya, Chen Linxuan, James Morse, Fuad Tabba,
Sean Christopherson, Shivank Garg, Ackerley Tng, Gregory Price,
Aravind Ramesh, Ajay Joshi, venkataravis@micron.com,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
nvdimm@lists.linux.dev, linux-cxl@vger.kernel.org,
linux-fsdevel@vger.kernel.org
On 26/04/13 04:40PM, Ira Weiny wrote:
> Ira Weiny wrote:
> > Alison Schofield wrote:
> > > On Fri, Mar 27, 2026 at 09:03:26PM +0000, John Groves wrote:
> > > > From: John Groves <john@groves.net>
> > > >
>
> [snip]
>
> > > >
> > > > Description:
> > > >
> > > > This patch series introduces the required dax support for famfs.
> > > > Previous versions of the famfs series included both dax and fuse patches.
> > > > This series separates them into separate patch series' (and the fuse
> > > > series dependends on this dax series).
> > > >
> > > > The famfs user space code can be found at [1]
> > > >
> > > > Dax Overview:
> > > >
> > > > This series introduces a new "famfs mode" of devdax, whose driver is
> > > > drivers/dax/fsdev.c. This driver supports dax_iomap_rw() and
> > > > dax_iomap_fault() calls against a character dax instance. A dax device
> > > > now can be converted among three modes: 'system-ram', 'devdax' and
> > > > 'famfs' via daxctl or sysfs (e.g. unbind devdax and bind famfs instead).
> > > >
> > > > In famfs mode, a dax device initializes its pages consistent with the
> > > > fsdaxmode of pmem. Raw read/write/mmap are not supported in this mode,
> > > > but famfs is happy in this mode - using dax_iomap_rw() for read/write and
> > > > dax_iomap_fault() for mmap faults.
> > > >
> > >
> > > Here's what I found:
> > >
> > > famfs-v10 on 7.0-rc5 + ndctl v84:
> > > dax suite all pass 13/13, so no regression appears
> > >
> > > famfs-v10 on 7.0-rc5 +
> > > (ndctl v84 w https://github.com/jagalactic/ndctl/tree/famfs
> > > top 3 patches + edit daxctl-famfs.sh to use cxl-test:
> > >
> > > existing dax suite keeps passing
> > > daxctl-famfs.sh oops w the new test at # Restore original mode"
> > > seems easy to repoduce, maybe cannot go back to system-ram???
> >
> > John have you been able to reproduce this?
> >
> > Ira
>
> John I've found a different crash with the daxctl-famfs.sh test. See
> below.
>
> I got the ndctl repo with the test from Alison.
>
> I'm not at all clear what is happening at this point...
>
> Ira
>
> <crash>
>
> [ 519.007691] BUG: TASK stack guard page was hit at ffffc90001767fc8 (stack is ffffc90001768000..ffffc9000176c000)
> [ 519.007694] Oops: stack guard page: 0000 [#1] SMP NOPTI
> [ 519.007697] CPU: 0 UID: 0 PID: 1465 Comm: daxctl Tainted: G O 7.0.0-rc6ira+ #68 PREEMPT(full)
> [ 519.007699] Tainted: [O]=OOT_MODULE
> [ 519.007700] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS edk2-20250812-19.fc42 08/12/2025
> [ 519.007701] RIP: 0010:sprintf+0xc/0x50
> [ 519.007709] Code: 24 10 e8 37 f8 ff ff c9 c3 cc cc cc cc 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 55 48 89 e5 48 83 ec 48 48 8d 45 10 <48>
> 89 54 24 28 48 89 f2 be ff ff ff 7f 48 89 4c 24 30 48 89 e1 48
> [ 519.007710] RSP: 0018:ffffc90001767fd0 EFLAGS: 00010282
> [ 519.007712] RAX: ffffc90001768028 RBX: ffffc90001768068 RCX: 0000000000001e08
> [ 519.007712] RDX: 0000000000000207 RSI: ffffffff82abab1c RDI: ffffc90001768068
> [ 519.007713] RBP: ffffc90001768018 R08: 0000000000000000 R09: 0000000000000001
> [ 519.007713] R10: ffffc90001768110 R11: 0000000000000002 R12: 0000000000000800
> [ 519.007714] R13: ffffc90001768068 R14: 0000000000000000 R15: ffffffff839c71c0
> [ 519.007715] FS: 00007fb94b807c80(0000) GS:ffff8880f9e9c000(0000) knlGS:0000000000000000
> [ 519.007717] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [ 519.007717] CR2: ffffc90001767fc8 CR3: 0000000077d2e005 CR4: 0000000000770ef0
> [ 519.007720] PKRU: 55555554
> [ 519.007721] Call Trace:
> [ 519.007722] <TASK>
> [ 519.007723] info_print_prefix+0xc0/0xe0
> [ 519.007728] record_print_text+0x58/0x2d0
> [ 519.007730] printk_get_next_message+0xd8/0x220
> [ 519.007733] console_flush_one_record+0x1a5/0x390
> [ 519.007735] console_unlock+0x5a/0xe0
> [ 519.007737] vprintk_emit+0x2e8/0x340
> [ 519.007738] _printk+0x48/0x50
> [ 519.007741] ? printk_get_next_message+0x70/0x220
> [ 519.007743] __dump_page.cold+0x3c/0x331
> [ 519.007746] ? dump_page+0x1b/0x30
> [ 519.007748] dump_page+0x1b/0x30
> [ 519.007749] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007751] get_pfnblock_migratetype+0xa/0x20
> [ 519.007753] __dump_page.cold+0x1c6/0x331
> [ 519.007755] ? dump_page+0x1b/0x30
> [ 519.007756] dump_page+0x1b/0x30
> [ 519.007756] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007757] get_pfnblock_migratetype+0xa/0x20
> [ 519.007758] __dump_page.cold+0x1c6/0x331
> [ 519.007760] ? dump_page+0x1b/0x30
> [ 519.007761] dump_page+0x1b/0x30
> [ 519.007761] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007762] get_pfnblock_migratetype+0xa/0x20
> [ 519.007763] __dump_page.cold+0x1c6/0x331
> [ 519.007765] ? dump_page+0x1b/0x30
> [ 519.007765] dump_page+0x1b/0x30
> [ 519.007766] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007767] get_pfnblock_migratetype+0xa/0x20
> [ 519.007772] __dump_page.cold+0x1c6/0x331
> [ 519.007774] ? dump_page+0x1b/0x30
> [ 519.007775] dump_page+0x1b/0x30
> [ 519.007775] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007776] get_pfnblock_migratetype+0xa/0x20
> [ 519.007777] __dump_page.cold+0x1c6/0x331
> [ 519.007779] ? dump_page+0x1b/0x30
> [ 519.007780] dump_page+0x1b/0x30
> [ 519.007780] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007781] get_pfnblock_migratetype+0xa/0x20
> [ 519.007782] __dump_page.cold+0x1c6/0x331
> [ 519.007784] ? dump_page+0x1b/0x30
> [ 519.007785] dump_page+0x1b/0x30
> [ 519.007785] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007786] get_pfnblock_migratetype+0xa/0x20
> [ 519.007787] __dump_page.cold+0x1c6/0x331
> [ 519.007789] ? dump_page+0x1b/0x30
> [ 519.007790] dump_page+0x1b/0x30
> [ 519.007790] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007791] get_pfnblock_migratetype+0xa/0x20
> [ 519.007792] __dump_page.cold+0x1c6/0x331
> [ 519.007794] ? dump_page+0x1b/0x30
> [ 519.007795] dump_page+0x1b/0x30
> [ 519.007795] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007796] get_pfnblock_migratetype+0xa/0x20
> [ 519.007797] __dump_page.cold+0x1c6/0x331
> [ 519.007799] ? dump_page+0x1b/0x30
> [ 519.007800] dump_page+0x1b/0x30
> [ 519.007800] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007801] get_pfnblock_migratetype+0xa/0x20
> [ 519.007802] __dump_page.cold+0x1c6/0x331
> [ 519.007804] ? dump_page+0x1b/0x30
> [ 519.007805] dump_page+0x1b/0x30
> [ 519.007808] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007809] get_pfnblock_migratetype+0xa/0x20
> [ 519.007810] __dump_page.cold+0x1c6/0x331
> [ 519.007812] ? dump_page+0x1b/0x30
> [ 519.007813] dump_page+0x1b/0x30
> [ 519.007813] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007814] get_pfnblock_migratetype+0xa/0x20
> [ 519.007815] __dump_page.cold+0x1c6/0x331
> [ 519.007817] ? dump_page+0x1b/0x30
> [ 519.007818] dump_page+0x1b/0x30
> [ 519.007818] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007819] get_pfnblock_migratetype+0xa/0x20
> [ 519.007820] __dump_page.cold+0x1c6/0x331
> [ 519.007822] ? dump_page+0x1b/0x30
> [ 519.007823] dump_page+0x1b/0x30
> [ 519.007824] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007824] get_pfnblock_migratetype+0xa/0x20
> [ 519.007825] __dump_page.cold+0x1c6/0x331
> [ 519.007827] ? dump_page+0x1b/0x30
> [ 519.007828] dump_page+0x1b/0x30
> [ 519.007829] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007829] get_pfnblock_migratetype+0xa/0x20
> [ 519.007830] __dump_page.cold+0x1c6/0x331
> [ 519.007833] ? dump_page+0x1b/0x30
> [ 519.007833] dump_page+0x1b/0x30
> [ 519.007834] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007834] get_pfnblock_migratetype+0xa/0x20
> [ 519.007835] __dump_page.cold+0x1c6/0x331
> [ 519.007838] ? dump_page+0x1b/0x30
> [ 519.007838] dump_page+0x1b/0x30
> [ 519.007839] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007840] get_pfnblock_migratetype+0xa/0x20
> [ 519.007841] __dump_page.cold+0x1c6/0x331
> [ 519.007843] ? dump_page+0x1b/0x30
> [ 519.007843] dump_page+0x1b/0x30
> [ 519.007844] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007845] get_pfnblock_migratetype+0xa/0x20
> [ 519.007846] __dump_page.cold+0x1c6/0x331
> [ 519.007848] ? dump_page+0x1b/0x30
> [ 519.007849] dump_page+0x1b/0x30
> [ 519.007849] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007850] get_pfnblock_migratetype+0xa/0x20
> [ 519.007851] __dump_page.cold+0x1c6/0x331
> [ 519.007853] ? dump_page+0x1b/0x30
> [ 519.007854] dump_page+0x1b/0x30
> [ 519.007854] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007855] get_pfnblock_migratetype+0xa/0x20
> [ 519.007856] __dump_page.cold+0x1c6/0x331
> [ 519.007858] ? dump_page+0x1b/0x30
> [ 519.007859] dump_page+0x1b/0x30
> [ 519.007859] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007860] get_pfnblock_migratetype+0xa/0x20
> [ 519.007861] __dump_page.cold+0x1c6/0x331
> [ 519.007863] ? dump_page+0x1b/0x30
> [ 519.007864] dump_page+0x1b/0x30
> [ 519.007864] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007865] get_pfnblock_migratetype+0xa/0x20
> [ 519.007866] __dump_page.cold+0x1c6/0x331
> [ 519.007868] ? dump_page+0x1b/0x30
> [ 519.007869] dump_page+0x1b/0x30
> [ 519.007869] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007870] get_pfnblock_migratetype+0xa/0x20
> [ 519.007871] __dump_page.cold+0x1c6/0x331
> [ 519.007873] ? dump_page+0x1b/0x30
> [ 519.007874] dump_page+0x1b/0x30
> [ 519.007874] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007875] get_pfnblock_migratetype+0xa/0x20
> [ 519.007876] __dump_page.cold+0x1c6/0x331
> [ 519.007878] ? dump_page+0x1b/0x30
> [ 519.007879] dump_page+0x1b/0x30
> [ 519.007880] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007880] get_pfnblock_migratetype+0xa/0x20
> [ 519.007881] __dump_page.cold+0x1c6/0x331
> [ 519.007883] ? dump_page+0x1b/0x30
> [ 519.007884] dump_page+0x1b/0x30
> [ 519.007885] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007885] get_pfnblock_migratetype+0xa/0x20
> [ 519.007886] __dump_page.cold+0x1c6/0x331
> [ 519.007889] ? dump_page+0x1b/0x30
> [ 519.007889] dump_page+0x1b/0x30
> [ 519.007890] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007890] get_pfnblock_migratetype+0xa/0x20
> [ 519.007891] __dump_page.cold+0x1c6/0x331
> [ 519.007894] ? dump_page+0x1b/0x30
> [ 519.007894] dump_page+0x1b/0x30
> [ 519.007895] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007895] get_pfnblock_migratetype+0xa/0x20
> [ 519.007896] __dump_page.cold+0x1c6/0x331
> [ 519.007899] ? dump_page+0x1b/0x30
> [ 519.007899] dump_page+0x1b/0x30
> [ 519.007900] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007900] get_pfnblock_migratetype+0xa/0x20
> [ 519.007901] __dump_page.cold+0x1c6/0x331
> [ 519.007904] ? dump_page+0x1b/0x30
> [ 519.007904] dump_page+0x1b/0x30
> [ 519.007905] __get_pfnblock_flags_mask+0x6c/0xe0
> [ 519.007905] get_pfnblock_migratetype+0xa/0x20
> [ 519.007906] __dump_page.cold+0x1c6/0x331
> [ 519.007907] ? do_file_open+0xbe/0x150
> [ 519.007910] ? stack_depot_save_flags+0x24/0x910
> [ 519.007918] ? dump_page+0x1b/0x30
> [ 519.007919] dump_page+0x1b/0x30
> [ 519.007920] memmap_init_range+0x2f6/0x310
> [ 519.007922] move_pfn_range_to_zone+0xee/0x220
> [ 519.007924] mhp_init_memmap_on_memory+0x23/0xb0
> [ 519.007926] memory_subsys_online+0x122/0x1a0
> [ 519.007929] device_online+0x49/0x80
> [ 519.007931] state_store+0x8e/0xa0
> [ 519.007932] kernfs_fop_write_iter+0x136/0x1f0
> [ 519.007935] vfs_write+0x205/0x460
> [ 519.007937] ksys_write+0x57/0xd0
> [ 519.007938] do_syscall_64+0x106/0x5f0
> [ 519.007940] ? irqentry_exit+0x6c/0x520
> [ 519.007941] ? exc_page_fault+0x66/0x180
> [ 519.007942] entry_SYSCALL_64_after_hwframe+0x76/0x7e
> [ 519.007944] RIP: 0033:0x7fb94ba3473e
> [ 519.007946] Code: 4d 89 d8 e8 d4 bc 00 00 4c 8b 5d f8 41 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 11 c9 c3 0f 1f 80 00 00 00 00 48 8b 45 10 0f 05 <c9>
> c3 83 e2 39 83 fa 08 75 e7 e8 13 ff ff ff 0f 1f 00 f3 0f 1e fa
> [ 519.007946] RSP: 002b:00007fff47c8ddd0 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
> [ 519.007948] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fb94ba3473e
> [ 519.007948] RDX: 000000000000000f RSI: 00007fb94bc21a3e RDI: 0000000000000004
> [ 519.007949] RBP: 00007fff47c8dde0 R08: 0000000000000000 R09: 0000000000000000
> [ 519.007949] R10: 0000000000000000 R11: 0000000000000202 R12: 00007fff47c8e3f8
> [ 519.007950] R13: 0000000000000006 R14: 00007fb94bc67000 R15: 0000000000413d88
> [ 519.007951] </TASK>
> [ 519.007951] Modules linked in: cxl_test(O) cxl_acpi(O) device_dax(O) fsdev_dax kmem nd_pmem(O) nd_btt(O) cxl_pmu dax_cxl dax_pmem(O) cxl_pci nd_e820
> (O) nfit(O) cxl_mock_mem(O) cxl_pmem(O) cxl_mem(O) cxl_port(O) cxl_mock(O) libnvdimm(O) nfit_test_iomap(O) cxl_core(O) fwctl [last unloaded: cxl_acpi(O
> )]
> [ 519.007962] ---[ end trace 0000000000000000 ]---
> [ 519.007963] RIP: 0010:sprintf+0xc/0x50
> [ 519.007964] Code: 24 10 e8 37 f8 ff ff c9 c3 cc cc cc cc 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 55 48 89 e5 48 83 ec 48 48 8d 45 10 <48>
> 89 54 24 28 48 89 f2 be ff ff ff 7f 48 89 4c 24 30 48 89 e1 48
> [ 519.007965] RSP: 0018:ffffc90001767fd0 EFLAGS: 00010282
> [ 519.007966] RAX: ffffc90001768028 RBX: ffffc90001768068 RCX: 0000000000001e08
> [ 519.007966] RDX: 0000000000000207 RSI: ffffffff82abab1c RDI: ffffc90001768068
> [ 519.007967] RBP: ffffc90001768018 R08: 0000000000000000 R09: 0000000000000001
> [ 519.007967] R10: ffffc90001768110 R11: 0000000000000002 R12: 0000000000000800
> [ 519.007967] R13: ffffc90001768068 R14: 0000000000000000 R15: ffffffff839c71c0
> [ 519.007968] FS: 00007fb94b807c80(0000) GS:ffff8880f9e9c000(0000) knlGS:0000000000000000
> [ 519.007969] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [ 519.007969] CR2: ffffc90001767fc8 CR3: 0000000077d2e005 CR4: 0000000000770ef0
> [ 519.007971] PKRU: 55555554
> [ 519.007972] Kernel panic - not syncing: Fatal exception in interrupt
> [ 519.008404] Kernel Offset: disabled
> [ 519.083400] ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]---
Dang. Obviously runaway recursion; I don't recognize anything in
the stack, but will start trying to reproduce it.
John
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH V10 0/8] dax: prepare for famfs
2026-03-30 21:21 ` [PATCH V10 0/8] dax: prepare for famfs Alison Schofield
2026-04-13 20:51 ` Ira Weiny
@ 2026-04-13 22:41 ` Alison Schofield
1 sibling, 0 replies; 16+ messages in thread
From: Alison Schofield @ 2026-04-13 22:41 UTC (permalink / raw)
To: John Groves
Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org
On Mon, Mar 30, 2026 at 02:21:48PM -0700, Alison Schofield wrote:
> On Fri, Mar 27, 2026 at 09:03:26PM +0000, John Groves wrote:
> > From: John Groves <john@groves.net>
> >
> > This patch series along with the bundled patches to fuse are available
> > as a git tag at [0].
> >
> > Dropped the "bundle" thread. If this submission goes smoothly, I'll update
> > the fuse patches to v10 (very little change there as yet).
> >
> > Changes v9 -> v10
> > - Minor modernizations per comments from (mostly) Jonathan
> > - Minor Kconfig simplification
> > - bus.c:dax_match_type(): don't make fsdev_dax eligible for automatic binding
> > where devdax would otherwise bind
> > - dax-private.h: add missing kerneldoc comment for field cached_size in
> > struct dev_dax_range (thanks Dave)
> > - fsdev_write_dax(): s/pmem_addr/addr/ (thanks Dave)
> > - include/linux/dax.h: remove a spuriously-added declaration of inode_dax()
> > (thanks Jonathan)
> >
> > Description:
> >
> > This patch series introduces the required dax support for famfs.
> > Previous versions of the famfs series included both dax and fuse patches.
> > This series separates them into separate patch series' (and the fuse
> > series dependends on this dax series).
> >
> > The famfs user space code can be found at [1]
> >
> > Dax Overview:
> >
> > This series introduces a new "famfs mode" of devdax, whose driver is
> > drivers/dax/fsdev.c. This driver supports dax_iomap_rw() and
> > dax_iomap_fault() calls against a character dax instance. A dax device
> > now can be converted among three modes: 'system-ram', 'devdax' and
> > 'famfs' via daxctl or sysfs (e.g. unbind devdax and bind famfs instead).
> >
> > In famfs mode, a dax device initializes its pages consistent with the
> > fsdaxmode of pmem. Raw read/write/mmap are not supported in this mode,
> > but famfs is happy in this mode - using dax_iomap_rw() for read/write and
> > dax_iomap_fault() for mmap faults.
> >
>
> Here's what I found:
>
> famfs-v10 on 7.0-rc5 + ndctl v84:
> dax suite all pass 13/13, so no regression appears
>
> famfs-v10 on 7.0-rc5 +
> (ndctl v84 w https://github.com/jagalactic/ndctl/tree/famfs
> top 3 patches + edit daxctl-famfs.sh to use cxl-test:
>
> existing dax suite keeps passing
> daxctl-famfs.sh oops w the new test at # Restore original mode"
> seems easy to repoduce, maybe cannot go back to system-ram???
My stack trace differed from Ira's. I hit:
[ 88.991865] probe of dax0.0 returned 0 after 2371506 usecs
[ 88.996717] page: refcount:0 mapcount:1 mapping:0000000000000000 index:0x0 pfn:0x3ff028000
[ 88.997592] BUG: unable to handle page fault for address: ffffc9000f4c8033
[ 88.998256] #PF: supervisor read access in kernel mode
[ 88.998728] #PF: error_code(0x0000) - not-present page
[ 88.999254] PGD 80a067 P4D 80a067 PUD 193e067 PMD 79baf067 PTE 0
[ 88.999799] Oops: Oops: 0000 [#1] SMP NOPTI
[ 89.000253] CPU: 5 UID: 0 PID: 1476 Comm: daxctl Tainted: G O 7.0.0-rc5+ #182 PREEMPT(full)
[ 89.001092] Tainted: [O]=OOT_MODULE
[ 89.001630] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
[ 89.002345] RIP: 0010:is_free_buddy_page+0x39/0x60
[ 89.002816] Code: 00 00 00 48 c1 fe 06 eb 0a 48 83 c1 01 48 83 f9 0b 74 30 44 89 c0 48 89 fa d3 e0 83 e8 01 48 98 48 21 f0 48 c1 e0 06 48 29 c2 <80> 7a 33 f0 75 d9 48 8b 42 28 48 39 c8 72 d0 b8 01 00 00 00 e9 ce
[ 89.004504] RSP: 0018:ffffc9000f4cf828 EFLAGS: 00010286
[ 89.005039] RAX: 0000000000007a80 RBX: ffffc9000f4cf8a0 RCX: 0000000000000009
[ 89.005674] RDX: ffffc9000f4c8000 RSI: ffffff7c003d33ea RDI: ffffc9000f4cfa80
[ 89.006350] RBP: ffffc9000f4cf838 R08: 0000000000000001 R09: 00000000ffefffff
[ 89.007000] R10: ffffc9000f4cfa38 R11: ffff888376ffe000 R12: ffffc9000f4cfa80
[ 89.007673] R13: ffffc9000f4cf9a0 R14: 0000000000000006 R15: 0000000000000001
[ 89.008395] FS: 00007f3fbca2e7c0(0000) GS:ffff8881fa75f000(0000) knlGS:0000000000000000
[ 89.009156] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 89.009715] CR2: ffffc9000f4c8033 CR3: 000000012f638003 CR4: 0000000000370ef0
[ 89.010447] Call Trace:
[ 89.010767] <TASK>
[ 89.011083] ? set_ps_flags.constprop.0+0x3c/0x70
[ 89.011559] snapshot_page+0x2ca/0x330
[ 89.011974] __dump_page+0x2e/0x380
[ 89.012362] ? up+0x5a/0x90
[ 89.012704] dump_page+0x16/0x50
[ 89.013108] ? dump_page+0x16/0x50
[ 89.013489] __get_pfnblock_flags_mask+0x6f/0xd0
[ 89.013958] get_pfnblock_migratetype+0xe/0x30
[ 89.014412] __dump_page+0x15b/0x380
[ 89.014816] dump_page+0x16/0x50
[ 89.015210] ? dump_page+0x16/0x50
[ 89.015587] __set_pfnblock_flags_mask.constprop.0+0x6f/0xf0
[ 89.016195] init_pageblock_migratetype+0x39/0x60
[ 89.016692] memmap_init_range+0x165/0x290
[ 89.017205] move_pfn_range_to_zone+0xed/0x200
[ 89.017688] mhp_init_memmap_on_memory+0x23/0xb0
[ 89.018223] memory_subsys_online+0x127/0x1a0
[ 89.018693] device_online+0x4d/0x90
[ 89.019149] state_store+0x96/0xa0
[ 89.019552] dev_attr_store+0x12/0x30
[ 89.019975] sysfs_kf_write+0x48/0x70
[ 89.020381] kernfs_fop_write_iter+0x160/0x210
[ 89.020876] vfs_write+0x261/0x500
[ 89.021311] ksys_write+0x5c/0xf0
[ 89.021701] __x64_sys_write+0x14/0x20
[ 89.022180] x64_sys_call+0x1cb7/0x2010
[ 89.022640] do_syscall_64+0xb1/0x560
[ 89.023096] entry_SYSCALL_64_after_hwframe+0x71/0x79
[ 89.023615] RIP: 0033:0x7f3fbc901c37
[ 89.024050] Code: 0f 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 48 89 54 24 18 48 89 74 24
[ 89.025768] RSP: 002b:00007ffdbdf63c68 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
[ 89.026517] RAX: ffffffffffffffda RBX: 00007ffdbdf64228 RCX: 00007f3fbc901c37
[ 89.027280] RDX: 000000000000000f RSI: 00007f3fbcb554de RDI: 0000000000000004
[ 89.027934] RBP: 00007ffdbdf63ca0 R08: 0000000000000000 R09: 0000000000000073
[ 89.028610] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
[ 89.029337] R13: 00007ffdbdf64260 R14: 0000000000414da0 R15: 00007f3fbcb9b000
[ 89.030051] </TASK>
[ 89.030364] Modules linked in: cxl_test(O) cxl_acpi(O) cxl_pmem(O) device_dax(O) fsdev_dax kmem dax_pmem(O) nd_pmem(O) dax_cxl nd_btt(O) nd_e820(O) nfit(O) cxl_mock_mem(O) cxl_mem(O) cxl_port(O) cxl_mock(O) libnvdimm(O) nfit_test_iomap(O) cxl_core(O) fwctl [last unloaded: cxl_pmem(O)]
[ 89.032575] CR2: ffffc9000f4c8033
[ 89.032960] ---[ end trace 0000000000000000 ]---
[ 89.033460] RIP: 0010:is_free_buddy_page+0x39/0x60
[ 89.033948] Code: 00 00 00 48 c1 fe 06 eb 0a 48 83 c1 01 48 83 f9 0b 74 30 44 89 c0 48 89 fa d3 e0 83 e8 01 48 98 48 21 f0 48 c1 e0 06 48 29 c2 <80> 7a 33 f0 75 d9 48 8b 42 28 48 39 c8 72 d0 b8 01 00 00 00 e9 ce
[ 89.035645] RSP: 0018:ffffc9000f4cf828 EFLAGS: 00010286
[ 89.036235] RAX: 0000000000007a80 RBX: ffffc9000f4cf8a0 RCX: 0000000000000009
[ 89.036910] RDX: ffffc9000f4c8000 RSI: ffffff7c003d33ea RDI: ffffc9000f4cfa80
[ 89.037588] RBP: ffffc9000f4cf838 R08: 0000000000000001 R09: 00000000ffefffff
[ 89.038310] R10: ffffc9000f4cfa38 R11: ffff888376ffe000 R12: ffffc9000f4cfa80
[ 89.039008] R13: ffffc9000f4cf9a0 R14: 0000000000000006 R15: 0000000000000001
[ 89.039710] FS: 00007f3fbca2e7c0(0000) GS:ffff8881fa75f000(0000) knlGS:0000000000000000
[ 89.040506] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 89.041129] CR2: ffffc9000f4c8033 CR3: 000000012f638003 CR4: 0000000000370ef0
[ 89.041836] note: daxctl[1476] exited with irqs disabled
>
> Let me know if you need more info.
>
> -- Alison
>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2026-04-13 22:42 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260327210311.79099-1-john@jagalactic.com>
2026-03-27 21:03 ` [PATCH V10 0/8] dax: prepare for famfs John Groves
2026-03-27 21:04 ` [PATCH V10 1/8] dax: move dax_pgoff_to_phys from [drivers/dax/] device.c to bus.c John Groves
2026-03-27 21:04 ` [PATCH V10 2/8] dax: Factor out dax_folio_reset_order() helper John Groves
2026-03-27 21:04 ` [PATCH V10 3/8] dax: add fsdev.c driver for fs-dax on character dax John Groves
2026-03-27 21:04 ` [PATCH V10 4/8] dax: Save the kva from memremap John Groves
2026-03-27 21:04 ` [PATCH V10 5/8] dax: Add dax_operations for use by fs-dax on fsdev dax John Groves
2026-03-27 21:05 ` [PATCH V10 6/8] dax: Add dax_set_ops() for setting dax_operations at bind time John Groves
2026-03-27 21:05 ` [PATCH V10 7/8] dax: Add fs_dax_get() func to prepare dax for fs-dax usage John Groves
2026-03-27 21:05 ` [PATCH V10 8/8] dax: export dax_dev_get() John Groves
2026-03-30 21:21 ` [PATCH V10 0/8] dax: prepare for famfs Alison Schofield
2026-04-13 20:51 ` Ira Weiny
2026-04-13 21:37 ` Ira Weiny
2026-04-13 21:40 ` Ira Weiny
2026-04-13 22:26 ` John Groves
2026-04-13 22:22 ` John Groves
2026-04-13 22:41 ` Alison Schofield
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox