xref: /linux/fs/nfs/symlink.c (revision b24413180f5600bcb3bb70fbed5cf186b60864bd)
1*b2441318SGreg 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 
291da177e4SLinus Torvalds static int nfs_symlink_filler(struct inode *inode, struct page *page)
301da177e4SLinus Torvalds {
311da177e4SLinus Torvalds 	int error;
321da177e4SLinus Torvalds 
33cc314eefSLinus Torvalds 	error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE);
341da177e4SLinus Torvalds 	if (error < 0)
351da177e4SLinus Torvalds 		goto error;
361da177e4SLinus Torvalds 	SetPageUptodate(page);
371da177e4SLinus Torvalds 	unlock_page(page);
381da177e4SLinus Torvalds 	return 0;
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds error:
411da177e4SLinus Torvalds 	SetPageError(page);
421da177e4SLinus Torvalds 	unlock_page(page);
431da177e4SLinus Torvalds 	return -EIO;
441da177e4SLinus Torvalds }
451da177e4SLinus Torvalds 
466b255391SAl Viro static const char *nfs_get_link(struct dentry *dentry,
47fceef393SAl Viro 				struct inode *inode,
48fceef393SAl Viro 				struct delayed_call *done)
491da177e4SLinus Torvalds {
501da177e4SLinus Torvalds 	struct page *page;
51717d44e8STrond Myklebust 	void *err;
52717d44e8STrond Myklebust 
530d0def49SAl Viro 	if (!dentry) {
540d0def49SAl Viro 		err = ERR_PTR(nfs_revalidate_mapping_rcu(inode));
550d0def49SAl Viro 		if (err)
560d0def49SAl Viro 			return err;
570d0def49SAl Viro 		page = find_get_page(inode->i_mapping, 0);
580d0def49SAl Viro 		if (!page)
596b255391SAl Viro 			return ERR_PTR(-ECHILD);
600d0def49SAl Viro 		if (!PageUptodate(page)) {
610d0def49SAl Viro 			put_page(page);
620d0def49SAl Viro 			return ERR_PTR(-ECHILD);
630d0def49SAl Viro 		}
640d0def49SAl Viro 	} else {
651cda707dSTrond Myklebust 		err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
661da177e4SLinus Torvalds 		if (err)
67680baacbSAl Viro 			return err;
681da177e4SLinus Torvalds 		page = read_cache_page(&inode->i_data, 0,
691da177e4SLinus Torvalds 					(filler_t *)nfs_symlink_filler, inode);
70680baacbSAl Viro 		if (IS_ERR(page))
71680baacbSAl Viro 			return ERR_CAST(page);
720d0def49SAl Viro 	}
73fceef393SAl Viro 	set_delayed_call(done, page_put_link, page);
7421fc61c7SAl Viro 	return page_address(page);
751da177e4SLinus Torvalds }
761da177e4SLinus Torvalds 
771da177e4SLinus Torvalds /*
781da177e4SLinus Torvalds  * symlinks can't do much...
791da177e4SLinus Torvalds  */
8092e1d5beSArjan van de Ven const struct inode_operations nfs_symlink_inode_operations = {
816b255391SAl Viro 	.get_link	= nfs_get_link,
821da177e4SLinus Torvalds 	.getattr	= nfs_getattr,
831da177e4SLinus Torvalds 	.setattr	= nfs_setattr,
841da177e4SLinus Torvalds };
85