37
37
#include <linux/rculist_bl.h>
38
38
#include <linux/prefetch.h>
39
39
#include <linux/ratelimit.h>
40
+ #include <linux/list_lru.h>
40
41
#include "internal.h"
41
42
#include "mount.h"
42
43
@@ -356,28 +357,17 @@ static void dentry_unlink_inode(struct dentry * dentry)
356
357
}
357
358
358
359
/*
359
- * dentry_lru_(add|del|move_list ) must be called with d_lock held.
360
+ * dentry_lru_(add|del)_list ) must be called with d_lock held.
360
361
*/
361
362
static void dentry_lru_add (struct dentry * dentry )
362
363
{
363
364
if (unlikely (!(dentry -> d_flags & DCACHE_LRU_LIST ))) {
364
- spin_lock (& dentry -> d_sb -> s_dentry_lru_lock );
365
+ if (list_lru_add (& dentry -> d_sb -> s_dentry_lru , & dentry -> d_lru ))
366
+ this_cpu_inc (nr_dentry_unused );
365
367
dentry -> d_flags |= DCACHE_LRU_LIST ;
366
- list_add (& dentry -> d_lru , & dentry -> d_sb -> s_dentry_lru );
367
- dentry -> d_sb -> s_nr_dentry_unused ++ ;
368
- this_cpu_inc (nr_dentry_unused );
369
- spin_unlock (& dentry -> d_sb -> s_dentry_lru_lock );
370
368
}
371
369
}
372
370
373
- static void __dentry_lru_del (struct dentry * dentry )
374
- {
375
- list_del_init (& dentry -> d_lru );
376
- dentry -> d_flags &= ~DCACHE_LRU_LIST ;
377
- dentry -> d_sb -> s_nr_dentry_unused -- ;
378
- this_cpu_dec (nr_dentry_unused );
379
- }
380
-
381
371
/*
382
372
* Remove a dentry with references from the LRU.
383
373
*
@@ -393,27 +383,9 @@ static void dentry_lru_del(struct dentry *dentry)
393
383
return ;
394
384
}
395
385
396
- if (!list_empty (& dentry -> d_lru )) {
397
- spin_lock (& dentry -> d_sb -> s_dentry_lru_lock );
398
- __dentry_lru_del (dentry );
399
- spin_unlock (& dentry -> d_sb -> s_dentry_lru_lock );
400
- }
401
- }
402
-
403
- static void dentry_lru_move_list (struct dentry * dentry , struct list_head * list )
404
- {
405
- BUG_ON (dentry -> d_flags & DCACHE_SHRINK_LIST );
406
-
407
- spin_lock (& dentry -> d_sb -> s_dentry_lru_lock );
408
- if (list_empty (& dentry -> d_lru )) {
409
- dentry -> d_flags |= DCACHE_LRU_LIST ;
410
- list_add_tail (& dentry -> d_lru , list );
411
- } else {
412
- list_move_tail (& dentry -> d_lru , list );
413
- dentry -> d_sb -> s_nr_dentry_unused -- ;
386
+ if (list_lru_del (& dentry -> d_sb -> s_dentry_lru , & dentry -> d_lru ))
414
387
this_cpu_dec (nr_dentry_unused );
415
- }
416
- spin_unlock (& dentry -> d_sb -> s_dentry_lru_lock );
388
+ dentry -> d_flags &= ~DCACHE_LRU_LIST ;
417
389
}
418
390
419
391
/**
@@ -901,12 +873,72 @@ static void shrink_dentry_list(struct list_head *list)
901
873
rcu_read_unlock ();
902
874
}
903
875
876
+ static enum lru_status
877
+ dentry_lru_isolate (struct list_head * item , spinlock_t * lru_lock , void * arg )
878
+ {
879
+ struct list_head * freeable = arg ;
880
+ struct dentry * dentry = container_of (item , struct dentry , d_lru );
881
+
882
+
883
+ /*
884
+ * we are inverting the lru lock/dentry->d_lock here,
885
+ * so use a trylock. If we fail to get the lock, just skip
886
+ * it
887
+ */
888
+ if (!spin_trylock (& dentry -> d_lock ))
889
+ return LRU_SKIP ;
890
+
891
+ /*
892
+ * Referenced dentries are still in use. If they have active
893
+ * counts, just remove them from the LRU. Otherwise give them
894
+ * another pass through the LRU.
895
+ */
896
+ if (dentry -> d_lockref .count ) {
897
+ list_del_init (& dentry -> d_lru );
898
+ spin_unlock (& dentry -> d_lock );
899
+ return LRU_REMOVED ;
900
+ }
901
+
902
+ if (dentry -> d_flags & DCACHE_REFERENCED ) {
903
+ dentry -> d_flags &= ~DCACHE_REFERENCED ;
904
+ spin_unlock (& dentry -> d_lock );
905
+
906
+ /*
907
+ * The list move itself will be made by the common LRU code. At
908
+ * this point, we've dropped the dentry->d_lock but keep the
909
+ * lru lock. This is safe to do, since every list movement is
910
+ * protected by the lru lock even if both locks are held.
911
+ *
912
+ * This is guaranteed by the fact that all LRU management
913
+ * functions are intermediated by the LRU API calls like
914
+ * list_lru_add and list_lru_del. List movement in this file
915
+ * only ever occur through this functions or through callbacks
916
+ * like this one, that are called from the LRU API.
917
+ *
918
+ * The only exceptions to this are functions like
919
+ * shrink_dentry_list, and code that first checks for the
920
+ * DCACHE_SHRINK_LIST flag. Those are guaranteed to be
921
+ * operating only with stack provided lists after they are
922
+ * properly isolated from the main list. It is thus, always a
923
+ * local access.
924
+ */
925
+ return LRU_ROTATE ;
926
+ }
927
+
928
+ dentry -> d_flags |= DCACHE_SHRINK_LIST ;
929
+ list_move_tail (& dentry -> d_lru , freeable );
930
+ this_cpu_dec (nr_dentry_unused );
931
+ spin_unlock (& dentry -> d_lock );
932
+
933
+ return LRU_REMOVED ;
934
+ }
935
+
904
936
/**
905
937
* prune_dcache_sb - shrink the dcache
906
938
* @sb: superblock
907
- * @count : number of entries to try to free
939
+ * @nr_to_scan : number of entries to try to free
908
940
*
909
- * Attempt to shrink the superblock dcache LRU by @count entries. This is
941
+ * Attempt to shrink the superblock dcache LRU by @nr_to_scan entries. This is
910
942
* done when we need more memory an called from the superblock shrinker
911
943
* function.
912
944
*
@@ -915,45 +947,12 @@ static void shrink_dentry_list(struct list_head *list)
915
947
*/
916
948
long prune_dcache_sb (struct super_block * sb , unsigned long nr_to_scan )
917
949
{
918
- struct dentry * dentry ;
919
- LIST_HEAD (referenced );
920
- LIST_HEAD (tmp );
921
- long freed = 0 ;
950
+ LIST_HEAD (dispose );
951
+ long freed ;
922
952
923
- relock :
924
- spin_lock (& sb -> s_dentry_lru_lock );
925
- while (!list_empty (& sb -> s_dentry_lru )) {
926
- dentry = list_entry (sb -> s_dentry_lru .prev ,
927
- struct dentry , d_lru );
928
- BUG_ON (dentry -> d_sb != sb );
929
-
930
- if (!spin_trylock (& dentry -> d_lock )) {
931
- spin_unlock (& sb -> s_dentry_lru_lock );
932
- cpu_relax ();
933
- goto relock ;
934
- }
935
-
936
- if (dentry -> d_flags & DCACHE_REFERENCED ) {
937
- dentry -> d_flags &= ~DCACHE_REFERENCED ;
938
- list_move (& dentry -> d_lru , & referenced );
939
- spin_unlock (& dentry -> d_lock );
940
- } else {
941
- list_move (& dentry -> d_lru , & tmp );
942
- dentry -> d_flags |= DCACHE_SHRINK_LIST ;
943
- this_cpu_dec (nr_dentry_unused );
944
- sb -> s_nr_dentry_unused -- ;
945
- spin_unlock (& dentry -> d_lock );
946
- freed ++ ;
947
- if (!-- nr_to_scan )
948
- break ;
949
- }
950
- cond_resched_lock (& sb -> s_dentry_lru_lock );
951
- }
952
- if (!list_empty (& referenced ))
953
- list_splice (& referenced , & sb -> s_dentry_lru );
954
- spin_unlock (& sb -> s_dentry_lru_lock );
955
-
956
- shrink_dentry_list (& tmp );
953
+ freed = list_lru_walk (& sb -> s_dentry_lru , dentry_lru_isolate ,
954
+ & dispose , nr_to_scan );
955
+ shrink_dentry_list (& dispose );
957
956
return freed ;
958
957
}
959
958
@@ -987,24 +986,10 @@ shrink_dcache_list(
987
986
*/
988
987
void shrink_dcache_sb (struct super_block * sb )
989
988
{
990
- LIST_HEAD (tmp );
991
-
992
- spin_lock (& sb -> s_dentry_lru_lock );
993
- while (!list_empty (& sb -> s_dentry_lru )) {
994
- /*
995
- * account for removal here so we don't need to handle it later
996
- * even though the dentry is no longer on the lru list.
997
- */
998
- list_splice_init (& sb -> s_dentry_lru , & tmp );
999
- this_cpu_sub (nr_dentry_unused , sb -> s_nr_dentry_unused );
1000
- sb -> s_nr_dentry_unused = 0 ;
1001
- spin_unlock (& sb -> s_dentry_lru_lock );
989
+ long disposed ;
1002
990
1003
- shrink_dcache_list (& tmp );
1004
-
1005
- spin_lock (& sb -> s_dentry_lru_lock );
1006
- }
1007
- spin_unlock (& sb -> s_dentry_lru_lock );
991
+ disposed = list_lru_dispose_all (& sb -> s_dentry_lru , shrink_dcache_list );
992
+ this_cpu_sub (nr_dentry_unused , disposed );
1008
993
}
1009
994
EXPORT_SYMBOL (shrink_dcache_sb );
1010
995
@@ -1366,7 +1351,8 @@ static enum d_walk_ret select_collect(void *_data, struct dentry *dentry)
1366
1351
if (dentry -> d_lockref .count ) {
1367
1352
dentry_lru_del (dentry );
1368
1353
} else if (!(dentry -> d_flags & DCACHE_SHRINK_LIST )) {
1369
- dentry_lru_move_list (dentry , & data -> dispose );
1354
+ dentry_lru_del (dentry );
1355
+ list_add_tail (& dentry -> d_lru , & data -> dispose );
1370
1356
dentry -> d_flags |= DCACHE_SHRINK_LIST ;
1371
1357
data -> found ++ ;
1372
1358
ret = D_WALK_NORETRY ;
0 commit comments