diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2013-10-10 09:11:43 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2014-04-02 09:38:49 -0400 |
commit | 6b12c1b37e5556af073c1ebfa04c1f9df3a2beaf (patch) | |
tree | 75735adf59b0aac02487c41f0ad512893cfa902a /fs/fuse/file.c | |
parent | 482fce55d2809d639fd0d2e6249c89dedc20eeae (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.c | 73 |
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 | */ | ||
1959 | static 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; | ||
1993 | success: | ||
1994 | *pagep = page; | ||
1995 | return 0; | ||
1996 | |||
1997 | cleanup: | ||
1998 | unlock_page(page); | ||
1999 | page_cache_release(page); | ||
2000 | error: | ||
2001 | return err; | ||
2002 | } | ||
2003 | |||
2004 | static 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 | |||
1955 | static int fuse_launder_page(struct page *page) | 2026 | static 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 | ||
2984 | void fuse_init_file_inode(struct inode *inode) | 3057 | void fuse_init_file_inode(struct inode *inode) |