diff options
Diffstat (limited to 'fs/namei.c')
| -rw-r--r-- | fs/namei.c | 50 |
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 | ||
| 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); |
