Re: [PATCH V4 0/2] ndctl: Add daxctl support for the new "famfs" mode of devdax
From: Alison Schofield <alison.schofield@intel.com>
Date: 2026-02-09 23:13:18
Also in:
linux-cxl, linux-fsdevel, lkml, nvdimm
Subsystem:
the rest · Maintainer:
Linus Torvalds
On Sun, Jan 18, 2026 at 10:36:02PM +0000, John Groves wrote:
From: John Groves <john@groves.net> No change since V2 - re-sending due to technical challenges. No change since V1 - reposting as V2 to keep this with the related kernel (dax and fuse) patches and libfuse patches. This short series adds support and tests to daxctl for famfs[1]. The famfs kernel patch series, under the same "compound cover" as this series, adds a new 'fsdev_dax' driver for devdax. When that driver is bound (instead of device_dax), the device is in 'famfs' mode rather than 'devdax' mode.
Hi John, I fired this all up and ran it. It got through all but it's last test case before failing. Three things appended: 1) the diff I applied to daxctl-famfs.sh to run the test 2) testlog.txt output of the test 3) RIP: 0010:is_free_buddy_page+0x39/0x60 kernel log 1) Diff I applied to execute the test:
diff --git a/test/daxctl-famfs.sh b/test/daxctl-famfs.sh
index 12fbfefa3144..a4e8d87b9762 100755
--- a/test/daxctl-famfs.sh
+++ b/test/daxctl-famfs.sh@@ -9,6 +9,17 @@ rc=77 trap 'cleanup $LINENO' ERR +# Use cxl-test module to get the DAX device of the CXL auto region, +# which also makes this test NON destructive. +# +# The $CXL list below is a delay because find_daxdev() was not +# finding the DAX region without it. +# +modprobe -r cxl-test +modprobe cxl-test +$CXL list + + daxdev="" original_mode=""
2) Log of Meson test suite run on 2026-02-09T14:52:40.498801
1/1 ndctl:dax / daxctl-famfs.sh INTERRUPT 230.60s killed by signal 15 SIGTERM
22:52:40 MALLOC_PERTURB_=233 LC_ALL=C TEST_PATH=/root/ndctl/build/test NDCTL=/root/ndctl/build/ndctl/ndctl DAXCTL=/root/ndctl/build/daxctl/daxctl DATA_PATH=/root/ndctl/test CXL=/root/ndctl/build/cxl/cxl /root/ndctl/test/daxctl-famfs.sh
----------------------------------- output -----------------------------------
stdout:
Found dax device: dax6.0 (current mode: system-ram)
=== Testing famfs mode transitions ===
Device is in system-ram mode, attempting to convert to devdax...
[
{
"chardev":"dax6.0",
"size":536870912,
"target_node":0,
"align":2097152,
"mode":"devdax"
}
]
Initial mode: devdax - OK
Testing devdax -> famfs... [
{
"chardev":"dax6.0",
"size":536870912,
"target_node":0,
"align":2097152,
"mode":"famfs"
}
]
OK
Testing famfs -> famfs (re-enable)... [
{
"chardev":"dax6.0",
"size":536870912,
"target_node":0,
"align":2097152,
"mode":"famfs"
}
]
OK
Testing famfs -> devdax... [
{
"chardev":"dax6.0",
"size":536870912,
"target_node":0,
"align":2097152,
"mode":"devdax"
}
]
OK
Testing devdax -> devdax (re-enable)... [
{
"chardev":"dax6.0",
"size":536870912,
"target_node":0,
"align":2097152,
"mode":"devdax"
}
]
OK
=== Testing JSON output for mode field ===
Testing JSON output for devdax mode... OK
[
{
"chardev":"dax6.0",
"size":536870912,
"target_node":0,
"align":2097152,
"mode":"famfs"
}
]
Testing JSON output for famfs mode... OK
[
{
"chardev":"dax6.0",
"size":536870912,
"target_node":0,
"align":2097152,
"mode":"devdax"
}
]
=== Testing error handling ===
[
{
"chardev":"dax6.0",
"size":536870912,
"target_node":0,
"align":2097152,
"mode":"famfs"
}
]
Testing invalid mode rejection... OK (correctly rejected)
[
{
"chardev":"dax6.0",
"size":536870912,
"target_node":0,
"align":2097152,
"mode":"devdax"
}
]
=== Testing system-ram transitions with famfs ===
Testing devdax -> system-ram... [
{
"chardev":"dax6.0",
"size":536870912,
"target_node":0,
"align":2097152,
"mode":"system-ram",
"online_memblocks":0,
"total_memblocks":4
}
]
OK
Testing system-ram -> famfs (should fail)... OK (correctly rejected)
Testing system-ram -> devdax -> famfs... [
{
"chardev":"dax6.0",
"size":536870912,
"target_node":0,
"align":2097152,
"mode":"devdax"
}
]
[
{
"chardev":"dax6.0",
"size":536870912,
"target_node":0,
"align":2097152,
"mode":"famfs"
}
]
OK
[
{
"chardev":"dax6.0",
"size":536870912,
"target_node":0,
"align":2097152,
"mode":"devdax"
}
]
Restoring device to original mode: system-ram
Error at line 255
stderr:
+ rc=77
++ dirname /root/ndctl/test/daxctl-famfs.sh
+ . /root/ndctl/test/common+++ basename /root/ndctl/test/daxctl-famfs.sh
++ test_basename=daxctl-famfs.sh
++ '[' -z /root/ndctl/build/ndctl/ndctl ']'
++ '[' -z /root/ndctl/build/daxctl/daxctl ']'
++ '[' -z /root/ndctl/build/cxl/cxl ']'
++ '[' -z /root/ndctl/build/test ']'
++ NFIT_TEST_BUS0=nfit_test.0
++ NFIT_TEST_BUS1=nfit_test.1
++ CXL_TEST_BUS=cxl_test
++ ACPI_BUS=ACPI.NFIT
++ E820_BUS=e820
++ CXL_TEST_QOS_CLASS=42
+ trap 'cleanup $LINENO' ERR
+ modprobe -r cxl-test
+ modprobe cxl-test
+ /root/ndctl/build/cxl/cxl list
+ daxdev=
+ original_mode=
+ main
+ check_fsdev_dax
+ modinfo fsdev_dax
+ return 0
+ find_daxdev
++ /root/ndctl/build/daxctl/daxctl list
++ jq -er '.[0].chardev // empty'
+ daxdev=dax6.0
+ [[ ! -n dax6.0 ]]
++ /root/ndctl/build/daxctl/daxctl list -d dax6.0
++ jq -er '.[].mode'
+ original_mode=system-ram
+ printf 'Found dax device: %s (current mode: %s)\n' dax6.0 system-ram
+ rc=1
+ test_famfs_mode_transitions
+ printf '\n=== Testing famfs mode transitions ===\n'
+ ensure_devdax_mode
+ local mode
++ daxctl_get_mode dax6.0
++ /root/ndctl/build/daxctl/daxctl list -d dax6.0
++ jq -er '.[].mode'
+ mode=system-ram
+ [[ system-ram == \d\e\v\d\a\x ]]
+ [[ system-ram == \s\y\s\t\e\m\-\r\a\m ]]
+ printf 'Device is in system-ram mode, attempting to convert to devdax...\n'
+ /root/ndctl/build/daxctl/daxctl reconfigure-device -f -m devdax dax6.0dax6.0: all memory sections (4) already offline reconfigured 1 device ++ daxctl_get_mode dax6.0 ++ /root/ndctl/build/daxctl/daxctl list -d dax6.0 ++ jq -er '.[].mode' + [[ devdax == \d\e\v\d\a\x ]] ++ daxctl_get_mode dax6.0 ++ /root/ndctl/build/daxctl/daxctl list -d dax6.0 ++ jq -er '.[].mode' + [[ devdax == \d\e\v\d\a\x ]] + printf 'Initial mode: devdax - OK\n' + printf 'Testing devdax -> famfs... ' + /root/ndctl/build/daxctl/daxctl reconfigure-device -m famfs dax6.0 reconfigured 1 device ++ daxctl_get_mode dax6.0 ++ /root/ndctl/build/daxctl/daxctl list -d dax6.0 ++ jq -er '.[].mode' + [[ famfs == \f\a\m\f\s ]] + printf 'OK\n' + printf 'Testing famfs -> famfs (re-enable)... ' + /root/ndctl/build/daxctl/daxctl reconfigure-device -m famfs dax6.0 reconfigured 1 device ++ daxctl_get_mode dax6.0 ++ /root/ndctl/build/daxctl/daxctl list -d dax6.0 ++ jq -er '.[].mode' + [[ famfs == \f\a\m\f\s ]] + printf 'OK\n' + printf 'Testing famfs -> devdax... ' + /root/ndctl/build/daxctl/daxctl reconfigure-device -m devdax dax6.0 reconfigured 1 device ++ daxctl_get_mode dax6.0 ++ /root/ndctl/build/daxctl/daxctl list -d dax6.0 ++ jq -er '.[].mode' + [[ devdax == \d\e\v\d\a\x ]] + printf 'OK\n' + printf 'Testing devdax -> devdax (re-enable)... ' + /root/ndctl/build/daxctl/daxctl reconfigure-device -m devdax dax6.0 reconfigured 1 device ++ daxctl_get_mode dax6.0 ++ /root/ndctl/build/daxctl/daxctl list -d dax6.0 ++ jq -er '.[].mode' + [[ devdax == \d\e\v\d\a\x ]] + printf 'OK\n' + test_json_output + printf '\n=== Testing JSON output for mode field ===\n' + ensure_devdax_mode + local mode ++ daxctl_get_mode dax6.0 ++ /root/ndctl/build/daxctl/daxctl list -d dax6.0 ++ jq -er '.[].mode' + mode=devdax + [[ devdax == \d\e\v\d\a\x ]] + return 0 + printf 'Testing JSON output for devdax mode... ' ++ /root/ndctl/build/daxctl/daxctl list -d dax6.0 ++ jq -er '.[].mode' + mode=devdax + [[ devdax == \d\e\v\d\a\x ]] + printf 'OK\n' + /root/ndctl/build/daxctl/daxctl reconfigure-device -m famfs dax6.0 reconfigured 1 device + printf 'Testing JSON output for famfs mode... ' ++ /root/ndctl/build/daxctl/daxctl list -d dax6.0 ++ jq -er '.[].mode' + mode=famfs + [[ famfs == \f\a\m\f\s ]] + printf 'OK\n' + /root/ndctl/build/daxctl/daxctl reconfigure-device -m devdax dax6.0 reconfigured 1 device + test_error_handling + printf '\n=== Testing error handling ===\n' + /root/ndctl/build/daxctl/daxctl reconfigure-device -m famfs dax6.0 reconfigured 1 device + printf 'Testing invalid mode rejection... ' + /root/ndctl/build/daxctl/daxctl reconfigure-device -m invalidmode dax6.0 + printf 'OK (correctly rejected)\n' + /root/ndctl/build/daxctl/daxctl reconfigure-device -m devdax dax6.0 reconfigured 1 device + check_kmem + modinfo kmem + return 0 ++ cat /sys/devices/system/memory/auto_online_blocks + saved_policy=offline + echo offline + test_system_ram_transitions + printf '\n=== Testing system-ram transitions with famfs ===\n' + ensure_devdax_mode + local mode ++ daxctl_get_mode dax6.0 ++ /root/ndctl/build/daxctl/daxctl list -d dax6.0 ++ jq -er '.[].mode' + mode=devdax + [[ devdax == \d\e\v\d\a\x ]] + return 0 ++ daxctl_get_mode dax6.0 ++ /root/ndctl/build/daxctl/daxctl list -d dax6.0 ++ jq -er '.[].mode' + [[ devdax == \d\e\v\d\a\x ]] + printf 'Testing devdax -> system-ram... ' + /root/ndctl/build/daxctl/daxctl reconfigure-device -N -m system-ram dax6.0 reconfigured 1 device ++ daxctl_get_mode dax6.0 ++ /root/ndctl/build/daxctl/daxctl list -d dax6.0 ++ jq -er '.[].mode' + [[ system-ram == \s\y\s\t\e\m\-\r\a\m ]] + printf 'OK\n' + printf 'Testing system-ram -> famfs (should fail)... ' + /root/ndctl/build/daxctl/daxctl reconfigure-device -m famfs dax6.0 + printf 'OK (correctly rejected)\n' + printf 'Testing system-ram -> devdax -> famfs... ' + /root/ndctl/build/daxctl/daxctl reconfigure-device -f -m devdax dax6.0 dax6.0: all memory sections (4) already offline reconfigured 1 device ++ daxctl_get_mode dax6.0 ++ /root/ndctl/build/daxctl/daxctl list -d dax6.0 ++ jq -er '.[].mode' + [[ devdax == \d\e\v\d\a\x ]] + /root/ndctl/build/daxctl/daxctl reconfigure-device -m famfs dax6.0 reconfigured 1 device ++ daxctl_get_mode dax6.0 ++ /root/ndctl/build/daxctl/daxctl list -d dax6.0 ++ jq -er '.[].mode' + [[ famfs == \f\a\m\f\s ]] + printf 'OK\n' + /root/ndctl/build/daxctl/daxctl reconfigure-device -m devdax dax6.0 reconfigured 1 device + echo offline + printf '\nRestoring device to original mode: %s\n' system-ram + /root/ndctl/build/daxctl/daxctl reconfigure-device -f -m system-ram dax6.0 /root/ndctl/test/daxctl-famfs.sh: line 231: 1266 Killed "$DAXCTL" reconfigure-device -f -m "$original_mode" "$daxdev" ++ cleanup 255 ++ printf 'Error at line %d\n' 255 ++ [[ -n dax6.0 ]] ++ [[ -n system-ram ]] ++ /root/ndctl/build/daxctl/daxctl reconfigure-device -f -m system-ram dax6.0 ------------------------------------------------------------------------------ Summary of Failures: 1/1 ndctl:dax / daxctl-famfs.sh INTERRUPT 230.60s killed by signal 15 SIGTERM Ok: 0 Expected Fail: 0 Fail: 1 Unexpected Pass: 0 Skipped: 0 Timeout: 0 3) BUG: unable to handle page fault for address: ffffc9000f508033 [ 343.806681] #PF: supervisor read access in kernel mode [ 343.808158] #PF: error_code(0x0000) - not-present page [ 343.809635] PGD 80a067 P4D 80a067 PUD 1936067 PMD 12eeb9067 PTE 0 [ 343.811357] Oops: Oops: 0000 [#1] SMP NOPTI [ 343.812634] CPU: 4 UID: 0 PID: 1266 Comm: daxctl Tainted: G O 6.19.0-rc5+ #106 PREEMPT(voluntary) [ 343.815263] Tainted: [O]=OOT_MODULE [ 343.816423] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 [ 343.818507] RIP: 0010:is_free_buddy_page+0x39/0x60 [ 343.819466] 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 c3 cc [ 343.822668] RSP: 0018:ffffc9000f50f828 EFLAGS: 00010286 [ 343.823719] RAX: 0000000000007a80 RBX: ffffc9000f50f8a0 RCX: 0000000000000009 [ 343.825021] RDX: ffffc9000f508000 RSI: ffffff7c003d43ea RDI: ffffc9000f50fa80 [ 343.826343] RBP: ffffc9000f50f838 R08: 0000000000000001 R09: 00000000ffefffff [ 343.827651] R10: ffffc9000f50fa38 R11: ffff888376ffe000 R12: ffffc9000f50fa80 [ 343.828834] R13: ffffc9000f50f9a0 R14: 0000000000000006 R15: 0000000000000001 [ 343.829725] FS: 00007f0f83e087c0(0000) GS:ffff8881fa8f8000(0000) knlGS:0000000000000000 [ 343.830765] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 343.831581] CR2: ffffc9000f508033 CR3: 000000012dec6003 CR4: 0000000000370ef0 [ 343.832517] Call Trace: [ 343.832964] <TASK> [ 343.833385] ? set_ps_flags.constprop.0+0x3c/0x70 [ 343.834099] snapshot_page+0x2ca/0x330 [ 343.834679] __dump_page+0x2e/0x380 [ 343.835260] ? up+0x5a/0x90 [ 343.835757] dump_page+0x16/0x50 [ 343.836324] ? dump_page+0x16/0x50 [ 343.836861] __get_pfnblock_flags_mask+0x6f/0xd0 [ 343.837520] get_pfnblock_migratetype+0xe/0x30 [ 343.838192] __dump_page+0x15b/0x380 [ 343.838692] dump_page+0x16/0x50 [ 343.839111] ? dump_page+0x16/0x50 [ 343.839504] __set_pfnblock_flags_mask.constprop.0+0x6f/0xf0 [ 343.840093] init_pageblock_migratetype+0x39/0x60 [ 343.840589] memmap_init_range+0x165/0x290 [ 343.841069] move_pfn_range_to_zone+0xed/0x200 [ 343.841548] mhp_init_memmap_on_memory+0x23/0xb0 [ 343.842062] memory_subsys_online+0x127/0x1a0 [ 343.842542] device_online+0x4d/0x90 [ 343.842986] state_store+0x96/0xa0 [ 343.843393] dev_attr_store+0x12/0x30 [ 343.843809] sysfs_kf_write+0x48/0x70 [ 343.844231] kernfs_fop_write_iter+0x160/0x210 [ 343.844714] vfs_write+0x261/0x500 [ 343.845185] ksys_write+0x5c/0xf0 [ 343.845584] __x64_sys_write+0x14/0x20 [ 343.846040] x64_sys_call+0x1fbc/0x1ff0 [ 343.846480] do_syscall_64+0x67/0x370 [ 343.846905] entry_SYSCALL_64_after_hwframe+0x71/0x79 [ 343.847432] RIP: 0033:0x7f0f83d01c37 [ 343.847838] 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 [ 343.849536] RSP: 002b:00007ffe63e1f148 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 [ 343.850282] RAX: ffffffffffffffda RBX: 00007ffe63e1f708 RCX: 00007f0f83d01c37 [ 343.850997] RDX: 000000000000000f RSI: 00007f0f83ef543e RDI: 0000000000000004 [ 343.851692] RBP: 00007ffe63e1f180 R08: 0000000000000000 R09: 0000000000000073 [ 343.852405] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 [ 343.853112] R13: 00007ffe63e1f740 R14: 0000000000414da0 R15: 00007f0f83f3b000 [ 343.853789] </TASK> [ 343.854109] Modules linked in: cxl_test(O) cxl_mem(O) cxl_pmem(O) cxl_acpi(O) cxl_port(O) cxl_mock(O) device_dax(O) fsdev_dax kmem dax_cxl cxl_mock_mem(O) cxl_core(O) dax_pmem(O) nd_pmem(O) nd_btt(O) nfit(O) nd_e820(O) libnvdimm(O) nfit_test_iomap(O) [last unloaded: cxl_mock(O)] [ 343.856252] CR2: ffffc9000f508033 [ 343.856656] ---[ end trace 0000000000000000 ]--- [ 343.857172] RIP: 0010:is_free_buddy_page+0x39/0x60 [ 343.857678] 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 c3 cc [ 343.859395] RSP: 0018:ffffc9000f50f828 EFLAGS: 00010286 [ 343.859929] RAX: 0000000000007a80 RBX: ffffc9000f50f8a0 RCX: 0000000000000009 [ 343.860614] RDX: ffffc9000f508000 RSI: ffffff7c003d43ea RDI: ffffc9000f50fa80 [ 343.861333] RBP: ffffc9000f50f838 R08: 0000000000000001 R09: 00000000ffefffff [ 343.862076] R10: ffffc9000f50fa38 R11: ffff888376ffe000 R12: ffffc9000f50fa80 [ 343.862753] R13: ffffc9000f50f9a0 R14: 0000000000000006 R15: 0000000000000001 [ 343.863477] FS: 00007f0f83e087c0(0000) GS:ffff8881fa8f8000(0000) knlGS:0000000000000000 [ 343.864268] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 343.864855] CR2: ffffc9000f508033 CR3: 000000012dec6003 CR4: 0000000000370ef0 [ 343.865542] note: daxctl[1266] exited with irqs disabled