forked from Minki/linux
e9b5b23e95
By making filler_t the same as read_folio, we can use the same function for both in gfs2. We can push the use of folios down one more level in jffs2 and nfs. We also increase type safety for future users of the various read_cache_page() family of functions by forcing the parameter to be a pointer to struct file (or NULL). Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>
86 lines
1.9 KiB
C
86 lines
1.9 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* linux/fs/nfs/symlink.c
|
|
*
|
|
* Copyright (C) 1992 Rick Sladkey
|
|
*
|
|
* Optimization changes Copyright (C) 1994 Florian La Roche
|
|
*
|
|
* Jun 7 1999, cache symlink lookups in the page cache. -DaveM
|
|
*
|
|
* nfs symlink handling code
|
|
*/
|
|
|
|
#include <linux/time.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/sunrpc/clnt.h>
|
|
#include <linux/nfs.h>
|
|
#include <linux/nfs2.h>
|
|
#include <linux/nfs_fs.h>
|
|
#include <linux/pagemap.h>
|
|
#include <linux/stat.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/string.h>
|
|
|
|
/* Symlink caching in the page cache is even more simplistic
|
|
* and straight-forward than readdir caching.
|
|
*/
|
|
|
|
static int nfs_symlink_filler(struct file *file, struct folio *folio)
|
|
{
|
|
struct inode *inode = folio->mapping->host;
|
|
int error;
|
|
|
|
error = NFS_PROTO(inode)->readlink(inode, &folio->page, 0, PAGE_SIZE);
|
|
if (error < 0)
|
|
goto error;
|
|
folio_mark_uptodate(folio);
|
|
folio_unlock(folio);
|
|
return 0;
|
|
|
|
error:
|
|
folio_set_error(folio);
|
|
folio_unlock(folio);
|
|
return -EIO;
|
|
}
|
|
|
|
static const char *nfs_get_link(struct dentry *dentry,
|
|
struct inode *inode,
|
|
struct delayed_call *done)
|
|
{
|
|
struct page *page;
|
|
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)
|
|
return ERR_PTR(-ECHILD);
|
|
if (!PageUptodate(page)) {
|
|
put_page(page);
|
|
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,
|
|
NULL);
|
|
if (IS_ERR(page))
|
|
return ERR_CAST(page);
|
|
}
|
|
set_delayed_call(done, page_put_link, page);
|
|
return page_address(page);
|
|
}
|
|
|
|
/*
|
|
* symlinks can't do much...
|
|
*/
|
|
const struct inode_operations nfs_symlink_inode_operations = {
|
|
.get_link = nfs_get_link,
|
|
.getattr = nfs_getattr,
|
|
.setattr = nfs_setattr,
|
|
};
|