diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/dcache.c | 76 |
1 files changed, 24 insertions, 52 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 494a9def5dce..9b15c5c37277 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -246,23 +246,6 @@ static void __d_free(struct rcu_head *head) | |||
246 | kmem_cache_free(dentry_cache, dentry); | 246 | kmem_cache_free(dentry_cache, dentry); |
247 | } | 247 | } |
248 | 248 | ||
249 | /* | ||
250 | * no locks, please. | ||
251 | */ | ||
252 | static void d_free(struct dentry *dentry) | ||
253 | { | ||
254 | BUG_ON((int)dentry->d_lockref.count > 0); | ||
255 | this_cpu_dec(nr_dentry); | ||
256 | if (dentry->d_op && dentry->d_op->d_release) | ||
257 | dentry->d_op->d_release(dentry); | ||
258 | |||
259 | /* if dentry was never visible to RCU, immediate free is OK */ | ||
260 | if (!(dentry->d_flags & DCACHE_RCUACCESS)) | ||
261 | __d_free(&dentry->d_u.d_rcu); | ||
262 | else | ||
263 | call_rcu(&dentry->d_u.d_rcu, __d_free); | ||
264 | } | ||
265 | |||
266 | /** | 249 | /** |
267 | * dentry_rcuwalk_barrier - invalidate in-progress rcu-walk lookups | 250 | * dentry_rcuwalk_barrier - invalidate in-progress rcu-walk lookups |
268 | * @dentry: the target dentry | 251 | * @dentry: the target dentry |
@@ -420,40 +403,6 @@ static void dentry_lru_del(struct dentry *dentry) | |||
420 | } | 403 | } |
421 | 404 | ||
422 | /** | 405 | /** |
423 | * d_kill - kill dentry and return parent | ||
424 | * @dentry: dentry to kill | ||
425 | * @parent: parent dentry | ||
426 | * | ||
427 | * The dentry must already be unhashed and removed from the LRU. | ||
428 | * | ||
429 | * If this is the root of the dentry tree, return NULL. | ||
430 | * | ||
431 | * dentry->d_lock and parent->d_lock must be held by caller, and are dropped by | ||
432 | * d_kill. | ||
433 | */ | ||
434 | static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) | ||
435 | __releases(dentry->d_lock) | ||
436 | __releases(parent->d_lock) | ||
437 | __releases(dentry->d_inode->i_lock) | ||
438 | { | ||
439 | list_del(&dentry->d_u.d_child); | ||
440 | /* | ||
441 | * Inform d_walk() that we are no longer attached to the | ||
442 | * dentry tree | ||
443 | */ | ||
444 | dentry->d_flags |= DCACHE_DENTRY_KILLED; | ||
445 | if (parent) | ||
446 | spin_unlock(&parent->d_lock); | ||
447 | dentry_iput(dentry); | ||
448 | /* | ||
449 | * dentry_iput drops the locks, at which point nobody (except | ||
450 | * transient RCU lookups) can reach this dentry. | ||
451 | */ | ||
452 | d_free(dentry); | ||
453 | return parent; | ||
454 | } | ||
455 | |||
456 | /** | ||
457 | * d_drop - drop a dentry | 406 | * d_drop - drop a dentry |
458 | * @dentry: dentry to drop | 407 | * @dentry: dentry to drop |
459 | * | 408 | * |
@@ -546,7 +495,30 @@ relock: | |||
546 | dentry_lru_del(dentry); | 495 | dentry_lru_del(dentry); |
547 | /* if it was on the hash then remove it */ | 496 | /* if it was on the hash then remove it */ |
548 | __d_drop(dentry); | 497 | __d_drop(dentry); |
549 | return d_kill(dentry, parent); | 498 | list_del(&dentry->d_u.d_child); |
499 | /* | ||
500 | * Inform d_walk() that we are no longer attached to the | ||
501 | * dentry tree | ||
502 | */ | ||
503 | dentry->d_flags |= DCACHE_DENTRY_KILLED; | ||
504 | if (parent) | ||
505 | spin_unlock(&parent->d_lock); | ||
506 | dentry_iput(dentry); | ||
507 | /* | ||
508 | * dentry_iput drops the locks, at which point nobody (except | ||
509 | * transient RCU lookups) can reach this dentry. | ||
510 | */ | ||
511 | BUG_ON((int)dentry->d_lockref.count > 0); | ||
512 | this_cpu_dec(nr_dentry); | ||
513 | if (dentry->d_op && dentry->d_op->d_release) | ||
514 | dentry->d_op->d_release(dentry); | ||
515 | |||
516 | /* if dentry was never visible to RCU, immediate free is OK */ | ||
517 | if (!(dentry->d_flags & DCACHE_RCUACCESS)) | ||
518 | __d_free(&dentry->d_u.d_rcu); | ||
519 | else | ||
520 | call_rcu(&dentry->d_u.d_rcu, __d_free); | ||
521 | return parent; | ||
550 | } | 522 | } |
551 | 523 | ||
552 | /* | 524 | /* |