aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exportfs/expfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exportfs/expfs.c')
-rw-r--r--fs/exportfs/expfs.c128
1 files changed, 72 insertions, 56 deletions
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index db86006956b0..1e6f556514d6 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -6,11 +6,36 @@
6#include <linux/mount.h> 6#include <linux/mount.h>
7#include <linux/namei.h> 7#include <linux/namei.h>
8 8
9struct export_operations export_op_default; 9#define dprintk(fmt, args...) do{}while(0)
10 10
11#define CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun)
12 11
13#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;
33
34 if (nop->get_name)
35 return nop->get_name(dir, name, child);
36 else
37 return get_name(dir, name, child);
38}
14 39
15static struct dentry * 40static struct dentry *
16find_acceptable_alias(struct dentry *result, 41find_acceptable_alias(struct dentry *result,
@@ -78,7 +103,7 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
78{ 103{
79 struct dentry *result = NULL; 104 struct dentry *result = NULL;
80 struct dentry *target_dir; 105 struct dentry *target_dir;
81 int err; 106 int err = -ESTALE;
82 struct export_operations *nops = sb->s_export_op; 107 struct export_operations *nops = sb->s_export_op;
83 struct dentry *alias; 108 struct dentry *alias;
84 int noprogress; 109 int noprogress;
@@ -87,14 +112,10 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
87 /* 112 /*
88 * Attempt to find the inode. 113 * Attempt to find the inode.
89 */ 114 */
90 result = CALL(sb->s_export_op,get_dentry)(sb,obj); 115 result = exportfs_get_dentry(sb, obj);
91 err = -ESTALE; 116 if (IS_ERR(result))
92 if (result == NULL) 117 return result;
93 goto err_out; 118
94 if (IS_ERR(result)) {
95 err = PTR_ERR(result);
96 goto err_out;
97 }
98 if (S_ISDIR(result->d_inode->i_mode) && 119 if (S_ISDIR(result->d_inode->i_mode) &&
99 (result->d_flags & DCACHE_DISCONNECTED)) { 120 (result->d_flags & DCACHE_DISCONNECTED)) {
100 /* it is an unconnected directory, we must connect it */ 121 /* it is an unconnected directory, we must connect it */
@@ -122,11 +143,11 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
122 if (parent == NULL) 143 if (parent == NULL)
123 goto err_result; 144 goto err_result;
124 145
125 target_dir = CALL(sb->s_export_op,get_dentry)(sb,parent); 146 target_dir = exportfs_get_dentry(sb,parent);
126 if (IS_ERR(target_dir)) 147 if (IS_ERR(target_dir)) {
127 err = PTR_ERR(target_dir); 148 err = PTR_ERR(target_dir);
128 if (target_dir == NULL || IS_ERR(target_dir))
129 goto err_result; 149 goto err_result;
150 }
130 } 151 }
131 /* 152 /*
132 * Now we need to make sure that target_dir is properly connected. 153 * Now we need to make sure that target_dir is properly connected.
@@ -177,18 +198,27 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
177 spin_unlock(&pd->d_lock); 198 spin_unlock(&pd->d_lock);
178 noprogress = 0; 199 noprogress = 0;
179 } else { 200 } else {
180 /* we have hit the top of a disconnected path. Try 201 /*
181 * to find parent and connect 202 * We have hit the top of a disconnected path, try to
182 * note: racing with some other process renaming a 203 * find parent and connect.
183 * directory isn't much of a problem here. If someone 204 *
184 * renames the directory, it will end up properly 205 * Racing with some other process renaming a directory
185 * connected, which is what we want 206 * isn't much of a problem here. If someone renames
207 * the directory, it will end up properly connected,
208 * which is what we want
209 *
210 * Getting the parent can't be supported generically,
211 * the locking is too icky.
212 *
213 * Instead we just return EACCES. If server reboots
214 * or inodes get flushed, you lose
186 */ 215 */
187 struct dentry *ppd; 216 struct dentry *ppd = ERR_PTR(-EACCES);
188 struct dentry *npd; 217 struct dentry *npd;
189 218
190 mutex_lock(&pd->d_inode->i_mutex); 219 mutex_lock(&pd->d_inode->i_mutex);
191 ppd = CALL(nops,get_parent)(pd); 220 if (nops->get_parent)
221 ppd = nops->get_parent(pd);
192 mutex_unlock(&pd->d_inode->i_mutex); 222 mutex_unlock(&pd->d_inode->i_mutex);
193 223
194 if (IS_ERR(ppd)) { 224 if (IS_ERR(ppd)) {
@@ -199,7 +229,7 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
199 break; 229 break;
200 } 230 }
201 dprintk("find_exported_dentry: find name of %lu in %lu\n", pd->d_inode->i_ino, ppd->d_inode->i_ino); 231 dprintk("find_exported_dentry: find name of %lu in %lu\n", pd->d_inode->i_ino, ppd->d_inode->i_ino);
202 err = CALL(nops,get_name)(ppd, nbuf, pd); 232 err = exportfs_get_name(ppd, nbuf, pd);
203 if (err) { 233 if (err) {
204 dput(ppd); 234 dput(ppd);
205 dput(pd); 235 dput(pd);
@@ -250,7 +280,7 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
250 /* if we weren't after a directory, have one more step to go */ 280 /* if we weren't after a directory, have one more step to go */
251 if (result != target_dir) { 281 if (result != target_dir) {
252 struct dentry *nresult; 282 struct dentry *nresult;
253 err = CALL(nops,get_name)(target_dir, nbuf, result); 283 err = exportfs_get_name(target_dir, nbuf, result);
254 if (!err) { 284 if (!err) {
255 mutex_lock(&target_dir->d_inode->i_mutex); 285 mutex_lock(&target_dir->d_inode->i_mutex);
256 nresult = lookup_one_len(nbuf, target_dir, strlen(nbuf)); 286 nresult = lookup_one_len(nbuf, target_dir, strlen(nbuf));
@@ -286,23 +316,9 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
286 dput(target_dir); 316 dput(target_dir);
287 err_result: 317 err_result:
288 dput(result); 318 dput(result);
289 err_out:
290 return ERR_PTR(err); 319 return ERR_PTR(err);
291} 320}
292 321
293
294
295static struct dentry *get_parent(struct dentry *child)
296{
297 /* get_parent cannot be supported generically, the locking
298 * is too icky.
299 * instead, we just return EACCES. If server reboots or inodes
300 * get flushed, you lose
301 */
302 return ERR_PTR(-EACCES);
303}
304
305
306struct getdents_callback { 322struct getdents_callback {
307 char *name; /* name that was found. It already points to a 323 char *name; /* name that was found. It already points to a
308 buffer NAME_MAX+1 is size */ 324 buffer NAME_MAX+1 is size */
@@ -392,11 +408,6 @@ out:
392 return error; 408 return error;
393} 409}
394 410
395static struct dentry *get_dentry(struct super_block *sb, void *vobjp)
396{
397 return ERR_PTR(-ESTALE);
398}
399
400/** 411/**
401 * export_encode_fh - default export_operations->encode_fh function 412 * export_encode_fh - default export_operations->encode_fh function
402 * @dentry: the dentry to encode 413 * @dentry: the dentry to encode
@@ -472,9 +483,15 @@ static struct dentry *export_decode_fh(struct super_block *sb, __u32 *fh, int fh
472int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, 483int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
473 int connectable) 484 int connectable)
474{ 485{
475 struct export_operations *nop = dentry->d_sb->s_export_op; 486 struct export_operations *nop = dentry->d_sb->s_export_op;
487 int error;
476 488
477 return CALL(nop, encode_fh)(dentry, fh, max_len, connectable); 489 if (nop->encode_fh)
490 error = nop->encode_fh(dentry, fh, max_len, connectable);
491 else
492 error = export_encode_fh(dentry, fh, max_len, connectable);
493
494 return error;
478} 495}
479EXPORT_SYMBOL_GPL(exportfs_encode_fh); 496EXPORT_SYMBOL_GPL(exportfs_encode_fh);
480 497
@@ -483,21 +500,20 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, __u32 *fh, int fh_len,
483 void *context) 500 void *context)
484{ 501{
485 struct export_operations *nop = mnt->mnt_sb->s_export_op; 502 struct export_operations *nop = mnt->mnt_sb->s_export_op;
503 struct dentry *result;
486 504
487 return CALL(nop, decode_fh)(mnt->mnt_sb, fh, fh_len, fileid_type, 505 if (nop->decode_fh) {
506 result = nop->decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type,
488 acceptable, context); 507 acceptable, context);
508 } else {
509 result = export_decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type,
510 acceptable, context);
511 }
512
513 return result;
489} 514}
490EXPORT_SYMBOL_GPL(exportfs_decode_fh); 515EXPORT_SYMBOL_GPL(exportfs_decode_fh);
491 516
492struct export_operations export_op_default = {
493 .decode_fh = export_decode_fh,
494 .encode_fh = export_encode_fh,
495
496 .get_name = get_name,
497 .get_parent = get_parent,
498 .get_dentry = get_dentry,
499};
500
501EXPORT_SYMBOL(find_exported_dentry); 517EXPORT_SYMBOL(find_exported_dentry);
502 518
503MODULE_LICENSE("GPL"); 519MODULE_LICENSE("GPL");