summaryrefslogtreecommitdiffstats
path: root/fs/coda/symlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/coda/symlink.c')
-rw-r--r--fs/coda/symlink.c116
1 files changed, 24 insertions, 92 deletions
diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c
index cfe0dbcb7..872370cf9 100644
--- a/fs/coda/symlink.c
+++ b/fs/coda/symlink.c
@@ -14,9 +14,6 @@
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/locks.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <linux/string.h>
#include <linux/coda.h>
#include <linux/coda_linux.h>
@@ -25,99 +22,34 @@
#include <linux/coda_cache.h>
#include <linux/coda_proc.h>
-static int coda_readlink(struct dentry *de, char *buffer, int length);
-static struct dentry *coda_follow_link(struct dentry *, struct dentry *,
- unsigned int);
-
-struct inode_operations coda_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 */
- coda_readlink, /* readlink */
- coda_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
-
-static int coda_readlink(struct dentry *de, char *buffer, int length)
+static int coda_symlink_filler(struct dentry *dentry, struct page *page)
{
- struct inode *inode = de->d_inode;
- int len;
- int error;
- char *buf;
- struct coda_inode_info *cp;
- ENTRY;
-
- cp = ITOC(inode);
- coda_vfs_stat.readlink++;
-
- /* the maximum length we receive is len */
- if ( length > CODA_MAXPATHLEN )
- len = CODA_MAXPATHLEN;
- else
- len = length;
- CODA_ALLOC(buf, char *, len);
- if ( !buf )
- return -ENOMEM;
-
- error = venus_readlink(inode->i_sb, &(cp->c_fid), buf, &len);
-
- CDEBUG(D_INODE, "result %s\n", buf);
- if (! error) {
- copy_to_user(buffer, buf, len);
- put_user('\0', buffer + len);
- error = len;
- }
- if ( buf )
- CODA_FREE(buf, len);
- return error;
-}
-
-static struct dentry *coda_follow_link(struct dentry *de, struct dentry *base,
- unsigned int follow)
-{
- struct inode *inode = de->d_inode;
+ struct inode *inode = dentry->d_inode;
int error;
struct coda_inode_info *cnp;
- unsigned int len;
- char mem[CODA_MAXPATHLEN];
- char *path;
- ENTRY;
- CDEBUG(D_INODE, "(%x/%ld)\n", inode->i_dev, inode->i_ino);
-
+ unsigned int len = PAGE_SIZE;
+ char *p = (char*)kmap(page);
+
cnp = ITOC(inode);
coda_vfs_stat.follow_link++;
- len = CODA_MAXPATHLEN;
- error = venus_readlink(inode->i_sb, &(cnp->c_fid), mem, &len);
-
- if (error) {
- dput(base);
- return ERR_PTR(error);
- }
- len = strlen(mem);
- path = kmalloc(len + 1, GFP_KERNEL);
- if (!path) {
- dput(base);
- return ERR_PTR(-ENOMEM);
- }
- memcpy(path, mem, len);
- path[len] = 0;
-
- base = lookup_dentry(path, base, follow);
- kfree(path);
- return base;
+ error = venus_readlink(inode->i_sb, &(cnp->c_fid), p, &len);
+ if (error)
+ goto fail;
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
+
+fail:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return error;
}
+
+struct inode_operations coda_symlink_inode_operations = {
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: coda_symlink_filler
+};