xref: /openbmc/linux/kernel/bpf/bpf_lru_list.c (revision 8730046c)
1 /* Copyright (c) 2016 Facebook
2  *
3  * This program is free software; you can redistribute it and/or
4  * modify it under the terms of version 2 of the GNU General Public
5  * License as published by the Free Software Foundation.
6  */
7 #include <linux/cpumask.h>
8 #include <linux/spinlock.h>
9 #include <linux/percpu.h>
10 
11 #include "bpf_lru_list.h"
12 
13 #define LOCAL_FREE_TARGET		(128)
14 #define LOCAL_NR_SCANS			LOCAL_FREE_TARGET
15 
16 #define PERCPU_FREE_TARGET		(16)
17 #define PERCPU_NR_SCANS			PERCPU_FREE_TARGET
18 
19 /* Helpers to get the local list index */
20 #define LOCAL_LIST_IDX(t)	((t) - BPF_LOCAL_LIST_T_OFFSET)
21 #define LOCAL_FREE_LIST_IDX	LOCAL_LIST_IDX(BPF_LRU_LOCAL_LIST_T_FREE)
22 #define LOCAL_PENDING_LIST_IDX	LOCAL_LIST_IDX(BPF_LRU_LOCAL_LIST_T_PENDING)
23 #define IS_LOCAL_LIST_TYPE(t)	((t) >= BPF_LOCAL_LIST_T_OFFSET)
24 
25 static int get_next_cpu(int cpu)
26 {
27 	cpu = cpumask_next(cpu, cpu_possible_mask);
28 	if (cpu >= nr_cpu_ids)
29 		cpu = cpumask_first(cpu_possible_mask);
30 	return cpu;
31 }
32 
33 /* Local list helpers */
34 static struct list_head *local_free_list(struct bpf_lru_locallist *loc_l)
35 {
36 	return &loc_l->lists[LOCAL_FREE_LIST_IDX];
37 }
38 
39 static struct list_head *local_pending_list(struct bpf_lru_locallist *loc_l)
40 {
41 	return &loc_l->lists[LOCAL_PENDING_LIST_IDX];
42 }
43 
44 /* bpf_lru_node helpers */
45 static bool bpf_lru_node_is_ref(const struct bpf_lru_node *node)
46 {
47 	return node->ref;
48 }
49 
50 static void bpf_lru_list_count_inc(struct bpf_lru_list *l,
51 				   enum bpf_lru_list_type type)
52 {
53 	if (type < NR_BPF_LRU_LIST_COUNT)
54 		l->counts[type]++;
55 }
56 
57 static void bpf_lru_list_count_dec(struct bpf_lru_list *l,
58 				   enum bpf_lru_list_type type)
59 {
60 	if (type < NR_BPF_LRU_LIST_COUNT)
61 		l->counts[type]--;
62 }
63 
64 static void __bpf_lru_node_move_to_free(struct bpf_lru_list *l,
65 					struct bpf_lru_node *node,
66 					struct list_head *free_list,
67 					enum bpf_lru_list_type tgt_free_type)
68 {
69 	if (WARN_ON_ONCE(IS_LOCAL_LIST_TYPE(node->type)))
70 		return;
71 
72 	/* If the removing node is the next_inactive_rotation candidate,
73 	 * move the next_inactive_rotation pointer also.
74 	 */
75 	if (&node->list == l->next_inactive_rotation)
76 		l->next_inactive_rotation = l->next_inactive_rotation->prev;
77 
78 	bpf_lru_list_count_dec(l, node->type);
79 
80 	node->type = tgt_free_type;
81 	list_move(&node->list, free_list);
82 }
83 
84 /* Move nodes from local list to the LRU list */
85 static void __bpf_lru_node_move_in(struct bpf_lru_list *l,
86 				   struct bpf_lru_node *node,
87 				   enum bpf_lru_list_type tgt_type)
88 {
89 	if (WARN_ON_ONCE(!IS_LOCAL_LIST_TYPE(node->type)) ||
90 	    WARN_ON_ONCE(IS_LOCAL_LIST_TYPE(tgt_type)))
91 		return;
92 
93 	bpf_lru_list_count_inc(l, tgt_type);
94 	node->type = tgt_type;
95 	node->ref = 0;
96 	list_move(&node->list, &l->lists[tgt_type]);
97 }
98 
99 /* Move nodes between or within active and inactive list (like
100  * active to inactive, inactive to active or tail of active back to
101  * the head of active).
102  */
103 static void __bpf_lru_node_move(struct bpf_lru_list *l,
104 				struct bpf_lru_node *node,
105 				enum bpf_lru_list_type tgt_type)
106 {
107 	if (WARN_ON_ONCE(IS_LOCAL_LIST_TYPE(node->type)) ||
108 	    WARN_ON_ONCE(IS_LOCAL_LIST_TYPE(tgt_type)))
109 		return;
110 
111 	if (node->type != tgt_type) {
112 		bpf_lru_list_count_dec(l, node->type);
113 		bpf_lru_list_count_inc(l, tgt_type);
114 		node->type = tgt_type;
115 	}
116 	node->ref = 0;
117 
118 	/* If the moving node is the next_inactive_rotation candidate,
119 	 * move the next_inactive_rotation pointer also.
120 	 */
121 	if (&node->list == l->next_inactive_rotation)
122 		l->next_inactive_rotation = l->next_inactive_rotation->prev;
123 
124 	list_move(&node->list, &l->lists[tgt_type]);
125 }
126 
127 static bool bpf_lru_list_inactive_low(const struct bpf_lru_list *l)
128 {
129 	return l->counts[BPF_LRU_LIST_T_INACTIVE] <
130 		l->counts[BPF_LRU_LIST_T_ACTIVE];
131 }
132 
133 /* Rotate the active list:
134  * 1. Start from tail
135  * 2. If the node has the ref bit set, it will be rotated
136  *    back to the head of active list with the ref bit cleared.
137  *    Give this node one more chance to survive in the active list.
138  * 3. If the ref bit is not set, move it to the head of the
139  *    inactive list.
140  * 4. It will at most scan nr_scans nodes
141  */
142 static void __bpf_lru_list_rotate_active(struct bpf_lru *lru,
143 					 struct bpf_lru_list *l)
144 {
145 	struct list_head *active = &l->lists[BPF_LRU_LIST_T_ACTIVE];
146 	struct bpf_lru_node *node, *tmp_node, *first_node;
147 	unsigned int i = 0;
148 
149 	first_node = list_first_entry(active, struct bpf_lru_node, list);
150 	list_for_each_entry_safe_reverse(node, tmp_node, active, list) {
151 		if (bpf_lru_node_is_ref(node))
152 			__bpf_lru_node_move(l, node, BPF_LRU_LIST_T_ACTIVE);
153 		else
154 			__bpf_lru_node_move(l, node, BPF_LRU_LIST_T_INACTIVE);
155 
156 		if (++i == lru->nr_scans || node == first_node)
157 			break;
158 	}
159 }
160 
161 /* Rotate the inactive list.  It starts from the next_inactive_rotation
162  * 1. If the node has ref bit set, it will be moved to the head
163  *    of active list with the ref bit cleared.
164  * 2. If the node does not have ref bit set, it will leave it
165  *    at its current location (i.e. do nothing) so that it can
166  *    be considered during the next inactive_shrink.
167  * 3. It will at most scan nr_scans nodes
168  */
169 static void __bpf_lru_list_rotate_inactive(struct bpf_lru *lru,
170 					   struct bpf_lru_list *l)
171 {
172 	struct list_head *inactive = &l->lists[BPF_LRU_LIST_T_INACTIVE];
173 	struct list_head *cur, *last, *next = inactive;
174 	struct bpf_lru_node *node;
175 	unsigned int i = 0;
176 
177 	if (list_empty(inactive))
178 		return;
179 
180 	last = l->next_inactive_rotation->next;
181 	if (last == inactive)
182 		last = last->next;
183 
184 	cur = l->next_inactive_rotation;
185 	while (i < lru->nr_scans) {
186 		if (cur == inactive) {
187 			cur = cur->prev;
188 			continue;
189 		}
190 
191 		node = list_entry(cur, struct bpf_lru_node, list);
192 		next = cur->prev;
193 		if (bpf_lru_node_is_ref(node))
194 			__bpf_lru_node_move(l, node, BPF_LRU_LIST_T_ACTIVE);
195 		if (cur == last)
196 			break;
197 		cur = next;
198 		i++;
199 	}
200 
201 	l->next_inactive_rotation = next;
202 }
203 
204 /* Shrink the inactive list.  It starts from the tail of the
205  * inactive list and only move the nodes without the ref bit
206  * set to the designated free list.
207  */
208 static unsigned int
209 __bpf_lru_list_shrink_inactive(struct bpf_lru *lru,
210 			       struct bpf_lru_list *l,
211 			       unsigned int tgt_nshrink,
212 			       struct list_head *free_list,
213 			       enum bpf_lru_list_type tgt_free_type)
214 {
215 	struct list_head *inactive = &l->lists[BPF_LRU_LIST_T_INACTIVE];
216 	struct bpf_lru_node *node, *tmp_node, *first_node;
217 	unsigned int nshrinked = 0;
218 	unsigned int i = 0;
219 
220 	first_node = list_first_entry(inactive, struct bpf_lru_node, list);
221 	list_for_each_entry_safe_reverse(node, tmp_node, inactive, list) {
222 		if (bpf_lru_node_is_ref(node)) {
223 			__bpf_lru_node_move(l, node, BPF_LRU_LIST_T_ACTIVE);
224 		} else if (lru->del_from_htab(lru->del_arg, node)) {
225 			__bpf_lru_node_move_to_free(l, node, free_list,
226 						    tgt_free_type);
227 			if (++nshrinked == tgt_nshrink)
228 				break;
229 		}
230 
231 		if (++i == lru->nr_scans)
232 			break;
233 	}
234 
235 	return nshrinked;
236 }
237 
238 /* 1. Rotate the active list (if needed)
239  * 2. Always rotate the inactive list
240  */
241 static void __bpf_lru_list_rotate(struct bpf_lru *lru, struct bpf_lru_list *l)
242 {
243 	if (bpf_lru_list_inactive_low(l))
244 		__bpf_lru_list_rotate_active(lru, l);
245 
246 	__bpf_lru_list_rotate_inactive(lru, l);
247 }
248 
249 /* Calls __bpf_lru_list_shrink_inactive() to shrink some
250  * ref-bit-cleared nodes and move them to the designated
251  * free list.
252  *
253  * If it cannot get a free node after calling
254  * __bpf_lru_list_shrink_inactive().  It will just remove
255  * one node from either inactive or active list without
256  * honoring the ref-bit.  It prefers inactive list to active
257  * list in this situation.
258  */
259 static unsigned int __bpf_lru_list_shrink(struct bpf_lru *lru,
260 					  struct bpf_lru_list *l,
261 					  unsigned int tgt_nshrink,
262 					  struct list_head *free_list,
263 					  enum bpf_lru_list_type tgt_free_type)
264 
265 {
266 	struct bpf_lru_node *node, *tmp_node;
267 	struct list_head *force_shrink_list;
268 	unsigned int nshrinked;
269 
270 	nshrinked = __bpf_lru_list_shrink_inactive(lru, l, tgt_nshrink,
271 						   free_list, tgt_free_type);
272 	if (nshrinked)
273 		return nshrinked;
274 
275 	/* Do a force shrink by ignoring the reference bit */
276 	if (!list_empty(&l->lists[BPF_LRU_LIST_T_INACTIVE]))
277 		force_shrink_list = &l->lists[BPF_LRU_LIST_T_INACTIVE];
278 	else
279 		force_shrink_list = &l->lists[BPF_LRU_LIST_T_ACTIVE];
280 
281 	list_for_each_entry_safe_reverse(node, tmp_node, force_shrink_list,
282 					 list) {
283 		if (lru->del_from_htab(lru->del_arg, node)) {
284 			__bpf_lru_node_move_to_free(l, node, free_list,
285 						    tgt_free_type);
286 			return 1;
287 		}
288 	}
289 
290 	return 0;
291 }
292 
293 /* Flush the nodes from the local pending list to the LRU list */
294 static void __local_list_flush(struct bpf_lru_list *l,
295 			       struct bpf_lru_locallist *loc_l)
296 {
297 	struct bpf_lru_node *node, *tmp_node;
298 
299 	list_for_each_entry_safe_reverse(node, tmp_node,
300 					 local_pending_list(loc_l), list) {
301 		if (bpf_lru_node_is_ref(node))
302 			__bpf_lru_node_move_in(l, node, BPF_LRU_LIST_T_ACTIVE);
303 		else
304 			__bpf_lru_node_move_in(l, node,
305 					       BPF_LRU_LIST_T_INACTIVE);
306 	}
307 }
308 
309 static void bpf_lru_list_push_free(struct bpf_lru_list *l,
310 				   struct bpf_lru_node *node)
311 {
312 	unsigned long flags;
313 
314 	if (WARN_ON_ONCE(IS_LOCAL_LIST_TYPE(node->type)))
315 		return;
316 
317 	raw_spin_lock_irqsave(&l->lock, flags);
318 	__bpf_lru_node_move(l, node, BPF_LRU_LIST_T_FREE);
319 	raw_spin_unlock_irqrestore(&l->lock, flags);
320 }
321 
322 static void bpf_lru_list_pop_free_to_local(struct bpf_lru *lru,
323 					   struct bpf_lru_locallist *loc_l)
324 {
325 	struct bpf_lru_list *l = &lru->common_lru.lru_list;
326 	struct bpf_lru_node *node, *tmp_node;
327 	unsigned int nfree = 0;
328 
329 	raw_spin_lock(&l->lock);
330 
331 	__local_list_flush(l, loc_l);
332 
333 	__bpf_lru_list_rotate(lru, l);
334 
335 	list_for_each_entry_safe(node, tmp_node, &l->lists[BPF_LRU_LIST_T_FREE],
336 				 list) {
337 		__bpf_lru_node_move_to_free(l, node, local_free_list(loc_l),
338 					    BPF_LRU_LOCAL_LIST_T_FREE);
339 		if (++nfree == LOCAL_FREE_TARGET)
340 			break;
341 	}
342 
343 	if (nfree < LOCAL_FREE_TARGET)
344 		__bpf_lru_list_shrink(lru, l, LOCAL_FREE_TARGET - nfree,
345 				      local_free_list(loc_l),
346 				      BPF_LRU_LOCAL_LIST_T_FREE);
347 
348 	raw_spin_unlock(&l->lock);
349 }
350 
351 static void __local_list_add_pending(struct bpf_lru *lru,
352 				     struct bpf_lru_locallist *loc_l,
353 				     int cpu,
354 				     struct bpf_lru_node *node,
355 				     u32 hash)
356 {
357 	*(u32 *)((void *)node + lru->hash_offset) = hash;
358 	node->cpu = cpu;
359 	node->type = BPF_LRU_LOCAL_LIST_T_PENDING;
360 	node->ref = 0;
361 	list_add(&node->list, local_pending_list(loc_l));
362 }
363 
364 struct bpf_lru_node *__local_list_pop_free(struct bpf_lru_locallist *loc_l)
365 {
366 	struct bpf_lru_node *node;
367 
368 	node = list_first_entry_or_null(local_free_list(loc_l),
369 					struct bpf_lru_node,
370 					list);
371 	if (node)
372 		list_del(&node->list);
373 
374 	return node;
375 }
376 
377 struct bpf_lru_node *__local_list_pop_pending(struct bpf_lru *lru,
378 					      struct bpf_lru_locallist *loc_l)
379 {
380 	struct bpf_lru_node *node;
381 	bool force = false;
382 
383 ignore_ref:
384 	/* Get from the tail (i.e. older element) of the pending list. */
385 	list_for_each_entry_reverse(node, local_pending_list(loc_l),
386 				    list) {
387 		if ((!bpf_lru_node_is_ref(node) || force) &&
388 		    lru->del_from_htab(lru->del_arg, node)) {
389 			list_del(&node->list);
390 			return node;
391 		}
392 	}
393 
394 	if (!force) {
395 		force = true;
396 		goto ignore_ref;
397 	}
398 
399 	return NULL;
400 }
401 
402 static struct bpf_lru_node *bpf_percpu_lru_pop_free(struct bpf_lru *lru,
403 						    u32 hash)
404 {
405 	struct list_head *free_list;
406 	struct bpf_lru_node *node = NULL;
407 	struct bpf_lru_list *l;
408 	unsigned long flags;
409 	int cpu = raw_smp_processor_id();
410 
411 	l = per_cpu_ptr(lru->percpu_lru, cpu);
412 
413 	raw_spin_lock_irqsave(&l->lock, flags);
414 
415 	__bpf_lru_list_rotate(lru, l);
416 
417 	free_list = &l->lists[BPF_LRU_LIST_T_FREE];
418 	if (list_empty(free_list))
419 		__bpf_lru_list_shrink(lru, l, PERCPU_FREE_TARGET, free_list,
420 				      BPF_LRU_LIST_T_FREE);
421 
422 	if (!list_empty(free_list)) {
423 		node = list_first_entry(free_list, struct bpf_lru_node, list);
424 		*(u32 *)((void *)node + lru->hash_offset) = hash;
425 		node->ref = 0;
426 		__bpf_lru_node_move(l, node, BPF_LRU_LIST_T_INACTIVE);
427 	}
428 
429 	raw_spin_unlock_irqrestore(&l->lock, flags);
430 
431 	return node;
432 }
433 
434 static struct bpf_lru_node *bpf_common_lru_pop_free(struct bpf_lru *lru,
435 						    u32 hash)
436 {
437 	struct bpf_lru_locallist *loc_l, *steal_loc_l;
438 	struct bpf_common_lru *clru = &lru->common_lru;
439 	struct bpf_lru_node *node;
440 	int steal, first_steal;
441 	unsigned long flags;
442 	int cpu = raw_smp_processor_id();
443 
444 	loc_l = per_cpu_ptr(clru->local_list, cpu);
445 
446 	raw_spin_lock_irqsave(&loc_l->lock, flags);
447 
448 	node = __local_list_pop_free(loc_l);
449 	if (!node) {
450 		bpf_lru_list_pop_free_to_local(lru, loc_l);
451 		node = __local_list_pop_free(loc_l);
452 	}
453 
454 	if (node)
455 		__local_list_add_pending(lru, loc_l, cpu, node, hash);
456 
457 	raw_spin_unlock_irqrestore(&loc_l->lock, flags);
458 
459 	if (node)
460 		return node;
461 
462 	/* No free nodes found from the local free list and
463 	 * the global LRU list.
464 	 *
465 	 * Steal from the local free/pending list of the
466 	 * current CPU and remote CPU in RR.  It starts
467 	 * with the loc_l->next_steal CPU.
468 	 */
469 
470 	first_steal = loc_l->next_steal;
471 	steal = first_steal;
472 	do {
473 		steal_loc_l = per_cpu_ptr(clru->local_list, steal);
474 
475 		raw_spin_lock_irqsave(&steal_loc_l->lock, flags);
476 
477 		node = __local_list_pop_free(steal_loc_l);
478 		if (!node)
479 			node = __local_list_pop_pending(lru, steal_loc_l);
480 
481 		raw_spin_unlock_irqrestore(&steal_loc_l->lock, flags);
482 
483 		steal = get_next_cpu(steal);
484 	} while (!node && steal != first_steal);
485 
486 	loc_l->next_steal = steal;
487 
488 	if (node) {
489 		raw_spin_lock_irqsave(&loc_l->lock, flags);
490 		__local_list_add_pending(lru, loc_l, cpu, node, hash);
491 		raw_spin_unlock_irqrestore(&loc_l->lock, flags);
492 	}
493 
494 	return node;
495 }
496 
497 struct bpf_lru_node *bpf_lru_pop_free(struct bpf_lru *lru, u32 hash)
498 {
499 	if (lru->percpu)
500 		return bpf_percpu_lru_pop_free(lru, hash);
501 	else
502 		return bpf_common_lru_pop_free(lru, hash);
503 }
504 
505 static void bpf_common_lru_push_free(struct bpf_lru *lru,
506 				     struct bpf_lru_node *node)
507 {
508 	unsigned long flags;
509 
510 	if (WARN_ON_ONCE(node->type == BPF_LRU_LIST_T_FREE) ||
511 	    WARN_ON_ONCE(node->type == BPF_LRU_LOCAL_LIST_T_FREE))
512 		return;
513 
514 	if (node->type == BPF_LRU_LOCAL_LIST_T_PENDING) {
515 		struct bpf_lru_locallist *loc_l;
516 
517 		loc_l = per_cpu_ptr(lru->common_lru.local_list, node->cpu);
518 
519 		raw_spin_lock_irqsave(&loc_l->lock, flags);
520 
521 		if (unlikely(node->type != BPF_LRU_LOCAL_LIST_T_PENDING)) {
522 			raw_spin_unlock_irqrestore(&loc_l->lock, flags);
523 			goto check_lru_list;
524 		}
525 
526 		node->type = BPF_LRU_LOCAL_LIST_T_FREE;
527 		node->ref = 0;
528 		list_move(&node->list, local_free_list(loc_l));
529 
530 		raw_spin_unlock_irqrestore(&loc_l->lock, flags);
531 		return;
532 	}
533 
534 check_lru_list:
535 	bpf_lru_list_push_free(&lru->common_lru.lru_list, node);
536 }
537 
538 static void bpf_percpu_lru_push_free(struct bpf_lru *lru,
539 				     struct bpf_lru_node *node)
540 {
541 	struct bpf_lru_list *l;
542 	unsigned long flags;
543 
544 	l = per_cpu_ptr(lru->percpu_lru, node->cpu);
545 
546 	raw_spin_lock_irqsave(&l->lock, flags);
547 
548 	__bpf_lru_node_move(l, node, BPF_LRU_LIST_T_FREE);
549 
550 	raw_spin_unlock_irqrestore(&l->lock, flags);
551 }
552 
553 void bpf_lru_push_free(struct bpf_lru *lru, struct bpf_lru_node *node)
554 {
555 	if (lru->percpu)
556 		bpf_percpu_lru_push_free(lru, node);
557 	else
558 		bpf_common_lru_push_free(lru, node);
559 }
560 
561 void bpf_common_lru_populate(struct bpf_lru *lru, void *buf, u32 node_offset,
562 			     u32 elem_size, u32 nr_elems)
563 {
564 	struct bpf_lru_list *l = &lru->common_lru.lru_list;
565 	u32 i;
566 
567 	for (i = 0; i < nr_elems; i++) {
568 		struct bpf_lru_node *node;
569 
570 		node = (struct bpf_lru_node *)(buf + node_offset);
571 		node->type = BPF_LRU_LIST_T_FREE;
572 		node->ref = 0;
573 		list_add(&node->list, &l->lists[BPF_LRU_LIST_T_FREE]);
574 		buf += elem_size;
575 	}
576 }
577 
578 void bpf_percpu_lru_populate(struct bpf_lru *lru, void *buf, u32 node_offset,
579 			     u32 elem_size, u32 nr_elems)
580 {
581 	u32 i, pcpu_entries;
582 	int cpu;
583 	struct bpf_lru_list *l;
584 
585 	pcpu_entries = nr_elems / num_possible_cpus();
586 
587 	i = 0;
588 
589 	for_each_possible_cpu(cpu) {
590 		struct bpf_lru_node *node;
591 
592 		l = per_cpu_ptr(lru->percpu_lru, cpu);
593 again:
594 		node = (struct bpf_lru_node *)(buf + node_offset);
595 		node->cpu = cpu;
596 		node->type = BPF_LRU_LIST_T_FREE;
597 		node->ref = 0;
598 		list_add(&node->list, &l->lists[BPF_LRU_LIST_T_FREE]);
599 		i++;
600 		buf += elem_size;
601 		if (i == nr_elems)
602 			break;
603 		if (i % pcpu_entries)
604 			goto again;
605 	}
606 }
607 
608 void bpf_lru_populate(struct bpf_lru *lru, void *buf, u32 node_offset,
609 		      u32 elem_size, u32 nr_elems)
610 {
611 	if (lru->percpu)
612 		bpf_percpu_lru_populate(lru, buf, node_offset, elem_size,
613 					nr_elems);
614 	else
615 		bpf_common_lru_populate(lru, buf, node_offset, elem_size,
616 					nr_elems);
617 }
618 
619 static void bpf_lru_locallist_init(struct bpf_lru_locallist *loc_l, int cpu)
620 {
621 	int i;
622 
623 	for (i = 0; i < NR_BPF_LRU_LOCAL_LIST_T; i++)
624 		INIT_LIST_HEAD(&loc_l->lists[i]);
625 
626 	loc_l->next_steal = cpu;
627 
628 	raw_spin_lock_init(&loc_l->lock);
629 }
630 
631 static void bpf_lru_list_init(struct bpf_lru_list *l)
632 {
633 	int i;
634 
635 	for (i = 0; i < NR_BPF_LRU_LIST_T; i++)
636 		INIT_LIST_HEAD(&l->lists[i]);
637 
638 	for (i = 0; i < NR_BPF_LRU_LIST_COUNT; i++)
639 		l->counts[i] = 0;
640 
641 	l->next_inactive_rotation = &l->lists[BPF_LRU_LIST_T_INACTIVE];
642 
643 	raw_spin_lock_init(&l->lock);
644 }
645 
646 int bpf_lru_init(struct bpf_lru *lru, bool percpu, u32 hash_offset,
647 		 del_from_htab_func del_from_htab, void *del_arg)
648 {
649 	int cpu;
650 
651 	if (percpu) {
652 		lru->percpu_lru = alloc_percpu(struct bpf_lru_list);
653 		if (!lru->percpu_lru)
654 			return -ENOMEM;
655 
656 		for_each_possible_cpu(cpu) {
657 			struct bpf_lru_list *l;
658 
659 			l = per_cpu_ptr(lru->percpu_lru, cpu);
660 			bpf_lru_list_init(l);
661 		}
662 		lru->nr_scans = PERCPU_NR_SCANS;
663 	} else {
664 		struct bpf_common_lru *clru = &lru->common_lru;
665 
666 		clru->local_list = alloc_percpu(struct bpf_lru_locallist);
667 		if (!clru->local_list)
668 			return -ENOMEM;
669 
670 		for_each_possible_cpu(cpu) {
671 			struct bpf_lru_locallist *loc_l;
672 
673 			loc_l = per_cpu_ptr(clru->local_list, cpu);
674 			bpf_lru_locallist_init(loc_l, cpu);
675 		}
676 
677 		bpf_lru_list_init(&clru->lru_list);
678 		lru->nr_scans = LOCAL_NR_SCANS;
679 	}
680 
681 	lru->percpu = percpu;
682 	lru->del_from_htab = del_from_htab;
683 	lru->del_arg = del_arg;
684 	lru->hash_offset = hash_offset;
685 
686 	return 0;
687 }
688 
689 void bpf_lru_destroy(struct bpf_lru *lru)
690 {
691 	if (lru->percpu)
692 		free_percpu(lru->percpu_lru);
693 	else
694 		free_percpu(lru->common_lru.local_list);
695 }
696