aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exportfs/expfs.c
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2007-07-23 05:20:10 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2007-07-23 05:20:10 -0400
commit39fe5434cb9de5da40510028b17b96bc4eb312b3 (patch)
tree7a02a317b9ad57da51ca99887c119e779ccf3f13 /fs/exportfs/expfs.c
parent0fc72b81d3111d114ab378935b1cf07680ca1289 (diff)
parentf695baf2df9e0413d3521661070103711545207a (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'fs/exportfs/expfs.c')
-rw-r--r--fs/exportfs/expfs.c439
1 files changed, 220 insertions, 219 deletions
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index e98f6cd7200c..8adb32a9387a 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -1,15 +1,45 @@
1 1
2#include <linux/exportfs.h>
2#include <linux/fs.h> 3#include <linux/fs.h>
3#include <linux/file.h> 4#include <linux/file.h>
4#include <linux/module.h> 5#include <linux/module.h>
6#include <linux/mount.h>
5#include <linux/namei.h> 7#include <linux/namei.h>
6 8
7struct export_operations export_op_default; 9#define dprintk(fmt, args...) do{}while(0)
8 10
9#define CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun)
10 11
11#define dprintk(fmt, args...) do{}while(0) 12static int get_name(struct dentry *dentry, char *name,
13 struct dentry *child);
14
15
16static struct dentry *exportfs_get_dentry(struct super_block *sb, void *obj)
17{
18 struct dentry *result = ERR_PTR(-ESTALE);
19
20 if (sb->s_export_op->get_dentry) {
21 result = sb->s_export_op->get_dentry(sb, obj);
22 if (!result)
23 result = ERR_PTR(-ESTALE);
24 }
25
26 return result;
27}
28
29static int exportfs_get_name(struct dentry *dir, char *name,
30 struct dentry *child)
31{
32 struct export_operations *nop = dir->d_sb->s_export_op;
12 33
34 if (nop->get_name)
35 return nop->get_name(dir, name, child);
36 else
37 return get_name(dir, name, child);
38}
39
40/*
41 * Check if the dentry or any of it's aliases is acceptable.
42 */
13static struct dentry * 43static struct dentry *
14find_acceptable_alias(struct dentry *result, 44find_acceptable_alias(struct dentry *result,
15 int (*acceptable)(void *context, struct dentry *dentry), 45 int (*acceptable)(void *context, struct dentry *dentry),
@@ -17,6 +47,9 @@ find_acceptable_alias(struct dentry *result,
17{ 47{
18 struct dentry *dentry, *toput = NULL; 48 struct dentry *dentry, *toput = NULL;
19 49
50 if (acceptable(context, result))
51 return result;
52
20 spin_lock(&dcache_lock); 53 spin_lock(&dcache_lock);
21 list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) { 54 list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) {
22 dget_locked(dentry); 55 dget_locked(dentry);
@@ -37,130 +70,50 @@ find_acceptable_alias(struct dentry *result,
37 return NULL; 70 return NULL;
38} 71}
39 72
40/** 73/*
41 * find_exported_dentry - helper routine to implement export_operations->decode_fh 74 * Find root of a disconnected subtree and return a reference to it.
42 * @sb: The &super_block identifying the filesystem
43 * @obj: An opaque identifier of the object to be found - passed to
44 * get_inode
45 * @parent: An optional opqaue identifier of the parent of the object.
46 * @acceptable: A function used to test possible &dentries to see if they are
47 * acceptable
48 * @context: A parameter to @acceptable so that it knows on what basis to
49 * judge.
50 *
51 * find_exported_dentry is the central helper routine to enable file systems
52 * to provide the decode_fh() export_operation. It's main task is to take
53 * an &inode, find or create an appropriate &dentry structure, and possibly
54 * splice this into the dcache in the correct place.
55 *
56 * The decode_fh() operation provided by the filesystem should call
57 * find_exported_dentry() with the same parameters that it received except
58 * that instead of the file handle fragment, pointers to opaque identifiers
59 * for the object and optionally its parent are passed. The default decode_fh
60 * routine passes one pointer to the start of the filehandle fragment, and
61 * one 8 bytes into the fragment. It is expected that most filesystems will
62 * take this approach, though the offset to the parent identifier may well be
63 * different.
64 *
65 * find_exported_dentry() will call get_dentry to get an dentry pointer from
66 * the file system. If any &dentry in the d_alias list is acceptable, it will
67 * be returned. Otherwise find_exported_dentry() will attempt to splice a new
68 * &dentry into the dcache using get_name() and get_parent() to find the
69 * appropriate place.
70 */ 75 */
71 76static struct dentry *
72struct dentry * 77find_disconnected_root(struct dentry *dentry)
73find_exported_dentry(struct super_block *sb, void *obj, void *parent,
74 int (*acceptable)(void *context, struct dentry *de),
75 void *context)
76{ 78{
77 struct dentry *result = NULL; 79 dget(dentry);
78 struct dentry *target_dir; 80 spin_lock(&dentry->d_lock);
79 int err; 81 while (!IS_ROOT(dentry) &&
80 struct export_operations *nops = sb->s_export_op; 82 (dentry->d_parent->d_flags & DCACHE_DISCONNECTED)) {
81 struct dentry *alias; 83 struct dentry *parent = dentry->d_parent;
82 int noprogress; 84 dget(parent);
83 char nbuf[NAME_MAX+1]; 85 spin_unlock(&dentry->d_lock);
84 86 dput(dentry);
85 /* 87 dentry = parent;
86 * Attempt to find the inode. 88 spin_lock(&dentry->d_lock);
87 */
88 result = CALL(sb->s_export_op,get_dentry)(sb,obj);
89 err = -ESTALE;
90 if (result == NULL)
91 goto err_out;
92 if (IS_ERR(result)) {
93 err = PTR_ERR(result);
94 goto err_out;
95 } 89 }
96 if (S_ISDIR(result->d_inode->i_mode) && 90 spin_unlock(&dentry->d_lock);
97 (result->d_flags & DCACHE_DISCONNECTED)) { 91 return dentry;
98 /* it is an unconnected directory, we must connect it */ 92}
99 ;
100 } else {
101 if (acceptable(context, result))
102 return result;
103 if (S_ISDIR(result->d_inode->i_mode)) {
104 err = -EACCES;
105 goto err_result;
106 }
107 93
108 alias = find_acceptable_alias(result, acceptable, context);
109 if (alias)
110 return alias;
111 }
112
113 /* It's a directory, or we are required to confirm the file's
114 * location in the tree based on the parent information
115 */
116 dprintk("find_exported_dentry: need to look harder for %s/%d\n",sb->s_id,*(int*)obj);
117 if (S_ISDIR(result->d_inode->i_mode))
118 target_dir = dget(result);
119 else {
120 if (parent == NULL)
121 goto err_result;
122 94
123 target_dir = CALL(sb->s_export_op,get_dentry)(sb,parent); 95/*
124 if (IS_ERR(target_dir)) 96 * Make sure target_dir is fully connected to the dentry tree.
125 err = PTR_ERR(target_dir); 97 *
126 if (target_dir == NULL || IS_ERR(target_dir)) 98 * It may already be, as the flag isn't always updated when connection happens.
127 goto err_result; 99 */
128 } 100static int
129 /* 101reconnect_path(struct super_block *sb, struct dentry *target_dir)
130 * Now we need to make sure that target_dir is properly connected. 102{
131 * It may already be, as the flag isn't always updated when connection 103 char nbuf[NAME_MAX+1];
132 * happens. 104 int noprogress = 0;
133 * So, we walk up parent links until we find a connected directory, 105 int err = -ESTALE;
134 * or we run out of directories. Then we find the parent, find
135 * the name of the child in that parent, and do a lookup.
136 * This should connect the child into the parent
137 * We then repeat.
138 */
139 106
140 /* it is possible that a confused file system might not let us complete 107 /*
108 * It is possible that a confused file system might not let us complete
141 * the path to the root. For example, if get_parent returns a directory 109 * the path to the root. For example, if get_parent returns a directory
142 * in which we cannot find a name for the child. While this implies a 110 * in which we cannot find a name for the child. While this implies a
143 * very sick filesystem we don't want it to cause knfsd to spin. Hence 111 * very sick filesystem we don't want it to cause knfsd to spin. Hence
144 * the noprogress counter. If we go through the loop 10 times (2 is 112 * the noprogress counter. If we go through the loop 10 times (2 is
145 * probably enough) without getting anywhere, we just give up 113 * probably enough) without getting anywhere, we just give up
146 */ 114 */
147 noprogress= 0;
148 while (target_dir->d_flags & DCACHE_DISCONNECTED && noprogress++ < 10) { 115 while (target_dir->d_flags & DCACHE_DISCONNECTED && noprogress++ < 10) {
149 struct dentry *pd = target_dir; 116 struct dentry *pd = find_disconnected_root(target_dir);
150
151 dget(pd);
152 spin_lock(&pd->d_lock);
153 while (!IS_ROOT(pd) &&
154 (pd->d_parent->d_flags&DCACHE_DISCONNECTED)) {
155 struct dentry *parent = pd->d_parent;
156
157 dget(parent);
158 spin_unlock(&pd->d_lock);
159 dput(pd);
160 pd = parent;
161 spin_lock(&pd->d_lock);
162 }
163 spin_unlock(&pd->d_lock);
164 117
165 if (!IS_ROOT(pd)) { 118 if (!IS_ROOT(pd)) {
166 /* must have found a connected parent - great */ 119 /* must have found a connected parent - great */
@@ -175,29 +128,40 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
175 spin_unlock(&pd->d_lock); 128 spin_unlock(&pd->d_lock);
176 noprogress = 0; 129 noprogress = 0;
177 } else { 130 } else {
178 /* we have hit the top of a disconnected path. Try 131 /*
179 * to find parent and connect 132 * We have hit the top of a disconnected path, try to
180 * note: racing with some other process renaming a 133 * find parent and connect.
181 * directory isn't much of a problem here. If someone 134 *
182 * renames the directory, it will end up properly 135 * Racing with some other process renaming a directory
183 * connected, which is what we want 136 * isn't much of a problem here. If someone renames
137 * the directory, it will end up properly connected,
138 * which is what we want
139 *
140 * Getting the parent can't be supported generically,
141 * the locking is too icky.
142 *
143 * Instead we just return EACCES. If server reboots
144 * or inodes get flushed, you lose
184 */ 145 */
185 struct dentry *ppd; 146 struct dentry *ppd = ERR_PTR(-EACCES);
186 struct dentry *npd; 147 struct dentry *npd;
187 148
188 mutex_lock(&pd->d_inode->i_mutex); 149 mutex_lock(&pd->d_inode->i_mutex);
189 ppd = CALL(nops,get_parent)(pd); 150 if (sb->s_export_op->get_parent)
151 ppd = sb->s_export_op->get_parent(pd);
190 mutex_unlock(&pd->d_inode->i_mutex); 152 mutex_unlock(&pd->d_inode->i_mutex);
191 153
192 if (IS_ERR(ppd)) { 154 if (IS_ERR(ppd)) {
193 err = PTR_ERR(ppd); 155 err = PTR_ERR(ppd);
194 dprintk("find_exported_dentry: get_parent of %ld failed, err %d\n", 156 dprintk("%s: get_parent of %ld failed, err %d\n",
195 pd->d_inode->i_ino, err); 157 __FUNCTION__, pd->d_inode->i_ino, err);
196 dput(pd); 158 dput(pd);
197 break; 159 break;
198 } 160 }
199 dprintk("find_exported_dentry: find name of %lu in %lu\n", pd->d_inode->i_ino, ppd->d_inode->i_ino); 161
200 err = CALL(nops,get_name)(ppd, nbuf, pd); 162 dprintk("%s: find name of %lu in %lu\n", __FUNCTION__,
163 pd->d_inode->i_ino, ppd->d_inode->i_ino);
164 err = exportfs_get_name(ppd, nbuf, pd);
201 if (err) { 165 if (err) {
202 dput(ppd); 166 dput(ppd);
203 dput(pd); 167 dput(pd);
@@ -208,13 +172,14 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
208 continue; 172 continue;
209 break; 173 break;
210 } 174 }
211 dprintk("find_exported_dentry: found name: %s\n", nbuf); 175 dprintk("%s: found name: %s\n", __FUNCTION__, nbuf);
212 mutex_lock(&ppd->d_inode->i_mutex); 176 mutex_lock(&ppd->d_inode->i_mutex);
213 npd = lookup_one_len(nbuf, ppd, strlen(nbuf)); 177 npd = lookup_one_len(nbuf, ppd, strlen(nbuf));
214 mutex_unlock(&ppd->d_inode->i_mutex); 178 mutex_unlock(&ppd->d_inode->i_mutex);
215 if (IS_ERR(npd)) { 179 if (IS_ERR(npd)) {
216 err = PTR_ERR(npd); 180 err = PTR_ERR(npd);
217 dprintk("find_exported_dentry: lookup failed: %d\n", err); 181 dprintk("%s: lookup failed: %d\n",
182 __FUNCTION__, err);
218 dput(ppd); 183 dput(ppd);
219 dput(pd); 184 dput(pd);
220 break; 185 break;
@@ -227,7 +192,7 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
227 if (npd == pd) 192 if (npd == pd)
228 noprogress = 0; 193 noprogress = 0;
229 else 194 else
230 printk("find_exported_dentry: npd != pd\n"); 195 printk("%s: npd != pd\n", __FUNCTION__);
231 dput(npd); 196 dput(npd);
232 dput(ppd); 197 dput(ppd);
233 if (IS_ROOT(pd)) { 198 if (IS_ROOT(pd)) {
@@ -243,15 +208,101 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
243 /* something went wrong - oh-well */ 208 /* something went wrong - oh-well */
244 if (!err) 209 if (!err)
245 err = -ESTALE; 210 err = -ESTALE;
246 goto err_target; 211 return err;
247 } 212 }
248 /* if we weren't after a directory, have one more step to go */ 213
249 if (result != target_dir) { 214 return 0;
250 struct dentry *nresult; 215}
251 err = CALL(nops,get_name)(target_dir, nbuf, result); 216
217/**
218 * find_exported_dentry - helper routine to implement export_operations->decode_fh
219 * @sb: The &super_block identifying the filesystem
220 * @obj: An opaque identifier of the object to be found - passed to
221 * get_inode
222 * @parent: An optional opqaue identifier of the parent of the object.
223 * @acceptable: A function used to test possible &dentries to see if they are
224 * acceptable
225 * @context: A parameter to @acceptable so that it knows on what basis to
226 * judge.
227 *
228 * find_exported_dentry is the central helper routine to enable file systems
229 * to provide the decode_fh() export_operation. It's main task is to take
230 * an &inode, find or create an appropriate &dentry structure, and possibly
231 * splice this into the dcache in the correct place.
232 *
233 * The decode_fh() operation provided by the filesystem should call
234 * find_exported_dentry() with the same parameters that it received except
235 * that instead of the file handle fragment, pointers to opaque identifiers
236 * for the object and optionally its parent are passed. The default decode_fh
237 * routine passes one pointer to the start of the filehandle fragment, and
238 * one 8 bytes into the fragment. It is expected that most filesystems will
239 * take this approach, though the offset to the parent identifier may well be
240 * different.
241 *
242 * find_exported_dentry() will call get_dentry to get an dentry pointer from
243 * the file system. If any &dentry in the d_alias list is acceptable, it will
244 * be returned. Otherwise find_exported_dentry() will attempt to splice a new
245 * &dentry into the dcache using get_name() and get_parent() to find the
246 * appropriate place.
247 */
248
249struct dentry *
250find_exported_dentry(struct super_block *sb, void *obj, void *parent,
251 int (*acceptable)(void *context, struct dentry *de),
252 void *context)
253{
254 struct dentry *result, *alias;
255 int err = -ESTALE;
256
257 /*
258 * Attempt to find the inode.
259 */
260 result = exportfs_get_dentry(sb, obj);
261 if (IS_ERR(result))
262 return result;
263
264 if (S_ISDIR(result->d_inode->i_mode)) {
265 if (!(result->d_flags & DCACHE_DISCONNECTED)) {
266 if (acceptable(context, result))
267 return result;
268 err = -EACCES;
269 goto err_result;
270 }
271
272 err = reconnect_path(sb, result);
273 if (err)
274 goto err_result;
275 } else {
276 struct dentry *target_dir, *nresult;
277 char nbuf[NAME_MAX+1];
278
279 alias = find_acceptable_alias(result, acceptable, context);
280 if (alias)
281 return alias;
282
283 if (parent == NULL)
284 goto err_result;
285
286 target_dir = exportfs_get_dentry(sb,parent);
287 if (IS_ERR(target_dir)) {
288 err = PTR_ERR(target_dir);
289 goto err_result;
290 }
291
292 err = reconnect_path(sb, target_dir);
293 if (err) {
294 dput(target_dir);
295 goto err_result;
296 }
297
298 /*
299 * As we weren't after a directory, have one more step to go.
300 */
301 err = exportfs_get_name(target_dir, nbuf, result);
252 if (!err) { 302 if (!err) {
253 mutex_lock(&target_dir->d_inode->i_mutex); 303 mutex_lock(&target_dir->d_inode->i_mutex);
254 nresult = lookup_one_len(nbuf, target_dir, strlen(nbuf)); 304 nresult = lookup_one_len(nbuf, target_dir,
305 strlen(nbuf));
255 mutex_unlock(&target_dir->d_inode->i_mutex); 306 mutex_unlock(&target_dir->d_inode->i_mutex);
256 if (!IS_ERR(nresult)) { 307 if (!IS_ERR(nresult)) {
257 if (nresult->d_inode) { 308 if (nresult->d_inode) {
@@ -261,11 +312,8 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
261 dput(nresult); 312 dput(nresult);
262 } 313 }
263 } 314 }
315 dput(target_dir);
264 } 316 }
265 dput(target_dir);
266 /* now result is properly connected, it is our best bet */
267 if (acceptable(context, result))
268 return result;
269 317
270 alias = find_acceptable_alias(result, acceptable, context); 318 alias = find_acceptable_alias(result, acceptable, context);
271 if (alias) 319 if (alias)
@@ -275,32 +323,16 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
275 dput(result); 323 dput(result);
276 /* It might be justifiable to return ESTALE here, 324 /* It might be justifiable to return ESTALE here,
277 * but the filehandle at-least looks reasonable good 325 * but the filehandle at-least looks reasonable good
278 * and it just be a permission problem, so returning 326 * and it may just be a permission problem, so returning
279 * -EACCESS is safer 327 * -EACCESS is safer
280 */ 328 */
281 return ERR_PTR(-EACCES); 329 return ERR_PTR(-EACCES);
282 330
283 err_target:
284 dput(target_dir);
285 err_result: 331 err_result:
286 dput(result); 332 dput(result);
287 err_out:
288 return ERR_PTR(err); 333 return ERR_PTR(err);
289} 334}
290 335
291
292
293static struct dentry *get_parent(struct dentry *child)
294{
295 /* get_parent cannot be supported generically, the locking
296 * is too icky.
297 * instead, we just return EACCES. If server reboots or inodes
298 * get flushed, you lose
299 */
300 return ERR_PTR(-EACCES);
301}
302
303
304struct getdents_callback { 336struct getdents_callback {
305 char *name; /* name that was found. It already points to a 337 char *name; /* name that was found. It already points to a
306 buffer NAME_MAX+1 is size */ 338 buffer NAME_MAX+1 is size */
@@ -390,61 +422,6 @@ out:
390 return error; 422 return error;
391} 423}
392 424
393
394static struct dentry *export_iget(struct super_block *sb, unsigned long ino, __u32 generation)
395{
396
397 /* iget isn't really right if the inode is currently unallocated!!
398 * This should really all be done inside each filesystem
399 *
400 * ext2fs' read_inode has been strengthed to return a bad_inode if
401 * the inode had been deleted.
402 *
403 * Currently we don't know the generation for parent directory, so
404 * a generation of 0 means "accept any"
405 */
406 struct inode *inode;
407 struct dentry *result;
408 if (ino == 0)
409 return ERR_PTR(-ESTALE);
410 inode = iget(sb, ino);
411 if (inode == NULL)
412 return ERR_PTR(-ENOMEM);
413 if (is_bad_inode(inode)
414 || (generation && inode->i_generation != generation)
415 ) {
416 /* we didn't find the right inode.. */
417 dprintk("fh_verify: Inode %lu, Bad count: %d %d or version %u %u\n",
418 inode->i_ino,
419 inode->i_nlink, atomic_read(&inode->i_count),
420 inode->i_generation,
421 generation);
422
423 iput(inode);
424 return ERR_PTR(-ESTALE);
425 }
426 /* now to find a dentry.
427 * If possible, get a well-connected one
428 */
429 result = d_alloc_anon(inode);
430 if (!result) {
431 iput(inode);
432 return ERR_PTR(-ENOMEM);
433 }
434 return result;
435}
436
437
438static struct dentry *get_object(struct super_block *sb, void *vobjp)
439{
440 __u32 *objp = vobjp;
441 unsigned long ino = objp[0];
442 __u32 generation = objp[1];
443
444 return export_iget(sb, ino, generation);
445}
446
447
448/** 425/**
449 * export_encode_fh - default export_operations->encode_fh function 426 * export_encode_fh - default export_operations->encode_fh function
450 * @dentry: the dentry to encode 427 * @dentry: the dentry to encode
@@ -517,16 +494,40 @@ static struct dentry *export_decode_fh(struct super_block *sb, __u32 *fh, int fh
517 acceptable, context); 494 acceptable, context);
518} 495}
519 496
520struct export_operations export_op_default = { 497int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
521 .decode_fh = export_decode_fh, 498 int connectable)
522 .encode_fh = export_encode_fh, 499{
500 struct export_operations *nop = dentry->d_sb->s_export_op;
501 int error;
502
503 if (nop->encode_fh)
504 error = nop->encode_fh(dentry, fh, max_len, connectable);
505 else
506 error = export_encode_fh(dentry, fh, max_len, connectable);
523 507
524 .get_name = get_name, 508 return error;
525 .get_parent = get_parent, 509}
526 .get_dentry = get_object, 510EXPORT_SYMBOL_GPL(exportfs_encode_fh);
527}; 511
512struct dentry *exportfs_decode_fh(struct vfsmount *mnt, __u32 *fh, int fh_len,
513 int fileid_type, int (*acceptable)(void *, struct dentry *),
514 void *context)
515{
516 struct export_operations *nop = mnt->mnt_sb->s_export_op;
517 struct dentry *result;
518
519 if (nop->decode_fh) {
520 result = nop->decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type,
521 acceptable, context);
522 } else {
523 result = export_decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type,
524 acceptable, context);
525 }
526
527 return result;
528}
529EXPORT_SYMBOL_GPL(exportfs_decode_fh);
528 530
529EXPORT_SYMBOL(export_op_default);
530EXPORT_SYMBOL(find_exported_dentry); 531EXPORT_SYMBOL(find_exported_dentry);
531 532
532MODULE_LICENSE("GPL"); 533MODULE_LICENSE("GPL");