summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeffle Xu <jefflexu@linux.alibaba.com>2021-11-25 15:05:29 +0800
committerMiklos Szeredi <mszeredi@redhat.com>2021-12-14 11:09:37 +0100
commitc3cb6f935e322fa183988032e318b293d9e4fe53 (patch)
tree0c8d38c2b190aa597aa30ff98a9324f926bce7f5
parent2ee019fadcca343c3deea6a1767965bdf23fc3d0 (diff)
downloadlinux-stable-c3cb6f935e322fa183988032e318b293d9e4fe53.tar.gz
linux-stable-c3cb6f935e322fa183988032e318b293d9e4fe53.tar.bz2
linux-stable-c3cb6f935e322fa183988032e318b293d9e4fe53.zip
fuse: mark inode DONT_CACHE when per inode DAX hint changes
When the per inode DAX hint changes while the file is still *opened*, it is quite complicated and maybe fragile to dynamically change the DAX state. Hence mark the inode and corresponding dentries as DONE_CACHE once the per inode DAX hint changes, so that the inode instance will be evicted and freed as soon as possible once the file is closed and the last reference to the inode is put. And then when the file gets reopened next time, the new instantiated inode will reflect the new DAX state. In summary, when the per inode DAX hint changes for an *opened* file, the DAX state of the file won't be updated until this file is closed and reopened later. Signed-off-by: Jeffle Xu <jefflexu@linux.alibaba.com> Reviewed-by: Vivek Goyal <vgoyal@redhat.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--fs/fuse/dax.c9
-rw-r--r--fs/fuse/fuse_i.h1
-rw-r--r--fs/fuse/inode.c3
3 files changed, 13 insertions, 0 deletions
diff --git a/fs/fuse/dax.c b/fs/fuse/dax.c
index 663270dc6e20..182b24a14804 100644
--- a/fs/fuse/dax.c
+++ b/fs/fuse/dax.c
@@ -1361,6 +1361,15 @@ void fuse_dax_inode_init(struct inode *inode, unsigned int flags)
inode->i_data.a_ops = &fuse_dax_file_aops;
}
+void fuse_dax_dontcache(struct inode *inode, unsigned int flags)
+{
+ struct fuse_conn *fc = get_fuse_conn(inode);
+
+ if (fuse_is_inode_dax_mode(fc->dax_mode) &&
+ ((bool) IS_DAX(inode) != (bool) (flags & FUSE_ATTR_DAX)))
+ d_mark_dontcache(inode);
+}
+
bool fuse_dax_check_alignment(struct fuse_conn *fc, unsigned int map_alignment)
{
if (fc->dax && (map_alignment > FUSE_DAX_SHIFT)) {
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 6d63bd403a43..e8e59fbdefeb 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1296,6 +1296,7 @@ void fuse_dax_conn_free(struct fuse_conn *fc);
bool fuse_dax_inode_alloc(struct super_block *sb, struct fuse_inode *fi);
void fuse_dax_inode_init(struct inode *inode, unsigned int flags);
void fuse_dax_inode_cleanup(struct inode *inode);
+void fuse_dax_dontcache(struct inode *inode, unsigned int flags);
bool fuse_dax_check_alignment(struct fuse_conn *fc, unsigned int map_alignment);
void fuse_dax_cancel_work(struct fuse_conn *fc);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index c256fd82af3c..ee846ce371d8 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -301,6 +301,9 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
if (inval)
invalidate_inode_pages2(inode->i_mapping);
}
+
+ if (IS_ENABLED(CONFIG_FUSE_DAX))
+ fuse_dax_dontcache(inode, attr->flags);
}
static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)