linux/fs/nfs/symlink.c
<<
>>
Prefs
   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
  28static 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
  39error:
  40        SetPageError(page);
  41        unlock_page(page);
  42        return -EIO;
  43}
  44
  45static 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 */
  79const 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