Linux filesystem development
 help / color / mirror / Atom feed
* Re: [PATCH V4 0/2] ndctl: Add daxctl support for the new "famfs" mode of devdax
       [not found]   ` <0100019bd34040d9-0b6e9e4c-ecd4-464d-ab9d-88a251215442-000000@email.amazonses.com>
@ 2026-02-09 23:13     ` Alison Schofield
  2026-02-11 14:31       ` John Groves
       [not found]     ` <20260118223629.92852-1-john@jagalactic.com>
       [not found]     ` <20260118223640.92878-1-john@jagalactic.com>
  2 siblings, 1 reply; 12+ messages in thread
From: Alison Schofield @ 2026-02-09 23:13 UTC (permalink / raw)
  To: John Groves
  Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
	John Groves, John Groves, Jonathan Corbet, 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,
	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 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.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 ]]
++ 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



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH V4 0/2] ndctl: Add daxctl support for the new "famfs" mode of devdax
  2026-02-09 23:13     ` [PATCH V4 0/2] ndctl: Add daxctl support for the new "famfs" mode of devdax Alison Schofield
@ 2026-02-11 14:31       ` John Groves
  0 siblings, 0 replies; 12+ messages in thread
From: John Groves @ 2026-02-11 14:31 UTC (permalink / raw)
  To: Alison Schofield
  Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
	John Groves, John Groves, Jonathan Corbet, 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,
	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/02/09 03:13PM, Alison Schofield wrote:
> 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=""

[snip]

Thank you Allison! I'm still working to reproduce the BUG you found (and 
cover this in my jenkins automation), but I think I have the fix already: 
when existing famfs mode (unbinding drivers/dax/fsdev.c), a
fsdev_clear_folio_state() call is needed. I've added that for v8 as a devm
action...

I'm not 100% up to speed on how to use the test infrastructure, and may
ping you with questions later...

Regards,
John


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH V4 1/2] daxctl: Add support for famfs mode
       [not found]       ` <0100019bd340cdd5-89036a70-3ef5-4c34-abf8-07a3ea4d9f92-000000@email.amazonses.com>
@ 2026-02-19 21:47         ` Dave Jiang
  2026-02-27  2:00         ` Alison Schofield
  1 sibling, 0 replies; 12+ messages in thread
From: Dave Jiang @ 2026-02-19 21:47 UTC (permalink / raw)
  To: John Groves, John Groves, Miklos Szeredi, Dan Williams,
	Bernd Schubert, Alison Schofield
  Cc: John Groves, John Groves, Jonathan Corbet, Vishal Verma,
	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, 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 1/18/26 3:36 PM, John Groves wrote:
> From: John Groves <John@Groves.net>
> 
> Putting a daxdev in famfs mode means binding it to fsdev_dax.ko
> (drivers/dax/fsdev.c). Finding a daxdev bound to fsdev_dax means
> it is in famfs mode.
> 
> The test is added to the destructive test suite since it
> modifies device modes.
> 
> With devdax, famfs, and system-ram modes, the previous logic that assumed
> 'not in mode X means in mode Y' needed to get slightly more complicated
> 
> Add explicit mode detection functions:
> - daxctl_dev_is_famfs_mode(): check if bound to fsdev_dax driver
> - daxctl_dev_is_devdax_mode(): check if bound to device_dax driver
> 
> Fix mode transition logic in device.c:
> - disable_devdax_device(): verify device is actually in devdax mode
> - disable_famfs_device(): verify device is actually in famfs mode
> - All reconfig_mode_*() functions now explicitly check each mode
> - Handle unknown mode with error instead of wrong assumption
> 
> Modify json.c to show 'unknown' if device is not in a recognized mode.
> 
> Signed-off-by: John Groves <john@groves.net>
> ---
>  daxctl/device.c                | 126 ++++++++++++++++++++++++++++++---
>  daxctl/json.c                  |   6 +-
>  daxctl/lib/libdaxctl-private.h |   2 +
>  daxctl/lib/libdaxctl.c         |  77 ++++++++++++++++++++
>  daxctl/lib/libdaxctl.sym       |   7 ++
>  daxctl/libdaxctl.h             |   3 +
>  6 files changed, 210 insertions(+), 11 deletions(-)
> 
> diff --git a/daxctl/device.c b/daxctl/device.c
> index e3993b1..14e1796 100644
> --- a/daxctl/device.c
> +++ b/daxctl/device.c
> @@ -42,6 +42,7 @@ enum dev_mode {
>  	DAXCTL_DEV_MODE_UNKNOWN,
>  	DAXCTL_DEV_MODE_DEVDAX,
>  	DAXCTL_DEV_MODE_RAM,
> +	DAXCTL_DEV_MODE_FAMFS,
>  };
>  
>  struct mapping {
> @@ -471,6 +472,13 @@ static const char *parse_device_options(int argc, const char **argv,
>  					"--no-online is incompatible with --mode=devdax\n");
>  				rc =  -EINVAL;
>  			}
> +		} else if (strcmp(param.mode, "famfs") == 0) {
> +			reconfig_mode = DAXCTL_DEV_MODE_FAMFS;
> +			if (param.no_online) {
> +				fprintf(stderr,
> +					"--no-online is incompatible with --mode=famfs\n");
> +				rc =  -EINVAL;
> +			}
>  		}
>  		break;
>  	case ACTION_CREATE:
> @@ -696,8 +704,42 @@ static int disable_devdax_device(struct daxctl_dev *dev)
>  	int rc;
>  
>  	if (mem) {
> -		fprintf(stderr, "%s was already in system-ram mode\n",
> -			devname);
> +		fprintf(stderr, "%s is in system-ram mode\n", devname);
> +		return 1;
> +	}
> +	if (daxctl_dev_is_famfs_mode(dev)) {
> +		fprintf(stderr, "%s is in famfs mode\n", devname);
> +		return 1;
> +	}
> +	if (!daxctl_dev_is_devdax_mode(dev)) {
> +		fprintf(stderr, "%s is not in devdax mode\n", devname);
> +		return 1;
> +	}
> +	rc = daxctl_dev_disable(dev);
> +	if (rc) {
> +		fprintf(stderr, "%s: disable failed: %s\n",
> +			daxctl_dev_get_devname(dev), strerror(-rc));
> +		return rc;
> +	}
> +	return 0;
> +}
> +
> +static int disable_famfs_device(struct daxctl_dev *dev)
> +{
> +	struct daxctl_memory *mem = daxctl_dev_get_memory(dev);
> +	const char *devname = daxctl_dev_get_devname(dev);
> +	int rc;
> +
> +	if (mem) {
> +		fprintf(stderr, "%s is in system-ram mode\n", devname);
> +		return 1;
> +	}
> +	if (daxctl_dev_is_devdax_mode(dev)) {
> +		fprintf(stderr, "%s is in devdax mode\n", devname);
> +		return 1;
> +	}
> +	if (!daxctl_dev_is_famfs_mode(dev)) {
> +		fprintf(stderr, "%s is not in famfs mode\n", devname);
>  		return 1;
>  	}
>  	rc = daxctl_dev_disable(dev);
> @@ -711,6 +753,7 @@ static int disable_devdax_device(struct daxctl_dev *dev)
>  
>  static int reconfig_mode_system_ram(struct daxctl_dev *dev)
>  {
> +	struct daxctl_memory *mem = daxctl_dev_get_memory(dev);
>  	const char *devname = daxctl_dev_get_devname(dev);
>  	int rc, skip_enable = 0;
>  
> @@ -724,11 +767,21 @@ static int reconfig_mode_system_ram(struct daxctl_dev *dev)
>  	}
>  
>  	if (daxctl_dev_is_enabled(dev)) {
> -		rc = disable_devdax_device(dev);
> -		if (rc < 0)
> -			return rc;
> -		if (rc > 0)
> +		if (mem) {
> +			/* already in system-ram mode */
>  			skip_enable = 1;
> +		} else if (daxctl_dev_is_famfs_mode(dev)) {
> +			rc = disable_famfs_device(dev);
> +			if (rc)
> +				return rc;
> +		} else if (daxctl_dev_is_devdax_mode(dev)) {
> +			rc = disable_devdax_device(dev);
> +			if (rc)
> +				return rc;
> +		} else {
> +			fprintf(stderr, "%s: unknown mode\n", devname);
> +			return -EINVAL;
> +		}
>  	}
>  
>  	if (!skip_enable) {
> @@ -750,7 +803,7 @@ static int disable_system_ram_device(struct daxctl_dev *dev)
>  	int rc;
>  
>  	if (!mem) {
> -		fprintf(stderr, "%s was already in devdax mode\n", devname);
> +		fprintf(stderr, "%s is not in system-ram mode\n", devname);
>  		return 1;
>  	}
>  
> @@ -786,12 +839,28 @@ static int disable_system_ram_device(struct daxctl_dev *dev)
>  
>  static int reconfig_mode_devdax(struct daxctl_dev *dev)
>  {
> +	struct daxctl_memory *mem = daxctl_dev_get_memory(dev);
> +	const char *devname = daxctl_dev_get_devname(dev);
>  	int rc;
>  
>  	if (daxctl_dev_is_enabled(dev)) {
> -		rc = disable_system_ram_device(dev);
> -		if (rc)
> -			return rc;
> +		if (mem) {
> +			rc = disable_system_ram_device(dev);
> +			if (rc)
> +				return rc;
> +		} else if (daxctl_dev_is_famfs_mode(dev)) {
> +			rc = disable_famfs_device(dev);
> +			if (rc)
> +				return rc;
> +		} else if (daxctl_dev_is_devdax_mode(dev)) {
> +			/* already in devdax mode, just re-enable */
> +			rc = daxctl_dev_disable(dev);
> +			if (rc)
> +				return rc;
> +		} else {
> +			fprintf(stderr, "%s: unknown mode\n", devname);
> +			return -EINVAL;
> +		}
>  	}
>  
>  	rc = daxctl_dev_enable_devdax(dev);
> @@ -801,6 +870,40 @@ static int reconfig_mode_devdax(struct daxctl_dev *dev)
>  	return 0;
>  }
>  
> +static int reconfig_mode_famfs(struct daxctl_dev *dev)
> +{
> +	struct daxctl_memory *mem = daxctl_dev_get_memory(dev);
> +	const char *devname = daxctl_dev_get_devname(dev);
> +	int rc;
> +
> +	if (daxctl_dev_is_enabled(dev)) {
> +		if (mem) {
> +			fprintf(stderr,
> +				"%s is in system-ram mode, must be in devdax mode to convert to famfs\n",
> +				devname);
> +			return -EINVAL;
> +		} else if (daxctl_dev_is_famfs_mode(dev)) {
> +			/* already in famfs mode, just re-enable */
> +			rc = daxctl_dev_disable(dev);
> +			if (rc)
> +				return rc;
> +		} else if (daxctl_dev_is_devdax_mode(dev)) {
> +			rc = disable_devdax_device(dev);
> +			if (rc)
> +				return rc;
> +		} else {
> +			fprintf(stderr, "%s: unknown mode\n", devname);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	rc = daxctl_dev_enable_famfs(dev);
> +	if (rc)
> +		return rc;
> +
> +	return 0;
> +}
> +
>  static int do_create(struct daxctl_region *region, long long val,
>  		     struct json_object **jdevs)
>  {
> @@ -887,6 +990,9 @@ static int do_reconfig(struct daxctl_dev *dev, enum dev_mode mode,
>  	case DAXCTL_DEV_MODE_DEVDAX:
>  		rc = reconfig_mode_devdax(dev);
>  		break;
> +	case DAXCTL_DEV_MODE_FAMFS:
> +		rc = reconfig_mode_famfs(dev);
> +		break;
>  	default:
>  		fprintf(stderr, "%s: unknown mode requested: %d\n",
>  			devname, mode);
> diff --git a/daxctl/json.c b/daxctl/json.c
> index 3cbce9d..01f139b 100644
> --- a/daxctl/json.c
> +++ b/daxctl/json.c
> @@ -48,8 +48,12 @@ struct json_object *util_daxctl_dev_to_json(struct daxctl_dev *dev,
>  
>  	if (mem)
>  		jobj = json_object_new_string("system-ram");
> -	else
> +	else if (daxctl_dev_is_famfs_mode(dev))
> +		jobj = json_object_new_string("famfs");
> +	else if (daxctl_dev_is_devdax_mode(dev))
>  		jobj = json_object_new_string("devdax");
> +	else
> +		jobj = json_object_new_string("unknown");
>  	if (jobj)
>  		json_object_object_add(jdev, "mode", jobj);
>  
> diff --git a/daxctl/lib/libdaxctl-private.h b/daxctl/lib/libdaxctl-private.h
> index ae45311..0bb73e8 100644
> --- a/daxctl/lib/libdaxctl-private.h
> +++ b/daxctl/lib/libdaxctl-private.h
> @@ -21,12 +21,14 @@ static const char *dax_subsystems[] = {
>  enum daxctl_dev_mode {
>  	DAXCTL_DEV_MODE_DEVDAX = 0,
>  	DAXCTL_DEV_MODE_RAM,
> +	DAXCTL_DEV_MODE_FAMFS,
>  	DAXCTL_DEV_MODE_END,
>  };
>  
>  static const char *dax_modules[] = {
>  	[DAXCTL_DEV_MODE_DEVDAX] = "device_dax",
>  	[DAXCTL_DEV_MODE_RAM] = "kmem",
> +	[DAXCTL_DEV_MODE_FAMFS] = "fsdev_dax",
>  };
>  
>  enum memory_op {
> diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c
> index b7fa0de..0a6cbfe 100644
> --- a/daxctl/lib/libdaxctl.c
> +++ b/daxctl/lib/libdaxctl.c
> @@ -418,6 +418,78 @@ DAXCTL_EXPORT int daxctl_dev_is_system_ram_capable(struct daxctl_dev *dev)
>  	return false;
>  }
>  
> +/*
> + * Check if device is currently in famfs mode (bound to fsdev_dax driver)
> + */
> +DAXCTL_EXPORT int daxctl_dev_is_famfs_mode(struct daxctl_dev *dev)

Should this return bool?

> +{
> +	const char *devname = daxctl_dev_get_devname(dev);
> +	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
> +	char *mod_path, *mod_base;
> +	char path[200];
> +	const int len = sizeof(path);
> +
> +	if (!device_model_is_dax_bus(dev))
> +		return false;
> +
> +	if (!daxctl_dev_is_enabled(dev))
> +		return false;
> +
> +	if (snprintf(path, len, "%s/driver", dev->dev_path) >= len) {
> +		err(ctx, "%s: buffer too small!\n", devname);
> +		return false;
> +	}
> +
> +	mod_path = realpath(path, NULL);
> +	if (!mod_path)
> +		return false;
> +
> +	mod_base = basename(mod_path);
> +	if (strcmp(mod_base, dax_modules[DAXCTL_DEV_MODE_FAMFS]) == 0) {
> +		free(mod_path);
> +		return true;
> +	}
> +
> +	free(mod_path);
> +	return false;
> +}
> +
> +/*
> + * Check if device is currently in devdax mode (bound to device_dax driver)
> + */
> +DAXCTL_EXPORT int daxctl_dev_is_devdax_mode(struct daxctl_dev *dev)

return bool?

DJ

> +{
> +	const char *devname = daxctl_dev_get_devname(dev);
> +	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
> +	char *mod_path, *mod_base;
> +	char path[200];
> +	const int len = sizeof(path);
> +
> +	if (!device_model_is_dax_bus(dev))
> +		return false;
> +
> +	if (!daxctl_dev_is_enabled(dev))
> +		return false;
> +
> +	if (snprintf(path, len, "%s/driver", dev->dev_path) >= len) {
> +		err(ctx, "%s: buffer too small!\n", devname);
> +		return false;
> +	}
> +
> +	mod_path = realpath(path, NULL);
> +	if (!mod_path)
> +		return false;
> +
> +	mod_base = basename(mod_path);
> +	if (strcmp(mod_base, dax_modules[DAXCTL_DEV_MODE_DEVDAX]) == 0) {
> +		free(mod_path);
> +		return true;
> +	}
> +
> +	free(mod_path);
> +	return false;
> +}
> +
>  /*
>   * This checks for the device to be in system-ram mode, so calling
>   * daxctl_dev_get_memory() on a devdax mode device will always return NULL.
> @@ -982,6 +1054,11 @@ DAXCTL_EXPORT int daxctl_dev_enable_ram(struct daxctl_dev *dev)
>  	return daxctl_dev_enable(dev, DAXCTL_DEV_MODE_RAM);
>  }
>  
> +DAXCTL_EXPORT int daxctl_dev_enable_famfs(struct daxctl_dev *dev)
> +{
> +	return daxctl_dev_enable(dev, DAXCTL_DEV_MODE_FAMFS);
> +}
> +
>  DAXCTL_EXPORT int daxctl_dev_disable(struct daxctl_dev *dev)
>  {
>  	const char *devname = daxctl_dev_get_devname(dev);
> diff --git a/daxctl/lib/libdaxctl.sym b/daxctl/lib/libdaxctl.sym
> index 3098811..2a812c6 100644
> --- a/daxctl/lib/libdaxctl.sym
> +++ b/daxctl/lib/libdaxctl.sym
> @@ -104,3 +104,10 @@ LIBDAXCTL_10 {
>  global:
>  	daxctl_dev_is_system_ram_capable;
>  } LIBDAXCTL_9;
> +
> +LIBDAXCTL_11 {
> +global:
> +	daxctl_dev_enable_famfs;
> +	daxctl_dev_is_famfs_mode;
> +	daxctl_dev_is_devdax_mode;
> +} LIBDAXCTL_10;
> diff --git a/daxctl/libdaxctl.h b/daxctl/libdaxctl.h
> index 53c6bbd..84fcdb4 100644
> --- a/daxctl/libdaxctl.h
> +++ b/daxctl/libdaxctl.h
> @@ -72,12 +72,15 @@ int daxctl_dev_is_enabled(struct daxctl_dev *dev);
>  int daxctl_dev_disable(struct daxctl_dev *dev);
>  int daxctl_dev_enable_devdax(struct daxctl_dev *dev);
>  int daxctl_dev_enable_ram(struct daxctl_dev *dev);
> +int daxctl_dev_enable_famfs(struct daxctl_dev *dev);
>  int daxctl_dev_get_target_node(struct daxctl_dev *dev);
>  int daxctl_dev_will_auto_online_memory(struct daxctl_dev *dev);
>  int daxctl_dev_has_online_memory(struct daxctl_dev *dev);
>  
>  struct daxctl_memory;
>  int daxctl_dev_is_system_ram_capable(struct daxctl_dev *dev);
> +int daxctl_dev_is_famfs_mode(struct daxctl_dev *dev);
> +int daxctl_dev_is_devdax_mode(struct daxctl_dev *dev);
>  struct daxctl_memory *daxctl_dev_get_memory(struct daxctl_dev *dev);
>  struct daxctl_dev *daxctl_memory_get_dev(struct daxctl_memory *mem);
>  const char *daxctl_memory_get_node_path(struct daxctl_memory *mem);


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH V4 2/2] Add test/daxctl-famfs.sh to test famfs mode transitions:
       [not found]       ` <0100019bd340f73c-90b0fafb-786e-4368-85f0-149ffa1d637a-000000@email.amazonses.com>
@ 2026-02-19 22:02         ` Dave Jiang
  0 siblings, 0 replies; 12+ messages in thread
From: Dave Jiang @ 2026-02-19 22:02 UTC (permalink / raw)
  To: John Groves, John Groves, Miklos Szeredi, Dan Williams,
	Bernd Schubert, Alison Schofield
  Cc: John Groves, John Groves, Jonathan Corbet, Vishal Verma,
	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, 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 1/18/26 3:36 PM, John Groves wrote:
> From: John Groves <John@Groves.net>
> 
> - devdax <-> famfs mode switches
> - Verify famfs -> system-ram is rejected (must go via devdax)
> - Test JSON output shows correct mode
> - Test error handling for invalid modes
> 
> The test is added to the destructive test suite since it
> modifies device modes.
> 
> Signed-off-by: John Groves <john@groves.net>
> ---
>  test/daxctl-famfs.sh | 253 +++++++++++++++++++++++++++++++++++++++++++
>  test/meson.build     |   2 +
>  2 files changed, 255 insertions(+)
>  create mode 100755 test/daxctl-famfs.sh
> 
> diff --git a/test/daxctl-famfs.sh b/test/daxctl-famfs.sh
> new file mode 100755
> index 0000000..12fbfef
> --- /dev/null
> +++ b/test/daxctl-famfs.sh
> @@ -0,0 +1,253 @@
> +#!/bin/bash -Ex
> +# SPDX-License-Identifier: GPL-2.0
> +# Copyright (C) 2025 Micron Technology, Inc. All rights reserved.
> +#
> +# Test daxctl famfs mode transitions and mode detection
> +
> +rc=77
> +. $(dirname $0)/common
> +
> +trap 'cleanup $LINENO' ERR
> +
> +daxdev=""
> +original_mode=""
> +
> +cleanup()
> +{
> +	printf "Error at line %d\n" "$1"
> +	# Try to restore to original mode if we know it
> +	if [[ $daxdev && $original_mode ]]; then
> +		"$DAXCTL" reconfigure-device -f -m "$original_mode" "$daxdev" 2>/dev/null || true
> +	fi
> +	exit $rc
> +}
> +
> +# Check if fsdev_dax module is available
> +check_fsdev_dax()
> +{
> +	if modinfo fsdev_dax &>/dev/null; then
> +		return 0
> +	fi
> +	if grep -qF "fsdev_dax" "/lib/modules/$(uname -r)/modules.builtin" 2>/dev/null; then
> +		return 0
> +	fi
> +	printf "fsdev_dax module not available, skipping\n"
> +	exit 77
> +}

Wonder if a common bash function can be created for this and put in "common"

check_kmod_available()?

DJ

> +
> +# Check if kmem module is available (needed for system-ram mode tests)
> +check_kmem()
> +{
> +	if modinfo kmem &>/dev/null; then
> +		return 0
> +	fi
> +	if grep -qF "kmem" "/lib/modules/$(uname -r)/modules.builtin" 2>/dev/null; then
> +		return 0
> +	fi
> +	printf "kmem module not available, skipping system-ram tests\n"
> +	return 1
> +}
> +
> +# Find an existing dax device to test with
> +find_daxdev()
> +{
> +	# Look for any available dax device
> +	daxdev=$("$DAXCTL" list | jq -er '.[0].chardev // empty' 2>/dev/null) || true
> +
> +	if [[ ! $daxdev ]]; then
> +		printf "No dax device found, skipping\n"
> +		exit 77
> +	fi
> +
> +	# Save the original mode so we can restore it
> +	original_mode=$("$DAXCTL" list -d "$daxdev" | jq -er '.[].mode')
> +
> +	printf "Found dax device: %s (current mode: %s)\n" "$daxdev" "$original_mode"
> +}
> +
> +daxctl_get_mode()
> +{
> +	"$DAXCTL" list -d "$1" | jq -er '.[].mode'
> +}
> +
> +# Ensure device is in devdax mode for testing
> +ensure_devdax_mode()
> +{
> +	local mode
> +	mode=$(daxctl_get_mode "$daxdev")
> +
> +	if [[ "$mode" == "devdax" ]]; then
> +		return 0
> +	fi
> +
> +	if [[ "$mode" == "system-ram" ]]; then
> +		printf "Device is in system-ram mode, attempting to convert to devdax...\n"
> +		"$DAXCTL" reconfigure-device -f -m devdax "$daxdev"
> +	elif [[ "$mode" == "famfs" ]]; then
> +		printf "Device is in famfs mode, converting to devdax...\n"
> +		"$DAXCTL" reconfigure-device -m devdax "$daxdev"
> +	else
> +		printf "Device is in unknown mode: %s\n" "$mode"
> +		return 1
> +	fi
> +
> +	[[ $(daxctl_get_mode "$daxdev") == "devdax" ]]
> +}
> +
> +#
> +# Test basic mode transitions involving famfs
> +#
> +test_famfs_mode_transitions()
> +{
> +	printf "\n=== Testing famfs mode transitions ===\n"
> +
> +	# Ensure starting in devdax mode
> +	ensure_devdax_mode
> +	[[ $(daxctl_get_mode "$daxdev") == "devdax" ]]
> +	printf "Initial mode: devdax - OK\n"
> +
> +	# Test: devdax -> famfs
> +	printf "Testing devdax -> famfs... "
> +	"$DAXCTL" reconfigure-device -m famfs "$daxdev"
> +	[[ $(daxctl_get_mode "$daxdev") == "famfs" ]]
> +	printf "OK\n"
> +
> +	# Test: famfs -> famfs (re-enable in same mode)
> +	printf "Testing famfs -> famfs (re-enable)... "
> +	"$DAXCTL" reconfigure-device -m famfs "$daxdev"
> +	[[ $(daxctl_get_mode "$daxdev") == "famfs" ]]
> +	printf "OK\n"
> +
> +	# Test: famfs -> devdax
> +	printf "Testing famfs -> devdax... "
> +	"$DAXCTL" reconfigure-device -m devdax "$daxdev"
> +	[[ $(daxctl_get_mode "$daxdev") == "devdax" ]]
> +	printf "OK\n"
> +
> +	# Test: devdax -> devdax (re-enable in same mode)
> +	printf "Testing devdax -> devdax (re-enable)... "
> +	"$DAXCTL" reconfigure-device -m devdax "$daxdev"
> +	[[ $(daxctl_get_mode "$daxdev") == "devdax" ]]
> +	printf "OK\n"
> +}
> +
> +#
> +# Test mode transitions with system-ram (requires kmem)
> +#
> +test_system_ram_transitions()
> +{
> +	printf "\n=== Testing system-ram transitions with famfs ===\n"
> +
> +	# Ensure we start in devdax mode
> +	ensure_devdax_mode
> +	[[ $(daxctl_get_mode "$daxdev") == "devdax" ]]
> +
> +	# Test: devdax -> system-ram
> +	printf "Testing devdax -> system-ram... "
> +	"$DAXCTL" reconfigure-device -N -m system-ram "$daxdev"
> +	[[ $(daxctl_get_mode "$daxdev") == "system-ram" ]]
> +	printf "OK\n"
> +
> +	# Test: system-ram -> famfs should fail
> +	printf "Testing system-ram -> famfs (should fail)... "
> +	if "$DAXCTL" reconfigure-device -m famfs "$daxdev" 2>/dev/null; then
> +		printf "FAILED - should have been rejected\n"
> +		return 1
> +	fi
> +	printf "OK (correctly rejected)\n"
> +
> +	# Test: system-ram -> devdax -> famfs (proper path)
> +	printf "Testing system-ram -> devdax -> famfs... "
> +	"$DAXCTL" reconfigure-device -f -m devdax "$daxdev"
> +	[[ $(daxctl_get_mode "$daxdev") == "devdax" ]]
> +	"$DAXCTL" reconfigure-device -m famfs "$daxdev"
> +	[[ $(daxctl_get_mode "$daxdev") == "famfs" ]]
> +	printf "OK\n"
> +
> +	# Restore to devdax for subsequent tests
> +	"$DAXCTL" reconfigure-device -m devdax "$daxdev"
> +}
> +
> +#
> +# Test JSON output shows correct mode
> +#
> +test_json_output()
> +{
> +	printf "\n=== Testing JSON output for mode field ===\n"
> +
> +	# Test devdax mode in JSON
> +	ensure_devdax_mode
> +	printf "Testing JSON output for devdax mode... "
> +	mode=$("$DAXCTL" list -d "$daxdev" | jq -er '.[].mode')
> +	[[ "$mode" == "devdax" ]]
> +	printf "OK\n"
> +
> +	# Test famfs mode in JSON
> +	"$DAXCTL" reconfigure-device -m famfs "$daxdev"
> +	printf "Testing JSON output for famfs mode... "
> +	mode=$("$DAXCTL" list -d "$daxdev" | jq -er '.[].mode')
> +	[[ "$mode" == "famfs" ]]
> +	printf "OK\n"
> +
> +	# Restore to devdax
> +	"$DAXCTL" reconfigure-device -m devdax "$daxdev"
> +}
> +
> +#
> +# Test error messages for invalid transitions
> +#
> +test_error_handling()
> +{
> +	printf "\n=== Testing error handling ===\n"
> +
> +	# Ensure we're in famfs mode
> +	"$DAXCTL" reconfigure-device -m famfs "$daxdev"
> +
> +	# Test that invalid mode is rejected
> +	printf "Testing invalid mode rejection... "
> +	if "$DAXCTL" reconfigure-device -m invalidmode "$daxdev" 2>/dev/null; then
> +		printf "FAILED - invalid mode should be rejected\n"
> +		return 1
> +	fi
> +	printf "OK (correctly rejected)\n"
> +
> +	# Restore to devdax
> +	"$DAXCTL" reconfigure-device -m devdax "$daxdev"
> +}
> +
> +#
> +# Main test sequence
> +#
> +main()
> +{
> +	check_fsdev_dax
> +	find_daxdev
> +
> +	rc=1  # From here on, failures are real failures
> +
> +	test_famfs_mode_transitions
> +	test_json_output
> +	test_error_handling
> +
> +	# System-ram tests require kmem module
> +	if check_kmem; then
> +		# Save and disable online policy for system-ram tests
> +		saved_policy="$(cat /sys/devices/system/memory/auto_online_blocks)"
> +		echo "offline" > /sys/devices/system/memory/auto_online_blocks
> +
> +		test_system_ram_transitions
> +
> +		# Restore online policy
> +		echo "$saved_policy" > /sys/devices/system/memory/auto_online_blocks
> +	fi
> +
> +	# Restore original mode
> +	printf "\nRestoring device to original mode: %s\n" "$original_mode"
> +	"$DAXCTL" reconfigure-device -f -m "$original_mode" "$daxdev"
> +
> +	printf "\n=== All famfs tests passed ===\n"
> +
> +	exit 0
> +}
> +
> +main
> diff --git a/test/meson.build b/test/meson.build
> index 615376e..ad1d393 100644
> --- a/test/meson.build
> +++ b/test/meson.build
> @@ -209,6 +209,7 @@ if get_option('destructive').enabled()
>    device_dax_fio = find_program('device-dax-fio.sh')
>    daxctl_devices = find_program('daxctl-devices.sh')
>    daxctl_create = find_program('daxctl-create.sh')
> +  daxctl_famfs = find_program('daxctl-famfs.sh')
>    dm = find_program('dm.sh')
>    mmap_test = find_program('mmap.sh')
>  
> @@ -226,6 +227,7 @@ if get_option('destructive').enabled()
>      [ 'device-dax-fio.sh', device_dax_fio, 'dax'   ],
>      [ 'daxctl-devices.sh', daxctl_devices, 'dax'   ],
>      [ 'daxctl-create.sh',  daxctl_create,  'dax'   ],
> +    [ 'daxctl-famfs.sh',   daxctl_famfs,   'dax'   ],
>      [ 'dm.sh',             dm,		   'dax'   ],
>      [ 'mmap.sh',           mmap_test,	   'dax'   ],
>    ]


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH V4 1/2] daxctl: Add support for famfs mode
       [not found]       ` <0100019bd340cdd5-89036a70-3ef5-4c34-abf8-07a3ea4d9f92-000000@email.amazonses.com>
  2026-02-19 21:47         ` [PATCH V4 1/2] daxctl: Add support for famfs mode Dave Jiang
@ 2026-02-27  2:00         ` Alison Schofield
  2026-04-20 23:17           ` Alison Schofield
  2026-04-26 23:56           ` John Groves
  1 sibling, 2 replies; 12+ messages in thread
From: Alison Schofield @ 2026-02-27  2:00 UTC (permalink / raw)
  To: John Groves
  Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
	John Groves, John Groves, Jonathan Corbet, 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,
	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 Sun, Jan 18, 2026 at 10:36:38PM +0000, John Groves wrote:
> From: John Groves <John@Groves.net>
> 
> Putting a daxdev in famfs mode means binding it to fsdev_dax.ko
> (drivers/dax/fsdev.c). Finding a daxdev bound to fsdev_dax means
> it is in famfs mode.
> 
> The test is added to the destructive test suite since it
> modifies device modes.

Make it clear that it is added in a separate patch. (and assume you
can drop the destructive part too.)

> 
> With devdax, famfs, and system-ram modes, the previous logic that assumed
> 'not in mode X means in mode Y' needed to get slightly more complicated
> 
> Add explicit mode detection functions:
> - daxctl_dev_is_famfs_mode(): check if bound to fsdev_dax driver
> - daxctl_dev_is_devdax_mode(): check if bound to device_dax driver


The precedence check (ram->famfs->devdax->unknown) now happens in multiple
places. How about adding a daxctl_dev_get_mode() helper to centralize that.
It could be private for now, unless you expect external users to need it.

daxctl_dev_is_famfs_mode() and _is_devdax_mode() are nearly identical aside
from the module name. Refactoring the shared part into a single helper will
also make it easier to add a daxctl_dev_get_mode() without duplicating the
precedence logic.

> 
> Fix mode transition logic in device.c:
> - disable_devdax_device(): verify device is actually in devdax mode
> - disable_famfs_device(): verify device is actually in famfs mode
> - All reconfig_mode_*() functions now explicitly check each mode
> - Handle unknown mode with error instead of wrong assumption

Wondering about 'Fix' mode transition logic. Was prior logic broken and
should any of these changes be in a precursor patch that is a 'fix'.


> 
> Modify json.c to show 'unknown' if device is not in a recognized mode.

I think this means disabled devices will always look unknown even when
the intended mode is devdax or famfs, but disabled. This seems to
change the meaning of mode from 'configured' to 'active' personality.
Can you detect the configured mode even when disabled?
Perhaps a man page change about this new behavior?

snip


>  
> @@ -724,11 +767,21 @@ static int reconfig_mode_system_ram(struct daxctl_dev *dev)
>  	}
>  
>  	if (daxctl_dev_is_enabled(dev)) {
> -		rc = disable_devdax_device(dev);
> -		if (rc < 0)
> -			return rc;
> -		if (rc > 0)

Please check the return code semantics.
This gets rid of the <0 vs >0 distinction. That means a '1' skip
becomes an error return to the caller. Is that what you want?

Previously, we had a return 1 from disable_devdax_device for
“not applicable / already in other mode” and I think that is now
gone.


> +		if (mem) {
> +			/* already in system-ram mode */
>  			skip_enable = 1;
> +		} else if (daxctl_dev_is_famfs_mode(dev)) {
> +			rc = disable_famfs_device(dev);
> +			if (rc)
> +				return rc;
> +		} else if (daxctl_dev_is_devdax_mode(dev)) {
> +			rc = disable_devdax_device(dev);
> +			if (rc)
> +				return rc;
> +		} else {
> +			fprintf(stderr, "%s: unknown mode\n", devname);
> +			return -EINVAL;
> +		}
>  	}
>  

snip

>  static int reconfig_mode_devdax(struct daxctl_dev *dev)
>  {
> +	struct daxctl_memory *mem = daxctl_dev_get_memory(dev);
> +	const char *devname = daxctl_dev_get_devname(dev);
>  	int rc;
>  
>  	if (daxctl_dev_is_enabled(dev)) {
> -		rc = disable_system_ram_device(dev);
> -		if (rc)
> -			return rc;
> +		if (mem) {
> +			rc = disable_system_ram_device(dev);
> +			if (rc)
> +				return rc;
> +		} else if (daxctl_dev_is_famfs_mode(dev)) {
> +			rc = disable_famfs_device(dev);
> +			if (rc)
> +				return rc;
> +		} else if (daxctl_dev_is_devdax_mode(dev)) {
> +			/* already in devdax mode, just re-enable */
> +			rc = daxctl_dev_disable(dev);
> +			if (rc)

disable_* helpers print an error message on disable failure.
Seems this should too.


> +				return rc;
> +		} else {
> +			fprintf(stderr, "%s: unknown mode\n", devname);
> +			return -EINVAL;
> +		}
>  	}
>  
>  	rc = daxctl_dev_enable_devdax(dev);
> @@ -801,6 +870,40 @@ static int reconfig_mode_devdax(struct daxctl_dev *dev)
>  	return 0;
>  }
>  
> +static int reconfig_mode_famfs(struct daxctl_dev *dev)
> +{
> +	struct daxctl_memory *mem = daxctl_dev_get_memory(dev);
> +	const char *devname = daxctl_dev_get_devname(dev);
> +	int rc;
> +
> +	if (daxctl_dev_is_enabled(dev)) {
> +		if (mem) {
> +			fprintf(stderr,
> +				"%s is in system-ram mode, must be in devdax mode to convert to famfs\n",
> +				devname);
> +			return -EINVAL;
> +		} else if (daxctl_dev_is_famfs_mode(dev)) {
> +			/* already in famfs mode, just re-enable */
> +			rc = daxctl_dev_disable(dev);
> +			if (rc)
> +				return rc;
> +		} else if (daxctl_dev_is_devdax_mode(dev)) {
> +			rc = disable_devdax_device(dev);
> +			if (rc)

and here too...the disable error message.


> +				return rc;
> +		} else {
> +			fprintf(stderr, "%s: unknown mode\n", devname);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	rc = daxctl_dev_enable_famfs(dev);
> +	if (rc)
> +		return rc;
> +
> +	return 0;
> +}

snip

> +DAXCTL_EXPORT int daxctl_dev_is_famfs_mode(struct daxctl_dev *dev)
> +{
> +	const char *devname = daxctl_dev_get_devname(dev);
> +	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
> +	char *mod_path, *mod_base;
> +	char path[200];

We have PATH_MAX for the above.

> +	const int len = sizeof(path);
> +
> +	if (!device_model_is_dax_bus(dev))
> +		return false;
> +
> +	if (!daxctl_dev_is_enabled(dev))
> +		return false;
> +
> +	if (snprintf(path, len, "%s/driver", dev->dev_path) >= len) {
> +		err(ctx, "%s: buffer too small!\n", devname);
> +		return false;
> +	}
> +
> +	mod_path = realpath(path, NULL);
> +	if (!mod_path)

Maybe a dbg() level err msg here

> +		return false;
> +
> +	mod_base = basename(mod_path);

Please use path_basename() because of this:
https://lore.kernel.org/all/20260116043056.542346-1-alison.schofield@intel.com/

Give me a minute ;) to push that to the pending branch and you can
work from there: https://github.com/pmem/ndctl/commits/pending/

snip to end.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH V4 1/2] daxctl: Add support for famfs mode
  2026-02-27  2:00         ` Alison Schofield
@ 2026-04-20 23:17           ` Alison Schofield
  2026-04-21  1:47             ` John Groves
  2026-04-26 23:56           ` John Groves
  1 sibling, 1 reply; 12+ messages in thread
From: Alison Schofield @ 2026-04-20 23:17 UTC (permalink / raw)
  To: John Groves
  Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
	John Groves, John Groves, Jonathan Corbet, 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,
	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 Thu, Feb 26, 2026 at 06:00:41PM -0800, Alison Schofield wrote:
> On Sun, Jan 18, 2026 at 10:36:38PM +0000, John Groves wrote:
> > From: John Groves <John@Groves.net>
> > 

Hi John,

This is where I left off with the actual changes to "daxctl" for FAMFS.
We need a new rev of this ndctl set that includes both patches rebased
on ndctl pending and addressing the review comments below for daxctl.
(Although I've used more recent branches, I haven't looked at whether
these issues were addressed in the code.)

With a new rev, I'll take another look at ensuring a dax device is
available for the unit test.

Thanks!

--Alison


> > Putting a daxdev in famfs mode means binding it to fsdev_dax.ko
> > (drivers/dax/fsdev.c). Finding a daxdev bound to fsdev_dax means
> > it is in famfs mode.
> > 
> > The test is added to the destructive test suite since it
> > modifies device modes.
> 
> Make it clear that it is added in a separate patch. (and assume you
> can drop the destructive part too.)
> 
> > 
> > With devdax, famfs, and system-ram modes, the previous logic that assumed
> > 'not in mode X means in mode Y' needed to get slightly more complicated
> > 
> > Add explicit mode detection functions:
> > - daxctl_dev_is_famfs_mode(): check if bound to fsdev_dax driver
> > - daxctl_dev_is_devdax_mode(): check if bound to device_dax driver
> 
> 
> The precedence check (ram->famfs->devdax->unknown) now happens in multiple
> places. How about adding a daxctl_dev_get_mode() helper to centralize that.
> It could be private for now, unless you expect external users to need it.
> 
> daxctl_dev_is_famfs_mode() and _is_devdax_mode() are nearly identical aside
> from the module name. Refactoring the shared part into a single helper will
> also make it easier to add a daxctl_dev_get_mode() without duplicating the
> precedence logic.
> 
> > 
> > Fix mode transition logic in device.c:
> > - disable_devdax_device(): verify device is actually in devdax mode
> > - disable_famfs_device(): verify device is actually in famfs mode
> > - All reconfig_mode_*() functions now explicitly check each mode
> > - Handle unknown mode with error instead of wrong assumption
> 
> Wondering about 'Fix' mode transition logic. Was prior logic broken and
> should any of these changes be in a precursor patch that is a 'fix'.
> 
> 
> > 
> > Modify json.c to show 'unknown' if device is not in a recognized mode.
> 
> I think this means disabled devices will always look unknown even when
> the intended mode is devdax or famfs, but disabled. This seems to
> change the meaning of mode from 'configured' to 'active' personality.
> Can you detect the configured mode even when disabled?
> Perhaps a man page change about this new behavior?
> 
> snip
> 
> 
> >  
> > @@ -724,11 +767,21 @@ static int reconfig_mode_system_ram(struct daxctl_dev *dev)
> >  	}
> >  
> >  	if (daxctl_dev_is_enabled(dev)) {
> > -		rc = disable_devdax_device(dev);
> > -		if (rc < 0)
> > -			return rc;
> > -		if (rc > 0)
> 
> Please check the return code semantics.
> This gets rid of the <0 vs >0 distinction. That means a '1' skip
> becomes an error return to the caller. Is that what you want?
> 
> Previously, we had a return 1 from disable_devdax_device for
> “not applicable / already in other mode” and I think that is now
> gone.
> 
> 
> > +		if (mem) {
> > +			/* already in system-ram mode */
> >  			skip_enable = 1;
> > +		} else if (daxctl_dev_is_famfs_mode(dev)) {
> > +			rc = disable_famfs_device(dev);
> > +			if (rc)
> > +				return rc;
> > +		} else if (daxctl_dev_is_devdax_mode(dev)) {
> > +			rc = disable_devdax_device(dev);
> > +			if (rc)
> > +				return rc;
> > +		} else {
> > +			fprintf(stderr, "%s: unknown mode\n", devname);
> > +			return -EINVAL;
> > +		}
> >  	}
> >  
> 
> snip
> 
> >  static int reconfig_mode_devdax(struct daxctl_dev *dev)
> >  {
> > +	struct daxctl_memory *mem = daxctl_dev_get_memory(dev);
> > +	const char *devname = daxctl_dev_get_devname(dev);
> >  	int rc;
> >  
> >  	if (daxctl_dev_is_enabled(dev)) {
> > -		rc = disable_system_ram_device(dev);
> > -		if (rc)
> > -			return rc;
> > +		if (mem) {
> > +			rc = disable_system_ram_device(dev);
> > +			if (rc)
> > +				return rc;
> > +		} else if (daxctl_dev_is_famfs_mode(dev)) {
> > +			rc = disable_famfs_device(dev);
> > +			if (rc)
> > +				return rc;
> > +		} else if (daxctl_dev_is_devdax_mode(dev)) {
> > +			/* already in devdax mode, just re-enable */
> > +			rc = daxctl_dev_disable(dev);
> > +			if (rc)
> 
> disable_* helpers print an error message on disable failure.
> Seems this should too.
> 
> 
> > +				return rc;
> > +		} else {
> > +			fprintf(stderr, "%s: unknown mode\n", devname);
> > +			return -EINVAL;
> > +		}
> >  	}
> >  
> >  	rc = daxctl_dev_enable_devdax(dev);
> > @@ -801,6 +870,40 @@ static int reconfig_mode_devdax(struct daxctl_dev *dev)
> >  	return 0;
> >  }
> >  
> > +static int reconfig_mode_famfs(struct daxctl_dev *dev)
> > +{
> > +	struct daxctl_memory *mem = daxctl_dev_get_memory(dev);
> > +	const char *devname = daxctl_dev_get_devname(dev);
> > +	int rc;
> > +
> > +	if (daxctl_dev_is_enabled(dev)) {
> > +		if (mem) {
> > +			fprintf(stderr,
> > +				"%s is in system-ram mode, must be in devdax mode to convert to famfs\n",
> > +				devname);
> > +			return -EINVAL;
> > +		} else if (daxctl_dev_is_famfs_mode(dev)) {
> > +			/* already in famfs mode, just re-enable */
> > +			rc = daxctl_dev_disable(dev);
> > +			if (rc)
> > +				return rc;
> > +		} else if (daxctl_dev_is_devdax_mode(dev)) {
> > +			rc = disable_devdax_device(dev);
> > +			if (rc)
> 
> and here too...the disable error message.
> 
> 
> > +				return rc;
> > +		} else {
> > +			fprintf(stderr, "%s: unknown mode\n", devname);
> > +			return -EINVAL;
> > +		}
> > +	}
> > +
> > +	rc = daxctl_dev_enable_famfs(dev);
> > +	if (rc)
> > +		return rc;
> > +
> > +	return 0;
> > +}
> 
> snip
> 
> > +DAXCTL_EXPORT int daxctl_dev_is_famfs_mode(struct daxctl_dev *dev)
> > +{
> > +	const char *devname = daxctl_dev_get_devname(dev);
> > +	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
> > +	char *mod_path, *mod_base;
> > +	char path[200];
> 
> We have PATH_MAX for the above.
> 
> > +	const int len = sizeof(path);
> > +
> > +	if (!device_model_is_dax_bus(dev))
> > +		return false;
> > +
> > +	if (!daxctl_dev_is_enabled(dev))
> > +		return false;
> > +
> > +	if (snprintf(path, len, "%s/driver", dev->dev_path) >= len) {
> > +		err(ctx, "%s: buffer too small!\n", devname);
> > +		return false;
> > +	}
> > +
> > +	mod_path = realpath(path, NULL);
> > +	if (!mod_path)
> 
> Maybe a dbg() level err msg here
> 
> > +		return false;
> > +
> > +	mod_base = basename(mod_path);
> 
> Please use path_basename() because of this:
> https://lore.kernel.org/all/20260116043056.542346-1-alison.schofield@intel.com/
> 
> Give me a minute ;) to push that to the pending branch and you can
> work from there: https://github.com/pmem/ndctl/commits/pending/
> 
> snip to end.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH V4 1/2] daxctl: Add support for famfs mode
  2026-04-20 23:17           ` Alison Schofield
@ 2026-04-21  1:47             ` John Groves
  2026-04-22 18:09               ` Ira Weiny
  0 siblings, 1 reply; 12+ messages in thread
From: John Groves @ 2026-04-21  1:47 UTC (permalink / raw)
  To: Alison Schofield, John Groves
  Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
	John Groves (jgroves), Jonathan Corbet, 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, 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, Apr 20, 2026, at 6:17 PM, Alison Schofield wrote:
> On Thu, Feb 26, 2026 at 06:00:41PM -0800, Alison Schofield wrote:
> > On Sun, Jan 18, 2026 at 10:36:38PM +0000, John Groves wrote:
> > > From: John Groves <John@Groves.net>
> > > 
> 
> Hi John,
> 
> This is where I left off with the actual changes to "daxctl" for FAMFS.
> We need a new rev of this ndctl set that includes both patches rebased
> on ndctl pending and addressing the review comments below for daxctl.
> (Although I've used more recent branches, I haven't looked at whether
> these issues were addressed in the code.)
> 
> With a new rev, I'll take another look at ensuring a dax device is
> available for the unit test.
> 
> Thanks!
> 
> --Alison
> 

Will you be on the DAX call tomorrow? If so, let's work out a plan and assign
my action items as necessary. Not that I need any more action items :D

Thanks!
John


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH V4 1/2] daxctl: Add support for famfs mode
  2026-04-21  1:47             ` John Groves
@ 2026-04-22 18:09               ` Ira Weiny
  0 siblings, 0 replies; 12+ messages in thread
From: Ira Weiny @ 2026-04-22 18:09 UTC (permalink / raw)
  To: John Groves, Alison Schofield, John Groves
  Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
	John Groves (jgroves), Jonathan Corbet, 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, 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 wrote:
> 
> 
> On Mon, Apr 20, 2026, at 6:17 PM, Alison Schofield wrote:
> > On Thu, Feb 26, 2026 at 06:00:41PM -0800, Alison Schofield wrote:
> > > On Sun, Jan 18, 2026 at 10:36:38PM +0000, John Groves wrote:
> > > > From: John Groves <John@Groves.net>
> > > > 
> > 
> > Hi John,
> > 
> > This is where I left off with the actual changes to "daxctl" for FAMFS.
> > We need a new rev of this ndctl set that includes both patches rebased
> > on ndctl pending and addressing the review comments below for daxctl.
> > (Although I've used more recent branches, I haven't looked at whether
> > these issues were addressed in the code.)
> > 
> > With a new rev, I'll take another look at ensuring a dax device is
> > available for the unit test.
> > 
> > Thanks!
> > 
> > --Alison
> > 
> 
> Will you be on the DAX call tomorrow? If so, let's work out a plan and assign
> my action items as necessary. Not that I need any more action items :D

What plan do you need?  Now that the kernel changes have been merged, we
need to have an updated daxctl patch set which Alison can apply so that
rc1 can be tested without me applying this set.

This is a pain for me to apply by hand.  Please update this and submit
with Alison for merging soon.

Ira

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH V4 1/2] daxctl: Add support for famfs mode
  2026-02-27  2:00         ` Alison Schofield
  2026-04-20 23:17           ` Alison Schofield
@ 2026-04-26 23:56           ` John Groves
  2026-04-28  4:38             ` Alison Schofield
  1 sibling, 1 reply; 12+ messages in thread
From: John Groves @ 2026-04-26 23:56 UTC (permalink / raw)
  To: Alison Schofield
  Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
	John Groves, John Groves, Jonathan Corbet, 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,
	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

Maybe I'm overcomplicating things (it's one of the things I do), 
but I'm still struggling through how to address all these issues. 
Some comments inline.

On 26/02/26 06:00PM, Alison Schofield wrote:
> On Sun, Jan 18, 2026 at 10:36:38PM +0000, John Groves wrote:
> > From: John Groves <John@Groves.net>
> > 
> > Putting a daxdev in famfs mode means binding it to fsdev_dax.ko
> > (drivers/dax/fsdev.c). Finding a daxdev bound to fsdev_dax means
> > it is in famfs mode.
> > 
> > The test is added to the destructive test suite since it
> > modifies device modes.
> 
> Make it clear that it is added in a separate patch. (and assume you
> can drop the destructive part too.)
> 
> > 
> > With devdax, famfs, and system-ram modes, the previous logic that assumed
> > 'not in mode X means in mode Y' needed to get slightly more complicated
> > 
> > Add explicit mode detection functions:
> > - daxctl_dev_is_famfs_mode(): check if bound to fsdev_dax driver
> > - daxctl_dev_is_devdax_mode(): check if bound to device_dax driver
> 
> 
> The precedence check (ram->famfs->devdax->unknown) now happens in multiple
> places. How about adding a daxctl_dev_get_mode() helper to centralize that.
> It could be private for now, unless you expect external users to need it.
> 
> daxctl_dev_is_famfs_mode() and _is_devdax_mode() are nearly identical aside
> from the module name. Refactoring the shared part into a single helper will
> also make it easier to add a daxctl_dev_get_mode() without duplicating the
> precedence logic.
> 
> > 
> > Fix mode transition logic in device.c:
> > - disable_devdax_device(): verify device is actually in devdax mode
> > - disable_famfs_device(): verify device is actually in famfs mode
> > - All reconfig_mode_*() functions now explicitly check each mode
> > - Handle unknown mode with error instead of wrong assumption
> 
> Wondering about 'Fix' mode transition logic. Was prior logic broken and
> should any of these changes be in a precursor patch that is a 'fix'.
> 
> 
> > 
> > Modify json.c to show 'unknown' if device is not in a recognized mode.
> 
> I think this means disabled devices will always look unknown even when
> the intended mode is devdax or famfs, but disabled. This seems to
> change the meaning of mode from 'configured' to 'active' personality.
> Can you detect the configured mode even when disabled?
> Perhaps a man page change about this new behavior?

Good point; before famfs mode there were just 2 modes, and 
not-system-ram == devdax mode is the current standard, even if no driver 
is bound. At some level that's a conflation, but I'll revise and stick 
with that unless you have a better idea.

Is that how you want it? No driver == devdax mode?

Any thoughts?

> 
> snip
> 
> 
> >  
> > @@ -724,11 +767,21 @@ static int reconfig_mode_system_ram(struct daxctl_dev *dev)
> >  	}
> >  
> >  	if (daxctl_dev_is_enabled(dev)) {
> > -		rc = disable_devdax_device(dev);
> > -		if (rc < 0)
> > -			return rc;
> > -		if (rc > 0)
> 
> Please check the return code semantics.
> This gets rid of the <0 vs >0 distinction. That means a '1' skip
> becomes an error return to the caller. Is that what you want?
> 
> Previously, we had a return 1 from disable_devdax_device for
> “not applicable / already in other mode” and I think that is now
> gone.
> 
> 
> > +		if (mem) {
> > +			/* already in system-ram mode */
> >  			skip_enable = 1;
> > +		} else if (daxctl_dev_is_famfs_mode(dev)) {
> > +			rc = disable_famfs_device(dev);
> > +			if (rc)
> > +				return rc;
> > +		} else if (daxctl_dev_is_devdax_mode(dev)) {
> > +			rc = disable_devdax_device(dev);
> > +			if (rc)
> > +				return rc;
> > +		} else {
> > +			fprintf(stderr, "%s: unknown mode\n", devname);
> > +			return -EINVAL;
> > +		}
> >  	}
> >  
> 
> snip
> 
> >  static int reconfig_mode_devdax(struct daxctl_dev *dev)
> >  {
> > +	struct daxctl_memory *mem = daxctl_dev_get_memory(dev);
> > +	const char *devname = daxctl_dev_get_devname(dev);
> >  	int rc;
> >  
> >  	if (daxctl_dev_is_enabled(dev)) {
> > -		rc = disable_system_ram_device(dev);
> > -		if (rc)
> > -			return rc;
> > +		if (mem) {
> > +			rc = disable_system_ram_device(dev);
> > +			if (rc)
> > +				return rc;
> > +		} else if (daxctl_dev_is_famfs_mode(dev)) {
> > +			rc = disable_famfs_device(dev);
> > +			if (rc)
> > +				return rc;
> > +		} else if (daxctl_dev_is_devdax_mode(dev)) {
> > +			/* already in devdax mode, just re-enable */
> > +			rc = daxctl_dev_disable(dev);
> > +			if (rc)
> 
> disable_* helpers print an error message on disable failure.
> Seems this should too.
> 
> 
> > +				return rc;
> > +		} else {
> > +			fprintf(stderr, "%s: unknown mode\n", devname);
> > +			return -EINVAL;
> > +		}
> >  	}
> >  
> >  	rc = daxctl_dev_enable_devdax(dev);
> > @@ -801,6 +870,40 @@ static int reconfig_mode_devdax(struct daxctl_dev *dev)
> >  	return 0;
> >  }
> >  
> > +static int reconfig_mode_famfs(struct daxctl_dev *dev)
> > +{
> > +	struct daxctl_memory *mem = daxctl_dev_get_memory(dev);
> > +	const char *devname = daxctl_dev_get_devname(dev);
> > +	int rc;
> > +
> > +	if (daxctl_dev_is_enabled(dev)) {
> > +		if (mem) {
> > +			fprintf(stderr,
> > +				"%s is in system-ram mode, must be in devdax mode to convert to famfs\n",
> > +				devname);
> > +			return -EINVAL;
> > +		} else if (daxctl_dev_is_famfs_mode(dev)) {
> > +			/* already in famfs mode, just re-enable */
> > +			rc = daxctl_dev_disable(dev);
> > +			if (rc)
> > +				return rc;
> > +		} else if (daxctl_dev_is_devdax_mode(dev)) {
> > +			rc = disable_devdax_device(dev);
> > +			if (rc)
> 
> and here too...the disable error message.
> 
> 
> > +				return rc;
> > +		} else {
> > +			fprintf(stderr, "%s: unknown mode\n", devname);
> > +			return -EINVAL;
> > +		}
> > +	}
> > +
> > +	rc = daxctl_dev_enable_famfs(dev);
> > +	if (rc)
> > +		return rc;
> > +
> > +	return 0;
> > +}
> 
> snip
> 
> > +DAXCTL_EXPORT int daxctl_dev_is_famfs_mode(struct daxctl_dev *dev)
> > +{
> > +	const char *devname = daxctl_dev_get_devname(dev);
> > +	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
> > +	char *mod_path, *mod_base;
> > +	char path[200];
> 
> We have PATH_MAX for the above.

Done, thanks...

> 
> > +	const int len = sizeof(path);
> > +
> > +	if (!device_model_is_dax_bus(dev))
> > +		return false;
> > +
> > +	if (!daxctl_dev_is_enabled(dev))
> > +		return false;
> > +
> > +	if (snprintf(path, len, "%s/driver", dev->dev_path) >= len) {
> > +		err(ctx, "%s: buffer too small!\n", devname);
> > +		return false;
> > +	}
> > +
> > +	mod_path = realpath(path, NULL);
> > +	if (!mod_path)
> 
> Maybe a dbg() level err msg here
> 
> > +		return false;
> > +
> > +	mod_base = basename(mod_path);
> 
> Please use path_basename() because of this:
> https://lore.kernel.org/all/20260116043056.542346-1-alison.schofield@intel.com/
> 
> Give me a minute ;) to push that to the pending branch and you can
> work from there: https://github.com/pmem/ndctl/commits/pending/
> 
> snip to end.

Done, thanks

Still chewing on the other stuff


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH V4 1/2] daxctl: Add support for famfs mode
  2026-04-26 23:56           ` John Groves
@ 2026-04-28  4:38             ` Alison Schofield
  2026-04-28 19:14               ` Ira Weiny
  0 siblings, 1 reply; 12+ messages in thread
From: Alison Schofield @ 2026-04-28  4:38 UTC (permalink / raw)
  To: John Groves
  Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
	John Groves, John Groves, Jonathan Corbet, 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,
	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 Sun, Apr 26, 2026 at 06:56:46PM -0500, John Groves wrote:
> Maybe I'm overcomplicating things (it's one of the things I do), 
> but I'm still struggling through how to address all these issues. 
> Some comments inline.


Jumping to the part you commented on, which I think was the biggie:

> 
> On 26/02/26 06:00PM, Alison Schofield wrote:
> > On Sun, Jan 18, 2026 at 10:36:38PM +0000, John Groves wrote:
> > > From: John Groves <John@Groves.net>
> > > 
> > > Putting a daxdev in famfs mode means binding it to fsdev_dax.ko
> > > (drivers/dax/fsdev.c). Finding a daxdev bound to fsdev_dax means
> > > it is in famfs mode.
> > > 
> > > The test is added to the destructive test suite since it
> > > modifies device modes.
> > 
> > Make it clear that it is added in a separate patch. (and assume you
> > can drop the destructive part too.)
> > 
> > > 
> > > With devdax, famfs, and system-ram modes, the previous logic that assumed
> > > 'not in mode X means in mode Y' needed to get slightly more complicated
> > > 
> > > Add explicit mode detection functions:
> > > - daxctl_dev_is_famfs_mode(): check if bound to fsdev_dax driver
> > > - daxctl_dev_is_devdax_mode(): check if bound to device_dax driver
> > 
> > 
> > The precedence check (ram->famfs->devdax->unknown) now happens in multiple
> > places. How about adding a daxctl_dev_get_mode() helper to centralize that.
> > It could be private for now, unless you expect external users to need it.
> > 
> > daxctl_dev_is_famfs_mode() and _is_devdax_mode() are nearly identical aside
> > from the module name. Refactoring the shared part into a single helper will
> > also make it easier to add a daxctl_dev_get_mode() without duplicating the
> > precedence logic.
> > 
> > > 
> > > Fix mode transition logic in device.c:
> > > - disable_devdax_device(): verify device is actually in devdax mode
> > > - disable_famfs_device(): verify device is actually in famfs mode
> > > - All reconfig_mode_*() functions now explicitly check each mode
> > > - Handle unknown mode with error instead of wrong assumption
> > 
> > Wondering about 'Fix' mode transition logic. Was prior logic broken and
> > should any of these changes be in a precursor patch that is a 'fix'.
> > 
> > 
> > > 
> > > Modify json.c to show 'unknown' if device is not in a recognized mode.
> > 
> > I think this means disabled devices will always look unknown even when
> > the intended mode is devdax or famfs, but disabled. This seems to
> > change the meaning of mode from 'configured' to 'active' personality.
> > Can you detect the configured mode even when disabled?
> > Perhaps a man page change about this new behavior?
> 
> Good point; before famfs mode there were just 2 modes, and 
> not-system-ram == devdax mode is the current standard, even if no driver 
> is bound. At some level that's a conflation, but I'll revise and stick 
> with that unless you have a better idea.
> 
> Is that how you want it? No driver == devdax mode?
> 
> Any thoughts?
> 

I do think we need to introduce "unknown" rather than keep reporting
devdax for all non-system-ram devices. With famfs added, that old
"not system-ram == devdax" shortcut just isn’t true anymore, and in the
unbound case we really don’t know if it’s devdax or famfs. I’d rather say
"unknown" than guess wrong.

That said, I don’t think we should drop to "unknown" when we actually do
know the mode. In particular, disable shouldn’t cause us to lose it. We
already report state separately, so I’d expect something like this:
	mode=devdax,  state=disabled
and not like this:
	mode=unknown, state=disabled
for a device that we knew was devdax (same idea for famfs).

Also wondering about behavior here: if a device ends up in mode="unknown",
what does enable-device do? It doesn’t take a mode, so if we’ve lost that
info across disable it’s not obvious how we pick which driver to bind.
Before famfs we kind of got away with defaulting to devdax, but that
doesn’t really work anymore.

So I think the rule should be: report a real mode when we can, and only
use "unknown" when it’s actually ambiguous. That keeps disable/enable
workflows predictable.

And if we do introduce "unknown", we need to document when it shows up,
since this is a change from the old behavior.

-- Alison

snipping here, I didn't see any questions or comments below here
expect for the done on the PATH_MAX usage.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH V4 1/2] daxctl: Add support for famfs mode
  2026-04-28  4:38             ` Alison Schofield
@ 2026-04-28 19:14               ` Ira Weiny
  2026-04-28 20:06                 ` John Groves
  0 siblings, 1 reply; 12+ messages in thread
From: Ira Weiny @ 2026-04-28 19:14 UTC (permalink / raw)
  To: Alison Schofield, John Groves
  Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
	John Groves, John Groves, Jonathan Corbet, 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,
	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 Sun, Apr 26, 2026 at 06:56:46PM -0500, John Groves wrote:
> > Maybe I'm overcomplicating things (it's one of the things I do), 
> > but I'm still struggling through how to address all these issues. 
> > Some comments inline.
> 
> 
> Jumping to the part you commented on, which I think was the biggie:
> 
> > 
> > On 26/02/26 06:00PM, Alison Schofield wrote:
> > > On Sun, Jan 18, 2026 at 10:36:38PM +0000, John Groves wrote:
> > > > From: John Groves <John@Groves.net>
> > > > 
> > > > Putting a daxdev in famfs mode means binding it to fsdev_dax.ko
> > > > (drivers/dax/fsdev.c). Finding a daxdev bound to fsdev_dax means
> > > > it is in famfs mode.
> > > > 
> > > > The test is added to the destructive test suite since it
> > > > modifies device modes.
> > > 
> > > Make it clear that it is added in a separate patch. (and assume you
> > > can drop the destructive part too.)
> > > 
> > > > 
> > > > With devdax, famfs, and system-ram modes, the previous logic that assumed
> > > > 'not in mode X means in mode Y' needed to get slightly more complicated
> > > > 
> > > > Add explicit mode detection functions:
> > > > - daxctl_dev_is_famfs_mode(): check if bound to fsdev_dax driver
> > > > - daxctl_dev_is_devdax_mode(): check if bound to device_dax driver
> > > 
> > > 
> > > The precedence check (ram->famfs->devdax->unknown) now happens in multiple
> > > places. How about adding a daxctl_dev_get_mode() helper to centralize that.
> > > It could be private for now, unless you expect external users to need it.
> > > 
> > > daxctl_dev_is_famfs_mode() and _is_devdax_mode() are nearly identical aside
> > > from the module name. Refactoring the shared part into a single helper will
> > > also make it easier to add a daxctl_dev_get_mode() without duplicating the
> > > precedence logic.
> > > 
> > > > 
> > > > Fix mode transition logic in device.c:
> > > > - disable_devdax_device(): verify device is actually in devdax mode
> > > > - disable_famfs_device(): verify device is actually in famfs mode
> > > > - All reconfig_mode_*() functions now explicitly check each mode
> > > > - Handle unknown mode with error instead of wrong assumption
> > > 
> > > Wondering about 'Fix' mode transition logic. Was prior logic broken and
> > > should any of these changes be in a precursor patch that is a 'fix'.
> > > 
> > > 
> > > > 
> > > > Modify json.c to show 'unknown' if device is not in a recognized mode.
> > > 
> > > I think this means disabled devices will always look unknown even when
> > > the intended mode is devdax or famfs, but disabled. This seems to
> > > change the meaning of mode from 'configured' to 'active' personality.
> > > Can you detect the configured mode even when disabled?
> > > Perhaps a man page change about this new behavior?
> > 
> > Good point; before famfs mode there were just 2 modes, and 
> > not-system-ram == devdax mode is the current standard, even if no driver 
> > is bound. At some level that's a conflation, but I'll revise and stick 
> > with that unless you have a better idea.
> > 
> > Is that how you want it? No driver == devdax mode?
> > 
> > Any thoughts?
> > 
> 
> I do think we need to introduce "unknown" rather than keep reporting
> devdax for all non-system-ram devices. With famfs added, that old
> "not system-ram == devdax" shortcut just isn’t true anymore, and in the
> unbound case we really don’t know if it’s devdax or famfs. I’d rather say
> "unknown" than guess wrong.

While I like the explicit nature of 'unknown' we are unfortunately past
that point now.

Current users expect a new device to come up as devdax.  I think a new
specifier needs to be added to bring a device up as famfs.  Because this
is the new way of doing things it may be that famfs needs to be specified
explicitly somewhere.  I'm not quite sure where right off.

But the current behavior needs to be maintained despite it being 'wrong'
or a 'lie'...  It is just the way it was.

Ira

> 
> That said, I don’t think we should drop to "unknown" when we actually do
> know the mode. In particular, disable shouldn’t cause us to lose it. We
> already report state separately, so I’d expect something like this:
> 	mode=devdax,  state=disabled
> and not like this:
> 	mode=unknown, state=disabled
> for a device that we knew was devdax (same idea for famfs).
> 
> Also wondering about behavior here: if a device ends up in mode="unknown",
> what does enable-device do? It doesn’t take a mode, so if we’ve lost that
> info across disable it’s not obvious how we pick which driver to bind.
> Before famfs we kind of got away with defaulting to devdax, but that
> doesn’t really work anymore.
> 
> So I think the rule should be: report a real mode when we can, and only
> use "unknown" when it’s actually ambiguous. That keeps disable/enable
> workflows predictable.
> 
> And if we do introduce "unknown", we need to document when it shows up,
> since this is a change from the old behavior.
> 
> -- Alison
> 
> snipping here, I didn't see any questions or comments below here
> expect for the done on the PATH_MAX usage.
> 
> 



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH V4 1/2] daxctl: Add support for famfs mode
  2026-04-28 19:14               ` Ira Weiny
@ 2026-04-28 20:06                 ` John Groves
  0 siblings, 0 replies; 12+ messages in thread
From: John Groves @ 2026-04-28 20:06 UTC (permalink / raw)
  To: Ira Weiny, Alison Schofield, John Groves
  Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
	John Groves (jgroves), Jonathan Corbet, 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, 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 Tue, Apr 28, 2026, at 2:14 PM, Ira Weiny wrote:
> Alison Schofield wrote:
> > On Sun, Apr 26, 2026 at 06:56:46PM -0500, John Groves wrote:
> > > Maybe I'm overcomplicating things (it's one of the things I do), 
> > > but I'm still struggling through how to address all these issues. 
> > > Some comments inline.
> > 
> > 
> > Jumping to the part you commented on, which I think was the biggie:
> > 
> > > 
> > > On 26/02/26 06:00PM, Alison Schofield wrote:
> > > > On Sun, Jan 18, 2026 at 10:36:38PM +0000, John Groves wrote:
> > > > > From: John Groves <John@Groves.net>
> > > > > 
> > > > > Putting a daxdev in famfs mode means binding it to fsdev_dax.ko
> > > > > (drivers/dax/fsdev.c). Finding a daxdev bound to fsdev_dax means
> > > > > it is in famfs mode.
> > > > > 
> > > > > The test is added to the destructive test suite since it
> > > > > modifies device modes.
> > > > 
> > > > Make it clear that it is added in a separate patch. (and assume you
> > > > can drop the destructive part too.)
> > > > 
> > > > > 
> > > > > With devdax, famfs, and system-ram modes, the previous logic that assumed
> > > > > 'not in mode X means in mode Y' needed to get slightly more complicated
> > > > > 
> > > > > Add explicit mode detection functions:
> > > > > - daxctl_dev_is_famfs_mode(): check if bound to fsdev_dax driver
> > > > > - daxctl_dev_is_devdax_mode(): check if bound to device_dax driver
> > > > 
> > > > 
> > > > The precedence check (ram->famfs->devdax->unknown) now happens in multiple
> > > > places. How about adding a daxctl_dev_get_mode() helper to centralize that.
> > > > It could be private for now, unless you expect external users to need it.
> > > > 
> > > > daxctl_dev_is_famfs_mode() and _is_devdax_mode() are nearly identical aside
> > > > from the module name. Refactoring the shared part into a single helper will
> > > > also make it easier to add a daxctl_dev_get_mode() without duplicating the
> > > > precedence logic.
> > > > 
> > > > > 
> > > > > Fix mode transition logic in device.c:
> > > > > - disable_devdax_device(): verify device is actually in devdax mode
> > > > > - disable_famfs_device(): verify device is actually in famfs mode
> > > > > - All reconfig_mode_*() functions now explicitly check each mode
> > > > > - Handle unknown mode with error instead of wrong assumption
> > > > 
> > > > Wondering about 'Fix' mode transition logic. Was prior logic broken and
> > > > should any of these changes be in a precursor patch that is a 'fix'.
> > > > 
> > > > 
> > > > > 
> > > > > Modify json.c to show 'unknown' if device is not in a recognized mode.
> > > > 
> > > > I think this means disabled devices will always look unknown even when
> > > > the intended mode is devdax or famfs, but disabled. This seems to
> > > > change the meaning of mode from 'configured' to 'active' personality.
> > > > Can you detect the configured mode even when disabled?
> > > > Perhaps a man page change about this new behavior?
> > > 
> > > Good point; before famfs mode there were just 2 modes, and 
> > > not-system-ram == devdax mode is the current standard, even if no driver 
> > > is bound. At some level that's a conflation, but I'll revise and stick 
> > > with that unless you have a better idea.
> > > 
> > > Is that how you want it? No driver == devdax mode?
> > > 
> > > Any thoughts?
> > > 
> > 
> > I do think we need to introduce "unknown" rather than keep reporting
> > devdax for all non-system-ram devices. With famfs added, that old
> > "not system-ram == devdax" shortcut just isn’t true anymore, and in the
> > unbound case we really don’t know if it’s devdax or famfs. I’d rather say
> > "unknown" than guess wrong.
> 
> While I like the explicit nature of 'unknown' we are unfortunately past
> that point now.
> 
> Current users expect a new device to come up as devdax.  I think a new
> specifier needs to be added to bring a device up as famfs.  Because this
> is the new way of doing things it may be that famfs needs to be specified
> explicitly somewhere.  I'm not quite sure where right off.
> 
> But the current behavior needs to be maintained despite it being 'wrong'
> or a 'lie'...  It is just the way it was.
> 
> Ira

I think for famfs it's easier than that. The famfs tools already put it in famfs
mode when needed. I don't think it ever needs to have a sticky default
to anything but devdax.

The following famfs operations already check and change the mode 
if necessary:

- famfs mount
- mkfs.famfs
- famfs fsck /dev/dax0.0 

So I don't see any problem with preserving the existing quirkiness.

I'll get a patch v5 out asap that continues to mark unbound daxdev as
'devdax' and also 'disabled'. No change to system-ram mode. 

I think this might be all we need...

<snip>

John

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-04-28 20:07 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <0100019bd33a16b4-6da11a99-d883-4cfc-b561-97973253bc4a-000000@email.amazonses.com>
     [not found] ` <20260118223548.92823-1-john@jagalactic.com>
     [not found]   ` <0100019bd34040d9-0b6e9e4c-ecd4-464d-ab9d-88a251215442-000000@email.amazonses.com>
2026-02-09 23:13     ` [PATCH V4 0/2] ndctl: Add daxctl support for the new "famfs" mode of devdax Alison Schofield
2026-02-11 14:31       ` John Groves
     [not found]     ` <20260118223629.92852-1-john@jagalactic.com>
     [not found]       ` <0100019bd340cdd5-89036a70-3ef5-4c34-abf8-07a3ea4d9f92-000000@email.amazonses.com>
2026-02-19 21:47         ` [PATCH V4 1/2] daxctl: Add support for famfs mode Dave Jiang
2026-02-27  2:00         ` Alison Schofield
2026-04-20 23:17           ` Alison Schofield
2026-04-21  1:47             ` John Groves
2026-04-22 18:09               ` Ira Weiny
2026-04-26 23:56           ` John Groves
2026-04-28  4:38             ` Alison Schofield
2026-04-28 19:14               ` Ira Weiny
2026-04-28 20:06                 ` John Groves
     [not found]     ` <20260118223640.92878-1-john@jagalactic.com>
     [not found]       ` <0100019bd340f73c-90b0fafb-786e-4368-85f0-149ffa1d637a-000000@email.amazonses.com>
2026-02-19 22:02         ` [PATCH V4 2/2] Add test/daxctl-famfs.sh to test famfs mode transitions: Dave Jiang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox