From: John Groves <[email protected]>

Gate the iomap resolution path on the state of the daxdev backing each
referenced extent. famfs_dax_err() returns an error if the daxdev slot is
invalid (-EIO), was flagged dax_err (-EIO), or has reported a memory error
via notify_failure (-EHWPOISON). famfs_fileofs_to_daxofs() calls it and,
on error, marks the file (meta->error) and stops allowing access.

Memory errors are at least somewhat more likely on disaggregated memory
than on-board memory. In general the recovery is to unmount and
re-initialize the memory, though degraded modes may be possible in the
future when famfs supports file systems backed by more than one daxdev
(data on a working daxdev can still be accessed). For now, return errors
for any file that has touched an invalid or errored daxdev.

Signed-off-by: John Groves <[email protected]>
---
 fs/fuse/famfs.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/fs/fuse/famfs.c b/fs/fuse/famfs.c
index ac56317944d9..8d13282e8949 100644
--- a/fs/fuse/famfs.c
+++ b/fs/fuse/famfs.c
@@ -589,6 +589,26 @@ famfs_file_init_dax(
 
 static int famfs_file_bad(struct inode *inode);
 
+static int famfs_dax_err(struct famfs_daxdev *dd)
+{
+       if (!dd->valid) {
+               pr_err("%s: daxdev=%s invalid\n",
+                      __func__, dd->name);
+               return -EIO;
+       }
+       if (dd->dax_err) {
+               pr_err("%s: daxdev=%s dax_err\n",
+                      __func__, dd->name);
+               return -EIO;
+       }
+       if (dd->error) {
+               pr_err("%s: daxdev=%s memory error\n",
+                      __func__, dd->name);
+               return -EHWPOISON;
+       }
+       return 0;
+}
+
 /**
  * famfs_fileofs_to_daxofs() - Resolve (file, offset, len) to (daxdev, offset, 
len)
  *
@@ -661,6 +681,7 @@ famfs_fileofs_to_daxofs(struct inode *inode, struct iomap 
*iomap,
                u64 daxdev_idx           = meta->se[i].dev_index;
                loff_t ext_len_remainder = dax_ext_len - local_offset;
                struct famfs_daxdev *dd;
+               int rc;
 
                if (daxdev_idx >= fc->dax_devlist->nslots) {
                        pr_err("%s: daxdev_idx %llu >= nslots %d\n",
@@ -670,6 +691,13 @@ famfs_fileofs_to_daxofs(struct inode *inode, struct iomap 
*iomap,
 
                dd = &fc->dax_devlist->devlist[daxdev_idx];
 
+               rc = famfs_dax_err(dd);
+               if (rc) {
+                       /* Shut down access to this file */
+                       meta->error = true;
+                       return rc;
+               }
+
                iomap->addr    = dax_ext_offset + local_offset;
                iomap->offset  = file_offset;
                iomap->length  = min_t(loff_t, len, ext_len_remainder);
-- 
2.53.0



Reply via email to