xref: /linux/fs/nfs/symlink.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
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