From 4ec373b74e96f92cf273631d31c82ec53727cf02 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Wed, 14 May 2025 18:13:14 +0100 Subject: [PATCH] fs: Pass a folio to page_put_link() 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)" Link: https://lore.kernel.org/20250514171316.3002934-4-willy@infradead.org Signed-off-by: Christian Brauner --- 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 83ac192e7fdd1..33b82529cb6e4 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 7b76611d1a8c5..e64446be1f057 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -5387,7 +5387,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); } @@ -5399,6 +5399,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) { @@ -5408,12 +5419,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 004a8f6c568e3..58146e9354020 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.39.5