[PATCH V11 0/9] famfs: port into fuse

John Groves <[email protected]> Mon, 20 Jul 2026 03:44:08 +0000
Newsgroups dev.linux.lists.fuse-devel,dev.linux.lists.nvdimm,org.kernel.vger.linux-cxl,org.kernel.vger.linux-doc,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel
Message-ID <0100019f7d9fbe81-6cb16662-2522-47ea-a152-fab0ee3d9b35-000000@email.amazonses.com>
From: John Groves <[email protected]>=0D=0A=0D=0AThis has been quite a gaun=
tlet so far. Some requests were made but eventually=0D=0Aruled out (e.g. =
using BPF for fault handling).=20=0D=0A=0D=0AConcrete requests (demands=3F=
) from the fuse community included the following:=0D=0A- Pass daxdevs int=
o the kernel via an ioctl rather than a new fuse=0D=0A  message/response=0D=
=0A- Lose the famfs interleaved extent format. I have complied with this =
request.=0D=0A  It makes some things worse, but we'll discuss that later.=
=0D=0A=0D=0AThere has also been a desire from the fuse community for famf=
s to use an=0D=0Aexperimental implementation of virtual backing-devs from=
 Darrick. I'm leaving=0D=0Athis out as a potential future optimization - =
although Darrick has announced=0D=0Athat he (and $employer) intend to aba=
ndon that work, so it's not clear whether=0D=0Athat will become viable.=0D=
=0A=0D=0ANOTE: the dax support that famfs requires (devdax fs-dax / fsdev=
) is now in=0D=0Aupstream Linux, so this series no longer depends on a bu=
ndled or out-of-tree=0D=0Adax patch set - it applies on mainline. (It cur=
rently uses the upstream=0D=0Adax_dev_get(); a follow-on will switch to d=
ax_dev_find() once that helper is=0D=0Aupstream too - see "Changes v10 ->=
 v11" below.) There are a few orthogonal=0D=0Afix patches for the devdax =
stack, and one that will trigger a patch to this=0D=0Acode (changing from=
 dax_get_get() to dax_dev_find()). I'll patch this code=0D=0Awhen that fi=
x lands.=0D=0A=0D=0AChanges v10 -> v11=0D=0A- The dax support famfs depen=
ds on is now upstream, so this series no longer=0D=0A  carries or depends=
 on a bundled dax patch set (v10 was based on Ira's=0D=0A  for-7.1/dax-fa=
mfs branch [0]); v11 applies on mainline.=0D=0A- Dropped the controversia=
l famfs interleaved extent format structures from=0D=0A  the ABI.=0D=0A- =
Daxdev acquisition changed from a fuse message to an ioctl. The=0D=0A  GE=
T_DAXDEV message/response (kernel pulls a daxdev by pathname) has been=0D=
=0A  replaced by FUSE_DEV_IOC_DAXDEV_OPEN: the fuse server now pushes eac=
h=0D=0A  daxdev to the kernel by fd, and the kernel resolves it and acqui=
res it=0D=0A  exclusively via fs_dax_get(). This removes the GET_DAXDEV m=
essage plumbing=0D=0A  (patch "famfs_fuse: GET_DAXDEV message and daxdev_=
table" becomes=0D=0A  "fuse: register fs-dax daxdevs via FUSE_DEV_IOC_DAX=
DEV_OPEN").=0D=0A- New patch "famfs_fuse: fail I/O on invalid or errored =
daxdevs": the iomap=0D=0A  resolution path now gates on the state of the =
backing daxdev (slot never=0D=0A  installed, exclusive acquire failed, or=
 a memory error was reported via=0D=0A  notify_failure) and fails the acc=
ess (-EIO / -EHWPOISON) rather than=0D=0A  mapping it.=0D=0A- Removed FUS=
E_FAMFS_MAX_EXTENTS. A GET_FMAP reply is now bounded by the=0D=0A  reply =
buffer size rather than a separate extent-count cap.=0D=0A- Code-review p=
ass over the whole series (self-review of every patch).=0D=0A=0D=0A=0D=0A=
Description:=0D=0A=0D=0AThis patch series introduces famfs into the fuse =
file system framework.=0D=0AThe dax support that famfs relies on is now u=
pstream.=0D=0A=0D=0AThe famfs user space code can be found at [1].=0D=0A=0D=
=0AFuse Overview:=0D=0A=0D=0AFamfs started as a standalone file system, b=
ut this series is intended to=0D=0Apermanently supersede that implementat=
ion. At a high level, famfs adds one=0D=0Anew fuse server message plus on=
e device ioctl:=0D=0A=0D=0AGET_FMAP                 - Retrieves a famfs f=
map (the file-to-dax map for a=0D=0A                           famfs file=
)=0D=0AFUSE_DEV_IOC_DAXDEV_OPEN - The fuse server pushes a daxdev (by fd)=
 that was=0D=0A                           referenced by an fmap, so the k=
ernel can acquire=0D=0A                           it=0D=0A=0D=0AFamfs Ove=
rview=0D=0A=0D=0AFamfs exposes shared memory as a file system. Famfs cons=
umes shared=0D=0Amemory from dax devices, and provides memory-mappable fi=
les that map=0D=0Adirectly to the memory - no page cache involvement. Fam=
fs differs from=0D=0Aconventional file systems in fs-dax mode, in that it=
 handles in-memory=0D=0Ametadata in a sharable way (which begins with nev=
er caching dirty shared=0D=0Ametadata).=0D=0A=0D=0AFamfs started as a sta=
ndalone file system [2,3], but the consensus at=0D=0ALSFMM was that it sh=
ould be ported into fuse [4,5].=0D=0A=0D=0AThe key performance requiremen=
t is that famfs must resolve mapping faults=0D=0Awithout upcalls. This is=
 achieved by fully caching the file-to-devdax=0D=0Ametadata for all activ=
e files. The fmap is retrieved via the GET_FMAP=0D=0Amessage/response; th=
e daxdevs an fmap references are registered by the=0D=0Aserver via the FU=
SE_DEV_IOC_DAXDEV_OPEN ioctl.=0D=0A=0D=0AFamfs remains the first fs-dax f=
ile system that is backed by devdax=0D=0Arather than pmem in fs-dax mode =
(hence the need for the new dax mode).=0D=0A=0D=0ANotes=0D=0A=0D=0A- When=
 a file is opened in a famfs mount, the OPEN is followed by a=0D=0A  GET_=
FMAP message and response. The "fmap" is the full file-to-dax=0D=0A  mapp=
ing, allowing the fuse/famfs kernel code to handle=0D=0A  read/write/faul=
t without any upcalls.=0D=0A=0D=0A- Each fmap is checked for extents that=
 reference previously-unknown=0D=0A  daxdevs. The fuse server registers e=
ach such daxdev with the kernel=0D=0A  via the FUSE_DEV_IOC_DAXDEV_OPEN i=
octl (passing an fd to the devdax=0D=0A  device), rather than the kernel =
pulling it by name.=0D=0A=0D=0A- Daxdevs are stored in a table (which mig=
ht become an xarray at some=0D=0A  point). When entries are added to the =
table, we acquire exclusive=0D=0A  access to the daxdev via the fs_dax_ge=
t() call (modeled after how=0D=0A  fs-dax handles this with pmem devices)=
=2E Famfs provides=0D=0A  holder_operations to devdax, providing a notifi=
cation path in the=0D=0A  event of memory errors or forced reconfiguratio=
n.=0D=0A=0D=0A- If devdax notifies famfs of memory errors on a dax device=
, famfs=0D=0A  currently blocks all subsequent accesses to data on that d=
evice. The=0D=0A  recovery is to re-initialize the memory and file system=
=2E Famfs is=0D=0A  memory, not storage...=0D=0A=0D=0A- Because famfs use=
s backing (devdax) devices, only privileged mounts are=0D=0A  supported (=
i.e. the fuse server requires CAP_SYS_RAWIO).=0D=0A=0D=0A- The famfs kern=
el code never accesses the memory directly - it only=0D=0A  facilitates r=
ead, write and mmap on behalf of user processes, using=0D=0A  fmap metada=
ta provided by its privileged fuse server. As such, the=0D=0A  RAS of the=
 shared memory affects applications, but not the kernel.=0D=0A=0D=0A- Fam=
fs has backing device(s), but they are devdax (char) rather than=0D=0A  b=
lock. Right now there is no way to tell the vfs layer that famfs has a=0D=
=0A  char backing device (unless we say it's block, but it's not). Curren=
tly=0D=0A  we use the standard anonymous fuse fs_type - but I'm not sure =
that's=0D=0A  ultimately optimal (thoughts=3F)=0D=0A=0D=0AChanges v9 -> v=
10=0D=0A- Rebased to Ira's for-7.1/dax-famfs branch [0], which contains t=
he required=0D=0A  dax patches=0D=0A- Add parentheses to FUSE_IS_VIRTIO_D=
AX() macro, in case something bad is=0D=0A  passed in as fuse_inode (than=
ks Jonathan's AI)=0D=0A=0D=0AChanges v8 -> v9=0D=0A- Kconfig: fs/fuse/Kco=
nfig:CONFIG_FUSE_FAMFS_DAX now depends on the=0D=0A  new CONFIG_DEV_DAX_F=
SDEV (from drivers/dax/Kconfig) rather than=0D=0A  just CONFIG_DEV_DAX an=
d CONFIG_FS_DAX. (CONFIG_FUSE_FAMFS_DAX=0D=0A  depends on those...)=0D=0A=
=0D=0AChanges v7 -> v8=0D=0A- Moved to inline __free declaration in fuse_=
get_fmap() and=0D=0A  famfs_fuse_meta_alloc(), famfs_teardown()=0D=0A- Ad=
opted FIELD_PREP() macro rather than manual bitfield manipulation=0D=0A- =
Minor doc edits=0D=0A- I dropped adding magic numbers to include/uapi/lin=
ux/magic.h. That=0D=0A  can be done later if appropriate=0D=0A=0D=0AChang=
es v6 -> v7=0D=0A- Fixed a regression in famfs_interleave_fileofs_to_daxo=
fs() that=0D=0A  was reported by Intel's kernel test robot=0D=0A- Added a=
 check in __fsdev_dax_direct_access() for negative return=0D=0A  from pgo=
ff_to_phys(), which would indicate an out-of-range offset=0D=0A- Fixed a =
bug in __famfs_meta_free(), where not all interleaved=0D=0A  extents were=
 freed=0D=0A- Added chunksize alignment checks in famfs_fuse_meta_alloc()=
 and=0D=0A  famfs_interleave_fileofs_to_daxofs() as interleaved chunks mu=
st=0D=0A  be PTE or PMD aligned=0D=0A- Simplified famfs_file_init_dax() a=
 bit=0D=0A- Re-ran CM's kernel code review prompts on the entire series a=
nd=0D=0A  fixed several minor issues=0D=0A=0D=0AChanges v4 -> v5 -> v6=0D=
=0A- None. Re-sending due to technical difficulties=0D=0A=0D=0AChanges v3=
 [9] -> v4=0D=0A- The patch "dax: prevent driver unbind while filesystem =
holds device"=0D=0A  has been dropped. Dan Williams indicated that the fa=
vored behavior is=0D=0A  for a file system to stop working if an underlyi=
ng driver is unbound,=0D=0A  rather than preventing the unbind.=0D=0A- Th=
e patch "famfs_fuse: Famfs mount opt: -o shadow=3D<shadowpath>" has=0D=0A=
  been dropped. Found a way for the famfs user space to do without the=0D=
=0A  -o opt (via getxattr).=0D=0A- Squashed the fs/fuse/Kconfig patch int=
o the first subsequent patch=0D=0A  that needed the change=0D=0A  ("famfs=
_fuse: Basic fuse kernel ABI enablement for famfs")=0D=0A- Many review co=
mments addressed.=0D=0A- Addressed minor kerneldoc infractions reported b=
y test robot.=0D=0A=0D=0AChanges v2 [7] -> v3=0D=0A- Dax: Completely new =
fsdev driver (drivers/dax/fsdev.c) replaces the=0D=0A  dev_dax_iomap modi=
fications to bus.c/device.c. Devdax devices can now=0D=0A  be switched am=
ong 'devdax', 'famfs' and 'system-ram' modes via daxctl=0D=0A  or sysfs.=0D=
=0A- Dax: fsdev uses MEMORY_DEVICE_FS_DAX type and leaves folios at order=
-0=0D=0A  (no vmemmap_shift), allowing fs-dax to manage folio lifecycles=0D=
=0A  dynamically like pmem does.=0D=0A- Dax: The "poisoned page" problem =
is properly fixed via=0D=0A  fsdev_clear_folio_state(), which clears stal=
e mapping/compound state=0D=0A  when fsdev binds. The temporary WARN_ON_O=
NCE workaround in fs/dax.c=0D=0A  has been removed.=0D=0A- Dax: Added dax=
_set_ops() so fsdev can set dax_operations at bind time=0D=0A  (and clear=
 them on unbind), since the dax_device is created before we=0D=0A  know w=
hich driver will bind.=0D=0A- Dax: Added custom bind/unbind sysfs handler=
s; unbind return -EBUSY if a=0D=0A  filesystem holds the device, preventi=
ng unbind while famfs is mounted.=0D=0A- Fuse: Famfs mounts now require t=
hat the fuse server/daemon has=0D=0A  CAP_SYS_RAWIO because they expose r=
aw memory devices.=0D=0A- Fuse: Added DAX address_space_operations with n=
oop_dirty_folio since=0D=0A  famfs is memory-backed with no writeback req=
uired.=0D=0A- Rebased to latest kernels, fully compatible with Alistair P=
opple=0D=0A  et. al's recent dax refactoring.=0D=0A- Ran this series thro=
ugh Chris Mason's code review AI prompts to check=0D=0A  for issues - sev=
eral subtle problems found and fixed.=0D=0A- Dropped RFC status - this ve=
rsion is intended to be mergeable.=0D=0A=0D=0AChanges v1 [8] -> v2:=0D=0A=
=0D=0A- The GET_FMAP message/response has been moved from LOOKUP to OPEN,=
 as=0D=0A  was the pretty much unanimous consensus.=0D=0A- Made the respo=
nse payload to GET_FMAP variable sized (patch 12)=0D=0A- Dodgy kerneldoc =
comments cleaned up or removed.=0D=0A- Fixed memory leak of fc->shadow in=
 patch 11 (thanks Joanne)=0D=0A- Dropped many pr_debug and pr_notice call=
s=0D=0A=0D=0A=0D=0AReferences=0D=0A=0D=0A[0] - https://git.kernel.org/pub=
/scm/linux/kernel/git/nvdimm/nvdimm.git/=0D=0A[1] - https://famfs.org (fa=
mfs user space)=0D=0A[2] - https://lore.kernel.org/linux-cxl/cover.170870=
[email protected]/=0D=0A[3] - https://lore.kernel.org/linux-cxl/co=
[email protected]/=0D=0A[4] - https://lwn.net/Articles/9=
83105/ (lsfmm 2024)=0D=0A[5] - https://lwn.net/Articles/1020170/ (lsfmm 2=
025)=0D=0A[6] - https://lore.kernel.org/linux-cxl/cover.8068ad144a7eea4a8=
[email protected]/=0D=0A[7=
] - https://lore.kernel.org/linux-fsdevel/20250703185032.46568-1-john@gro=
ves.net/ (famfs fuse v2)=0D=0A[8] - https://lore.kernel.org/linux-fsdevel=
/[email protected]/ (famfs fuse v1)=0D=0A[9] - https=
://lore.kernel.org/linux-fsdevel/[email protected]/T=
/#mb2c868801be16eca82dab239a1d201628534aea7 (famfs fuse v3)=0D=0A[10] - [=
TODO: John - famfs fuse v10 lore link]=0D=0A=0D=0A=0D=0AJohn Groves (9):=0D=
=0A  famfs_fuse: Update macro s/FUSE_IS_DAX/FUSE_IS_VIRTIO_DAX/=0D=0A  fa=
mfs_fuse: Basic fuse kernel ABI enablement for famfs=0D=0A  famfs_fuse: P=
lumb the GET_FMAP message/response=0D=0A  famfs_fuse: Create files with f=
amfs fmaps=0D=0A  famfs_fuse: register fs-dax daxdevs via FUSE_DEV_IOC_DA=
XDEV_OPEN=0D=0A  famfs_fuse: Plumb dax iomap and fuse read/write/mmap=0D=0A=
  famfs_fuse: fail I/O on invalid or errored daxdevs=0D=0A  famfs_fuse: A=
dd DAX address_space_operations with noop_dirty_folio=0D=0A  famfs_fuse: =
Add documentation=0D=0A=0D=0A Documentation/filesystems/famfs.rst |  143 =
++++=0D=0A Documentation/filesystems/index.rst |    1 +=0D=0A MAINTAINERS=
                         |    9 +=0D=0A fs/fuse/Kconfig                  =
   |   13 +=0D=0A fs/fuse/Makefile                    |    1 +=0D=0A fs/f=
use/dev.c                       |   31 +=0D=0A fs/fuse/dev.h             =
          |    1 +=0D=0A fs/fuse/dir.c                       |    2 +-=0D=
=0A fs/fuse/famfs.c                     | 1066 ++++++++++++++++++++++++++=
+=0D=0A fs/fuse/famfs_kfmap.h               |   91 +++=0D=0A fs/fuse/file=
=2Ec                      |   48 +-=0D=0A fs/fuse/fuse_i.h               =
     |  125 +++-=0D=0A fs/fuse/inode.c                     |   35 +-=0D=0A=
 fs/fuse/iomode.c                    |    2 +-=0D=0A include/uapi/linux/f=
use.h           |   55 +-=0D=0A 15 files changed, 1608 insertions(+), 15 =
deletions(-)=0D=0A create mode 100644 Documentation/filesystems/famfs.rst=
=0D=0A create mode 100644 fs/fuse/famfs.c=0D=0A create mode 100644 fs/fus=
e/famfs_kfmap.h=0D=0A=0D=0A--=20=0D=0A2.53.0=0D=0A=0D=0A