linux/fs/nfs/symlink.c
<<
>>
Prefs
   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
  29static int nfs_symlink_filler(void *data, struct page *page)
  30{
  31        struct inode *inode = data;
  32        int error;
  33
  34        error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE);
  35        if (error < 0)
  36                goto error;
  37        SetPageUptodate(page);
  38        unlock_page(page);
  39        return 0;
  40
  41error:
  42        SetPageError(page);
  43        unlock_page(page);
  44        return -EIO;
  45}
  46
  47static const char *nfs_get_link(struct dentry *dentry,
  48                                struct inode *inode,
  49                                struct delayed_call *done)
  50{
  51        struct page *page;
  52        void *err;
  53
  54        if (!dentry) {
  55                err = ERR_PTR(nfs_revalidate_mapping_rcu(inode));
  56                if (err)
  57                        return err;
  58                page = find_get_page(inode->i_mapping, 0);
  59                if (!page)
  60                        return ERR_PTR(-ECHILD);
  61                if (!PageUptodate(page)) {
  62                        put_page(page);
  63                        return ERR_PTR(-ECHILD);
  64                }
  65        } else {
  66                err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
  67                if (err)
  68                        return err;
  69                page = read_cache_page(&inode->i_data, 0, nfs_symlink_filler,
  70                                inode);
  71                if (IS_ERR(page))
  72                        return ERR_CAST(page);
  73        }
  74        set_delayed_call(done, page_put_link, page);
  75        return page_address(page);
  76}
  77
  78/*
  79 * symlinks can't do much...
  80 */
  81const struct inode_operations nfs_symlink_inode_operations = {
  82        .get_link       = nfs_get_link,
  83        .getattr        = nfs_getattr,
  84        .setattr        = nfs_setattr,
  85};
  86