1/* 2 * linux/fs/nfs/symlink.c 3 * 4 * Copyright (C) 1992 Rick Sladkey 5 * 6 * Optimization changes Copyright (C) 1994 Florian La Roche 7 * 8 * Jun 7 1999, cache symlink lookups in the page cache. -DaveM 9 * 10 * nfs symlink handling code 11 */ 12 13#define NFS_NEED_XDR_TYPES 14#include <linux/time.h> 15#include <linux/errno.h> 16#include <linux/sunrpc/clnt.h> 17#include <linux/nfs.h> 18#include <linux/nfs2.h> 19#include <linux/nfs_fs.h> 20#include <linux/pagemap.h> 21#include <linux/stat.h> 22#include <linux/mm.h> 23#include <linux/slab.h> 24#include <linux/string.h> 25#include <linux/namei.h> 26 27/* Symlink caching in the page cache is even more simplistic 28 * and straight-forward than readdir caching. 29 */ 30 31static int nfs_symlink_filler(struct inode *inode, struct page *page) 32{ 33 int error; 34 35 error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE); 36 if (error < 0) 37 goto error; 38 SetPageUptodate(page); 39 unlock_page(page); 40 return 0; 41 42error: 43 SetPageError(page); 44 unlock_page(page); 45 return -EIO; 46} 47 48static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd) 49{ 50 struct inode *inode = dentry->d_inode; 51 struct page *page; 52 void *err; 53 54 err = ERR_PTR(nfs_revalidate_mapping_nolock(inode, inode->i_mapping)); 55 if (err) 56 goto read_failed; 57 page = read_cache_page(&inode->i_data, 0, 58 (filler_t *)nfs_symlink_filler, inode); 59 if (IS_ERR(page)) { 60 err = page; 61 goto read_failed; 62 } 63 nd_set_link(nd, kmap(page)); 64 return page; 65 66read_failed: 67 nd_set_link(nd, err); 68 return NULL; 69} 70 71/* 72 * symlinks can't do much... 73 */ 74const struct inode_operations nfs_symlink_inode_operations = { 75 .readlink = generic_readlink, 76 .follow_link = nfs_follow_link, 77 .put_link = page_put_link, 78 .getattr = nfs_getattr, 79 .setattr = nfs_setattr, 80}; 81