af_unix: Detect Strongly Connected Components.
In the new GC, we use a simple graph algorithm, Tarjan's Strongly
Connected Components (SCC) algorithm, to find cyclic references.
The algorithm visits every vertex exactly once using depth-first
search (DFS).
DFS starts by pushing an input vertex to a stack and assigning it
a unique number. Two fields, index and lowlink, are initialised
with the number, but lowlink could be updated later during DFS.
If a vertex has an edge to an unvisited inflight vertex, we visit
it and do the same processing. So, we will have vertices in the
stack in the order they appear and number them consecutively in
the same order.
If a vertex has a back-edge to a visited vertex in the stack,
we update the predecessor's lowlink with the successor's index.
After iterating edges from the vertex, we check if its index
equals its lowlink.
If the lowlink is different from the index, it shows there was a
back-edge. Then, we go backtracking and propagate the lowlink to
its predecessor and resume the previous edge iteration from the
next edge.
If the lowlink is the same as the index, we pop vertices before
and including the vertex from the stack. Then, the set of vertices
is SCC, possibly forming a cycle. At the same time, we move the
vertices to unix_visited_vertices.
When we finish the algorithm, all vertices in each SCC will be
linked via unix_vertex.scc_entry.
Let's take an example. We have a graph including five inflight
vertices (F is not inflight):
A -> B -> C -> D -> E (-> F)
^ |
`---------'
Suppose that we start DFS from C. We will visit C, D, and B first
and initialise their index and lowlink. Then, the stack looks like
this:
> B = (3, 3) (index, lowlink)
D = (2, 2)
C = (1, 1)
When checking B's edge to C, we update B's lowlink with C's index
and propagate it to D.
B = (3, 1) (index, lowlink)
> D = (2, 1)
C = (1, 1)
Next, we visit E, which has no edge to an inflight vertex.
> E = (4, 4) (index, lowlink)
B = (3, 1)
D = (2, 1)
C = (1, 1)
When we leave from E, its index and lowlink are the same, so we
pop E from the stack as single-vertex SCC. Next, we leave from
B and D but do nothing because their lowlink are different from
their index.
B = (3, 1) (index, lowlink)
D = (2, 1)
> C = (1, 1)
Then, we leave from C, whose index and lowlink are the same, so
we pop B, D and C as SCC.
Last, we do DFS for the rest of vertices, A, which is also a
single-vertex SCC.
Finally, each unix_vertex.scc_entry is linked as follows:
A -. B -> C -> D E -.
^ | ^ | ^ |
`--' `---------' `--'
We use SCC later to decide whether we can garbage-collect the
sockets.
Note that we still cannot detect SCC properly if an edge points
to an embryo socket. The following two patches will sort it out.
Signed-off-by:
Kuniyuki Iwashima <kuniyu@amazon.com>
Acked-by:
Paolo Abeni <pabeni@redhat.com>
Link: https://lore.kernel.org/r/20240325202425.60930-7-kuniyu@amazon.com
Signed-off-by:
Jakub Kicinski <kuba@kernel.org>
-
mentioned in commit c3941906
-
mentioned in commit d946208f
-
mentioned in commit 9b58c367
-
mentioned in commit ab81bbc7
-
mentioned in commit 9c505362
-
mentioned in commit 8863130d
-
mentioned in commit 709c8b88
-
mentioned in commit e7bc8767
-
mentioned in commit 874ddfc5
-
mentioned in commit 76e6db6a
-
mentioned in commit 9eec13dc
-
mentioned in commit 599735f9
-
mentioned in commit c5f59aee
-
mentioned in commit 84c58120
-
mentioned in commit 7df1fef3
-
mentioned in commit b6c2e703
-
mentioned in commit a3e29ccb
-
mentioned in commit 7aa0b8af
-
mentioned in commit 90b58d89
-
mentioned in commit 57c2e24d
-
mentioned in commit 66e758f7
-
mentioned in commit 8940c774
-
mentioned in commit 7ad63be6
-
mentioned in commit 1874170c
-
mentioned in commit 0297e7dd
-
mentioned in commit 17e5789d
-
mentioned in commit 245ba9b0
-
mentioned in commit b113cef0
-
mentioned in commit e46d8eec
-
mentioned in commit 1c883463
-
mentioned in commit f20ec596
-
mentioned in commit faecd81a
-
mentioned in commit 3d0d92db
-
mentioned in commit 1d873e4a
-
mentioned in commit ed158995
-
mentioned in commit 993f72ec
-
mentioned in commit 5ea87f48
-
mentioned in commit 9b2e4325
-
mentioned in commit be31d82e
-
mentioned in commit b4a1224d
-
mentioned in commit ace409fb
-
mentioned in commit 968ab3b4
-
mentioned in commit 295f3f7f
-
mentioned in commit 3c455773
-
mentioned in commit 076ac12b
-
mentioned in commit a854c144
-
mentioned in commit b827fd75
-
mentioned in commit d05c3038
-
mentioned in commit 279ed20d
-
mentioned in commit a213abad