aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-13 22:55:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-13 22:55:10 -0400
commit89dc77bcdabf42ec99553f5837aa4bb8255a088c (patch)
tree5648f91439538e2a4fd892a4ab525dd99bb2a44d
parentbdbdfdef5766c2a60185e946df242f1bc0d37c09 (diff)
vfs: fix dentry LRU list handling and nr_dentry_unused accounting
The LRU list changes interacted badly with our nr_dentry_unused accounting, and even worse with the new DCACHE_LRU_LIST bit logic. This introduces helper functions to make sure everything follows the proper dcache d_lru list rules: the dentry cache is complicated by the fact that some of the hotpaths don't even want to look at the LRU list at all, and the fact that we use the same list entry in the dentry for both the LRU list and for our temporary shrinking lists when removing things from the LRU. The helper functions temporarily have some extra sanity checking for the flag bits that have to match the current LRU state of the dentry. We'll remove that before the final 3.12 release, but considering how easy it is to get wrong, this first cleanup version has some very particular sanity checking. Acked-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/dcache.c128
1 files changed, 101 insertions, 27 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 1bd4614ce93b..62538e705c9b 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -357,15 +357,80 @@ static void dentry_unlink_inode(struct dentry * dentry)
357} 357}
358 358
359/* 359/*
360 * The DCACHE_LRU_LIST bit is set whenever the 'd_lru' entry
361 * is in use - which includes both the "real" per-superblock
362 * LRU list _and_ the DCACHE_SHRINK_LIST use.
363 *
364 * The DCACHE_SHRINK_LIST bit is set whenever the dentry is
365 * on the shrink list (ie not on the superblock LRU list).
366 *
367 * The per-cpu "nr_dentry_unused" counters are updated with
368 * the DCACHE_LRU_LIST bit.
369 *
370 * These helper functions make sure we always follow the
371 * rules. d_lock must be held by the caller.
372 */
373#define D_FLAG_VERIFY(dentry,x) WARN_ON_ONCE(((dentry)->d_flags & (DCACHE_LRU_LIST | DCACHE_SHRINK_LIST)) != (x))
374static void d_lru_add(struct dentry *dentry)
375{
376 D_FLAG_VERIFY(dentry, 0);
377 dentry->d_flags |= DCACHE_LRU_LIST;
378 this_cpu_inc(nr_dentry_unused);
379 WARN_ON_ONCE(!list_lru_add(&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
380}
381
382static void d_lru_del(struct dentry *dentry)
383{
384 D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
385 dentry->d_flags &= ~DCACHE_LRU_LIST;
386 this_cpu_dec(nr_dentry_unused);
387 WARN_ON_ONCE(!list_lru_del(&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
388}
389
390static void d_shrink_del(struct dentry *dentry)
391{
392 D_FLAG_VERIFY(dentry, DCACHE_SHRINK_LIST | DCACHE_LRU_LIST);
393 list_del_init(&dentry->d_lru);
394 dentry->d_flags &= ~(DCACHE_SHRINK_LIST | DCACHE_LRU_LIST);
395 this_cpu_dec(nr_dentry_unused);
396}
397
398static void d_shrink_add(struct dentry *dentry, struct list_head *list)
399{
400 D_FLAG_VERIFY(dentry, 0);
401 list_add(&dentry->d_lru, list);
402 dentry->d_flags |= DCACHE_SHRINK_LIST | DCACHE_LRU_LIST;
403 this_cpu_inc(nr_dentry_unused);
404}
405
406/*
407 * These can only be called under the global LRU lock, ie during the
408 * callback for freeing the LRU list. "isolate" removes it from the
409 * LRU lists entirely, while shrink_move moves it to the indicated
410 * private list.
411 */
412static void d_lru_isolate(struct dentry *dentry)
413{
414 D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
415 dentry->d_flags &= ~DCACHE_LRU_LIST;
416 this_cpu_dec(nr_dentry_unused);
417 list_del_init(&dentry->d_lru);
418}
419
420static void d_lru_shrink_move(struct dentry *dentry, struct list_head *list)
421{
422 D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
423 dentry->d_flags |= DCACHE_SHRINK_LIST;
424 list_move_tail(&dentry->d_lru, list);
425}
426
427/*
360 * dentry_lru_(add|del)_list) must be called with d_lock held. 428 * dentry_lru_(add|del)_list) must be called with d_lock held.
361 */ 429 */
362static void dentry_lru_add(struct dentry *dentry) 430static void dentry_lru_add(struct dentry *dentry)
363{ 431{
364 if (unlikely(!(dentry->d_flags & DCACHE_LRU_LIST))) { 432 if (unlikely(!(dentry->d_flags & DCACHE_LRU_LIST)))
365 if (list_lru_add(&dentry->d_sb->s_dentry_lru, &dentry->d_lru)) 433 d_lru_add(dentry);
366 this_cpu_inc(nr_dentry_unused);
367 dentry->d_flags |= DCACHE_LRU_LIST;
368 }
369} 434}
370 435
371/* 436/*
@@ -377,15 +442,11 @@ static void dentry_lru_add(struct dentry *dentry)
377 */ 442 */
378static void dentry_lru_del(struct dentry *dentry) 443static void dentry_lru_del(struct dentry *dentry)
379{ 444{
380 if (dentry->d_flags & DCACHE_SHRINK_LIST) { 445 if (dentry->d_flags & DCACHE_LRU_LIST) {
381 list_del_init(&dentry->d_lru); 446 if (dentry->d_flags & DCACHE_SHRINK_LIST)
382 dentry->d_flags &= ~DCACHE_SHRINK_LIST; 447 return d_shrink_del(dentry);
383 return; 448 d_lru_del(dentry);
384 } 449 }
385
386 if (list_lru_del(&dentry->d_sb->s_dentry_lru, &dentry->d_lru))
387 this_cpu_dec(nr_dentry_unused);
388 dentry->d_flags &= ~DCACHE_LRU_LIST;
389} 450}
390 451
391/** 452/**
@@ -837,6 +898,12 @@ static void shrink_dentry_list(struct list_head *list)
837 dentry = list_entry_rcu(list->prev, struct dentry, d_lru); 898 dentry = list_entry_rcu(list->prev, struct dentry, d_lru);
838 if (&dentry->d_lru == list) 899 if (&dentry->d_lru == list)
839 break; /* empty */ 900 break; /* empty */
901
902 /*
903 * Get the dentry lock, and re-verify that the dentry is
904 * this on the shrinking list. If it is, we know that
905 * DCACHE_SHRINK_LIST and DCACHE_LRU_LIST are set.
906 */
840 spin_lock(&dentry->d_lock); 907 spin_lock(&dentry->d_lock);
841 if (dentry != list_entry(list->prev, struct dentry, d_lru)) { 908 if (dentry != list_entry(list->prev, struct dentry, d_lru)) {
842 spin_unlock(&dentry->d_lock); 909 spin_unlock(&dentry->d_lock);
@@ -848,8 +915,7 @@ static void shrink_dentry_list(struct list_head *list)
848 * to the LRU here, so we can simply remove it from the list 915 * to the LRU here, so we can simply remove it from the list
849 * here regardless of whether it is referenced or not. 916 * here regardless of whether it is referenced or not.
850 */ 917 */
851 list_del_init(&dentry->d_lru); 918 d_shrink_del(dentry);
852 dentry->d_flags &= ~DCACHE_SHRINK_LIST;
853 919
854 /* 920 /*
855 * We found an inuse dentry which was not removed from 921 * We found an inuse dentry which was not removed from
@@ -861,12 +927,20 @@ static void shrink_dentry_list(struct list_head *list)
861 } 927 }
862 rcu_read_unlock(); 928 rcu_read_unlock();
863 929
930 /*
931 * If 'try_to_prune()' returns a dentry, it will
932 * be the same one we passed in, and d_lock will
933 * have been held the whole time, so it will not
934 * have been added to any other lists. We failed
935 * to get the inode lock.
936 *
937 * We just add it back to the shrink list.
938 */
864 dentry = try_prune_one_dentry(dentry); 939 dentry = try_prune_one_dentry(dentry);
865 940
866 rcu_read_lock(); 941 rcu_read_lock();
867 if (dentry) { 942 if (dentry) {
868 dentry->d_flags |= DCACHE_SHRINK_LIST; 943 d_shrink_add(dentry, list);
869 list_add(&dentry->d_lru, list);
870 spin_unlock(&dentry->d_lock); 944 spin_unlock(&dentry->d_lock);
871 } 945 }
872 } 946 }
@@ -894,7 +968,7 @@ dentry_lru_isolate(struct list_head *item, spinlock_t *lru_lock, void *arg)
894 * another pass through the LRU. 968 * another pass through the LRU.
895 */ 969 */
896 if (dentry->d_lockref.count) { 970 if (dentry->d_lockref.count) {
897 list_del_init(&dentry->d_lru); 971 d_lru_isolate(dentry);
898 spin_unlock(&dentry->d_lock); 972 spin_unlock(&dentry->d_lock);
899 return LRU_REMOVED; 973 return LRU_REMOVED;
900 } 974 }
@@ -925,9 +999,7 @@ dentry_lru_isolate(struct list_head *item, spinlock_t *lru_lock, void *arg)
925 return LRU_ROTATE; 999 return LRU_ROTATE;
926 } 1000 }
927 1001
928 dentry->d_flags |= DCACHE_SHRINK_LIST; 1002 d_lru_shrink_move(dentry, freeable);
929 list_move_tail(&dentry->d_lru, freeable);
930 this_cpu_dec(nr_dentry_unused);
931 spin_unlock(&dentry->d_lock); 1003 spin_unlock(&dentry->d_lock);
932 1004
933 return LRU_REMOVED; 1005 return LRU_REMOVED;
@@ -972,9 +1044,7 @@ static enum lru_status dentry_lru_isolate_shrink(struct list_head *item,
972 if (!spin_trylock(&dentry->d_lock)) 1044 if (!spin_trylock(&dentry->d_lock))
973 return LRU_SKIP; 1045 return LRU_SKIP;
974 1046
975 dentry->d_flags |= DCACHE_SHRINK_LIST; 1047 d_lru_shrink_move(dentry, freeable);
976 list_move_tail(&dentry->d_lru, freeable);
977 this_cpu_dec(nr_dentry_unused);
978 spin_unlock(&dentry->d_lock); 1048 spin_unlock(&dentry->d_lock);
979 1049
980 return LRU_REMOVED; 1050 return LRU_REMOVED;
@@ -1362,9 +1432,13 @@ static enum d_walk_ret select_collect(void *_data, struct dentry *dentry)
1362 if (dentry->d_lockref.count) { 1432 if (dentry->d_lockref.count) {
1363 dentry_lru_del(dentry); 1433 dentry_lru_del(dentry);
1364 } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) { 1434 } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) {
1365 dentry_lru_del(dentry); 1435 /*
1366 list_add_tail(&dentry->d_lru, &data->dispose); 1436 * We can't use d_lru_shrink_move() because we
1367 dentry->d_flags |= DCACHE_SHRINK_LIST; 1437 * need to get the global LRU lock and do the
1438 * RLU accounting.
1439 */
1440 d_lru_del(dentry);
1441 d_shrink_add(dentry, &data->dispose);
1368 data->found++; 1442 data->found++;
1369 ret = D_WALK_NORETRY; 1443 ret = D_WALK_NORETRY;
1370 } 1444 }