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);
351da177e4SLinus Torvalds if (error < 0)
361da177e4SLinus Torvalds goto error;
37e9b5b23eSMatthew Wilcox (Oracle) folio_mark_uptodate(folio);
38e9b5b23eSMatthew Wilcox (Oracle) folio_unlock(folio);
391da177e4SLinus Torvalds return 0;
401da177e4SLinus Torvalds
411da177e4SLinus Torvalds error:
42e9b5b23eSMatthew Wilcox (Oracle) folio_set_error(folio);
43e9b5b23eSMatthew Wilcox (Oracle) folio_unlock(folio);
44*8cebc59dSSagi Grimberg return error;
451da177e4SLinus Torvalds }
461da177e4SLinus Torvalds
nfs_get_link(struct dentry * dentry,struct inode * inode,struct delayed_call * done)476b255391SAl Viro static 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)
606b255391SAl 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 {
661cda707dSTrond Myklebust err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
671da177e4SLinus Torvalds if (err)
68680baacbSAl Viro return err;
69a46126ccSChristoph Hellwig page = read_cache_page(&inode->i_data, 0, nfs_symlink_filler,
706ece0a04SMatthew Wilcox (Oracle) NULL);
71680baacbSAl Viro if (IS_ERR(page))
72680baacbSAl 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 Ven const 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