From fa5eee57e33e79b71b40e6950c29cc46f5cc5cb7 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 22 Oct 2021 17:03:02 +0200 Subject: [PATCH] fuse: selective attribute invalidation Only invalidate attributes that the operation might have changed. Introduce two constants for common combinations of changed attributes: FUSE_STATX_MODIFY: file contents are modified but not size FUSE_STATX_MODSIZE: size and/or file contents modified Signed-off-by: Miklos Szeredi --- fs/fuse/dax.c | 2 +- fs/fuse/dir.c | 4 ++-- fs/fuse/file.c | 16 ++++++++-------- fs/fuse/fuse_i.h | 8 ++++++++ 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/fs/fuse/dax.c b/fs/fuse/dax.c index 281d79f..89bf96f 100644 --- a/fs/fuse/dax.c +++ b/fs/fuse/dax.c @@ -735,7 +735,7 @@ static ssize_t fuse_dax_direct_write(struct kiocb *iocb, struct iov_iter *from) if (ret < 0) return ret; - fuse_invalidate_attr(inode); + fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE); fuse_write_update_size(inode, iocb->ki_pos); return ret; } diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 26587af..8315ca7 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -116,7 +116,7 @@ u64 entry_attr_timeout(struct fuse_entry_out *o) return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); } -static void fuse_invalidate_attr_mask(struct inode *inode, u32 mask) +void fuse_invalidate_attr_mask(struct inode *inode, u32 mask) { set_mask_bits(&get_fuse_inode(inode)->inval_mask, 0, mask); } @@ -756,7 +756,7 @@ static void fuse_update_ctime_in_cache(struct inode *inode) void fuse_update_ctime(struct inode *inode) { - fuse_invalidate_attr(inode); + fuse_invalidate_attr_mask(inode, STATX_CTIME); fuse_update_ctime_in_cache(inode); } diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 31266ca..06967d8 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -211,7 +211,7 @@ void fuse_finish_open(struct inode *inode, struct file *file) i_size_write(inode, 0); spin_unlock(&fi->lock); truncate_pagecache(inode, 0); - fuse_invalidate_attr(inode); + fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE); if (fc->writeback_cache) file_update_time(file); } else if (!(ff->open_flags & FOPEN_KEEP_CACHE)) { @@ -515,7 +515,7 @@ inval_attr_out: * enabled, i_blocks from cached attr may not be accurate. */ if (!err && fm->fc->writeback_cache) - fuse_invalidate_attr(inode); + fuse_invalidate_attr_mask(inode, STATX_BLOCKS); return err; } @@ -1266,7 +1266,7 @@ static ssize_t fuse_perform_write(struct kiocb *iocb, fuse_write_update_size(inode, pos); clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); - fuse_invalidate_attr(inode); + fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE); return res > 0 ? res : err; } @@ -1556,7 +1556,7 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) FUSE_DIO_WRITE); } } - fuse_invalidate_attr(inode); + fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE); if (res > 0) fuse_write_update_size(inode, iocb->ki_pos); inode_unlock(inode); @@ -1769,7 +1769,7 @@ static void fuse_writepage_end(struct fuse_mount *fm, struct fuse_args *args, * is enabled, we trust local ctime/mtime. */ if (!fc->writeback_cache) - fuse_invalidate_attr(inode); + fuse_invalidate_attr_mask(inode, FUSE_STATX_MODIFY); spin_lock(&fi->lock); rb_erase(&wpa->writepages_entry, &fi->writepages); while (wpa->next) { @@ -2875,7 +2875,7 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter) if (iov_iter_rw(iter) == WRITE) { ret = fuse_direct_io(io, iter, &pos, FUSE_DIO_WRITE); - fuse_invalidate_attr(inode); + fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE); } else { ret = __fuse_direct_read(io, iter, &pos); } @@ -2996,7 +2996,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) truncate_pagecache_range(inode, offset, offset + length - 1); - fuse_invalidate_attr(inode); + fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE); out: if (!(mode & FALLOC_FL_KEEP_SIZE)) @@ -3109,7 +3109,7 @@ static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in, file_update_time(file_out); } - fuse_invalidate_attr(inode_out); + fuse_invalidate_attr_mask(inode_out, FUSE_STATX_MODSIZE); err = outarg.size; out: diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index a59e36c..4f2f658 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1065,7 +1065,15 @@ void fuse_wait_aborted(struct fuse_conn *fc); /** * Invalidate inode attributes */ + +/* Attributes possibly changed on data modification */ +#define FUSE_STATX_MODIFY (STATX_MTIME | STATX_CTIME | STATX_BLOCKS) + +/* Attributes possibly changed on data and/or size modification */ +#define FUSE_STATX_MODSIZE (FUSE_STATX_MODIFY | STATX_SIZE) + void fuse_invalidate_attr(struct inode *inode); +void fuse_invalidate_attr_mask(struct inode *inode, u32 mask); void fuse_invalidate_entry_cache(struct dentry *entry); -- 2.7.4