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 /fs/dcache.c | |
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>
Diffstat (limited to 'fs/dcache.c')
-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 | /* |