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