6
6
*/
7
7
#include <linux/kernel.h>
8
8
#include <linux/module.h>
9
+ #include <linux/mm.h>
9
10
#include <linux/list_lru.h>
10
11
11
12
bool list_lru_add (struct list_lru * lru , struct list_head * item )
12
13
{
13
- spin_lock (& lru -> lock );
14
+ int nid = page_to_nid (virt_to_page (item ));
15
+ struct list_lru_node * nlru = & lru -> node [nid ];
16
+
17
+ spin_lock (& nlru -> lock );
18
+ WARN_ON_ONCE (nlru -> nr_items < 0 );
14
19
if (list_empty (item )) {
15
- list_add_tail (item , & lru -> list );
16
- lru -> nr_items ++ ;
17
- spin_unlock (& lru -> lock );
20
+ list_add_tail (item , & nlru -> list );
21
+ if (nlru -> nr_items ++ == 0 )
22
+ node_set (nid , lru -> active_nodes );
23
+ spin_unlock (& nlru -> lock );
18
24
return true;
19
25
}
20
- spin_unlock (& lru -> lock );
26
+ spin_unlock (& nlru -> lock );
21
27
return false;
22
28
}
23
29
EXPORT_SYMBOL_GPL (list_lru_add );
24
30
25
31
bool list_lru_del (struct list_lru * lru , struct list_head * item )
26
32
{
27
- spin_lock (& lru -> lock );
33
+ int nid = page_to_nid (virt_to_page (item ));
34
+ struct list_lru_node * nlru = & lru -> node [nid ];
35
+
36
+ spin_lock (& nlru -> lock );
28
37
if (!list_empty (item )) {
29
38
list_del_init (item );
30
- lru -> nr_items -- ;
31
- spin_unlock (& lru -> lock );
39
+ if (-- nlru -> nr_items == 0 )
40
+ node_clear (nid , lru -> active_nodes );
41
+ WARN_ON_ONCE (nlru -> nr_items < 0 );
42
+ spin_unlock (& nlru -> lock );
32
43
return true;
33
44
}
34
- spin_unlock (& lru -> lock );
45
+ spin_unlock (& nlru -> lock );
35
46
return false;
36
47
}
37
48
EXPORT_SYMBOL_GPL (list_lru_del );
38
49
39
- unsigned long list_lru_walk (struct list_lru * lru , list_lru_walk_cb isolate ,
40
- void * cb_arg , unsigned long nr_to_walk )
50
+ unsigned long list_lru_count (struct list_lru * lru )
41
51
{
52
+ unsigned long count = 0 ;
53
+ int nid ;
54
+
55
+ for_each_node_mask (nid , lru -> active_nodes ) {
56
+ struct list_lru_node * nlru = & lru -> node [nid ];
57
+
58
+ spin_lock (& nlru -> lock );
59
+ WARN_ON_ONCE (nlru -> nr_items < 0 );
60
+ count += nlru -> nr_items ;
61
+ spin_unlock (& nlru -> lock );
62
+ }
63
+
64
+ return count ;
65
+ }
66
+ EXPORT_SYMBOL_GPL (list_lru_count );
67
+
68
+ static unsigned long
69
+ list_lru_walk_node (struct list_lru * lru , int nid , list_lru_walk_cb isolate ,
70
+ void * cb_arg , unsigned long * nr_to_walk )
71
+ {
72
+
73
+ struct list_lru_node * nlru = & lru -> node [nid ];
42
74
struct list_head * item , * n ;
43
- unsigned long removed = 0 ;
75
+ unsigned long isolated = 0 ;
44
76
/*
45
77
* If we don't keep state of at which pass we are, we can loop at
46
78
* LRU_RETRY, since we have no guarantees that the caller will be able
@@ -50,18 +82,20 @@ unsigned long list_lru_walk(struct list_lru *lru, list_lru_walk_cb isolate,
50
82
*/
51
83
bool first_pass = true;
52
84
53
- spin_lock (& lru -> lock );
85
+ spin_lock (& nlru -> lock );
54
86
restart :
55
- list_for_each_safe (item , n , & lru -> list ) {
87
+ list_for_each_safe (item , n , & nlru -> list ) {
56
88
enum lru_status ret ;
57
- ret = isolate (item , & lru -> lock , cb_arg );
89
+ ret = isolate (item , & nlru -> lock , cb_arg );
58
90
switch (ret ) {
59
91
case LRU_REMOVED :
60
- lru -> nr_items -- ;
61
- removed ++ ;
92
+ if (-- nlru -> nr_items == 0 )
93
+ node_clear (nid , lru -> active_nodes );
94
+ WARN_ON_ONCE (nlru -> nr_items < 0 );
95
+ isolated ++ ;
62
96
break ;
63
97
case LRU_ROTATE :
64
- list_move_tail (item , & lru -> list );
98
+ list_move_tail (item , & nlru -> list );
65
99
break ;
66
100
case LRU_SKIP :
67
101
break ;
@@ -76,42 +110,84 @@ unsigned long list_lru_walk(struct list_lru *lru, list_lru_walk_cb isolate,
76
110
BUG ();
77
111
}
78
112
79
- if (nr_to_walk -- == 0 )
113
+ if (( * nr_to_walk ) -- == 0 )
80
114
break ;
81
115
82
116
}
83
- spin_unlock (& lru -> lock );
84
- return removed ;
117
+
118
+ spin_unlock (& nlru -> lock );
119
+ return isolated ;
120
+ }
121
+ EXPORT_SYMBOL_GPL (list_lru_walk_node );
122
+
123
+ unsigned long list_lru_walk (struct list_lru * lru , list_lru_walk_cb isolate ,
124
+ void * cb_arg , unsigned long nr_to_walk )
125
+ {
126
+ unsigned long isolated = 0 ;
127
+ int nid ;
128
+
129
+ for_each_node_mask (nid , lru -> active_nodes ) {
130
+ isolated += list_lru_walk_node (lru , nid , isolate ,
131
+ cb_arg , & nr_to_walk );
132
+ if (nr_to_walk <= 0 )
133
+ break ;
134
+ }
135
+ return isolated ;
85
136
}
86
137
EXPORT_SYMBOL_GPL (list_lru_walk );
87
138
88
- unsigned long list_lru_dispose_all (struct list_lru * lru ,
89
- list_lru_dispose_cb dispose )
139
+ static unsigned long list_lru_dispose_all_node (struct list_lru * lru , int nid ,
140
+ list_lru_dispose_cb dispose )
90
141
{
91
- unsigned long disposed = 0 ;
142
+ struct list_lru_node * nlru = & lru -> node [ nid ] ;
92
143
LIST_HEAD (dispose_list );
144
+ unsigned long disposed = 0 ;
93
145
94
- spin_lock (& lru -> lock );
95
- while (!list_empty (& lru -> list )) {
96
- list_splice_init (& lru -> list , & dispose_list );
97
- disposed += lru -> nr_items ;
98
- lru -> nr_items = 0 ;
99
- spin_unlock (& lru -> lock );
146
+ spin_lock (& nlru -> lock );
147
+ while (!list_empty (& nlru -> list )) {
148
+ list_splice_init (& nlru -> list , & dispose_list );
149
+ disposed += nlru -> nr_items ;
150
+ nlru -> nr_items = 0 ;
151
+ node_clear (nid , lru -> active_nodes );
152
+ spin_unlock (& nlru -> lock );
100
153
101
154
dispose (& dispose_list );
102
155
103
- spin_lock (& lru -> lock );
156
+ spin_lock (& nlru -> lock );
104
157
}
105
- spin_unlock (& lru -> lock );
158
+ spin_unlock (& nlru -> lock );
106
159
return disposed ;
107
160
}
108
161
162
+ unsigned long list_lru_dispose_all (struct list_lru * lru ,
163
+ list_lru_dispose_cb dispose )
164
+ {
165
+ unsigned long disposed ;
166
+ unsigned long total = 0 ;
167
+ int nid ;
168
+
169
+ do {
170
+ disposed = 0 ;
171
+ for_each_node_mask (nid , lru -> active_nodes ) {
172
+ disposed += list_lru_dispose_all_node (lru , nid ,
173
+ dispose );
174
+ }
175
+ total += disposed ;
176
+ } while (disposed != 0 );
177
+
178
+ return total ;
179
+ }
180
+
109
181
int list_lru_init (struct list_lru * lru )
110
182
{
111
- spin_lock_init (& lru -> lock );
112
- INIT_LIST_HEAD (& lru -> list );
113
- lru -> nr_items = 0 ;
183
+ int i ;
114
184
185
+ nodes_clear (lru -> active_nodes );
186
+ for (i = 0 ; i < MAX_NUMNODES ; i ++ ) {
187
+ spin_lock_init (& lru -> node [i ].lock );
188
+ INIT_LIST_HEAD (& lru -> node [i ].list );
189
+ lru -> node [i ].nr_items = 0 ;
190
+ }
115
191
return 0 ;
116
192
}
117
193
EXPORT_SYMBOL_GPL (list_lru_init );
0 commit comments