diff options
| author | Christoph Hellwig <hch@infradead.org> | 2010-10-10 05:36:26 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-10-25 21:26:13 -0400 |
| commit | a4633357ac610cd2f8740e28a31fc148a7960421 (patch) | |
| tree | 5c28962f355c545f888ab7b8e95e8bce5c2de599 | |
| parent | 3049cfe24ef3872ba74f90630356722cf988b80d (diff) | |
fs: clean up dentry lru modification
Always do a list_del_init on the LRU to make sure the list_empty invariant for
not beeing on the LRU always holds true, and fold dentry_lru_del_init into
dentry_lru_del. Replace the dentry_lru_add_tail primitive with a
dentry_lru_move_tail operations that simpler when the dentry already is one
the list, which is always is. Move the list_empty into dentry_lru_add to
fit the scheme of the other lru helpers, and simplify locking once we
move to a separate LRU lock.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | fs/dcache.c | 49 |
1 files changed, 23 insertions, 26 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index e987ad576a39..cc2b93802179 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -133,37 +133,34 @@ static void dentry_iput(struct dentry * dentry) | |||
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | /* | 135 | /* |
| 136 | * dentry_lru_(add|add_tail|del|del_init) must be called with dcache_lock held. | 136 | * dentry_lru_(add|del|move_tail) must be called with dcache_lock held. |
| 137 | */ | 137 | */ |
| 138 | static void dentry_lru_add(struct dentry *dentry) | 138 | static void dentry_lru_add(struct dentry *dentry) |
| 139 | { | 139 | { |
| 140 | list_add(&dentry->d_lru, &dentry->d_sb->s_dentry_lru); | 140 | if (list_empty(&dentry->d_lru)) { |
| 141 | dentry->d_sb->s_nr_dentry_unused++; | 141 | list_add(&dentry->d_lru, &dentry->d_sb->s_dentry_lru); |
| 142 | percpu_counter_inc(&nr_dentry_unused); | 142 | dentry->d_sb->s_nr_dentry_unused++; |
| 143 | } | 143 | percpu_counter_inc(&nr_dentry_unused); |
| 144 | 144 | } | |
| 145 | static void dentry_lru_add_tail(struct dentry *dentry) | ||
| 146 | { | ||
| 147 | list_add_tail(&dentry->d_lru, &dentry->d_sb->s_dentry_lru); | ||
| 148 | dentry->d_sb->s_nr_dentry_unused++; | ||
| 149 | percpu_counter_inc(&nr_dentry_unused); | ||
| 150 | } | 145 | } |
| 151 | 146 | ||
| 152 | static void dentry_lru_del(struct dentry *dentry) | 147 | static void dentry_lru_del(struct dentry *dentry) |
| 153 | { | 148 | { |
| 154 | if (!list_empty(&dentry->d_lru)) { | 149 | if (!list_empty(&dentry->d_lru)) { |
| 155 | list_del(&dentry->d_lru); | 150 | list_del_init(&dentry->d_lru); |
| 156 | dentry->d_sb->s_nr_dentry_unused--; | 151 | dentry->d_sb->s_nr_dentry_unused--; |
| 157 | percpu_counter_dec(&nr_dentry_unused); | 152 | percpu_counter_dec(&nr_dentry_unused); |
| 158 | } | 153 | } |
| 159 | } | 154 | } |
| 160 | 155 | ||
| 161 | static void dentry_lru_del_init(struct dentry *dentry) | 156 | static void dentry_lru_move_tail(struct dentry *dentry) |
| 162 | { | 157 | { |
| 163 | if (likely(!list_empty(&dentry->d_lru))) { | 158 | if (list_empty(&dentry->d_lru)) { |
| 164 | list_del_init(&dentry->d_lru); | 159 | list_add_tail(&dentry->d_lru, &dentry->d_sb->s_dentry_lru); |
| 165 | dentry->d_sb->s_nr_dentry_unused--; | 160 | dentry->d_sb->s_nr_dentry_unused++; |
| 166 | percpu_counter_dec(&nr_dentry_unused); | 161 | percpu_counter_inc(&nr_dentry_unused); |
| 162 | } else { | ||
| 163 | list_move_tail(&dentry->d_lru, &dentry->d_sb->s_dentry_lru); | ||
| 167 | } | 164 | } |
| 168 | } | 165 | } |
| 169 | 166 | ||
| @@ -253,8 +250,7 @@ repeat: | |||
| 253 | 250 | ||
| 254 | /* Otherwise leave it cached and ensure it's on the LRU */ | 251 | /* Otherwise leave it cached and ensure it's on the LRU */ |
| 255 | dentry->d_flags |= DCACHE_REFERENCED; | 252 | dentry->d_flags |= DCACHE_REFERENCED; |
| 256 | if (list_empty(&dentry->d_lru)) | 253 | dentry_lru_add(dentry); |
| 257 | dentry_lru_add(dentry); | ||
| 258 | 254 | ||
| 259 | spin_unlock(&dentry->d_lock); | 255 | spin_unlock(&dentry->d_lock); |
| 260 | spin_unlock(&dcache_lock); | 256 | spin_unlock(&dcache_lock); |
| @@ -333,7 +329,7 @@ EXPORT_SYMBOL(d_invalidate); | |||
| 333 | static inline struct dentry * __dget_locked(struct dentry *dentry) | 329 | static inline struct dentry * __dget_locked(struct dentry *dentry) |
| 334 | { | 330 | { |
| 335 | atomic_inc(&dentry->d_count); | 331 | atomic_inc(&dentry->d_count); |
| 336 | dentry_lru_del_init(dentry); | 332 | dentry_lru_del(dentry); |
| 337 | return dentry; | 333 | return dentry; |
| 338 | } | 334 | } |
| 339 | 335 | ||
| @@ -452,7 +448,7 @@ static void prune_one_dentry(struct dentry * dentry) | |||
| 452 | 448 | ||
| 453 | if (dentry->d_op && dentry->d_op->d_delete) | 449 | if (dentry->d_op && dentry->d_op->d_delete) |
| 454 | dentry->d_op->d_delete(dentry); | 450 | dentry->d_op->d_delete(dentry); |
| 455 | dentry_lru_del_init(dentry); | 451 | dentry_lru_del(dentry); |
| 456 | __d_drop(dentry); | 452 | __d_drop(dentry); |
| 457 | dentry = d_kill(dentry); | 453 | dentry = d_kill(dentry); |
| 458 | spin_lock(&dcache_lock); | 454 | spin_lock(&dcache_lock); |
| @@ -465,7 +461,7 @@ static void shrink_dentry_list(struct list_head *list) | |||
| 465 | 461 | ||
| 466 | while (!list_empty(list)) { | 462 | while (!list_empty(list)) { |
| 467 | dentry = list_entry(list->prev, struct dentry, d_lru); | 463 | dentry = list_entry(list->prev, struct dentry, d_lru); |
| 468 | dentry_lru_del_init(dentry); | 464 | dentry_lru_del(dentry); |
| 469 | 465 | ||
| 470 | /* | 466 | /* |
| 471 | * We found an inuse dentry which was not removed from | 467 | * We found an inuse dentry which was not removed from |
| @@ -650,7 +646,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | |||
| 650 | 646 | ||
| 651 | /* detach this root from the system */ | 647 | /* detach this root from the system */ |
| 652 | spin_lock(&dcache_lock); | 648 | spin_lock(&dcache_lock); |
| 653 | dentry_lru_del_init(dentry); | 649 | dentry_lru_del(dentry); |
| 654 | __d_drop(dentry); | 650 | __d_drop(dentry); |
| 655 | spin_unlock(&dcache_lock); | 651 | spin_unlock(&dcache_lock); |
| 656 | 652 | ||
| @@ -664,7 +660,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | |||
| 664 | spin_lock(&dcache_lock); | 660 | spin_lock(&dcache_lock); |
| 665 | list_for_each_entry(loop, &dentry->d_subdirs, | 661 | list_for_each_entry(loop, &dentry->d_subdirs, |
| 666 | d_u.d_child) { | 662 | d_u.d_child) { |
| 667 | dentry_lru_del_init(loop); | 663 | dentry_lru_del(loop); |
| 668 | __d_drop(loop); | 664 | __d_drop(loop); |
| 669 | cond_resched_lock(&dcache_lock); | 665 | cond_resched_lock(&dcache_lock); |
| 670 | } | 666 | } |
| @@ -841,14 +837,15 @@ resume: | |||
| 841 | struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child); | 837 | struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child); |
| 842 | next = tmp->next; | 838 | next = tmp->next; |
| 843 | 839 | ||
| 844 | dentry_lru_del_init(dentry); | ||
| 845 | /* | 840 | /* |
| 846 | * move only zero ref count dentries to the end | 841 | * move only zero ref count dentries to the end |
| 847 | * of the unused list for prune_dcache | 842 | * of the unused list for prune_dcache |
| 848 | */ | 843 | */ |
| 849 | if (!atomic_read(&dentry->d_count)) { | 844 | if (!atomic_read(&dentry->d_count)) { |
| 850 | dentry_lru_add_tail(dentry); | 845 | dentry_lru_move_tail(dentry); |
| 851 | found++; | 846 | found++; |
| 847 | } else { | ||
| 848 | dentry_lru_del(dentry); | ||
| 852 | } | 849 | } |
| 853 | 850 | ||
| 854 | /* | 851 | /* |
