diff options
-rw-r--r-- | fs/autofs4/root.c | 38 | ||||
-rw-r--r-- | fs/namei.c | 50 |
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 | ||
375 | static inline struct dentry * | ||
376 | do_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 | ||
769 | need_revalidate: | 789 | need_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 | ||
777 | fail: | 797 | fail: |
778 | return PTR_ERR(dentry); | 798 | return PTR_ERR(dentry); |