1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (C) 2022-2023 Isovalent, Inc.
4 node [colorscheme=accent4
,style=
filled] # Apply colorscheme to all nodes
5 graph [
splines=ortho
, nodesep=
1]
8 label =
"Key\n(locks held during operation)";
11 remote_lock [
shape=rectangle
,fillcolor=
4,label=
"remote CPU LRU lock"]
12 hash_lock [
shape=rectangle
,fillcolor=
3,label=
"hashtab lock"]
13 lru_lock [
shape=rectangle
,fillcolor=
2,label=
"LRU lock"]
14 local_lock [
shape=rectangle
,fillcolor=
1,label=
"local CPU LRU lock"]
15 no_lock [
shape=rectangle
,label=
"no locks held"]
18 begin [
shape=oval
,label=
"begin\nbpf_map_update()"]
20 // Nodes below with an 'fn_' prefix are roughly labeled by the C function
21 // names that initiate the corresponding logic in kernel/bpf/bpf_lru_list.c.
22 // Number suffixes and errno suffixes handle subsections of the corresponding
23 // logic in the function as of the writing of this dot.
25 // cf. __local_list_pop_free() / bpf_percpu_lru_pop_free()
26 local_freelist_check [
shape=
diamond,fillcolor=
1,
27 label=
"Local freelist\nnode available?"]
;
28 use_local_node [
shape=rectangle
,
29 label=
"Use node owned\nby this CPU"]
31 // cf. bpf_lru_pop_free()
32 common_lru_check [
shape=
diamond,
33 label=
"Map created with\ncommon LRU?\n(!BPF_F_NO_COMMON_LRU)"]
;
35 fn_bpf_lru_list_pop_free_to_local [
shape=rectangle
,fillcolor=
2,
36 label=
"Flush local pending,
37 Rotate Global list, move
39 from global -> local"]
40 // Also corresponds to:
41 // fn__local_list_flush()
42 // fn_bpf_lru_list_rotate()
43 fn___bpf_lru_node_move_to_free[
shape=
diamond,fillcolor=
2,
44 label=
"Able to free\nLOCAL_FREE_TARGET\nnodes?"]
46 fn___bpf_lru_list_shrink_inactive [
shape=rectangle
,fillcolor=
3,
47 label=
"Shrink inactive list
50 (global LRU -> local)"]
51 fn___bpf_lru_list_shrink [
shape=
diamond,fillcolor=
2,
52 label=
"> 0 entries in\nlocal free list?"]
53 fn___bpf_lru_list_shrink2 [
shape=rectangle
,fillcolor=
2,
54 label=
"Steal one node from
55 inactive, or if empty,
56 from active global list"]
57 fn___bpf_lru_list_shrink3 [
shape=rectangle
,fillcolor=
3,
58 label=
"Try to remove\nnode from hashtab"]
60 local_freelist_check2 [
shape=
diamond,label=
"Htab removal\nsuccessful?"]
61 common_lru_check2 [
shape=
diamond,
62 label=
"Map created with\ncommon LRU?\n(!BPF_F_NO_COMMON_LRU)"]
;
64 subgraph cluster_remote_lock {
65 label =
"Iterate through CPUs\n(start from current)";
69 local_freelist_check5 [
shape=
diamond,fillcolor=
4,
70 label=
"Steal a node from\nper-cpu freelist?"]
71 local_freelist_check6 [
shape=rectangle
,fillcolor=
4,
72 label=
"Steal a node from
73 (1) Unreferenced pending, or
74 (2) Any pending node"]
75 local_freelist_check7 [
shape=rectangle
,fillcolor=
3,
76 label=
"Try to remove\nnode from hashtab"]
77 fn_htab_lru_map_update_elem [
shape=
diamond,
78 label=
"Stole node\nfrom remote\nCPU?"]
79 fn_htab_lru_map_update_elem2 [
shape=
diamond,label=
"Iterated\nall CPUs?"]
80 // Also corresponds to:
82 // fn__local_list_pop_pending()
85 fn_bpf_lru_list_pop_free_to_local2 [
shape=rectangle
,
86 label=
"Use node that was\nnot recently referenced"]
87 local_freelist_check4 [
shape=rectangle
,
88 label=
"Use node that was\nactively referenced\nin global list"]
89 fn_htab_lru_map_update_elem_ENOMEM [
shape=oval
,label=
"return -ENOMEM"]
90 fn_htab_lru_map_update_elem3 [
shape=rectangle
,
91 label=
"Use node that was\nactively referenced\nin (another?) CPU's cache"]
92 fn_htab_lru_map_update_elem4 [
shape=rectangle
,fillcolor=
3,
93 label=
"Update hashmap\nwith new element"]
94 fn_htab_lru_map_update_elem5 [
shape=oval
,label=
"return 0"]
95 fn_htab_lru_map_update_elem_EBUSY [
shape=oval
,label=
"return -EBUSY"]
96 fn_htab_lru_map_update_elem_EEXIST [
shape=oval
,label=
"return -EEXIST"]
97 fn_htab_lru_map_update_elem_ENOENT [
shape=oval
,label=
"return -ENOENT"]
99 begin
-> local_freelist_check
100 local_freelist_check
-> use_local_node [xlabel=
"Y"]
101 local_freelist_check
-> common_lru_check [xlabel=
"N"]
102 common_lru_check
-> fn_bpf_lru_list_pop_free_to_local [xlabel=
"Y"]
103 common_lru_check
-> fn___bpf_lru_list_shrink_inactive [xlabel=
"N"]
104 fn_bpf_lru_list_pop_free_to_local
-> fn___bpf_lru_node_move_to_free
105 fn___bpf_lru_node_move_to_free
->
106 fn_bpf_lru_list_pop_free_to_local2 [xlabel=
"Y"]
107 fn___bpf_lru_node_move_to_free
->
108 fn___bpf_lru_list_shrink_inactive [xlabel=
"N"]
109 fn___bpf_lru_list_shrink_inactive
-> fn___bpf_lru_list_shrink
110 fn___bpf_lru_list_shrink
-> fn_bpf_lru_list_pop_free_to_local2 [xlabel =
"Y"]
111 fn___bpf_lru_list_shrink
-> fn___bpf_lru_list_shrink2 [xlabel=
"N"]
112 fn___bpf_lru_list_shrink2
-> fn___bpf_lru_list_shrink3
113 fn___bpf_lru_list_shrink3
-> local_freelist_check2
114 local_freelist_check2
-> local_freelist_check4 [xlabel =
"Y"]
115 local_freelist_check2
-> common_lru_check2 [xlabel =
"N"]
116 common_lru_check2
-> local_freelist_check5 [xlabel =
"Y"]
117 common_lru_check2
-> fn_htab_lru_map_update_elem_ENOMEM [xlabel =
"N"]
118 local_freelist_check5
-> fn_htab_lru_map_update_elem [xlabel =
"Y"]
119 local_freelist_check5
-> local_freelist_check6 [xlabel =
"N"]
120 local_freelist_check6
-> local_freelist_check7
121 local_freelist_check7
-> fn_htab_lru_map_update_elem
123 fn_htab_lru_map_update_elem
-> fn_htab_lru_map_update_elem3 [xlabel =
"Y"]
124 fn_htab_lru_map_update_elem
-> fn_htab_lru_map_update_elem2 [xlabel =
"N"]
125 fn_htab_lru_map_update_elem2
->
126 fn_htab_lru_map_update_elem_ENOMEM [xlabel =
"Y"]
127 fn_htab_lru_map_update_elem2
-> local_freelist_check5 [xlabel =
"N"]
128 fn_htab_lru_map_update_elem3
-> fn_htab_lru_map_update_elem4
130 use_local_node
-> fn_htab_lru_map_update_elem4
131 fn_bpf_lru_list_pop_free_to_local2
-> fn_htab_lru_map_update_elem4
132 local_freelist_check4
-> fn_htab_lru_map_update_elem4
134 fn_htab_lru_map_update_elem4
-> fn_htab_lru_map_update_elem5 [
headlabel=
"Success"]
135 fn_htab_lru_map_update_elem4
->
136 fn_htab_lru_map_update_elem_EBUSY [xlabel=
"Hashtab lock failed"]
137 fn_htab_lru_map_update_elem4
->
138 fn_htab_lru_map_update_elem_EEXIST [xlabel=
"BPF_EXIST set and\nkey already exists"]
139 fn_htab_lru_map_update_elem4
->
140 fn_htab_lru_map_update_elem_ENOENT [
headlabel=
"BPF_NOEXIST set\nand no such entry"]
142 // Create invisible pad nodes to line up various nodes
149 // Line up the key with the top of the graph
150 no_lock
-> local_lock [
style=
invis]
151 local_lock
-> lru_lock [
style=
invis]
152 lru_lock
-> hash_lock [
style=
invis]
153 hash_lock
-> remote_lock [
style=
invis]
154 remote_lock
-> local_freelist_check5 [
style=
invis]
155 remote_lock
-> fn___bpf_lru_list_shrink [
style=
invis]
157 // Line up return code nodes at the bottom of the graph
158 fn_htab_lru_map_update_elem
-> pad0 [
style=
invis]
159 pad0
-> pad1 [
style=
invis]
160 pad1
-> pad2 [
style=
invis]
161 //pad2-> fn_htab_lru_map_update_elem_ENOMEM [style=invis]
162 fn_htab_lru_map_update_elem4
-> pad3 [
style=
invis]
163 pad3
-> fn_htab_lru_map_update_elem5 [
style=
invis]
164 pad3
-> fn_htab_lru_map_update_elem_EBUSY [
style=
invis]
165 pad3
-> fn_htab_lru_map_update_elem_EEXIST [
style=
invis]
166 pad3
-> fn_htab_lru_map_update_elem_ENOENT [
style=
invis]
168 // Reduce diagram width by forcing some nodes to appear above others
169 local_freelist_check4
-> fn_htab_lru_map_update_elem3 [
style=
invis]
170 common_lru_check2
-> pad4 [
style=
invis]
171 pad4
-> local_freelist_check5 [
style=
invis]