Whamcloud - gitweb
c933a1a773cadf9ebc671729c8e96be9da4f0a3e
[fs/lustre-release.git] / lustre / obdfs / symlink.c
1 /*
2  *  linux/fs/ext2/symlink.c
3  *
4  * Copyright (C) 1992, 1993, 1994, 1995
5  * Remy Card (card@masi.ibp.fr)
6  * Laboratoire MASI - Institut Blaise Pascal
7  * Universite Pierre et Marie Curie (Paris VI)
8  *
9  *  from
10  *
11  *  linux/fs/minix/symlink.c
12  *
13  *  Copyright (C) 1991, 1992  Linus Torvalds
14  *
15  *  ext2 symlink handling code
16  *
17  * Modified for OBDFS: 
18  *  Copyright (C) 1999 Seagate Technology Inc. (author: braam@stelias.com)
19  */
20
21 #include <asm/uaccess.h>
22
23 #include <linux/errno.h>
24 #include <linux/fs.h>
25 #include <linux/sched.h>
26 #include <linux/mm.h>
27 #include <linux/stat.h>
28 #include <linux/locks.h>
29
30 #include <linux/obd_support.h> /* for ENTRY and EXIT only */
31 #include <linux/obdfs.h>
32
33 static int obdfs_readlink (struct dentry *, char *, int);
34 static struct dentry *obdfs_follow_link(struct dentry *, struct dentry *, unsigned int);
35
36 /*
37  * symlinks can't do much...
38  */
39 struct inode_operations obdfs_symlink_inode_operations = {
40         NULL,                   /* no file-operations */
41         NULL,                   /* create */
42         NULL,                   /* lookup */
43         NULL,                   /* link */
44         NULL,                   /* unlink */
45         NULL,                   /* symlink */
46         NULL,                   /* mkdir */
47         NULL,                   /* rmdir */
48         NULL,                   /* mknod */
49         NULL,                   /* rename */
50         obdfs_readlink,         /* readlink */
51         obdfs_follow_link,      /* follow_link */
52         NULL,                   /* get_block */
53         NULL,                   /* readpage */
54         NULL,                   /* writepage */
55         NULL,                   /* truncate */
56         NULL,                   /* permission */
57         NULL                    /* revalidate */
58 };
59
60 static struct dentry * obdfs_follow_link(struct dentry * dentry,
61                                          struct dentry *base,
62                                          unsigned int follow)
63 {
64         struct inode *inode = dentry->d_inode;
65         struct page *page = NULL;
66         char * link;
67
68         ENTRY;
69         link = (char *) inode->u.ext2_i.i_data;
70         if (inode->i_blocks) {
71                 IDEBUG(inode);
72                 page = obdfs_getpage(inode, 0, 0, 0);
73                 PDEBUG(page, "follow_link");
74                 if (!page) {
75                         dput(base);
76                         EXIT;
77                         return ERR_PTR(-EIO);
78                 }
79                 link = (char *)page_address(page);
80         }
81         UPDATE_ATIME(inode);
82         base = lookup_dentry(link, base, follow);
83         if (page) {
84                 page_cache_release(page);
85         }
86         EXIT;
87         return base;
88 }
89
90 static int obdfs_readlink (struct dentry * dentry, char * buffer, int buflen)
91 {
92         struct inode *inode = dentry->d_inode;
93         struct page *page = NULL;
94         char * link;
95         int i;
96
97         ENTRY;
98         if (buflen > inode->i_sb->s_blocksize - 1)
99                 buflen = inode->i_sb->s_blocksize - 1;
100
101         link = (char *) inode->u.ext2_i.i_data;
102         if (inode->i_blocks) {
103                 IDEBUG(inode);
104                 page = obdfs_getpage(inode, 0, 0, 0);
105                 PDEBUG(page, "readlink");
106                 if (!page) {
107                         EXIT;
108                         return 0;
109                 }
110                 link = (char *)page_address(page);
111         }
112
113         i = 0;
114         while (i < buflen && link[i])
115                 i++;
116         if (copy_to_user(buffer, link, i))
117                 i = -EFAULT;
118         if (page) {
119                 page_cache_release(page);
120         }
121         EXIT;
122         return i;
123 } /* obdfs_readlink */