diff options
-rw-r--r-- | fs/dcache.c | 24 |
1 files changed, 10 insertions, 14 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 920c87720385..bde6057c5df6 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -381,20 +381,17 @@ restart: | |||
381 | * Throw away a dentry - free the inode, dput the parent. This requires that | 381 | * Throw away a dentry - free the inode, dput the parent. This requires that |
382 | * the LRU list has already been removed. | 382 | * the LRU list has already been removed. |
383 | * | 383 | * |
384 | * If prune_parents is true, try to prune ancestors as well. | 384 | * Try to prune ancestors as well. This is necessary to prevent |
385 | * quadratic behavior of shrink_dcache_parent(), but is also expected | ||
386 | * to be beneficial in reducing dentry cache fragmentation. | ||
385 | * | 387 | * |
386 | * Called with dcache_lock, drops it and then regains. | 388 | * Called with dcache_lock, drops it and then regains. |
387 | * Called with dentry->d_lock held, drops it. | 389 | * Called with dentry->d_lock held, drops it. |
388 | */ | 390 | */ |
389 | static void prune_one_dentry(struct dentry * dentry, int prune_parents) | 391 | static void prune_one_dentry(struct dentry * dentry) |
390 | { | 392 | { |
391 | __d_drop(dentry); | 393 | __d_drop(dentry); |
392 | dentry = d_kill(dentry); | 394 | dentry = d_kill(dentry); |
393 | if (!prune_parents) { | ||
394 | dput(dentry); | ||
395 | spin_lock(&dcache_lock); | ||
396 | return; | ||
397 | } | ||
398 | 395 | ||
399 | /* | 396 | /* |
400 | * Prune ancestors. Locking is simpler than in dput(), | 397 | * Prune ancestors. Locking is simpler than in dput(), |
@@ -422,7 +419,6 @@ static void prune_one_dentry(struct dentry * dentry, int prune_parents) | |||
422 | * @count: number of entries to try and free | 419 | * @count: number of entries to try and free |
423 | * @sb: if given, ignore dentries for other superblocks | 420 | * @sb: if given, ignore dentries for other superblocks |
424 | * which are being unmounted. | 421 | * which are being unmounted. |
425 | * @prune_parents: if true, try to prune ancestors as well in one go | ||
426 | * | 422 | * |
427 | * Shrink the dcache. This is done when we need | 423 | * Shrink the dcache. This is done when we need |
428 | * more memory, or simply when we need to unmount | 424 | * more memory, or simply when we need to unmount |
@@ -433,7 +429,7 @@ static void prune_one_dentry(struct dentry * dentry, int prune_parents) | |||
433 | * all the dentries are in use. | 429 | * all the dentries are in use. |
434 | */ | 430 | */ |
435 | 431 | ||
436 | static void prune_dcache(int count, struct super_block *sb, int prune_parents) | 432 | static void prune_dcache(int count, struct super_block *sb) |
437 | { | 433 | { |
438 | spin_lock(&dcache_lock); | 434 | spin_lock(&dcache_lock); |
439 | for (; count ; count--) { | 435 | for (; count ; count--) { |
@@ -493,7 +489,7 @@ static void prune_dcache(int count, struct super_block *sb, int prune_parents) | |||
493 | * without taking the s_umount lock (I already hold it). | 489 | * without taking the s_umount lock (I already hold it). |
494 | */ | 490 | */ |
495 | if (sb && dentry->d_sb == sb) { | 491 | if (sb && dentry->d_sb == sb) { |
496 | prune_one_dentry(dentry, prune_parents); | 492 | prune_one_dentry(dentry); |
497 | continue; | 493 | continue; |
498 | } | 494 | } |
499 | /* | 495 | /* |
@@ -508,7 +504,7 @@ static void prune_dcache(int count, struct super_block *sb, int prune_parents) | |||
508 | s_umount = &dentry->d_sb->s_umount; | 504 | s_umount = &dentry->d_sb->s_umount; |
509 | if (down_read_trylock(s_umount)) { | 505 | if (down_read_trylock(s_umount)) { |
510 | if (dentry->d_sb->s_root != NULL) { | 506 | if (dentry->d_sb->s_root != NULL) { |
511 | prune_one_dentry(dentry, prune_parents); | 507 | prune_one_dentry(dentry); |
512 | up_read(s_umount); | 508 | up_read(s_umount); |
513 | continue; | 509 | continue; |
514 | } | 510 | } |
@@ -579,7 +575,7 @@ repeat: | |||
579 | spin_unlock(&dentry->d_lock); | 575 | spin_unlock(&dentry->d_lock); |
580 | continue; | 576 | continue; |
581 | } | 577 | } |
582 | prune_one_dentry(dentry, 1); | 578 | prune_one_dentry(dentry); |
583 | cond_resched_lock(&dcache_lock); | 579 | cond_resched_lock(&dcache_lock); |
584 | goto repeat; | 580 | goto repeat; |
585 | } | 581 | } |
@@ -858,7 +854,7 @@ void shrink_dcache_parent(struct dentry * parent) | |||
858 | int found; | 854 | int found; |
859 | 855 | ||
860 | while ((found = select_parent(parent)) != 0) | 856 | while ((found = select_parent(parent)) != 0) |
861 | prune_dcache(found, parent->d_sb, 1); | 857 | prune_dcache(found, parent->d_sb); |
862 | } | 858 | } |
863 | 859 | ||
864 | /* | 860 | /* |
@@ -878,7 +874,7 @@ static int shrink_dcache_memory(int nr, gfp_t gfp_mask) | |||
878 | if (nr) { | 874 | if (nr) { |
879 | if (!(gfp_mask & __GFP_FS)) | 875 | if (!(gfp_mask & __GFP_FS)) |
880 | return -1; | 876 | return -1; |
881 | prune_dcache(nr, NULL, 1); | 877 | prune_dcache(nr, NULL); |
882 | } | 878 | } |
883 | return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure; | 879 | return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure; |
884 | } | 880 | } |