* Copyright (C) 1999 Seagate Technology Inc. (author: braam@stelias.com)
*/
-#include <asm/uaccess.h>
-
-#include <linux/errno.h>
#include <linux/fs.h>
-#include <linux/sched.h>
+#include <linux/ext2_fs.h>
#include <linux/mm.h>
#include <linux/stat.h>
#include <linux/locks.h>
-
#include <linux/obd_support.h> /* for ENTRY and EXIT only */
#include <linux/obdfs.h>
-static struct dentry * obdfs_follow_link(struct dentry * dentry,
- struct dentry *base,
- unsigned int follow)
+static int obdfs_fast_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+ char *s = obdfs_i2info(dentry->d_inode)->oi_inline;
+ return vfs_readlink(dentry, buffer, buflen, s);
+}
+
+static struct dentry *obdfs_fast_follow_link(struct dentry *dentry, struct dentry *base, unsigned flags)
+{
+ char *s = obdfs_i2info(dentry->d_inode)->oi_inline;
+ return vfs_follow_link(dentry, base, flags, s);
+}
+
+struct inode_operations obdfs_fast_symlink_inode_operations = {
+ readlink: obdfs_fast_readlink,
+ follow_link: obdfs_fast_follow_link,
+};
+
+static int obdfs_readlink(struct dentry *dentry, char *buffer, int buflen)
{
- struct inode *inode = dentry->d_inode;
struct page *page = NULL;
- char * link;
+ int res;
ENTRY;
- link = obdfs_i2info(inode)->oi_inline;
- if (!obdfs_has_inline(inode)) {
- OIDEBUG(inode);
- page = obdfs_getpage(inode, 0, 0, 0);
- PDEBUG(page, "follow_link");
- if (!page) {
- dput(base);
- EXIT;
- return ERR_PTR(-EIO);
- }
- link = (char *)page_address(page);
- }
- UPDATE_ATIME(inode);
- base = lookup_dentry(link, base, follow);
- if (page) {
- page_cache_release(page);
+ OIDEBUG(dentry->d_inode);
+ page = obdfs_getpage(dentry->d_inode, 0, 0, 0);
+ /* PDEBUG(page, "readlink"); */
+ if (!page) {
+ EXIT;
+ return 0;
}
+ res = vfs_readlink(dentry, buffer, buflen, (char *)page_address(page));
+ page_cache_release(page);
EXIT;
- return base;
-}
+ return res;
+} /* obdfs_readlink */
-static int obdfs_readlink (struct dentry * dentry, char * buffer, int buflen)
+static struct dentry * obdfs_follow_link(struct dentry * dentry,
+ struct dentry *base,
+ unsigned int follow)
{
- struct inode *inode = dentry->d_inode;
struct page *page = NULL;
- char * link;
- int i;
+ struct dentry *res;
ENTRY;
- if (buflen > inode->i_sb->s_blocksize - 1)
- buflen = inode->i_sb->s_blocksize - 1;
-
- link = obdfs_i2info(inode)->oi_inline;
- if (!obdfs_has_inline(inode)) {
- OIDEBUG(inode);
- page = obdfs_getpage(inode, 0, 0, 0);
- PDEBUG(page, "readlink");
- if (!page) {
- EXIT;
- return 0;
- }
- link = (char *)page_address(page);
- }
-
- i = 0;
- while (i < buflen && link[i])
- i++;
- if (copy_to_user(buffer, link, i))
- i = -EFAULT;
- if (page) {
- page_cache_release(page);
+ OIDEBUG(dentry->d_inode);
+ page = obdfs_getpage(dentry->d_inode, 0, 0, 0);
+ /* PDEBUG(page, "follow_link"); */
+ if (!page) {
+ dput(base);
+ EXIT;
+ return ERR_PTR(-EIO);
}
+ res = vfs_follow_link(dentry, base, follow, (char *)page_address(page));
+ page_cache_release(page);
EXIT;
- return i;
-} /* obdfs_readlink */
+ return res;
+}
-/*
- * symlinks can't do much...
- */
struct inode_operations obdfs_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- obdfs_readlink, /* readlink */
- obdfs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
+ readlink: obdfs_readlink,
+ follow_link: obdfs_follow_link,
};
-