aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/file.c
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2013-10-10 09:11:43 -0400
committerMiklos Szeredi <mszeredi@suse.cz>2014-04-02 09:38:49 -0400
commit6b12c1b37e5556af073c1ebfa04c1f9df3a2beaf (patch)
tree75735adf59b0aac02487c41f0ad512893cfa902a /fs/fuse/file.c
parent482fce55d2809d639fd0d2e6249c89dedc20eeae (diff)
fuse: Implement write_begin/write_end callbacks
The .write_begin and .write_end are requiered to use generic routines (generic_file_aio_write --> ... --> generic_perform_write) for buffered writes. Signed-off-by: Maxim Patlasov <MPatlasov@parallels.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r--fs/fuse/file.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index b1873b510350..d8575304c062 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1952,6 +1952,77 @@ out:
1952 return err; 1952 return err;
1953} 1953}
1954 1954
1955/*
1956 * It's worthy to make sure that space is reserved on disk for the write,
1957 * but how to implement it without killing performance need more thinking.
1958 */
1959static int fuse_write_begin(struct file *file, struct address_space *mapping,
1960 loff_t pos, unsigned len, unsigned flags,
1961 struct page **pagep, void **fsdata)
1962{
1963 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
1964 struct fuse_conn *fc = get_fuse_conn(file->f_dentry->d_inode);
1965 struct page *page;
1966 loff_t fsize;
1967 int err = -ENOMEM;
1968
1969 WARN_ON(!fc->writeback_cache);
1970
1971 page = grab_cache_page_write_begin(mapping, index, flags);
1972 if (!page)
1973 goto error;
1974
1975 fuse_wait_on_page_writeback(mapping->host, page->index);
1976
1977 if (PageUptodate(page) || len == PAGE_CACHE_SIZE)
1978 goto success;
1979 /*
1980 * Check if the start this page comes after the end of file, in which
1981 * case the readpage can be optimized away.
1982 */
1983 fsize = i_size_read(mapping->host);
1984 if (fsize <= (pos & PAGE_CACHE_MASK)) {
1985 size_t off = pos & ~PAGE_CACHE_MASK;
1986 if (off)
1987 zero_user_segment(page, 0, off);
1988 goto success;
1989 }
1990 err = fuse_do_readpage(file, page);
1991 if (err)
1992 goto cleanup;
1993success:
1994 *pagep = page;
1995 return 0;
1996
1997cleanup:
1998 unlock_page(page);
1999 page_cache_release(page);
2000error:
2001 return err;
2002}
2003
2004static int fuse_write_end(struct file *file, struct address_space *mapping,
2005 loff_t pos, unsigned len, unsigned copied,
2006 struct page *page, void *fsdata)
2007{
2008 struct inode *inode = page->mapping->host;
2009
2010 if (!PageUptodate(page)) {
2011 /* Zero any unwritten bytes at the end of the page */
2012 size_t endoff = (pos + copied) & ~PAGE_CACHE_MASK;
2013 if (endoff)
2014 zero_user_segment(page, endoff, PAGE_CACHE_SIZE);
2015 SetPageUptodate(page);
2016 }
2017
2018 fuse_write_update_size(inode, pos + copied);
2019 set_page_dirty(page);
2020 unlock_page(page);
2021 page_cache_release(page);
2022
2023 return copied;
2024}
2025
1955static int fuse_launder_page(struct page *page) 2026static int fuse_launder_page(struct page *page)
1956{ 2027{
1957 int err = 0; 2028 int err = 0;
@@ -2979,6 +3050,8 @@ static const struct address_space_operations fuse_file_aops = {
2979 .set_page_dirty = __set_page_dirty_nobuffers, 3050 .set_page_dirty = __set_page_dirty_nobuffers,
2980 .bmap = fuse_bmap, 3051 .bmap = fuse_bmap,
2981 .direct_IO = fuse_direct_IO, 3052 .direct_IO = fuse_direct_IO,
3053 .write_begin = fuse_write_begin,
3054 .write_end = fuse_write_end,
2982}; 3055};
2983 3056
2984void fuse_init_file_inode(struct inode *inode) 3057void fuse_init_file_inode(struct inode *inode)