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
29a46126ccSChristoph Hellwigstatic int nfs_symlink_filler(void *data, struct page *page)
301da177e4SLinus Torvalds{
31a46126ccSChristoph Hellwig	struct inode *inode = data;
321da177e4SLinus Torvalds	int error;
331da177e4SLinus Torvalds
34cc314eefSLinus Torvalds	error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE);
351da177e4SLinus Torvalds	if (error < 0)
361da177e4SLinus Torvalds		goto error;
371da177e4SLinus Torvalds	SetPageUptodate(page);
381da177e4SLinus Torvalds	unlock_page(page);
391da177e4SLinus Torvalds	return 0;
401da177e4SLinus Torvalds
411da177e4SLinus Torvaldserror:
421da177e4SLinus Torvalds	SetPageError(page);
431da177e4SLinus Torvalds	unlock_page(page);
441da177e4SLinus Torvalds	return -EIO;
451da177e4SLinus Torvalds}
461da177e4SLinus Torvalds
476b255391SAl Virostatic const char *nfs_get_link(struct dentry *dentry,
48fceef393SAl Viro				struct inode *inode,
49fceef393SAl Viro				struct delayed_call *done)
501da177e4SLinus Torvalds{
511da177e4SLinus Torvalds	struct page *page;
52717d44e8STrond Myklebust	void *err;
53717d44e8STrond Myklebust
540d0def49SAl Viro	if (!dentry) {
550d0def49SAl Viro		err = ERR_PTR(nfs_revalidate_mapping_rcu(inode));
560d0def49SAl Viro		if (err)
570d0def49SAl Viro			return err;
580d0def49SAl Viro		page = find_get_page(inode->i_mapping, 0);
590d0def49SAl Viro		if (!page)
600d0def49SAl Viro			return ERR_PTR(-ECHILD);
610d0def49SAl Viro		if (!PageUptodate(page)) {
620d0def49SAl Viro			put_page(page);
630d0def49SAl Viro			return ERR_PTR(-ECHILD);
640d0def49SAl Viro		}
650d0def49SAl Viro	} else {
660d0def49SAl Viro		err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
670d0def49SAl Viro		if (err)
680d0def49SAl Viro			return err;
69a46126ccSChristoph Hellwig		page = read_cache_page(&inode->i_data, 0, nfs_symlink_filler,
70a46126ccSChristoph Hellwig				inode);
710d0def49SAl Viro		if (IS_ERR(page))
720d0def49SAl Viro			return ERR_CAST(page);
730d0def49SAl Viro	}
74fceef393SAl Viro	set_delayed_call(done, page_put_link, page);
7521fc61c7SAl Viro	return page_address(page);
761da177e4SLinus Torvalds}
771da177e4SLinus Torvalds
781da177e4SLinus Torvalds/*
791da177e4SLinus Torvalds * symlinks can't do much...
801da177e4SLinus Torvalds */
8192e1d5beSArjan van de Venconst struct inode_operations nfs_symlink_inode_operations = {
826b255391SAl Viro	.get_link	= nfs_get_link,
831da177e4SLinus Torvalds	.getattr	= nfs_getattr,
841da177e4SLinus Torvalds	.setattr	= nfs_setattr,
851da177e4SLinus Torvalds};
86