Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 2 : : /* 3 : : * linux/fs/nfs/symlink.c 4 : : * 5 : : * Copyright (C) 1992 Rick Sladkey 6 : : * 7 : : * Optimization changes Copyright (C) 1994 Florian La Roche 8 : : * 9 : : * Jun 7 1999, cache symlink lookups in the page cache. -DaveM 10 : : * 11 : : * nfs symlink handling code 12 : : */ 13 : : 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/string.h> 24 : : 25 : : /* Symlink caching in the page cache is even more simplistic 26 : : * and straight-forward than readdir caching. 27 : : */ 28 : : 29 : 0 : static int nfs_symlink_filler(void *data, struct page *page) 30 : : { 31 : 0 : struct inode *inode = data; 32 : 0 : int error; 33 : : 34 : 0 : error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE); 35 [ # # ]: 0 : if (error < 0) 36 : 0 : goto error; 37 : 0 : SetPageUptodate(page); 38 : 0 : unlock_page(page); 39 : 0 : return 0; 40 : : 41 : : error: 42 : 0 : SetPageError(page); 43 : 0 : unlock_page(page); 44 : 0 : return -EIO; 45 : : } 46 : : 47 : 0 : static const char *nfs_get_link(struct dentry *dentry, 48 : : struct inode *inode, 49 : : struct delayed_call *done) 50 : : { 51 : 0 : struct page *page; 52 : 0 : void *err; 53 : : 54 [ # # ]: 0 : if (!dentry) { 55 [ # # ]: 0 : err = ERR_PTR(nfs_revalidate_mapping_rcu(inode)); 56 [ # # ]: 0 : if (err) 57 : : return err; 58 : 0 : page = find_get_page(inode->i_mapping, 0); 59 [ # # ]: 0 : if (!page) 60 : : return ERR_PTR(-ECHILD); 61 [ # # ]: 0 : if (!PageUptodate(page)) { 62 : 0 : put_page(page); 63 : 0 : return ERR_PTR(-ECHILD); 64 : : } 65 : : } else { 66 [ # # ]: 0 : err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping)); 67 [ # # ]: 0 : if (err) 68 : : return err; 69 : 0 : page = read_cache_page(&inode->i_data, 0, nfs_symlink_filler, 70 : : inode); 71 [ # # ]: 0 : if (IS_ERR(page)) 72 : : return ERR_CAST(page); 73 : : } 74 : 0 : set_delayed_call(done, page_put_link, page); 75 : 0 : return page_address(page); 76 : : } 77 : : 78 : : /* 79 : : * symlinks can't do much... 80 : : */ 81 : : const struct inode_operations nfs_symlink_inode_operations = { 82 : : .get_link = nfs_get_link, 83 : : .getattr = nfs_getattr, 84 : : .setattr = nfs_setattr, 85 : : };