map_lru_hash_update.dot 7.3 KB

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