--- x/net/unix/garbage.c +++ y/net/unix/garbage.c @@ -237,6 +237,8 @@ static void inc_inflight(struct unix_soc usk->inflight++; } +static int recycle; + static void inc_inflight_move_tail(struct unix_sock *u) { u->inflight++; @@ -245,8 +247,10 @@ static void inc_inflight_move_tail(struc * of the list, so that it's checked even if it was already * passed over */ - if (test_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags)) + if (test_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags)) { list_move_tail(&u->link, &gc_candidates); + recycle++; + } } static bool gc_in_progress; @@ -259,6 +263,7 @@ static void __unix_gc(struct work_struct struct list_head cursor; spin_lock(&unix_gc_lock); + recycle = 0; /* First, select candidates for garbage collection. Only * in-flight sockets are considered, and from those only ones @@ -342,7 +347,7 @@ static void __unix_gc(struct work_struct spin_lock(&unix_gc_lock); /* All candidates should have been detached by now. */ - WARN_ON_ONCE(!list_empty(&gc_candidates)); + WARN_ON_ONCE(!list_empty(&gc_candidates) && !recycle); /* Paired with READ_ONCE() in wait_for_unix_gc(). */ WRITE_ONCE(gc_in_progress, false);