diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-05-28 13:51:12 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-05-29 08:46:08 -0400 |
commit | e55fd011549eae01a230e3cace6f4d031b6a3453 (patch) | |
tree | 7b65e96f985cf6daa9b0a40995c13e9b9be890a6 /fs | |
parent | 64fd72e0a44bdd62c5ca277cb24d0d02b2d8e9dc (diff) |
split dentry_kill()
... into trylocks and everything else. The latter (actual killing)
is __dentry_kill().
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/dcache.c | 62 |
1 files changed, 36 insertions, 26 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 6888dde4d568..1577c14dfb4e 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -441,36 +441,12 @@ void d_drop(struct dentry *dentry) | |||
441 | } | 441 | } |
442 | EXPORT_SYMBOL(d_drop); | 442 | EXPORT_SYMBOL(d_drop); |
443 | 443 | ||
444 | /* | 444 | static void __dentry_kill(struct dentry *dentry) |
445 | * Finish off a dentry we've decided to kill. | ||
446 | * dentry->d_lock must be held, returns with it unlocked. | ||
447 | * If ref is non-zero, then decrement the refcount too. | ||
448 | * Returns dentry requiring refcount drop, or NULL if we're done. | ||
449 | */ | ||
450 | static struct dentry * | ||
451 | dentry_kill(struct dentry *dentry, int unlock_on_failure) | ||
452 | __releases(dentry->d_lock) | ||
453 | { | 445 | { |
454 | struct inode *inode; | ||
455 | struct dentry *parent = NULL; | 446 | struct dentry *parent = NULL; |
456 | bool can_free = true; | 447 | bool can_free = true; |
457 | |||
458 | inode = dentry->d_inode; | ||
459 | if (inode && !spin_trylock(&inode->i_lock)) { | ||
460 | relock: | ||
461 | if (unlock_on_failure) { | ||
462 | spin_unlock(&dentry->d_lock); | ||
463 | cpu_relax(); | ||
464 | } | ||
465 | return dentry; /* try again with same dentry */ | ||
466 | } | ||
467 | if (!IS_ROOT(dentry)) | 448 | if (!IS_ROOT(dentry)) |
468 | parent = dentry->d_parent; | 449 | parent = dentry->d_parent; |
469 | if (parent && !spin_trylock(&parent->d_lock)) { | ||
470 | if (inode) | ||
471 | spin_unlock(&inode->i_lock); | ||
472 | goto relock; | ||
473 | } | ||
474 | 450 | ||
475 | /* | 451 | /* |
476 | * The dentry is now unrecoverably dead to the world. | 452 | * The dentry is now unrecoverably dead to the world. |
@@ -514,10 +490,44 @@ relock: | |||
514 | can_free = false; | 490 | can_free = false; |
515 | } | 491 | } |
516 | spin_unlock(&dentry->d_lock); | 492 | spin_unlock(&dentry->d_lock); |
517 | out: | ||
518 | if (likely(can_free)) | 493 | if (likely(can_free)) |
519 | dentry_free(dentry); | 494 | dentry_free(dentry); |
495 | } | ||
496 | |||
497 | /* | ||
498 | * Finish off a dentry we've decided to kill. | ||
499 | * dentry->d_lock must be held, returns with it unlocked. | ||
500 | * If ref is non-zero, then decrement the refcount too. | ||
501 | * Returns dentry requiring refcount drop, or NULL if we're done. | ||
502 | */ | ||
503 | static struct dentry * | ||
504 | dentry_kill(struct dentry *dentry, int unlock_on_failure) | ||
505 | __releases(dentry->d_lock) | ||
506 | { | ||
507 | struct inode *inode = dentry->d_inode; | ||
508 | struct dentry *parent = NULL; | ||
509 | |||
510 | if (inode && unlikely(!spin_trylock(&inode->i_lock))) | ||
511 | goto failed; | ||
512 | |||
513 | if (!IS_ROOT(dentry)) { | ||
514 | parent = dentry->d_parent; | ||
515 | if (unlikely(!spin_trylock(&parent->d_lock))) { | ||
516 | if (inode) | ||
517 | spin_unlock(&inode->i_lock); | ||
518 | goto failed; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | __dentry_kill(dentry); | ||
520 | return parent; | 523 | return parent; |
524 | |||
525 | failed: | ||
526 | if (unlock_on_failure) { | ||
527 | spin_unlock(&dentry->d_lock); | ||
528 | cpu_relax(); | ||
529 | } | ||
530 | return dentry; /* try again with same dentry */ | ||
521 | } | 531 | } |
522 | 532 | ||
523 | /* | 533 | /* |