diff options
author | Maxim Patlasov <MPatlasov@parallels.com> | 2013-10-10 09:11:54 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2014-04-02 09:38:50 -0400 |
commit | fe38d7df230b022e72014ef7aa799a4f2acfecf3 (patch) | |
tree | 58ac02af5d0c373b85841f355dc0f4b5641fb885 /fs/fuse | |
parent | 6b12c1b37e5556af073c1ebfa04c1f9df3a2beaf (diff) |
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>
Diffstat (limited to 'fs/fuse')
-rw-r--r-- | fs/fuse/file.c | 38 |
1 files changed, 23 insertions, 15 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index d8575304c062..d93f2a1aa7de 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -401,6 +401,21 @@ static int fuse_wait_on_page_writeback(struct inode *inode, pgoff_t index) | |||
401 | return 0; | 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 | static int fuse_flush(struct file *file, fl_owner_t id) | 419 | static int fuse_flush(struct file *file, fl_owner_t id) |
405 | { | 420 | { |
406 | struct inode *inode = file_inode(file); | 421 | struct inode *inode = file_inode(file); |
@@ -416,6 +431,14 @@ static int fuse_flush(struct file *file, fl_owner_t id) | |||
416 | if (fc->no_flush) | 431 | if (fc->no_flush) |
417 | return 0; | 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 | req = fuse_get_req_nofail_nopages(fc, file); | 442 | req = fuse_get_req_nofail_nopages(fc, file); |
420 | memset(&inarg, 0, sizeof(inarg)); | 443 | memset(&inarg, 0, sizeof(inarg)); |
421 | inarg.fh = ff->fh; | 444 | inarg.fh = ff->fh; |
@@ -436,21 +459,6 @@ static int fuse_flush(struct file *file, fl_owner_t id) | |||
436 | return err; | 459 | return err; |
437 | } | 460 | } |
438 | 461 | ||
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 | } | ||
453 | |||
454 | int fuse_fsync_common(struct file *file, loff_t start, loff_t end, | 462 | int fuse_fsync_common(struct file *file, loff_t start, loff_t end, |
455 | int datasync, int isdir) | 463 | int datasync, int isdir) |
456 | { | 464 | { |