Linux-2.3.7.. Let's be careful out there..
[davej-history.git] / fs / nfs / symlink.c
blobc6fc4d685229e25c3684ab469b88ac9b4728ec5a
1 /*
2 * linux/fs/nfs/symlink.c
4 * Copyright (C) 1992 Rick Sladkey
6 * Optimization changes Copyright (C) 1994 Florian La Roche
8 * Jun 7 1999, cache symlink lookups in the page cache. -DaveM
10 * nfs symlink handling code
13 #define NFS_NEED_XDR_TYPES
14 #include <linux/sched.h>
15 #include <linux/errno.h>
16 #include <linux/sunrpc/clnt.h>
17 #include <linux/nfs_fs.h>
18 #include <linux/nfs.h>
19 #include <linux/pagemap.h>
20 #include <linux/stat.h>
21 #include <linux/mm.h>
22 #include <linux/malloc.h>
23 #include <linux/string.h>
25 #include <asm/uaccess.h>
27 static int nfs_readlink(struct dentry *, char *, int);
28 static struct dentry *nfs_follow_link(struct dentry *, struct dentry *, unsigned int);
31 * symlinks can't do much...
33 struct inode_operations nfs_symlink_inode_operations = {
34 NULL, /* no file-operations */
35 NULL, /* create */
36 NULL, /* lookup */
37 NULL, /* link */
38 NULL, /* unlink */
39 NULL, /* symlink */
40 NULL, /* mkdir */
41 NULL, /* rmdir */
42 NULL, /* mknod */
43 NULL, /* rename */
44 nfs_readlink, /* readlink */
45 nfs_follow_link, /* follow_link */
46 NULL, /* bmap */
47 NULL, /* readpage */
48 NULL, /* writepage */
49 NULL, /* flushpage */
50 NULL, /* truncate */
51 NULL, /* permission */
52 NULL, /* smap */
53 NULL /* revalidate */
56 /* Symlink caching in the page cache is even more simplistic
57 * and straight-forward than readdir caching.
59 static struct page *try_to_get_symlink_page(struct dentry *dentry, struct inode *inode)
61 struct nfs_readlinkargs rl_args;
62 struct page *page, **hash;
63 unsigned long page_cache;
65 page = NULL;
66 page_cache = page_cache_alloc();
67 if (!page_cache)
68 goto out;
70 hash = page_hash(inode, 0);
71 repeat:
72 page = __find_lock_page(inode, 0, hash);
73 if (page) {
74 page_cache_free(page_cache);
75 goto unlock_out;
78 page = page_cache_entry(page_cache);
79 if (add_to_page_cache_unique(page, inode, 0, hash)) {
80 page_cache_release(page);
81 goto repeat;
84 /* We place the length at the beginning of the page,
85 * in host byte order, followed by the string. The
86 * XDR response verification will NULL terminate it.
88 rl_args.fh = NFS_FH(dentry);
89 rl_args.buffer = (const void *)page_cache;
90 if (rpc_call(NFS_CLIENT(inode), NFSPROC_READLINK,
91 &rl_args, NULL, 0) < 0)
92 goto error;
93 SetPageUptodate(page);
94 unlock_out:
95 UnlockPage(page);
96 out:
97 return page;
99 error:
100 SetPageError(page);
101 goto unlock_out;
104 static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen)
106 struct inode *inode = dentry->d_inode;
107 struct page *page;
108 u32 *p, len;
110 /* Caller revalidated the directory inode already. */
111 page = find_get_page(inode, 0);
112 if (!page)
113 goto no_readlink_page;
114 if (!Page_Uptodate(page))
115 goto readlink_read_error;
116 success:
117 p = (u32 *) page_address(page);
118 len = *p++;
119 if (len > buflen)
120 len = buflen;
121 copy_to_user(buffer, p, len);
122 page_cache_release(page);
123 return len;
125 no_readlink_page:
126 page = try_to_get_symlink_page(dentry, inode);
127 if (!page)
128 goto no_page;
129 if (Page_Uptodate(page))
130 goto success;
131 readlink_read_error:
132 page_cache_release(page);
133 no_page:
134 return -EIO;
137 static struct dentry *
138 nfs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow)
140 struct dentry *result;
141 struct inode *inode = dentry->d_inode;
142 struct page *page;
143 u32 *p;
145 /* Caller revalidated the directory inode already. */
146 page = find_get_page(inode, 0);
147 if (!page)
148 goto no_followlink_page;
149 if (!Page_Uptodate(page))
150 goto followlink_read_error;
151 success:
152 p = (u32 *) page_address(page);
153 result = lookup_dentry((char *) (p + 1), base, follow);
154 page_cache_release(page);
155 return result;
157 no_followlink_page:
158 page = try_to_get_symlink_page(dentry, inode);
159 if (!page)
160 goto no_page;
161 if (Page_Uptodate(page))
162 goto success;
163 followlink_read_error:
164 page_cache_release(page);
165 no_page:
166 return ERR_PTR(-EIO);