[PATCH V11 7/9] famfs_fuse: fail I/O on invalid or errored daxdevs

John Groves <[email protected]> Mon, 20 Jul 2026 03:46:35 +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 <0100019f7da1faa3-75c84002-18fc-4762-a69c-ef33d15a449d-000000@email.amazonses.com>
From: John Groves <[email protected]>=0D=0A=0D=0AGate the iomap resolution =
path on the state of the daxdev backing each=0D=0Areferenced extent. famf=
s_dax_err() returns an error if the daxdev slot is=0D=0Ainvalid (-EIO), w=
as flagged dax_err (-EIO), or has reported a memory error=0D=0Avia notify=
_failure (-EHWPOISON). famfs_fileofs_to_daxofs() calls it and,=0D=0Aon er=
ror, marks the file (meta->error) and stops allowing access.=0D=0A=0D=0AM=
emory errors are at least somewhat more likely on disaggregated memory=0D=
=0Athan on-board memory. In general the recovery is to unmount and=0D=0Ar=
e-initialize the memory, though degraded modes may be possible in the=0D=0A=
future when famfs supports file systems backed by more than one daxdev=0D=
=0A(data on a working daxdev can still be accessed). For now, return erro=
rs=0D=0Afor any file that has touched an invalid or errored daxdev.=0D=0A=
=0D=0ASigned-off-by: John Groves <[email protected]>=0D=0A---=0D=0A fs/fuse=
/famfs.c | 28 ++++++++++++++++++++++++++++=0D=0A 1 file changed, 28 inser=
tions(+)=0D=0A=0D=0Adiff --git a/fs/fuse/famfs.c b/fs/fuse/famfs.c=0D=0Ai=
ndex ac56317944d9..8d13282e8949 100644=0D=0A--- a/fs/fuse/famfs.c=0D=0A++=
+ b/fs/fuse/famfs.c=0D=0A@@ -589,6 +589,26 @@ famfs_file_init_dax(=0D=0A=20=
=0D=0A static int famfs_file_bad(struct inode *inode);=0D=0A=20=0D=0A+sta=
tic int famfs_dax_err(struct famfs_daxdev *dd)=0D=0A+{=0D=0A+=09if (!dd->=
valid) {=0D=0A+=09=09pr_err("%s: daxdev=3D%s invalid\n",=0D=0A+=09=09    =
   __func__, dd->name);=0D=0A+=09=09return -EIO;=0D=0A+=09}=0D=0A+=09if (=
dd->dax_err) {=0D=0A+=09=09pr_err("%s: daxdev=3D%s dax_err\n",=0D=0A+=09=09=
       __func__, dd->name);=0D=0A+=09=09return -EIO;=0D=0A+=09}=0D=0A+=09=
if (dd->error) {=0D=0A+=09=09pr_err("%s: daxdev=3D%s memory error\n",=0D=0A=
+=09=09       __func__, dd->name);=0D=0A+=09=09return -EHWPOISON;=0D=0A+=09=
}=0D=0A+=09return 0;=0D=0A+}=0D=0A+=0D=0A /**=0D=0A  * famfs_fileofs_to_d=
axofs() - Resolve (file, offset, len) to (daxdev, offset, len)=0D=0A  *=0D=
=0A@@ -661,6 +681,7 @@ famfs_fileofs_to_daxofs(struct inode *inode, struc=
t iomap *iomap,=0D=0A =09=09u64 daxdev_idx           =3D meta->se[i].dev_=
index;=0D=0A =09=09loff_t ext_len_remainder =3D dax_ext_len - local_offse=
t;=0D=0A =09=09struct famfs_daxdev *dd;=0D=0A+=09=09int rc;=0D=0A=20=0D=0A=
 =09=09if (daxdev_idx >=3D fc->dax_devlist->nslots) {=0D=0A =09=09=09pr_e=
rr("%s: daxdev_idx %llu >=3D nslots %d\n",=0D=0A@@ -670,6 +691,13 @@ famf=
s_fileofs_to_daxofs(struct inode *inode, struct iomap *iomap,=0D=0A=20=0D=
=0A =09=09dd =3D &fc->dax_devlist->devlist[daxdev_idx];=0D=0A=20=0D=0A+=09=
=09rc =3D famfs_dax_err(dd);=0D=0A+=09=09if (rc) {=0D=0A+=09=09=09/* Shut=
 down access to this file */=0D=0A+=09=09=09meta->error =3D true;=0D=0A+=09=
=09=09return rc;=0D=0A+=09=09}=0D=0A+=0D=0A =09=09iomap->addr    =3D dax_=
ext_offset + local_offset;=0D=0A =09=09iomap->offset  =3D file_offset;=0D=
=0A =09=09iomap->length  =3D min_t(loff_t, len, ext_len_remainder);=0D=0A=
--=20=0D=0A2.53.0=0D=0A=0D=0A