Commit fe38d7df230b022e72014ef7aa799a4f2acfecf3
Committed by
Miklos Szeredi
1 parent
6b12c1b37e
fuse: fuse_flush() should wait on writeback
The aim of .flush fop is to hint file-system that flushing its state or caches or any other important data to reliable storage would be desirable now. fuse_flush() passes this hint by sending FUSE_FLUSH request to userspace. However, dirty pages and pages under writeback may be not visible to userspace yet if we won't ensure it explicitly. Signed-off-by: Maxim Patlasov <MPatlasov@parallels.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Showing 1 changed file with 23 additions and 15 deletions Side-by-side Diff
fs/fuse/file.c
... | ... | @@ -401,6 +401,21 @@ |
401 | 401 | return 0; |
402 | 402 | } |
403 | 403 | |
404 | +/* | |
405 | + * Wait for all pending writepages on the inode to finish. | |
406 | + * | |
407 | + * This is currently done by blocking further writes with FUSE_NOWRITE | |
408 | + * and waiting for all sent writes to complete. | |
409 | + * | |
410 | + * This must be called under i_mutex, otherwise the FUSE_NOWRITE usage | |
411 | + * could conflict with truncation. | |
412 | + */ | |
413 | +static void fuse_sync_writes(struct inode *inode) | |
414 | +{ | |
415 | + fuse_set_nowrite(inode); | |
416 | + fuse_release_nowrite(inode); | |
417 | +} | |
418 | + | |
404 | 419 | static int fuse_flush(struct file *file, fl_owner_t id) |
405 | 420 | { |
406 | 421 | struct inode *inode = file_inode(file); |
... | ... | @@ -416,6 +431,14 @@ |
416 | 431 | if (fc->no_flush) |
417 | 432 | return 0; |
418 | 433 | |
434 | + err = filemap_write_and_wait(file->f_mapping); | |
435 | + if (err) | |
436 | + return err; | |
437 | + | |
438 | + mutex_lock(&inode->i_mutex); | |
439 | + fuse_sync_writes(inode); | |
440 | + mutex_unlock(&inode->i_mutex); | |
441 | + | |
419 | 442 | req = fuse_get_req_nofail_nopages(fc, file); |
420 | 443 | memset(&inarg, 0, sizeof(inarg)); |
421 | 444 | inarg.fh = ff->fh; |
... | ... | @@ -434,21 +457,6 @@ |
434 | 457 | err = 0; |
435 | 458 | } |
436 | 459 | return err; |
437 | -} | |
438 | - | |
439 | -/* | |
440 | - * Wait for all pending writepages on the inode to finish. | |
441 | - * | |
442 | - * This is currently done by blocking further writes with FUSE_NOWRITE | |
443 | - * and waiting for all sent writes to complete. | |
444 | - * | |
445 | - * This must be called under i_mutex, otherwise the FUSE_NOWRITE usage | |
446 | - * could conflict with truncation. | |
447 | - */ | |
448 | -static void fuse_sync_writes(struct inode *inode) | |
449 | -{ | |
450 | - fuse_set_nowrite(inode); | |
451 | - fuse_release_nowrite(inode); | |
452 | 460 | } |
453 | 461 | |
454 | 462 | int fuse_fsync_common(struct file *file, loff_t start, loff_t end, |