aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/autofs4/root.c38
-rw-r--r--fs/namei.c50
2 files changed, 65 insertions, 23 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 5100f984783f..27e17f96cada 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -137,7 +137,9 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
137 nd.flags = LOOKUP_DIRECTORY; 137 nd.flags = LOOKUP_DIRECTORY;
138 ret = (dentry->d_op->d_revalidate)(dentry, &nd); 138 ret = (dentry->d_op->d_revalidate)(dentry, &nd);
139 139
140 if (!ret) { 140 if (ret <= 0) {
141 if (ret < 0)
142 status = ret;
141 dcache_dir_close(inode, file); 143 dcache_dir_close(inode, file);
142 goto out; 144 goto out;
143 } 145 }
@@ -400,13 +402,23 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
400 struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); 402 struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
401 int oz_mode = autofs4_oz_mode(sbi); 403 int oz_mode = autofs4_oz_mode(sbi);
402 int flags = nd ? nd->flags : 0; 404 int flags = nd ? nd->flags : 0;
403 int status = 0; 405 int status = 1;
404 406
405 /* Pending dentry */ 407 /* Pending dentry */
406 if (autofs4_ispending(dentry)) { 408 if (autofs4_ispending(dentry)) {
407 if (!oz_mode) 409 /* The daemon never causes a mount to trigger */
408 status = try_to_fill_dentry(dentry, flags); 410 if (oz_mode)
409 return !status; 411 return 1;
412
413 /*
414 * A zero status is success otherwise we have a
415 * negative error code.
416 */
417 status = try_to_fill_dentry(dentry, flags);
418 if (status == 0)
419 return 1;
420
421 return status;
410 } 422 }
411 423
412 /* Negative dentry.. invalidate if "old" */ 424 /* Negative dentry.. invalidate if "old" */
@@ -421,9 +433,19 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
421 DPRINTK("dentry=%p %.*s, emptydir", 433 DPRINTK("dentry=%p %.*s, emptydir",
422 dentry, dentry->d_name.len, dentry->d_name.name); 434 dentry, dentry->d_name.len, dentry->d_name.name);
423 spin_unlock(&dcache_lock); 435 spin_unlock(&dcache_lock);
424 if (!oz_mode) 436 /* The daemon never causes a mount to trigger */
425 status = try_to_fill_dentry(dentry, flags); 437 if (oz_mode)
426 return !status; 438 return 1;
439
440 /*
441 * A zero status is success otherwise we have a
442 * negative error code.
443 */
444 status = try_to_fill_dentry(dentry, flags);
445 if (status == 0)
446 return 1;
447
448 return status;
427 } 449 }
428 spin_unlock(&dcache_lock); 450 spin_unlock(&dcache_lock);
429 451
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);