18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * NET3: Garbage Collector For AF_UNIX sockets 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Garbage Collector: 68c2ecf20Sopenharmony_ci * Copyright (C) Barak A. Pearlmutter. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Chopped about by Alan Cox 22/3/96 to make it fit the AF_UNIX socket problem. 98c2ecf20Sopenharmony_ci * If it doesn't work blame me, it worked when Barak sent it. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Assumptions: 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * - object w/ a bit 148c2ecf20Sopenharmony_ci * - free list 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * Current optimizations: 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * - explicit stack instead of recursion 198c2ecf20Sopenharmony_ci * - tail recurse on first born instead of immediate push/pop 208c2ecf20Sopenharmony_ci * - we gather the stuff that should not be killed into tree 218c2ecf20Sopenharmony_ci * and stack is just a path from root to the current pointer. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Future optimizations: 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * - don't just push entire root set; process in place 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * Fixes: 288c2ecf20Sopenharmony_ci * Alan Cox 07 Sept 1997 Vmalloc internal stack as needed. 298c2ecf20Sopenharmony_ci * Cope with changing max_files. 308c2ecf20Sopenharmony_ci * Al Viro 11 Oct 1998 318c2ecf20Sopenharmony_ci * Graph may have cycles. That is, we can send the descriptor 328c2ecf20Sopenharmony_ci * of foo to bar and vice versa. Current code chokes on that. 338c2ecf20Sopenharmony_ci * Fix: move SCM_RIGHTS ones into the separate list and then 348c2ecf20Sopenharmony_ci * skb_free() them all instead of doing explicit fput's. 358c2ecf20Sopenharmony_ci * Another problem: since fput() may block somebody may 368c2ecf20Sopenharmony_ci * create a new unix_socket when we are in the middle of sweep 378c2ecf20Sopenharmony_ci * phase. Fix: revert the logic wrt MARKED. Mark everything 388c2ecf20Sopenharmony_ci * upon the beginning and unmark non-junk ones. 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * [12 Oct 1998] AAARGH! New code purges all SCM_RIGHTS 418c2ecf20Sopenharmony_ci * sent to connect()'ed but still not accept()'ed sockets. 428c2ecf20Sopenharmony_ci * Fixed. Old code had slightly different problem here: 438c2ecf20Sopenharmony_ci * extra fput() in situation when we passed the descriptor via 448c2ecf20Sopenharmony_ci * such socket and closed it (descriptor). That would happen on 458c2ecf20Sopenharmony_ci * each unix_gc() until the accept(). Since the struct file in 468c2ecf20Sopenharmony_ci * question would go to the free list and might be reused... 478c2ecf20Sopenharmony_ci * That might be the reason of random oopses on filp_close() 488c2ecf20Sopenharmony_ci * in unrelated processes. 498c2ecf20Sopenharmony_ci * 508c2ecf20Sopenharmony_ci * AV 28 Feb 1999 518c2ecf20Sopenharmony_ci * Kill the explicit allocation of stack. Now we keep the tree 528c2ecf20Sopenharmony_ci * with root in dummy + pointer (gc_current) to one of the nodes. 538c2ecf20Sopenharmony_ci * Stack is represented as path from gc_current to dummy. Unmark 548c2ecf20Sopenharmony_ci * now means "add to tree". Push == "make it a son of gc_current". 558c2ecf20Sopenharmony_ci * Pop == "move gc_current to parent". We keep only pointers to 568c2ecf20Sopenharmony_ci * parents (->gc_tree). 578c2ecf20Sopenharmony_ci * AV 1 Mar 1999 588c2ecf20Sopenharmony_ci * Damn. Added missing check for ->dead in listen queues scanning. 598c2ecf20Sopenharmony_ci * 608c2ecf20Sopenharmony_ci * Miklos Szeredi 25 Jun 2007 618c2ecf20Sopenharmony_ci * Reimplement with a cycle collecting algorithm. This should 628c2ecf20Sopenharmony_ci * solve several problems with the previous code, like being racy 638c2ecf20Sopenharmony_ci * wrt receive and holding up unrelated socket operations. 648c2ecf20Sopenharmony_ci */ 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#include <linux/kernel.h> 678c2ecf20Sopenharmony_ci#include <linux/string.h> 688c2ecf20Sopenharmony_ci#include <linux/socket.h> 698c2ecf20Sopenharmony_ci#include <linux/un.h> 708c2ecf20Sopenharmony_ci#include <linux/net.h> 718c2ecf20Sopenharmony_ci#include <linux/fs.h> 728c2ecf20Sopenharmony_ci#include <linux/skbuff.h> 738c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 748c2ecf20Sopenharmony_ci#include <linux/file.h> 758c2ecf20Sopenharmony_ci#include <linux/proc_fs.h> 768c2ecf20Sopenharmony_ci#include <linux/mutex.h> 778c2ecf20Sopenharmony_ci#include <linux/wait.h> 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci#include <net/sock.h> 808c2ecf20Sopenharmony_ci#include <net/af_unix.h> 818c2ecf20Sopenharmony_ci#include <net/scm.h> 828c2ecf20Sopenharmony_ci#include <net/tcp_states.h> 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci#include "scm.h" 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/* Internal data structures and random procedures: */ 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistatic LIST_HEAD(gc_candidates); 898c2ecf20Sopenharmony_cistatic DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), 928c2ecf20Sopenharmony_ci struct sk_buff_head *hitlist) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci struct sk_buff *skb; 958c2ecf20Sopenharmony_ci struct sk_buff *next; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci spin_lock(&x->sk_receive_queue.lock); 988c2ecf20Sopenharmony_ci skb_queue_walk_safe(&x->sk_receive_queue, skb, next) { 998c2ecf20Sopenharmony_ci /* Do we have file descriptors ? */ 1008c2ecf20Sopenharmony_ci if (UNIXCB(skb).fp) { 1018c2ecf20Sopenharmony_ci bool hit = false; 1028c2ecf20Sopenharmony_ci /* Process the descriptors of this socket */ 1038c2ecf20Sopenharmony_ci int nfd = UNIXCB(skb).fp->count; 1048c2ecf20Sopenharmony_ci struct file **fp = UNIXCB(skb).fp->fp; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci while (nfd--) { 1078c2ecf20Sopenharmony_ci /* Get the socket the fd matches if it indeed does so */ 1088c2ecf20Sopenharmony_ci struct sock *sk = unix_get_socket(*fp++); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (sk) { 1118c2ecf20Sopenharmony_ci struct unix_sock *u = unix_sk(sk); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci /* Ignore non-candidates, they could 1148c2ecf20Sopenharmony_ci * have been added to the queues after 1158c2ecf20Sopenharmony_ci * starting the garbage collection 1168c2ecf20Sopenharmony_ci */ 1178c2ecf20Sopenharmony_ci if (test_bit(UNIX_GC_CANDIDATE, &u->gc_flags)) { 1188c2ecf20Sopenharmony_ci hit = true; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci func(u); 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci if (hit && hitlist != NULL) { 1258c2ecf20Sopenharmony_ci __skb_unlink(skb, &x->sk_receive_queue); 1268c2ecf20Sopenharmony_ci __skb_queue_tail(hitlist, skb); 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci spin_unlock(&x->sk_receive_queue.lock); 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic void scan_children(struct sock *x, void (*func)(struct unix_sock *), 1348c2ecf20Sopenharmony_ci struct sk_buff_head *hitlist) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci if (x->sk_state != TCP_LISTEN) { 1378c2ecf20Sopenharmony_ci scan_inflight(x, func, hitlist); 1388c2ecf20Sopenharmony_ci } else { 1398c2ecf20Sopenharmony_ci struct sk_buff *skb; 1408c2ecf20Sopenharmony_ci struct sk_buff *next; 1418c2ecf20Sopenharmony_ci struct unix_sock *u; 1428c2ecf20Sopenharmony_ci LIST_HEAD(embryos); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* For a listening socket collect the queued embryos 1458c2ecf20Sopenharmony_ci * and perform a scan on them as well. 1468c2ecf20Sopenharmony_ci */ 1478c2ecf20Sopenharmony_ci spin_lock(&x->sk_receive_queue.lock); 1488c2ecf20Sopenharmony_ci skb_queue_walk_safe(&x->sk_receive_queue, skb, next) { 1498c2ecf20Sopenharmony_ci u = unix_sk(skb->sk); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* An embryo cannot be in-flight, so it's safe 1528c2ecf20Sopenharmony_ci * to use the list link. 1538c2ecf20Sopenharmony_ci */ 1548c2ecf20Sopenharmony_ci BUG_ON(!list_empty(&u->link)); 1558c2ecf20Sopenharmony_ci list_add_tail(&u->link, &embryos); 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci spin_unlock(&x->sk_receive_queue.lock); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci while (!list_empty(&embryos)) { 1608c2ecf20Sopenharmony_ci u = list_entry(embryos.next, struct unix_sock, link); 1618c2ecf20Sopenharmony_ci scan_inflight(&u->sk, func, hitlist); 1628c2ecf20Sopenharmony_ci list_del_init(&u->link); 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic void dec_inflight(struct unix_sock *usk) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci atomic_long_dec(&usk->inflight); 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic void inc_inflight(struct unix_sock *usk) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci atomic_long_inc(&usk->inflight); 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic void inc_inflight_move_tail(struct unix_sock *u) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci atomic_long_inc(&u->inflight); 1808c2ecf20Sopenharmony_ci /* If this still might be part of a cycle, move it to the end 1818c2ecf20Sopenharmony_ci * of the list, so that it's checked even if it was already 1828c2ecf20Sopenharmony_ci * passed over 1838c2ecf20Sopenharmony_ci */ 1848c2ecf20Sopenharmony_ci if (test_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags)) 1858c2ecf20Sopenharmony_ci list_move_tail(&u->link, &gc_candidates); 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic bool gc_in_progress; 1898c2ecf20Sopenharmony_ci#define UNIX_INFLIGHT_TRIGGER_GC 16000 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_civoid wait_for_unix_gc(void) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci /* If number of inflight sockets is insane, 1948c2ecf20Sopenharmony_ci * force a garbage collect right now. 1958c2ecf20Sopenharmony_ci * Paired with the WRITE_ONCE() in unix_inflight(), 1968c2ecf20Sopenharmony_ci * unix_notinflight() and gc_in_progress(). 1978c2ecf20Sopenharmony_ci */ 1988c2ecf20Sopenharmony_ci if (READ_ONCE(unix_tot_inflight) > UNIX_INFLIGHT_TRIGGER_GC && 1998c2ecf20Sopenharmony_ci !READ_ONCE(gc_in_progress)) 2008c2ecf20Sopenharmony_ci unix_gc(); 2018c2ecf20Sopenharmony_ci wait_event(unix_gc_wait, gc_in_progress == false); 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci/* The external entry point: unix_gc() */ 2058c2ecf20Sopenharmony_civoid unix_gc(void) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci struct sk_buff *next_skb, *skb; 2088c2ecf20Sopenharmony_ci struct unix_sock *u; 2098c2ecf20Sopenharmony_ci struct unix_sock *next; 2108c2ecf20Sopenharmony_ci struct sk_buff_head hitlist; 2118c2ecf20Sopenharmony_ci struct list_head cursor; 2128c2ecf20Sopenharmony_ci LIST_HEAD(not_cycle_list); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci spin_lock(&unix_gc_lock); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci /* Avoid a recursive GC. */ 2178c2ecf20Sopenharmony_ci if (gc_in_progress) 2188c2ecf20Sopenharmony_ci goto out; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci /* Paired with READ_ONCE() in wait_for_unix_gc(). */ 2218c2ecf20Sopenharmony_ci WRITE_ONCE(gc_in_progress, true); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci /* First, select candidates for garbage collection. Only 2248c2ecf20Sopenharmony_ci * in-flight sockets are considered, and from those only ones 2258c2ecf20Sopenharmony_ci * which don't have any external reference. 2268c2ecf20Sopenharmony_ci * 2278c2ecf20Sopenharmony_ci * Holding unix_gc_lock will protect these candidates from 2288c2ecf20Sopenharmony_ci * being detached, and hence from gaining an external 2298c2ecf20Sopenharmony_ci * reference. Since there are no possible receivers, all 2308c2ecf20Sopenharmony_ci * buffers currently on the candidates' queues stay there 2318c2ecf20Sopenharmony_ci * during the garbage collection. 2328c2ecf20Sopenharmony_ci * 2338c2ecf20Sopenharmony_ci * We also know that no new candidate can be added onto the 2348c2ecf20Sopenharmony_ci * receive queues. Other, non candidate sockets _can_ be 2358c2ecf20Sopenharmony_ci * added to queue, so we must make sure only to touch 2368c2ecf20Sopenharmony_ci * candidates. 2378c2ecf20Sopenharmony_ci * 2388c2ecf20Sopenharmony_ci * Embryos, though never candidates themselves, affect which 2398c2ecf20Sopenharmony_ci * candidates are reachable by the garbage collector. Before 2408c2ecf20Sopenharmony_ci * being added to a listener's queue, an embryo may already 2418c2ecf20Sopenharmony_ci * receive data carrying SCM_RIGHTS, potentially making the 2428c2ecf20Sopenharmony_ci * passed socket a candidate that is not yet reachable by the 2438c2ecf20Sopenharmony_ci * collector. It becomes reachable once the embryo is 2448c2ecf20Sopenharmony_ci * enqueued. Therefore, we must ensure that no SCM-laden 2458c2ecf20Sopenharmony_ci * embryo appears in a (candidate) listener's queue between 2468c2ecf20Sopenharmony_ci * consecutive scan_children() calls. 2478c2ecf20Sopenharmony_ci */ 2488c2ecf20Sopenharmony_ci list_for_each_entry_safe(u, next, &gc_inflight_list, link) { 2498c2ecf20Sopenharmony_ci struct sock *sk = &u->sk; 2508c2ecf20Sopenharmony_ci long total_refs; 2518c2ecf20Sopenharmony_ci long inflight_refs; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci total_refs = file_count(sk->sk_socket->file); 2548c2ecf20Sopenharmony_ci inflight_refs = atomic_long_read(&u->inflight); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci BUG_ON(inflight_refs < 1); 2578c2ecf20Sopenharmony_ci BUG_ON(total_refs < inflight_refs); 2588c2ecf20Sopenharmony_ci if (total_refs == inflight_refs) { 2598c2ecf20Sopenharmony_ci list_move_tail(&u->link, &gc_candidates); 2608c2ecf20Sopenharmony_ci __set_bit(UNIX_GC_CANDIDATE, &u->gc_flags); 2618c2ecf20Sopenharmony_ci __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (sk->sk_state == TCP_LISTEN) { 2648c2ecf20Sopenharmony_ci unix_state_lock(sk); 2658c2ecf20Sopenharmony_ci unix_state_unlock(sk); 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci /* Now remove all internal in-flight reference to children of 2718c2ecf20Sopenharmony_ci * the candidates. 2728c2ecf20Sopenharmony_ci */ 2738c2ecf20Sopenharmony_ci list_for_each_entry(u, &gc_candidates, link) 2748c2ecf20Sopenharmony_ci scan_children(&u->sk, dec_inflight, NULL); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /* Restore the references for children of all candidates, 2778c2ecf20Sopenharmony_ci * which have remaining references. Do this recursively, so 2788c2ecf20Sopenharmony_ci * only those remain, which form cyclic references. 2798c2ecf20Sopenharmony_ci * 2808c2ecf20Sopenharmony_ci * Use a "cursor" link, to make the list traversal safe, even 2818c2ecf20Sopenharmony_ci * though elements might be moved about. 2828c2ecf20Sopenharmony_ci */ 2838c2ecf20Sopenharmony_ci list_add(&cursor, &gc_candidates); 2848c2ecf20Sopenharmony_ci while (cursor.next != &gc_candidates) { 2858c2ecf20Sopenharmony_ci u = list_entry(cursor.next, struct unix_sock, link); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci /* Move cursor to after the current position. */ 2888c2ecf20Sopenharmony_ci list_move(&cursor, &u->link); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci if (atomic_long_read(&u->inflight) > 0) { 2918c2ecf20Sopenharmony_ci list_move_tail(&u->link, ¬_cycle_list); 2928c2ecf20Sopenharmony_ci __clear_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags); 2938c2ecf20Sopenharmony_ci scan_children(&u->sk, inc_inflight_move_tail, NULL); 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci list_del(&cursor); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci /* Now gc_candidates contains only garbage. Restore original 2998c2ecf20Sopenharmony_ci * inflight counters for these as well, and remove the skbuffs 3008c2ecf20Sopenharmony_ci * which are creating the cycle(s). 3018c2ecf20Sopenharmony_ci */ 3028c2ecf20Sopenharmony_ci skb_queue_head_init(&hitlist); 3038c2ecf20Sopenharmony_ci list_for_each_entry(u, &gc_candidates, link) 3048c2ecf20Sopenharmony_ci scan_children(&u->sk, inc_inflight, &hitlist); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci /* not_cycle_list contains those sockets which do not make up a 3078c2ecf20Sopenharmony_ci * cycle. Restore these to the inflight list. 3088c2ecf20Sopenharmony_ci */ 3098c2ecf20Sopenharmony_ci while (!list_empty(¬_cycle_list)) { 3108c2ecf20Sopenharmony_ci u = list_entry(not_cycle_list.next, struct unix_sock, link); 3118c2ecf20Sopenharmony_ci __clear_bit(UNIX_GC_CANDIDATE, &u->gc_flags); 3128c2ecf20Sopenharmony_ci list_move_tail(&u->link, &gc_inflight_list); 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci spin_unlock(&unix_gc_lock); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci /* We need io_uring to clean its registered files, ignore all io_uring 3188c2ecf20Sopenharmony_ci * originated skbs. It's fine as io_uring doesn't keep references to 3198c2ecf20Sopenharmony_ci * other io_uring instances and so killing all other files in the cycle 3208c2ecf20Sopenharmony_ci * will put all io_uring references forcing it to go through normal 3218c2ecf20Sopenharmony_ci * release.path eventually putting registered files. 3228c2ecf20Sopenharmony_ci */ 3238c2ecf20Sopenharmony_ci skb_queue_walk_safe(&hitlist, skb, next_skb) { 3248c2ecf20Sopenharmony_ci if (skb->scm_io_uring) { 3258c2ecf20Sopenharmony_ci __skb_unlink(skb, &hitlist); 3268c2ecf20Sopenharmony_ci skb_queue_tail(&skb->sk->sk_receive_queue, skb); 3278c2ecf20Sopenharmony_ci } 3288c2ecf20Sopenharmony_ci } 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci /* Here we are. Hitlist is filled. Die. */ 3318c2ecf20Sopenharmony_ci __skb_queue_purge(&hitlist); 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci spin_lock(&unix_gc_lock); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci /* There could be io_uring registered files, just push them back to 3368c2ecf20Sopenharmony_ci * the inflight list 3378c2ecf20Sopenharmony_ci */ 3388c2ecf20Sopenharmony_ci list_for_each_entry_safe(u, next, &gc_candidates, link) 3398c2ecf20Sopenharmony_ci list_move_tail(&u->link, &gc_inflight_list); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci /* All candidates should have been detached by now. */ 3428c2ecf20Sopenharmony_ci BUG_ON(!list_empty(&gc_candidates)); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci /* Paired with READ_ONCE() in wait_for_unix_gc(). */ 3458c2ecf20Sopenharmony_ci WRITE_ONCE(gc_in_progress, false); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci wake_up(&unix_gc_wait); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci out: 3508c2ecf20Sopenharmony_ci spin_unlock(&unix_gc_lock); 3518c2ecf20Sopenharmony_ci} 352