diff mbox series

[2/2] fuse: Convert fuse_writepage_locked to take a folio

Message ID 20240228182940.1404651-2-willy@infradead.org (mailing list archive)
State New
Headers show
Series [1/2] fuse: Remove fuse_writepage | expand

Commit Message

Matthew Wilcox Feb. 28, 2024, 6:29 p.m. UTC
The one remaining caller of fuse_writepage_locked() already has a folio,
so convert this function entirely.  Saves a few calls to compound_head()
but no attempt is made to support large folios in this patch.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/fuse/file.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

Comments

Bernd Schubert April 13, 2024, 11:28 a.m. UTC | #1
On 2/28/24 19:29, Matthew Wilcox (Oracle) wrote:
> The one remaining caller of fuse_writepage_locked() already has a folio,
> so convert this function entirely.  Saves a few calls to compound_head()
> but no attempt is made to support large folios in this patch.
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> ---
>  fs/fuse/file.c | 30 +++++++++++++++---------------
>  1 file changed, 15 insertions(+), 15 deletions(-)
> 
> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
> index 340ccaafb3f7..f173cbce1d31 100644
> --- a/fs/fuse/file.c
> +++ b/fs/fuse/file.c
> @@ -2040,26 +2040,26 @@ static void fuse_writepage_add_to_bucket(struct fuse_conn *fc,
>  	rcu_read_unlock();
>  }
>  
> -static int fuse_writepage_locked(struct page *page)
> +static int fuse_writepage_locked(struct folio *folio)
>  {
> -	struct address_space *mapping = page->mapping;
> +	struct address_space *mapping = folio->mapping;
>  	struct inode *inode = mapping->host;
>  	struct fuse_conn *fc = get_fuse_conn(inode);
>  	struct fuse_inode *fi = get_fuse_inode(inode);
>  	struct fuse_writepage_args *wpa;
>  	struct fuse_args_pages *ap;
> -	struct page *tmp_page;
> +	struct folio *tmp_folio;
>  	int error = -ENOMEM;
>  
> -	set_page_writeback(page);
> +	folio_start_writeback(folio);
>  
>  	wpa = fuse_writepage_args_alloc();
>  	if (!wpa)
>  		goto err;
>  	ap = &wpa->ia.ap;
>  
> -	tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
> -	if (!tmp_page)
> +	tmp_folio = folio_alloc(GFP_NOFS | __GFP_HIGHMEM, 0);
> +	if (!tmp_folio)
>  		goto err_free;
>  
>  	error = -EIO;
> @@ -2068,21 +2068,21 @@ static int fuse_writepage_locked(struct page *page)
>  		goto err_nofile;
>  
>  	fuse_writepage_add_to_bucket(fc, wpa);
> -	fuse_write_args_fill(&wpa->ia, wpa->ia.ff, page_offset(page), 0);
> +	fuse_write_args_fill(&wpa->ia, wpa->ia.ff, folio_pos(folio), 0);
>  
> -	copy_highpage(tmp_page, page);
> +	folio_copy(tmp_folio, folio);
>  	wpa->ia.write.in.write_flags |= FUSE_WRITE_CACHE;
>  	wpa->next = NULL;
>  	ap->args.in_pages = true;
>  	ap->num_pages = 1;
> -	ap->pages[0] = tmp_page;
> +	ap->pages[0] = &tmp_folio->page;

Hi Matthew,

sorry for late review. The part I'm totally confused with (already
without this patch), why is this handling a single page only and not the
entire folio? Is it guaranteed that the folio has a single page only?



Thanks,
Bernd
Matthew Wilcox April 13, 2024, 3:59 p.m. UTC | #2
On Sat, Apr 13, 2024 at 01:28:31PM +0200, Bernd Schubert wrote:
> On 2/28/24 19:29, Matthew Wilcox (Oracle) wrote:
> > The one remaining caller of fuse_writepage_locked() already has a folio,
> > so convert this function entirely.  Saves a few calls to compound_head()
> > but no attempt is made to support large folios in this patch.
>
> sorry for late review. The part I'm totally confused with (already
> without this patch), why is this handling a single page only and not the
> entire folio? Is it guaranteed that the folio has a single page only?

Hi Bernd,

, filesystems have to tell the VFS that they support large folios before
they'll see a large folio.  That's a call to mapping_set_large_folios()
today, although there's proposals to make that more granular.

If there's interest in supporting large folios in FUSE, I'm happy to
help, but my primary motivation is sorting out struct page, not fixing
individual filesystems.
Bernd Schubert April 15, 2024, 12:48 p.m. UTC | #3
On 4/13/24 17:59, Matthew Wilcox wrote:
> On Sat, Apr 13, 2024 at 01:28:31PM +0200, Bernd Schubert wrote:
>> On 2/28/24 19:29, Matthew Wilcox (Oracle) wrote:
>>> The one remaining caller of fuse_writepage_locked() already has a folio,
>>> so convert this function entirely.  Saves a few calls to compound_head()
>>> but no attempt is made to support large folios in this patch.
>>
>> sorry for late review. The part I'm totally confused with (already
>> without this patch), why is this handling a single page only and not the
>> entire folio? Is it guaranteed that the folio has a single page only?
> 
> Hi Bernd,
> 
> , filesystems have to tell the VFS that they support large folios before
> they'll see a large folio.  That's a call to mapping_set_large_folios()
> today, although there's proposals to make that more granular.
> 
> If there's interest in supporting large folios in FUSE, I'm happy to
> help, but my primary motivation is sorting out struct page, not fixing
> individual filesystems.

Thank you Matthew! Especially for your quick reply on a Saturday!

I had totally missed mapping_set_large_folios. I will look into
converting fuse to large folios once I get to performance optimizations
for our file system. For now I was just going through all recent commits
and had already wondered about the single page folio before.


Thanks again,
Bernd
diff mbox series

Patch

diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 340ccaafb3f7..f173cbce1d31 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2040,26 +2040,26 @@  static void fuse_writepage_add_to_bucket(struct fuse_conn *fc,
 	rcu_read_unlock();
 }
 
-static int fuse_writepage_locked(struct page *page)
+static int fuse_writepage_locked(struct folio *folio)
 {
-	struct address_space *mapping = page->mapping;
+	struct address_space *mapping = folio->mapping;
 	struct inode *inode = mapping->host;
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_inode *fi = get_fuse_inode(inode);
 	struct fuse_writepage_args *wpa;
 	struct fuse_args_pages *ap;
-	struct page *tmp_page;
+	struct folio *tmp_folio;
 	int error = -ENOMEM;
 
-	set_page_writeback(page);
+	folio_start_writeback(folio);
 
 	wpa = fuse_writepage_args_alloc();
 	if (!wpa)
 		goto err;
 	ap = &wpa->ia.ap;
 
-	tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
-	if (!tmp_page)
+	tmp_folio = folio_alloc(GFP_NOFS | __GFP_HIGHMEM, 0);
+	if (!tmp_folio)
 		goto err_free;
 
 	error = -EIO;
@@ -2068,21 +2068,21 @@  static int fuse_writepage_locked(struct page *page)
 		goto err_nofile;
 
 	fuse_writepage_add_to_bucket(fc, wpa);
-	fuse_write_args_fill(&wpa->ia, wpa->ia.ff, page_offset(page), 0);
+	fuse_write_args_fill(&wpa->ia, wpa->ia.ff, folio_pos(folio), 0);
 
-	copy_highpage(tmp_page, page);
+	folio_copy(tmp_folio, folio);
 	wpa->ia.write.in.write_flags |= FUSE_WRITE_CACHE;
 	wpa->next = NULL;
 	ap->args.in_pages = true;
 	ap->num_pages = 1;
-	ap->pages[0] = tmp_page;
+	ap->pages[0] = &tmp_folio->page;
 	ap->descs[0].offset = 0;
 	ap->descs[0].length = PAGE_SIZE;
 	ap->args.end = fuse_writepage_end;
 	wpa->inode = inode;
 
 	inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK);
-	inc_node_page_state(tmp_page, NR_WRITEBACK_TEMP);
+	node_stat_add_folio(tmp_folio, NR_WRITEBACK_TEMP);
 
 	spin_lock(&fi->lock);
 	tree_insert(&fi->writepages, wpa);
@@ -2090,17 +2090,17 @@  static int fuse_writepage_locked(struct page *page)
 	fuse_flush_writepages(inode);
 	spin_unlock(&fi->lock);
 
-	end_page_writeback(page);
+	folio_end_writeback(folio);
 
 	return 0;
 
 err_nofile:
-	__free_page(tmp_page);
+	folio_put(tmp_folio);
 err_free:
 	kfree(wpa);
 err:
-	mapping_set_error(page->mapping, error);
-	end_page_writeback(page);
+	mapping_set_error(folio->mapping, error);
+	folio_end_writeback(folio);
 	return error;
 }
 
@@ -2466,7 +2466,7 @@  static int fuse_launder_folio(struct folio *folio)
 
 		/* Serialize with pending writeback for the same page */
 		fuse_wait_on_page_writeback(inode, folio->index);
-		err = fuse_writepage_locked(&folio->page);
+		err = fuse_writepage_locked(folio);
 		if (!err)
 			fuse_wait_on_page_writeback(inode, folio->index);
 	}