Whamcloud - gitweb
obdfs/super.c: add call to flush pages when unmounting filesystem
[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 */
34 struct dentry * obdfs_follow_link(struct dentry * dentry, 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 */
64 int obdfs_readlink (struct dentry * dentry, char * buffer, int buflen)
65 {
66         struct inode *inode = dentry->d_inode;
67         struct page *page = NULL;
68         char * link;
69         int i;
70
71         ENTRY;
72         if (buflen > inode->i_sb->s_blocksize - 1)
73                 buflen = inode->i_sb->s_blocksize - 1;
74
75         link = obdfs_i2info(inode)->oi_inline;
76         if (!obdfs_has_inline(inode)) {
77                 OIDEBUG(inode);
78                 page = obdfs_getpage(inode, 0, 0, 0);
79                 PDEBUG(page, "readlink");
80                 if (!page) {
81                         EXIT;
82                         return 0;
83                 }
84                 link = (char *)page_address(page);
85         }
86
87         i = 0;
88         while (i < buflen && link[i])
89                 i++;
90         if (copy_to_user(buffer, link, i))
91                 i = -EFAULT;
92         if (page) {
93                 page_cache_release(page);
94         }
95         EXIT;
96         return i;
97 } /* obdfs_readlink */
98
99 /*
100  * symlinks can't do much...
101  */
102 struct inode_operations obdfs_symlink_inode_operations = {
103         NULL,                   /* no file-operations */
104         NULL,                   /* create */
105         NULL,                   /* lookup */
106         NULL,                   /* link */
107         NULL,                   /* unlink */
108         NULL,                   /* symlink */
109         NULL,                   /* mkdir */
110         NULL,                   /* rmdir */
111         NULL,                   /* mknod */
112         NULL,                   /* rename */
113         obdfs_readlink,         /* readlink */
114         obdfs_follow_link,      /* follow_link */
115         NULL,                   /* get_block */
116         NULL,                   /* readpage */
117         NULL,                   /* writepage */
118         NULL,                   /* truncate */
119         NULL,                   /* permission */
120         NULL                    /* revalidate */
121 };
122