linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Use folios for symlinks in the page cache
@ 2025-05-14 17:13 Matthew Wilcox (Oracle)
  2025-05-14 17:13 ` [PATCH 1/3] fs: Convert __page_get_link() to use a folio Matthew Wilcox (Oracle)
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Matthew Wilcox (Oracle) @ 2025-05-14 17:13 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Matthew Wilcox (Oracle), Alexander Viro, linux-fsdevel, linux-nfs

FUSE already uses folios for its symlinks.  Mirror that conversion in
the generic code and the NFS code.  That lets us get rid of a few
folio->page->folio conversions in this path, and some of the few
remaining users of read_cache_page() / read_mapping_page().

If anyone's concerned about all the extra lines in the diffstat, it's
documentation that I've added.

Matthew Wilcox (Oracle) (3):
  fs: Convert __page_get_link() to use a folio
  nfs: Use a folio in nfs_get_link()
  fs: Pass a folio to page_put_link()

 fs/fuse/dir.c    |  2 +-
 fs/namei.c       | 48 ++++++++++++++++++++++++++++++++++++------------
 fs/nfs/symlink.c | 20 ++++++++++----------
 3 files changed, 47 insertions(+), 23 deletions(-)

-- 
2.47.2


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] fs: Convert __page_get_link() to use a folio
  2025-05-14 17:13 [PATCH 0/3] Use folios for symlinks in the page cache Matthew Wilcox (Oracle)
@ 2025-05-14 17:13 ` Matthew Wilcox (Oracle)
  2025-05-14 17:13 ` [PATCH 2/3] nfs: Use a folio in nfs_get_link() Matthew Wilcox (Oracle)
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Matthew Wilcox (Oracle) @ 2025-05-14 17:13 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Matthew Wilcox (Oracle), Alexander Viro, linux-fsdevel, linux-nfs

Retrieve a folio from the page cache instead of a page and operate
on it.  Removes two hidden calls to compound_head().

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

diff --git a/fs/namei.c b/fs/namei.c
index 84a0e0b0111c..8e82aa7ecb82 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -5403,25 +5403,25 @@ EXPORT_SYMBOL(vfs_get_link);
 static char *__page_get_link(struct dentry *dentry, struct inode *inode,
 			     struct delayed_call *callback)
 {
-	struct page *page;
+	struct folio *folio;
 	struct address_space *mapping = inode->i_mapping;
 
 	if (!dentry) {
-		page = find_get_page(mapping, 0);
-		if (!page)
+		folio = filemap_get_folio(mapping, 0);
+		if (IS_ERR(folio))
 			return ERR_PTR(-ECHILD);
-		if (!PageUptodate(page)) {
-			put_page(page);
+		if (!folio_test_uptodate(folio)) {
+			folio_put(folio);
 			return ERR_PTR(-ECHILD);
 		}
 	} else {
-		page = read_mapping_page(mapping, 0, NULL);
-		if (IS_ERR(page))
-			return (char*)page;
+		folio = read_mapping_folio(mapping, 0, NULL);
+		if (IS_ERR(folio))
+			return ERR_CAST(folio);
 	}
-	set_delayed_call(callback, page_put_link, page);
+	set_delayed_call(callback, page_put_link, &folio->page);
 	BUG_ON(mapping_gfp_mask(mapping) & __GFP_HIGHMEM);
-	return page_address(page);
+	return folio_address(folio);
 }
 
 const char *page_get_link_raw(struct dentry *dentry, struct inode *inode,
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] nfs: Use a folio in nfs_get_link()
  2025-05-14 17:13 [PATCH 0/3] Use folios for symlinks in the page cache Matthew Wilcox (Oracle)
  2025-05-14 17:13 ` [PATCH 1/3] fs: Convert __page_get_link() to use a folio Matthew Wilcox (Oracle)
@ 2025-05-14 17:13 ` Matthew Wilcox (Oracle)
  2025-05-19 19:28   ` Anna Schumaker
  2025-05-14 17:13 ` [PATCH 3/3] fs: Pass a folio to page_put_link() Matthew Wilcox (Oracle)
  2025-05-15 10:14 ` [PATCH 0/3] Use folios for symlinks in the page cache Christian Brauner
  3 siblings, 1 reply; 6+ messages in thread
From: Matthew Wilcox (Oracle) @ 2025-05-14 17:13 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Matthew Wilcox (Oracle), Alexander Viro, linux-fsdevel, linux-nfs

Mirror the changes to __page_get_link() by retrieving a folio from
the page cache instead of a page.  Removes two hidden calls to
compound_head().

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

diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 1c62a5a9f51d..004a8f6c568e 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -40,31 +40,31 @@ static const char *nfs_get_link(struct dentry *dentry,
 				struct inode *inode,
 				struct delayed_call *done)
 {
-	struct page *page;
+	struct folio *folio;
 	void *err;
 
 	if (!dentry) {
 		err = ERR_PTR(nfs_revalidate_mapping_rcu(inode));
 		if (err)
 			return err;
-		page = find_get_page(inode->i_mapping, 0);
-		if (!page)
+		folio = filemap_get_folio(inode->i_mapping, 0);
+		if (IS_ERR(folio))
 			return ERR_PTR(-ECHILD);
-		if (!PageUptodate(page)) {
-			put_page(page);
+		if (!folio_test_uptodate(folio)) {
+			folio_put(folio);
 			return ERR_PTR(-ECHILD);
 		}
 	} else {
 		err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
 		if (err)
 			return err;
-		page = read_cache_page(&inode->i_data, 0, nfs_symlink_filler,
+		folio = read_cache_folio(&inode->i_data, 0, nfs_symlink_filler,
 				NULL);
-		if (IS_ERR(page))
-			return ERR_CAST(page);
+		if (IS_ERR(folio))
+			return ERR_CAST(folio);
 	}
-	set_delayed_call(done, page_put_link, page);
-	return page_address(page);
+	set_delayed_call(done, page_put_link, &folio->page);
+	return folio_address(folio);
 }
 
 /*
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] fs: Pass a folio to page_put_link()
  2025-05-14 17:13 [PATCH 0/3] Use folios for symlinks in the page cache Matthew Wilcox (Oracle)
  2025-05-14 17:13 ` [PATCH 1/3] fs: Convert __page_get_link() to use a folio Matthew Wilcox (Oracle)
  2025-05-14 17:13 ` [PATCH 2/3] nfs: Use a folio in nfs_get_link() Matthew Wilcox (Oracle)
@ 2025-05-14 17:13 ` Matthew Wilcox (Oracle)
  2025-05-15 10:14 ` [PATCH 0/3] Use folios for symlinks in the page cache Christian Brauner
  3 siblings, 0 replies; 6+ messages in thread
From: Matthew Wilcox (Oracle) @ 2025-05-14 17:13 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Matthew Wilcox (Oracle), Alexander Viro, linux-fsdevel, linux-nfs

All callers now have a folio.  Pass it to page_put_link(), saving a
hidden call to compound_head().  Also add kernel-doc for page_get_link()
and page_put_link().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/fuse/dir.c    |  2 +-
 fs/namei.c       | 30 +++++++++++++++++++++++++++---
 fs/nfs/symlink.c |  2 +-
 3 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 83ac192e7fdd..33b82529cb6e 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1676,7 +1676,7 @@ static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
 		goto out_err;
 	}
 
-	set_delayed_call(callback, page_put_link, &folio->page);
+	set_delayed_call(callback, page_put_link, folio);
 
 	return folio_address(folio);
 
diff --git a/fs/namei.c b/fs/namei.c
index 8e82aa7ecb82..12d24f6da782 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -5419,7 +5419,7 @@ static char *__page_get_link(struct dentry *dentry, struct inode *inode,
 		if (IS_ERR(folio))
 			return ERR_CAST(folio);
 	}
-	set_delayed_call(callback, page_put_link, &folio->page);
+	set_delayed_call(callback, page_put_link, folio);
 	BUG_ON(mapping_gfp_mask(mapping) & __GFP_HIGHMEM);
 	return folio_address(folio);
 }
@@ -5431,6 +5431,17 @@ const char *page_get_link_raw(struct dentry *dentry, struct inode *inode,
 }
 EXPORT_SYMBOL_GPL(page_get_link_raw);
 
+/**
+ * page_get_link() - An implementation of the get_link inode_operation.
+ * @dentry: The directory entry which is the symlink.
+ * @inode: The inode for the symlink.
+ * @callback: Used to drop the reference to the symlink.
+ *
+ * Filesystems which store their symlinks in the page cache should use
+ * this to implement the get_link() member of their inode_operations.
+ *
+ * Return: A pointer to the NUL-terminated symlink.
+ */
 const char *page_get_link(struct dentry *dentry, struct inode *inode,
 					struct delayed_call *callback)
 {
@@ -5440,12 +5451,25 @@ const char *page_get_link(struct dentry *dentry, struct inode *inode,
 		nd_terminate_link(kaddr, inode->i_size, PAGE_SIZE - 1);
 	return kaddr;
 }
-
 EXPORT_SYMBOL(page_get_link);
 
+/**
+ * page_put_link() - Drop the reference to the symlink.
+ * @arg: The folio which contains the symlink.
+ *
+ * This is used internally by page_get_link().  It is exported for use
+ * by filesystems which need to implement a variant of page_get_link()
+ * themselves.  Despite the apparent symmetry, filesystems which use
+ * page_get_link() do not need to call page_put_link().
+ *
+ * The argument, while it has a void pointer type, must be a pointer to
+ * the folio which was retrieved from the page cache.  The delayed_call
+ * infrastructure is used to drop the reference count once the caller
+ * is done with the symlink.
+ */
 void page_put_link(void *arg)
 {
-	put_page(arg);
+	folio_put(arg);
 }
 EXPORT_SYMBOL(page_put_link);
 
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 004a8f6c568e..58146e935402 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -63,7 +63,7 @@ static const char *nfs_get_link(struct dentry *dentry,
 		if (IS_ERR(folio))
 			return ERR_CAST(folio);
 	}
-	set_delayed_call(done, page_put_link, &folio->page);
+	set_delayed_call(done, page_put_link, folio);
 	return folio_address(folio);
 }
 
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/3] Use folios for symlinks in the page cache
  2025-05-14 17:13 [PATCH 0/3] Use folios for symlinks in the page cache Matthew Wilcox (Oracle)
                   ` (2 preceding siblings ...)
  2025-05-14 17:13 ` [PATCH 3/3] fs: Pass a folio to page_put_link() Matthew Wilcox (Oracle)
@ 2025-05-15 10:14 ` Christian Brauner
  3 siblings, 0 replies; 6+ messages in thread
From: Christian Brauner @ 2025-05-15 10:14 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle)
  Cc: Christian Brauner, Alexander Viro, linux-fsdevel, linux-nfs

On Wed, 14 May 2025 18:13:11 +0100, Matthew Wilcox (Oracle) wrote:
> FUSE already uses folios for its symlinks.  Mirror that conversion in
> the generic code and the NFS code.  That lets us get rid of a few
> folio->page->folio conversions in this path, and some of the few
> remaining users of read_cache_page() / read_mapping_page().
> 
> If anyone's concerned about all the extra lines in the diffstat, it's
> documentation that I've added.
> 
> [...]

Applied to the vfs-6.16.misc branch of the vfs/vfs.git tree.
Patches in the vfs-6.16.misc branch should appear in linux-next soon.

Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.

It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.

Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs-6.16.misc

[1/3] fs: Convert __page_get_link() to use a folio
      https://git.kernel.org/vfs/vfs/c/5f152cc012f4
[2/3] nfs: Use a folio in nfs_get_link()
      https://git.kernel.org/vfs/vfs/c/cc8e87f312e0
[3/3] fs: Pass a folio to page_put_link()
      https://git.kernel.org/vfs/vfs/c/4ec373b74e96

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/3] nfs: Use a folio in nfs_get_link()
  2025-05-14 17:13 ` [PATCH 2/3] nfs: Use a folio in nfs_get_link() Matthew Wilcox (Oracle)
@ 2025-05-19 19:28   ` Anna Schumaker
  0 siblings, 0 replies; 6+ messages in thread
From: Anna Schumaker @ 2025-05-19 19:28 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle), Christian Brauner
  Cc: Alexander Viro, linux-fsdevel, linux-nfs



On 5/14/25 1:13 PM, Matthew Wilcox (Oracle) wrote:
> Mirror the changes to __page_get_link() by retrieving a folio from
> the page cache instead of a page.  Removes two hidden calls to
> compound_head().
> 
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>

Acked-by: Anna Schumaker <anna.schumaker@oracle.com>

> ---
>  fs/nfs/symlink.c | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
> index 1c62a5a9f51d..004a8f6c568e 100644
> --- a/fs/nfs/symlink.c
> +++ b/fs/nfs/symlink.c
> @@ -40,31 +40,31 @@ static const char *nfs_get_link(struct dentry *dentry,
>  				struct inode *inode,
>  				struct delayed_call *done)
>  {
> -	struct page *page;
> +	struct folio *folio;
>  	void *err;
>  
>  	if (!dentry) {
>  		err = ERR_PTR(nfs_revalidate_mapping_rcu(inode));
>  		if (err)
>  			return err;
> -		page = find_get_page(inode->i_mapping, 0);
> -		if (!page)
> +		folio = filemap_get_folio(inode->i_mapping, 0);
> +		if (IS_ERR(folio))
>  			return ERR_PTR(-ECHILD);
> -		if (!PageUptodate(page)) {
> -			put_page(page);
> +		if (!folio_test_uptodate(folio)) {
> +			folio_put(folio);
>  			return ERR_PTR(-ECHILD);
>  		}
>  	} else {
>  		err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
>  		if (err)
>  			return err;
> -		page = read_cache_page(&inode->i_data, 0, nfs_symlink_filler,
> +		folio = read_cache_folio(&inode->i_data, 0, nfs_symlink_filler,
>  				NULL);
> -		if (IS_ERR(page))
> -			return ERR_CAST(page);
> +		if (IS_ERR(folio))
> +			return ERR_CAST(folio);
>  	}
> -	set_delayed_call(done, page_put_link, page);
> -	return page_address(page);
> +	set_delayed_call(done, page_put_link, &folio->page);
> +	return folio_address(folio);
>  }
>  
>  /*


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-05-19 19:28 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-14 17:13 [PATCH 0/3] Use folios for symlinks in the page cache Matthew Wilcox (Oracle)
2025-05-14 17:13 ` [PATCH 1/3] fs: Convert __page_get_link() to use a folio Matthew Wilcox (Oracle)
2025-05-14 17:13 ` [PATCH 2/3] nfs: Use a folio in nfs_get_link() Matthew Wilcox (Oracle)
2025-05-19 19:28   ` Anna Schumaker
2025-05-14 17:13 ` [PATCH 3/3] fs: Pass a folio to page_put_link() Matthew Wilcox (Oracle)
2025-05-15 10:14 ` [PATCH 0/3] Use folios for symlinks in the page cache Christian Brauner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).