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