diff options
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r-- | fs/fuse/inode.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index d468643a68b2..c668c8436894 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -197,6 +197,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, | |||
197 | { | 197 | { |
198 | struct fuse_conn *fc = get_fuse_conn(inode); | 198 | struct fuse_conn *fc = get_fuse_conn(inode); |
199 | struct fuse_inode *fi = get_fuse_inode(inode); | 199 | struct fuse_inode *fi = get_fuse_inode(inode); |
200 | bool is_wb = fc->writeback_cache; | ||
200 | loff_t oldsize; | 201 | loff_t oldsize; |
201 | struct timespec old_mtime; | 202 | struct timespec old_mtime; |
202 | 203 | ||
@@ -211,10 +212,16 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, | |||
211 | fuse_change_attributes_common(inode, attr, attr_valid); | 212 | fuse_change_attributes_common(inode, attr, attr_valid); |
212 | 213 | ||
213 | oldsize = inode->i_size; | 214 | oldsize = inode->i_size; |
214 | i_size_write(inode, attr->size); | 215 | /* |
216 | * In case of writeback_cache enabled, the cached writes beyond EOF | ||
217 | * extend local i_size without keeping userspace server in sync. So, | ||
218 | * attr->size coming from server can be stale. We cannot trust it. | ||
219 | */ | ||
220 | if (!is_wb || !S_ISREG(inode->i_mode)) | ||
221 | i_size_write(inode, attr->size); | ||
215 | spin_unlock(&fc->lock); | 222 | spin_unlock(&fc->lock); |
216 | 223 | ||
217 | if (S_ISREG(inode->i_mode)) { | 224 | if (!is_wb && S_ISREG(inode->i_mode)) { |
218 | bool inval = false; | 225 | bool inval = false; |
219 | 226 | ||
220 | if (oldsize != attr->size) { | 227 | if (oldsize != attr->size) { |