summaryrefslogtreecommitdiff
path: root/net/unix/garbage.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/unix/garbage.c')
-rw-r--r--net/unix/garbage.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 33aadaa35346..8d0912c1d01a 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -101,6 +101,17 @@ struct unix_sock *unix_get_socket(struct file *filp)
return NULL;
}
+static struct unix_vertex *unix_edge_successor(struct unix_edge *edge)
+{
+ /* If an embryo socket has a fd,
+ * the listener indirectly holds the fd's refcnt.
+ */
+ if (edge->successor->listener)
+ return unix_sk(edge->successor->listener)->vertex;
+
+ return edge->successor->vertex;
+}
+
static LIST_HEAD(unix_unvisited_vertices);
enum unix_vertex_index {
@@ -209,6 +220,13 @@ out:
fpl->inflight = false;
}
+void unix_update_edges(struct unix_sock *receiver)
+{
+ spin_lock(&unix_gc_lock);
+ receiver->listener = NULL;
+ spin_unlock(&unix_gc_lock);
+}
+
int unix_prepare_fpl(struct scm_fp_list *fpl)
{
struct unix_vertex *vertex;
@@ -268,7 +286,7 @@ next_vertex:
/* Explore neighbour vertices (receivers of the current vertex's fd). */
list_for_each_entry(edge, &vertex->edges, vertex_entry) {
- struct unix_vertex *next_vertex = edge->successor->vertex;
+ struct unix_vertex *next_vertex = unix_edge_successor(edge);
if (!next_vertex)
continue;