diff options
Diffstat (limited to 'fs/dcache.c')
| -rw-r--r-- | fs/dcache.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index a1ff91eef108..fd4a428998ef 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -478,11 +478,12 @@ static void prune_dcache(int count, struct super_block *sb) | |||
| 478 | up_read(s_umount); | 478 | up_read(s_umount); |
| 479 | } | 479 | } |
| 480 | spin_unlock(&dentry->d_lock); | 480 | spin_unlock(&dentry->d_lock); |
| 481 | /* Cannot remove the first dentry, and it isn't appropriate | 481 | /* |
| 482 | * to move it to the head of the list, so give up, and try | 482 | * Insert dentry at the head of the list as inserting at the |
| 483 | * later | 483 | * tail leads to a cycle. |
| 484 | */ | 484 | */ |
| 485 | break; | 485 | list_add(&dentry->d_lru, &dentry_unused); |
| 486 | dentry_stat.nr_unused++; | ||
| 486 | } | 487 | } |
| 487 | spin_unlock(&dcache_lock); | 488 | spin_unlock(&dcache_lock); |
| 488 | } | 489 | } |
| @@ -556,6 +557,7 @@ repeat: | |||
| 556 | static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | 557 | static void shrink_dcache_for_umount_subtree(struct dentry *dentry) |
| 557 | { | 558 | { |
| 558 | struct dentry *parent; | 559 | struct dentry *parent; |
| 560 | unsigned detached = 0; | ||
| 559 | 561 | ||
| 560 | BUG_ON(!IS_ROOT(dentry)); | 562 | BUG_ON(!IS_ROOT(dentry)); |
| 561 | 563 | ||
| @@ -620,7 +622,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | |||
| 620 | atomic_dec(&parent->d_count); | 622 | atomic_dec(&parent->d_count); |
| 621 | 623 | ||
| 622 | list_del(&dentry->d_u.d_child); | 624 | list_del(&dentry->d_u.d_child); |
| 623 | dentry_stat.nr_dentry--; /* For d_free, below */ | 625 | detached++; |
| 624 | 626 | ||
| 625 | inode = dentry->d_inode; | 627 | inode = dentry->d_inode; |
| 626 | if (inode) { | 628 | if (inode) { |
| @@ -638,7 +640,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | |||
| 638 | * otherwise we ascend to the parent and move to the | 640 | * otherwise we ascend to the parent and move to the |
| 639 | * next sibling if there is one */ | 641 | * next sibling if there is one */ |
| 640 | if (!parent) | 642 | if (!parent) |
| 641 | return; | 643 | goto out; |
| 642 | 644 | ||
| 643 | dentry = parent; | 645 | dentry = parent; |
| 644 | 646 | ||
| @@ -647,6 +649,11 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | |||
| 647 | dentry = list_entry(dentry->d_subdirs.next, | 649 | dentry = list_entry(dentry->d_subdirs.next, |
| 648 | struct dentry, d_u.d_child); | 650 | struct dentry, d_u.d_child); |
| 649 | } | 651 | } |
| 652 | out: | ||
| 653 | /* several dentries were freed, need to correct nr_dentry */ | ||
| 654 | spin_lock(&dcache_lock); | ||
| 655 | dentry_stat.nr_dentry -= detached; | ||
| 656 | spin_unlock(&dcache_lock); | ||
| 650 | } | 657 | } |
| 651 | 658 | ||
| 652 | /* | 659 | /* |
