Unverified Commit a060d835 authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle) Committed by Christian Brauner
Browse files

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: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent 556d0ac0
Loading
Loading
Loading
Loading
+15 −14
Original line number Diff line number Diff line
@@ -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;
}