Commit 6b12c1b37e5556af073c1ebfa04c1f9df3a2beaf

Authored by Pavel Emelyanov
Committed by Miklos Szeredi
1 parent 482fce55d2

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>

Showing 1 changed file with 73 additions and 0 deletions Side-by-side Diff

... ... @@ -1952,6 +1952,77 @@
1952 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 2026 static int fuse_launder_page(struct page *page)
1956 2027 {
1957 2028 int err = 0;
... ... @@ -2979,6 +3050,8 @@
2979 3050 .set_page_dirty = __set_page_dirty_nobuffers,
2980 3051 .bmap = fuse_bmap,
2981 3052 .direct_IO = fuse_direct_IO,
  3053 + .write_begin = fuse_write_begin,
  3054 + .write_end = fuse_write_end,
2982 3055 };
2983 3056  
2984 3057 void fuse_init_file_inode(struct inode *inode)