|
@@ -839,6 +839,11 @@ static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
|
|
|
struct kstat *stat)
|
|
|
{
|
|
|
unsigned int blkbits;
|
|
|
+ struct fuse_conn *fc = get_fuse_conn(inode);
|
|
|
+
|
|
|
+ /* see the comment in fuse_change_attributes() */
|
|
|
+ if (fc->writeback_cache && S_ISREG(inode->i_mode))
|
|
|
+ attr->size = i_size_read(inode);
|
|
|
|
|
|
stat->dev = inode->i_sb->s_dev;
|
|
|
stat->ino = attr->ino;
|
|
@@ -1580,6 +1585,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
|
|
|
struct fuse_setattr_in inarg;
|
|
|
struct fuse_attr_out outarg;
|
|
|
bool is_truncate = false;
|
|
|
+ bool is_wb = fc->writeback_cache;
|
|
|
loff_t oldsize;
|
|
|
int err;
|
|
|
|
|
@@ -1651,7 +1657,9 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
|
|
|
fuse_change_attributes_common(inode, &outarg.attr,
|
|
|
attr_timeout(&outarg));
|
|
|
oldsize = inode->i_size;
|
|
|
- i_size_write(inode, outarg.attr.size);
|
|
|
+ /* see the comment in fuse_change_attributes() */
|
|
|
+ if (!is_wb || is_truncate || !S_ISREG(inode->i_mode))
|
|
|
+ i_size_write(inode, outarg.attr.size);
|
|
|
|
|
|
if (is_truncate) {
|
|
|
/* NOTE: this may release/reacquire fc->lock */
|
|
@@ -1663,7 +1671,8 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
|
|
|
* Only call invalidate_inode_pages2() after removing
|
|
|
* FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
|
|
|
*/
|
|
|
- if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
|
|
|
+ if ((is_truncate || !is_wb) &&
|
|
|
+ S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
|
|
|
truncate_pagecache(inode, outarg.attr.size);
|
|
|
invalidate_inode_pages2(inode->i_mapping);
|
|
|
}
|