forked from Minki/linux
92e1d5be91
Many struct inode_operations in the kernel can be "const". Marking them const moves these to the .rodata section, which avoids false sharing with potential dirty data. In addition it'll catch accidental writes at compile time to these shared resources. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
88 lines
1.8 KiB
C
88 lines
1.8 KiB
C
/*
|
|
* linux/fs/nfs/symlink.c
|
|
*
|
|
* Copyright (C) 1992 Rick Sladkey
|
|
*
|
|
* Optimization changes Copyright (C) 1994 Florian La Roche
|
|
*
|
|
* Jun 7 1999, cache symlink lookups in the page cache. -DaveM
|
|
*
|
|
* nfs symlink handling code
|
|
*/
|
|
|
|
#define NFS_NEED_XDR_TYPES
|
|
#include <linux/time.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/sunrpc/clnt.h>
|
|
#include <linux/nfs.h>
|
|
#include <linux/nfs2.h>
|
|
#include <linux/nfs_fs.h>
|
|
#include <linux/pagemap.h>
|
|
#include <linux/stat.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/string.h>
|
|
#include <linux/smp_lock.h>
|
|
#include <linux/namei.h>
|
|
|
|
/* Symlink caching in the page cache is even more simplistic
|
|
* and straight-forward than readdir caching.
|
|
*/
|
|
|
|
static int nfs_symlink_filler(struct inode *inode, struct page *page)
|
|
{
|
|
int error;
|
|
|
|
error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE);
|
|
if (error < 0)
|
|
goto error;
|
|
SetPageUptodate(page);
|
|
unlock_page(page);
|
|
return 0;
|
|
|
|
error:
|
|
SetPageError(page);
|
|
unlock_page(page);
|
|
return -EIO;
|
|
}
|
|
|
|
static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
|
|
{
|
|
struct inode *inode = dentry->d_inode;
|
|
struct page *page;
|
|
void *err;
|
|
|
|
err = ERR_PTR(nfs_revalidate_mapping_nolock(inode, inode->i_mapping));
|
|
if (err)
|
|
goto read_failed;
|
|
page = read_cache_page(&inode->i_data, 0,
|
|
(filler_t *)nfs_symlink_filler, inode);
|
|
if (IS_ERR(page)) {
|
|
err = page;
|
|
goto read_failed;
|
|
}
|
|
if (!PageUptodate(page)) {
|
|
err = ERR_PTR(-EIO);
|
|
goto getlink_read_error;
|
|
}
|
|
nd_set_link(nd, kmap(page));
|
|
return page;
|
|
|
|
getlink_read_error:
|
|
page_cache_release(page);
|
|
read_failed:
|
|
nd_set_link(nd, err);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* symlinks can't do much...
|
|
*/
|
|
const struct inode_operations nfs_symlink_inode_operations = {
|
|
.readlink = generic_readlink,
|
|
.follow_link = nfs_follow_link,
|
|
.put_link = page_put_link,
|
|
.getattr = nfs_getattr,
|
|
.setattr = nfs_setattr,
|
|
};
|