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 #include <linux/time.h> 14 #include <linux/errno.h> 15 #include <linux/sunrpc/clnt.h> 16 #include <linux/nfs.h> 17 #include <linux/nfs2.h> 18 #include <linux/nfs_fs.h> 19 #include <linux/pagemap.h> 20 #include <linux/stat.h> 21 #include <linux/mm.h> 22 #include <linux/string.h> 23 24 /* Symlink caching in the page cache is even more simplistic 25 * and straight-forward than readdir caching. 26 */ 27 28 static int nfs_symlink_filler(struct inode *inode, struct page *page) 29 { 30 int error; 31 32 error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE); 33 if (error < 0) 34 goto error; 35 SetPageUptodate(page); 36 unlock_page(page); 37 return 0; 38 39 error: 40 SetPageError(page); 41 unlock_page(page); 42 return -EIO; 43 } 44 45 static const char *nfs_get_link(struct dentry *dentry, 46 struct inode *inode, 47 struct delayed_call *done) 48 { 49 struct page *page; 50 void *err; 51 52 if (!dentry) { 53 err = ERR_PTR(nfs_revalidate_mapping_rcu(inode)); 54 if (err) 55 return err; 56 page = find_get_page(inode->i_mapping, 0); 57 if (!page) 58 return ERR_PTR(-ECHILD); 59 if (!PageUptodate(page)) { 60 put_page(page); 61 return ERR_PTR(-ECHILD); 62 } 63 } else { 64 err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping)); 65 if (err) 66 return err; 67 page = read_cache_page(&inode->i_data, 0, 68 (filler_t *)nfs_symlink_filler, inode); 69 if (IS_ERR(page)) 70 return ERR_CAST(page); 71 } 72 set_delayed_call(done, page_put_link, page); 73 return page_address(page); 74 } 75 76 /* 77 * symlinks can't do much... 78 */ 79 const struct inode_operations nfs_symlink_inode_operations = { 80 .readlink = generic_readlink, 81 .get_link = nfs_get_link, 82 .getattr = nfs_getattr, 83 .setattr = nfs_setattr, 84 }; 85