1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/fs/nfs/symlink.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) 1992 Rick Sladkey
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * Optimization changes Copyright (C) 1994 Florian La Roche
81da177e4SLinus Torvalds *
91da177e4SLinus Torvalds * Jun 7 1999, cache symlink lookups in the page cache. -DaveM
101da177e4SLinus Torvalds *
111da177e4SLinus Torvalds * nfs symlink handling code
121da177e4SLinus Torvalds */
131da177e4SLinus Torvalds
141da177e4SLinus Torvalds #include <linux/time.h>
151da177e4SLinus Torvalds #include <linux/errno.h>
161da177e4SLinus Torvalds #include <linux/sunrpc/clnt.h>
171da177e4SLinus Torvalds #include <linux/nfs.h>
181da177e4SLinus Torvalds #include <linux/nfs2.h>
191da177e4SLinus Torvalds #include <linux/nfs_fs.h>
201da177e4SLinus Torvalds #include <linux/pagemap.h>
211da177e4SLinus Torvalds #include <linux/stat.h>
221da177e4SLinus Torvalds #include <linux/mm.h>
231da177e4SLinus Torvalds #include <linux/string.h>
241da177e4SLinus Torvalds
251da177e4SLinus Torvalds /* Symlink caching in the page cache is even more simplistic
261da177e4SLinus Torvalds * and straight-forward than readdir caching.
271da177e4SLinus Torvalds */
281da177e4SLinus Torvalds
nfs_symlink_filler(struct file * file,struct folio * folio)29e9b5b23eSMatthew Wilcox (Oracle) static int nfs_symlink_filler(struct file *file, struct folio *folio)
301da177e4SLinus Torvalds {
31e9b5b23eSMatthew Wilcox (Oracle) struct inode *inode = folio->mapping->host;
321da177e4SLinus Torvalds int error;
331da177e4SLinus Torvalds
34e9b5b23eSMatthew Wilcox (Oracle) error = NFS_PROTO(inode)->readlink(inode, &folio->page, 0, PAGE_SIZE);
35*8f3ab6e4SMatthew Wilcox (Oracle) folio_end_read(folio, error == 0);
36*8f3ab6e4SMatthew Wilcox (Oracle) return error;
371da177e4SLinus Torvalds }
381da177e4SLinus Torvalds
nfs_get_link(struct dentry * dentry,struct inode * inode,struct delayed_call * done)396b255391SAl Viro static const char *nfs_get_link(struct dentry *dentry,
40fceef393SAl Viro struct inode *inode,
41fceef393SAl Viro struct delayed_call *done)
421da177e4SLinus Torvalds {
431da177e4SLinus Torvalds struct page *page;
44717d44e8STrond Myklebust void *err;
45717d44e8STrond Myklebust
460d0def49SAl Viro if (!dentry) {
470d0def49SAl Viro err = ERR_PTR(nfs_revalidate_mapping_rcu(inode));
480d0def49SAl Viro if (err)
490d0def49SAl Viro return err;
500d0def49SAl Viro page = find_get_page(inode->i_mapping, 0);
510d0def49SAl Viro if (!page)
526b255391SAl Viro return ERR_PTR(-ECHILD);
530d0def49SAl Viro if (!PageUptodate(page)) {
540d0def49SAl Viro put_page(page);
550d0def49SAl Viro return ERR_PTR(-ECHILD);
560d0def49SAl Viro }
570d0def49SAl Viro } else {
581cda707dSTrond Myklebust err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
591da177e4SLinus Torvalds if (err)
60680baacbSAl Viro return err;
61a46126ccSChristoph Hellwig page = read_cache_page(&inode->i_data, 0, nfs_symlink_filler,
626ece0a04SMatthew Wilcox (Oracle) NULL);
63680baacbSAl Viro if (IS_ERR(page))
64680baacbSAl Viro return ERR_CAST(page);
650d0def49SAl Viro }
66fceef393SAl Viro set_delayed_call(done, page_put_link, page);
6721fc61c7SAl Viro return page_address(page);
681da177e4SLinus Torvalds }
691da177e4SLinus Torvalds
701da177e4SLinus Torvalds /*
711da177e4SLinus Torvalds * symlinks can't do much...
721da177e4SLinus Torvalds */
7392e1d5beSArjan van de Ven const struct inode_operations nfs_symlink_inode_operations = {
746b255391SAl Viro .get_link = nfs_get_link,
751da177e4SLinus Torvalds .getattr = nfs_getattr,
761da177e4SLinus Torvalds .setattr = nfs_setattr,
771da177e4SLinus Torvalds };
78