summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2019-10-23 08:26:37 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2019-10-23 08:26:37 -0400
commite4648309b85a78f8c787457832269a8712a8673e (patch)
tree59b43e109af068370d36fd35a6f7d88be00c4e82
parentb24e7598db62386a95a3c8b9c75630c5d56fe077 (diff)
fuse: truncate pending writes on O_TRUNC
Make sure cached writes are not reordered around open(..., O_TRUNC), with the obvious wrong results. Fixes: 4d99ff8f12eb ("fuse: Turn writeback cache on") Cc: <stable@vger.kernel.org> # v3.15+ Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--fs/fuse/file.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 0f0225686aee..6edf949b9139 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -217,7 +217,7 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
217{ 217{
218 struct fuse_conn *fc = get_fuse_conn(inode); 218 struct fuse_conn *fc = get_fuse_conn(inode);
219 int err; 219 int err;
220 bool lock_inode = (file->f_flags & O_TRUNC) && 220 bool is_wb_truncate = (file->f_flags & O_TRUNC) &&
221 fc->atomic_o_trunc && 221 fc->atomic_o_trunc &&
222 fc->writeback_cache; 222 fc->writeback_cache;
223 223
@@ -225,16 +225,20 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
225 if (err) 225 if (err)
226 return err; 226 return err;
227 227
228 if (lock_inode) 228 if (is_wb_truncate) {
229 inode_lock(inode); 229 inode_lock(inode);
230 fuse_set_nowrite(inode);
231 }
230 232
231 err = fuse_do_open(fc, get_node_id(inode), file, isdir); 233 err = fuse_do_open(fc, get_node_id(inode), file, isdir);
232 234
233 if (!err) 235 if (!err)
234 fuse_finish_open(inode, file); 236 fuse_finish_open(inode, file);
235 237
236 if (lock_inode) 238 if (is_wb_truncate) {
239 fuse_release_nowrite(inode);
237 inode_unlock(inode); 240 inode_unlock(inode);
241 }
238 242
239 return err; 243 return err;
240} 244}