aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-05-28 13:51:12 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2014-05-29 08:46:08 -0400
commite55fd011549eae01a230e3cace6f4d031b6a3453 (patch)
tree7b65e96f985cf6daa9b0a40995c13e9b9be890a6 /fs
parent64fd72e0a44bdd62c5ca277cb24d0d02b2d8e9dc (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.c62
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}
442EXPORT_SYMBOL(d_drop); 442EXPORT_SYMBOL(d_drop);
443 443
444/* 444static 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 */
450static struct dentry *
451dentry_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)) {
460relock:
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);
517out:
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 */
503static struct dentry *
504dentry_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
525failed:
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/*