Whamcloud - gitweb
class/obdcontrol: added "basedev" parameter to the attach command
[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 /*
34 static int obdfs_readlink (struct dentry *, char *, int);
35 static struct dentry *obdfs_follow_link(struct dentry *, struct dentry *, unsigned int);
36 */
37
38 /*
39  * symlinks can't do much...
40  */
41 struct inode_operations obdfs_symlink_inode_operations = {
42         NULL,                   /* no file-operations */
43         NULL,                   /* create */
44         NULL,                   /* lookup */
45         NULL,                   /* link */
46         NULL,                   /* unlink */
47         NULL,                   /* symlink */
48         NULL,                   /* mkdir */
49         NULL,                   /* rmdir */
50         NULL,                   /* mknod */
51         NULL,                   /* rename */
52         obdfs_readlink,         /* readlink */
53         obdfs_follow_link,      /* follow_link */
54         NULL,                   /* get_block */
55         NULL,                   /* readpage */
56         NULL,                   /* writepage */
57         NULL,                   /* truncate */
58         NULL,                   /* permission */
59         NULL                    /* revalidate */
60 };
61
62 /* static */
63 struct dentry * obdfs_follow_link(struct dentry * dentry,
64                                          struct dentry *base,
65                                          unsigned int follow)
66 {
67         struct inode *inode = dentry->d_inode;
68         struct page *page = NULL;
69         char * link;
70
71         ENTRY;
72         link = (char *) inode->u.ext2_i.i_data;
73         if (inode->i_blocks) {
74                 IDEBUG(inode);
75                 page = obdfs_getpage(inode, 0, 0, 0);
76                 PDEBUG(page, "follow_link");
77                 if (!page) {
78                         dput(base);
79                         EXIT;
80                         return ERR_PTR(-EIO);
81                 }
82                 link = (char *)page_address(page);
83         }
84         UPDATE_ATIME(inode);
85         base = lookup_dentry(link, base, follow);
86         if (page) {
87                 page_cache_release(page);
88         }
89         EXIT;
90         return base;
91 }
92
93 /* static */
94 int obdfs_readlink (struct dentry * dentry, char * buffer, int buflen)
95 {
96         struct inode *inode = dentry->d_inode;
97         struct page *page = NULL;
98         char * link;
99         int i;
100
101         ENTRY;
102         if (buflen > inode->i_sb->s_blocksize - 1)
103                 buflen = inode->i_sb->s_blocksize - 1;
104
105         link = (char *) inode->u.ext2_i.i_data;
106         if (inode->i_blocks) {
107                 IDEBUG(inode);
108                 page = obdfs_getpage(inode, 0, 0, 0);
109                 PDEBUG(page, "readlink");
110                 if (!page) {
111                         EXIT;
112                         return 0;
113                 }
114                 link = (char *)page_address(page);
115         }
116
117         i = 0;
118         while (i < buflen && link[i])
119                 i++;
120         if (copy_to_user(buffer, link, i))
121                 i = -EFAULT;
122         if (page) {
123                 page_cache_release(page);
124         }
125         EXIT;
126         return i;
127 } /* obdfs_readlink */