fuse: Convert fuse_write_begin() to use a folio

Fetch a folio from the page cache instead of a page and use it throughout
removing several calls to compound_head() and supporting large folios
(in this function).  We still have to convert back to a page for calling
internal fuse functions, but hopefully they will be converted soon.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Matthew Wilcox (Oracle) 2024-07-11 16:58:06 -04:00 committed by Christian Brauner
parent 556d0ac068
commit a060d835cf
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2

View File

@ -2391,41 +2391,42 @@ static int fuse_write_begin(struct file *file, struct address_space *mapping,
{
pgoff_t index = pos >> PAGE_SHIFT;
struct fuse_conn *fc = get_fuse_conn(file_inode(file));
struct page *page;
struct folio *folio;
loff_t fsize;
int err = -ENOMEM;
WARN_ON(!fc->writeback_cache);
page = grab_cache_page_write_begin(mapping, index);
if (!page)
folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN,
mapping_gfp_mask(mapping));
if (IS_ERR(folio))
goto error;
fuse_wait_on_page_writeback(mapping->host, page->index);
fuse_wait_on_page_writeback(mapping->host, folio->index);
if (PageUptodate(page) || len == PAGE_SIZE)
if (folio_test_uptodate(folio) || len >= folio_size(folio))
goto success;
/*
* Check if the start this page comes after the end of file, in which
* case the readpage can be optimized away.
* Check if the start of this folio comes after the end of file,
* in which case the readpage can be optimized away.
*/
fsize = i_size_read(mapping->host);
if (fsize <= (pos & PAGE_MASK)) {
size_t off = pos & ~PAGE_MASK;
if (fsize <= folio_pos(folio)) {
size_t off = offset_in_folio(folio, pos);
if (off)
zero_user_segment(page, 0, off);
folio_zero_segment(folio, 0, off);
goto success;
}
err = fuse_do_readpage(file, page);
err = fuse_do_readpage(file, &folio->page);
if (err)
goto cleanup;
success:
*pagep = page;
*pagep = &folio->page;
return 0;
cleanup:
unlock_page(page);
put_page(page);
folio_unlock(folio);
folio_put(folio);
error:
return err;
}