aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2006-09-27 04:50:44 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-27 11:26:17 -0400
commitbcdc5e019d9f525a9f181a7de642d3a9c27c7610 (patch)
treec2a93b8456095b260bee2be6e169c116f4b0be84 /fs/namei.c
parent1183dc943cae8b0fddca0b310c26052b2355e04b (diff)
[PATCH] autofs4 needs to force fail return revalidate
For a long time now I have had a problem with not being able to return a lookup failure on an existsing directory. In autofs this corresponds to a mount failure on a autofs managed mount entry that is browsable (and so the mount point directory exists). While this problem has been present for a long time I've avoided resolving it because it was not very visible. But now that autofs v5 has "mount and expire on demand" of nested multiple mounts, such as is found when mounting an export list from a server, solving the problem cannot be avoided any longer. I've tried very hard to find a way to do this entirely within the autofs4 module but have not been able to find a satisfactory way to achieve it. So, I need to propose a change to the VFS. Signed-off-by: Ian Kent <raven@themaw.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c50
1 files changed, 35 insertions, 15 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 6b591c01b09f..808e4ea2bb94 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -372,6 +372,30 @@ void release_open_intent(struct nameidata *nd)
372 fput(nd->intent.open.file); 372 fput(nd->intent.open.file);
373} 373}
374 374
375static inline struct dentry *
376do_revalidate(struct dentry *dentry, struct nameidata *nd)
377{
378 int status = dentry->d_op->d_revalidate(dentry, nd);
379 if (unlikely(status <= 0)) {
380 /*
381 * The dentry failed validation.
382 * If d_revalidate returned 0 attempt to invalidate
383 * the dentry otherwise d_revalidate is asking us
384 * to return a fail status.
385 */
386 if (!status) {
387 if (!d_invalidate(dentry)) {
388 dput(dentry);
389 dentry = NULL;
390 }
391 } else {
392 dput(dentry);
393 dentry = ERR_PTR(status);
394 }
395 }
396 return dentry;
397}
398
375/* 399/*
376 * Internal lookup() using the new generic dcache. 400 * Internal lookup() using the new generic dcache.
377 * SMP-safe 401 * SMP-safe
@@ -386,12 +410,9 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name,
386 if (!dentry) 410 if (!dentry)
387 dentry = d_lookup(parent, name); 411 dentry = d_lookup(parent, name);
388 412
389 if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { 413 if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
390 if (!dentry->d_op->d_revalidate(dentry, nd) && !d_invalidate(dentry)) { 414 dentry = do_revalidate(dentry, nd);
391 dput(dentry); 415
392 dentry = NULL;
393 }
394 }
395 return dentry; 416 return dentry;
396} 417}
397 418
@@ -484,10 +505,9 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
484 */ 505 */
485 mutex_unlock(&dir->i_mutex); 506 mutex_unlock(&dir->i_mutex);
486 if (result->d_op && result->d_op->d_revalidate) { 507 if (result->d_op && result->d_op->d_revalidate) {
487 if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) { 508 result = do_revalidate(result, nd);
488 dput(result); 509 if (!result)
489 result = ERR_PTR(-ENOENT); 510 result = ERR_PTR(-ENOENT);
490 }
491 } 511 }
492 return result; 512 return result;
493} 513}
@@ -767,12 +787,12 @@ need_lookup:
767 goto done; 787 goto done;
768 788
769need_revalidate: 789need_revalidate:
770 if (dentry->d_op->d_revalidate(dentry, nd)) 790 dentry = do_revalidate(dentry, nd);
771 goto done; 791 if (!dentry)
772 if (d_invalidate(dentry)) 792 goto need_lookup;
773 goto done; 793 if (IS_ERR(dentry))
774 dput(dentry); 794 goto fail;
775 goto need_lookup; 795 goto done;
776 796
777fail: 797fail:
778 return PTR_ERR(dentry); 798 return PTR_ERR(dentry);