If we get a notify_failure() call on a daxdev, set its error flag and prevent further access to that device.
Signed-off-by: John Groves <j...@groves.net> --- fs/fuse/famfs.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/fs/fuse/famfs.c b/fs/fuse/famfs.c index 1973eb10b60b..62c01d5b9d78 100644 --- a/fs/fuse/famfs.c +++ b/fs/fuse/famfs.c @@ -20,6 +20,26 @@ #include "famfs_kfmap.h" #include "fuse_i.h" +static void famfs_set_daxdev_err( + struct fuse_conn *fc, struct dax_device *dax_devp); + +static int +famfs_dax_notify_failure(struct dax_device *dax_devp, u64 offset, + u64 len, int mf_flags) +{ + struct fuse_conn *fc = dax_holder(dax_devp); + + famfs_set_daxdev_err(fc, dax_devp); + + return 0; +} + +static const struct dax_holder_operations famfs_fuse_dax_holder_ops = { + .notify_failure = famfs_dax_notify_failure, +}; + +/*****************************************************************************/ + /* * famfs_teardown() * @@ -164,6 +184,15 @@ famfs_fuse_get_daxdev(struct fuse_mount *fm, const u64 index) goto out; } + err = fs_dax_get(daxdev->devp, fc, &famfs_fuse_dax_holder_ops); + if (err) { + up_write(&fc->famfs_devlist_sem); + pr_err("%s: fs_dax_get(%lld) failed\n", + __func__, (u64)daxdev->devno); + err = -EBUSY; + goto out; + } + daxdev->name = kstrdup(daxdev_out.name, GFP_KERNEL); wmb(); /* all daxdev fields must be visible before marking it valid */ daxdev->valid = 1; @@ -243,6 +272,38 @@ famfs_update_daxdev_table( return 0; } +static void +famfs_set_daxdev_err( + struct fuse_conn *fc, + struct dax_device *dax_devp) +{ + int i; + + /* Gotta search the list by dax_devp; + * read lock because we're not adding or removing daxdev entries + */ + down_read(&fc->famfs_devlist_sem); + for (i = 0; i < fc->dax_devlist->nslots; i++) { + if (fc->dax_devlist->devlist[i].valid) { + struct famfs_daxdev *dd = &fc->dax_devlist->devlist[i]; + + if (dd->devp != dax_devp) + continue; + + dd->error = true; + up_read(&fc->famfs_devlist_sem); + + pr_err("%s: memory error on daxdev %s (%d)\n", + __func__, dd->name, i); + goto done; + } + } + up_read(&fc->famfs_devlist_sem); + pr_err("%s: memory err on unrecognized daxdev\n", __func__); + +done: +} + /***************************************************************************/ void @@ -631,6 +692,7 @@ famfs_interleave_fileofs_to_daxofs(struct inode *inode, struct iomap *iomap, /* Is the data is in this striped extent? */ if (local_offset < ext_size) { + struct famfs_daxdev *dd; u64 chunk_num = local_offset / chunk_size; u64 chunk_offset = local_offset % chunk_size; u64 stripe_num = chunk_num / nstrips; @@ -640,9 +702,11 @@ famfs_interleave_fileofs_to_daxofs(struct inode *inode, struct iomap *iomap, u64 strip_dax_ofs = fei->ie_strips[strip_num].ext_offset; u64 strip_devidx = fei->ie_strips[strip_num].dev_index; - if (!fc->dax_devlist->devlist[strip_devidx].valid) { - pr_err("%s: daxdev=%lld invalid\n", __func__, - strip_devidx); + dd = &fc->dax_devlist->devlist[strip_devidx]; + if (!dd->valid || dd->error) { + pr_err("%s: daxdev=%lld %s\n", __func__, + strip_devidx, + dd->valid ? "error" : "invalid"); goto err_out; } iomap->addr = strip_dax_ofs + strip_offset; -- 2.49.0