Commit d347739a authored by Miklos Szeredi's avatar Miklos Szeredi

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: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 27ae449b
...@@ -732,11 +732,8 @@ static ssize_t fuse_dax_direct_write(struct kiocb *iocb, struct iov_iter *from) ...@@ -732,11 +732,8 @@ static ssize_t fuse_dax_direct_write(struct kiocb *iocb, struct iov_iter *from)
ssize_t ret; ssize_t ret;
ret = fuse_direct_io(&io, from, &iocb->ki_pos, FUSE_DIO_WRITE); 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, ret);
fuse_write_update_attr(inode, iocb->ki_pos);
return ret; return ret;
} }
......
...@@ -1591,7 +1591,7 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size, ...@@ -1591,7 +1591,7 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
end = outarg.offset + outarg.size; end = outarg.offset + outarg.size;
if (end > file_size) { if (end > file_size) {
file_size = end; file_size = end;
fuse_write_update_attr(inode, file_size); fuse_write_update_attr(inode, file_size, outarg.size);
} }
num = outarg.size; num = outarg.size;
......
...@@ -1066,7 +1066,7 @@ static ssize_t fuse_send_write(struct fuse_io_args *ia, loff_t pos, ...@@ -1066,7 +1066,7 @@ static ssize_t fuse_send_write(struct fuse_io_args *ia, loff_t pos,
return err ?: ia->write.out.size; 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_conn *fc = get_fuse_conn(inode);
struct fuse_inode *fi = get_fuse_inode(inode); struct fuse_inode *fi = get_fuse_inode(inode);
...@@ -1074,12 +1074,14 @@ bool fuse_write_update_attr(struct inode *inode, loff_t pos) ...@@ -1074,12 +1074,14 @@ bool fuse_write_update_attr(struct inode *inode, loff_t pos)
spin_lock(&fi->lock); spin_lock(&fi->lock);
fi->attr_version = atomic64_inc_return(&fc->attr_version); 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); i_size_write(inode, pos);
ret = true; ret = true;
} }
spin_unlock(&fi->lock); spin_unlock(&fi->lock);
fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE);
return ret; return ret;
} }
...@@ -1262,11 +1264,8 @@ static ssize_t fuse_perform_write(struct kiocb *iocb, ...@@ -1262,11 +1264,8 @@ static ssize_t fuse_perform_write(struct kiocb *iocb,
kfree(ap->pages); kfree(ap->pages);
} while (!err && iov_iter_count(ii)); } while (!err && iov_iter_count(ii));
if (res > 0) fuse_write_update_attr(inode, pos, res);
fuse_write_update_attr(inode, pos);
clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE);
return res > 0 ? res : err; return res > 0 ? res : err;
} }
...@@ -1554,11 +1553,9 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -1554,11 +1553,9 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
} else { } else {
res = fuse_direct_io(&io, from, &iocb->ki_pos, res = fuse_direct_io(&io, from, &iocb->ki_pos,
FUSE_DIO_WRITE); 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); inode_unlock(inode);
return res; return res;
...@@ -2900,9 +2897,8 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter) ...@@ -2900,9 +2897,8 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
kref_put(&io->refcnt, fuse_io_release); kref_put(&io->refcnt, fuse_io_release);
if (iov_iter_rw(iter) == WRITE) { if (iov_iter_rw(iter) == WRITE) {
if (ret > 0) fuse_write_update_attr(inode, pos, ret);
fuse_write_update_attr(inode, pos); if (ret < 0 && offset + count > i_size)
else if (ret < 0 && offset + count > i_size)
fuse_do_truncate(file); fuse_do_truncate(file);
} }
...@@ -2990,7 +2986,8 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, ...@@ -2990,7 +2986,8 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
/* we could have extended the file */ /* we could have extended the file */
if (!(mode & FALLOC_FL_KEEP_SIZE)) { 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) if (changed && fm->fc->writeback_cache)
file_update_time(file); file_update_time(file);
...@@ -3108,7 +3105,8 @@ static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in, ...@@ -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); ALIGN(pos_out + outarg.size, PAGE_SIZE) - 1);
if (fc->writeback_cache) { 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); file_update_time(file_out);
} }
......
...@@ -1217,7 +1217,7 @@ long fuse_ioctl_common(struct file *file, unsigned int cmd, ...@@ -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); __poll_t fuse_file_poll(struct file *file, poll_table *wait);
int fuse_dev_release(struct inode *inode, struct file *file); 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_flush_times(struct inode *inode, struct fuse_file *ff);
int fuse_write_inode(struct inode *inode, struct writeback_control *wbc); int fuse_write_inode(struct inode *inode, struct writeback_control *wbc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment