From mboxrd@z Thu Jan 1 00:00:00 1970 From: Pavel Emelyanov Subject: [PATCH 7/10] fuse: Flush files on wb close Date: Tue, 03 Jul 2012 19:56:18 +0400 Message-ID: <4FF31622.6080502@parallels.com> References: <4FF3156E.8030109@parallels.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Cc: Kirill Korotaev , James Bottomley To: fuse-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org, Miklos Szeredi , Alexander Viro , linux-fsdevel Return-path: In-Reply-To: <4FF3156E.8030109-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: fuse-devel-bounces-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org List-Id: linux-fsdevel.vger.kernel.org Any write request requires a file handle to report to the userspace. Thus when we close a file (and free the fuse_file with this info) we have to flush all the outstanding writeback cache. Note, that simply calling the filemap_write_and_wait() is not enough since fuse finishes page writeback immediatelly and thus the -wait part of the mentioned call will be no-op. Do real wait on per-inode writepages list. Signed-off-by: Pavel Emelyanov --- fs/fuse/file.c | 26 +++++++++++++++++++++++++- 1 files changed, 25 insertions(+), 1 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 9bc1390..d9d566e 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -137,6 +137,12 @@ static void fuse_file_put(struct fuse_file *ff, bool sync) } } +static void __fuse_file_put(struct fuse_file *ff) +{ + if (atomic_dec_and_test(&ff->count)) + BUG(); +} + int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, bool isdir) { @@ -285,8 +291,23 @@ static int fuse_open(struct inode *inode, struct file *file) return fuse_open_common(inode, file, false); } +static void fuse_flush_writeback(struct inode *inode, struct file *file) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_inode *fi = get_fuse_inode(inode); + + filemap_write_and_wait(file->f_mapping); + wait_event(fi->page_waitq, list_empty_careful(&fi->writepages)); + spin_unlock_wait(&fc->lock); +} + static int fuse_release(struct inode *inode, struct file *file) { + struct fuse_conn *fc = get_fuse_conn(inode); + + if (fc->writeback_cache) + fuse_flush_writeback(inode, file); + fuse_release_common(file, FUSE_RELEASE); /* return value is ignored by VFS */ @@ -1215,7 +1236,8 @@ static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req) for (i = 0; i < req->num_pages; i++) __free_page(req->pages[i]); - fuse_file_put(req->ff, false); + if (!fc->writeback_cache) + fuse_file_put(req->ff, false); } static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req) @@ -1232,6 +1254,8 @@ static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req) } bdi_writeout_inc(bdi); wake_up(&fi->page_waitq); + if (fc->writeback_cache) + __fuse_file_put(req->ff); } /* Called under fc->lock, may release and reacquire it */ -- 1.5.5.6 ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/