diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2021-10-22 17:03:02 +0200 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2021-10-28 09:45:32 +0200 |
commit | d347739a0e760e9f370aa021da3feacc37d3e511 (patch) | |
tree | 7af86ada5e4c3f6dbb41103b0260fb9780d59104 | |
parent | 27ae449ba26eb6c1cd217fa28339841c55bc79e1 (diff) | |
download | linux-stable-d347739a0e760e9f370aa021da3feacc37d3e511.tar.gz linux-stable-d347739a0e760e9f370aa021da3feacc37d3e511.tar.bz2 linux-stable-d347739a0e760e9f370aa021da3feacc37d3e511.zip |
fuse: always invalidate attributes after writes
Extend the fuse_write_update_attr() helper to invalidate cached attributes
after a write.
This has already been done in all cases except in fuse_notify_store(), so
this is mostly a cleanup.
fuse_direct_write_iter() calls fuse_direct_IO() which already calls
fuse_write_update_attr(), so don't repeat that again in the former.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r-- | fs/fuse/dax.c | 5 | ||||
-rw-r--r-- | fs/fuse/dev.c | 2 | ||||
-rw-r--r-- | fs/fuse/file.c | 26 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 2 |
4 files changed, 15 insertions, 20 deletions
diff --git a/fs/fuse/dax.c b/fs/fuse/dax.c index a73bae6497b0..713818d74de6 100644 --- a/fs/fuse/dax.c +++ b/fs/fuse/dax.c @@ -732,11 +732,8 @@ static ssize_t fuse_dax_direct_write(struct kiocb *iocb, struct iov_iter *from) ssize_t ret; ret = fuse_direct_io(&io, from, &iocb->ki_pos, FUSE_DIO_WRITE); - if (ret < 0) - return ret; - fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE); - fuse_write_update_attr(inode, iocb->ki_pos); + fuse_write_update_attr(inode, iocb->ki_pos, ret); return ret; } diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 75ae30d568ea..337fa6f5a7c6 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1591,7 +1591,7 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size, end = outarg.offset + outarg.size; if (end > file_size) { file_size = end; - fuse_write_update_attr(inode, file_size); + fuse_write_update_attr(inode, file_size, outarg.size); } num = outarg.size; diff --git a/fs/fuse/file.c b/fs/fuse/file.c index b5f37b8df0e0..c3fd88da2a0b 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1066,7 +1066,7 @@ static ssize_t fuse_send_write(struct fuse_io_args *ia, loff_t pos, return err ?: ia->write.out.size; } -bool fuse_write_update_attr(struct inode *inode, loff_t pos) +bool fuse_write_update_attr(struct inode *inode, loff_t pos, ssize_t written) { struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_inode *fi = get_fuse_inode(inode); @@ -1074,12 +1074,14 @@ bool fuse_write_update_attr(struct inode *inode, loff_t pos) spin_lock(&fi->lock); fi->attr_version = atomic64_inc_return(&fc->attr_version); - if (pos > inode->i_size) { + if (written > 0 && pos > inode->i_size) { i_size_write(inode, pos); ret = true; } spin_unlock(&fi->lock); + fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE); + return ret; } @@ -1262,11 +1264,8 @@ static ssize_t fuse_perform_write(struct kiocb *iocb, kfree(ap->pages); } while (!err && iov_iter_count(ii)); - if (res > 0) - fuse_write_update_attr(inode, pos); - + fuse_write_update_attr(inode, pos, res); clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); - fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE); return res > 0 ? res : err; } @@ -1554,11 +1553,9 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) } else { res = fuse_direct_io(&io, from, &iocb->ki_pos, FUSE_DIO_WRITE); + fuse_write_update_attr(inode, iocb->ki_pos, res); } } - fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE); - if (res > 0) - fuse_write_update_attr(inode, iocb->ki_pos); inode_unlock(inode); return res; @@ -2900,9 +2897,8 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter) kref_put(&io->refcnt, fuse_io_release); if (iov_iter_rw(iter) == WRITE) { - if (ret > 0) - fuse_write_update_attr(inode, pos); - else if (ret < 0 && offset + count > i_size) + fuse_write_update_attr(inode, pos, ret); + if (ret < 0 && offset + count > i_size) fuse_do_truncate(file); } @@ -2990,7 +2986,8 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, /* we could have extended the file */ if (!(mode & FALLOC_FL_KEEP_SIZE)) { - bool changed = fuse_write_update_attr(inode, offset + length); + bool changed = fuse_write_update_attr(inode, offset + length, + length); if (changed && fm->fc->writeback_cache) file_update_time(file); @@ -3108,7 +3105,8 @@ static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in, ALIGN(pos_out + outarg.size, PAGE_SIZE) - 1); if (fc->writeback_cache) { - fuse_write_update_attr(inode_out, pos_out + outarg.size); + fuse_write_update_attr(inode_out, pos_out + outarg.size, + outarg.size); file_update_time(file_out); } diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 7f5847a48b4b..66c410a733c1 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1217,7 +1217,7 @@ long fuse_ioctl_common(struct file *file, unsigned int cmd, __poll_t fuse_file_poll(struct file *file, poll_table *wait); int fuse_dev_release(struct inode *inode, struct file *file); -bool fuse_write_update_attr(struct inode *inode, loff_t pos); +bool fuse_write_update_attr(struct inode *inode, loff_t pos, ssize_t written); int fuse_flush_times(struct inode *inode, struct fuse_file *ff); int fuse_write_inode(struct inode *inode, struct writeback_control *wbc); |