]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - net/rxrpc/conn_object.c
rxrpc: Kill the client connection bundle concept
[mirror_ubuntu-bionic-kernel.git] / net / rxrpc / conn_object.c
CommitLineData
17926a79
DH
1/* RxRPC virtual connection handler
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
9b6d5398
JP
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
17926a79 14#include <linux/module.h>
5a0e3ad6 15#include <linux/slab.h>
17926a79
DH
16#include <linux/net.h>
17#include <linux/skbuff.h>
18#include <linux/crypto.h>
19#include <net/sock.h>
20#include <net/af_rxrpc.h>
21#include "ar-internal.h"
22
5873c083
DH
23/*
24 * Time till a connection expires after last use (in seconds).
25 */
dad8aff7 26unsigned int rxrpc_connection_expiry = 10 * 60;
5873c083 27
17926a79
DH
28static void rxrpc_connection_reaper(struct work_struct *work);
29
30LIST_HEAD(rxrpc_connections);
31DEFINE_RWLOCK(rxrpc_connection_lock);
17926a79
DH
32static DECLARE_DELAYED_WORK(rxrpc_connection_reap, rxrpc_connection_reaper);
33
17926a79
DH
34/*
35 * allocate a new connection
36 */
37static struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
38{
39 struct rxrpc_connection *conn;
40
41 _enter("");
42
43 conn = kzalloc(sizeof(struct rxrpc_connection), gfp);
44 if (conn) {
999b69f8
DH
45 spin_lock_init(&conn->channel_lock);
46 init_waitqueue_head(&conn->channel_wq);
17926a79 47 INIT_WORK(&conn->processor, &rxrpc_process_connection);
999b69f8 48 INIT_LIST_HEAD(&conn->link);
17926a79
DH
49 conn->calls = RB_ROOT;
50 skb_queue_head_init(&conn->rx_queue);
e0e4d82f 51 conn->security = &rxrpc_no_security;
17926a79
DH
52 rwlock_init(&conn->lock);
53 spin_lock_init(&conn->state_lock);
54 atomic_set(&conn->usage, 1);
55 conn->debug_id = atomic_inc_return(&rxrpc_debug_id);
999b69f8 56 atomic_set(&conn->avail_chans, RXRPC_MAXCALLS);
17926a79 57 conn->size_align = 4;
0d12f8a4 58 conn->header_size = sizeof(struct rxrpc_wire_header);
17926a79
DH
59 }
60
16c61add 61 _leave(" = %p{%d}", conn, conn ? conn->debug_id : 0);
17926a79
DH
62 return conn;
63}
64
17926a79
DH
65/*
66 * add a call to a connection's call-by-ID tree
67 */
68static void rxrpc_add_call_ID_to_conn(struct rxrpc_connection *conn,
69 struct rxrpc_call *call)
70{
71 struct rxrpc_call *xcall;
72 struct rb_node *parent, **p;
73 __be32 call_id;
74
75 write_lock_bh(&conn->lock);
76
77 call_id = call->call_id;
78 p = &conn->calls.rb_node;
79 parent = NULL;
80 while (*p) {
81 parent = *p;
82 xcall = rb_entry(parent, struct rxrpc_call, conn_node);
83
84 if (call_id < xcall->call_id)
85 p = &(*p)->rb_left;
86 else if (call_id > xcall->call_id)
87 p = &(*p)->rb_right;
88 else
89 BUG();
90 }
91
92 rb_link_node(&call->conn_node, parent, p);
93 rb_insert_color(&call->conn_node, &conn->calls);
94
95 write_unlock_bh(&conn->lock);
96}
97
98/*
999b69f8
DH
99 * Allocate a client connection. The caller must take care to clear any
100 * padding bytes in *cp.
17926a79 101 */
4a3388c8
DH
102static struct rxrpc_connection *
103rxrpc_alloc_client_connection(struct rxrpc_conn_parameters *cp,
104 struct rxrpc_transport *trans,
105 gfp_t gfp)
17926a79
DH
106{
107 struct rxrpc_connection *conn;
4a3388c8 108 int ret;
17926a79
DH
109
110 _enter("");
111
cc8feb8e 112 conn = rxrpc_alloc_connection(gfp);
17926a79 113 if (!conn) {
cc8feb8e 114 _leave(" = -ENOMEM");
4a3388c8 115 return ERR_PTR(-ENOMEM);
cc8feb8e 116 }
17926a79 117
cc8feb8e
DH
118 conn->params = *cp;
119 conn->proto.local = cp->local;
120 conn->proto.epoch = rxrpc_epoch;
121 conn->proto.cid = 0;
122 conn->proto.in_clientflag = 0;
123 conn->proto.family = cp->peer->srx.transport.family;
124 conn->out_clientflag = RXRPC_CLIENT_INITIATED;
125 conn->state = RXRPC_CONN_CLIENT;
cc8feb8e 126
4a3388c8
DH
127 switch (conn->proto.family) {
128 case AF_INET:
129 conn->proto.addr_size = sizeof(conn->proto.ipv4_addr);
130 conn->proto.ipv4_addr = cp->peer->srx.transport.sin.sin_addr;
131 conn->proto.port = cp->peer->srx.transport.sin.sin_port;
132 break;
133 }
134
999b69f8 135 ret = rxrpc_get_client_connection_id(conn, gfp);
4a3388c8
DH
136 if (ret < 0)
137 goto error_0;
cc8feb8e
DH
138
139 ret = rxrpc_init_client_conn_security(conn);
4a3388c8
DH
140 if (ret < 0)
141 goto error_1;
142
143 conn->security->prime_packet_security(conn);
17926a79 144
b3f57504 145 write_lock(&rxrpc_connection_lock);
cc8feb8e 146 list_add_tail(&conn->link, &rxrpc_connections);
b3f57504 147 write_unlock(&rxrpc_connection_lock);
17926a79 148
4a3388c8 149 key_get(conn->params.key);
999b69f8
DH
150 conn->trans = trans;
151 atomic_inc(&trans->usage);
4a3388c8
DH
152
153 _leave(" = %p", conn);
154 return conn;
155
156error_1:
157 rxrpc_put_client_connection_id(conn);
158error_0:
159 kfree(conn);
160 _leave(" = %d", ret);
161 return ERR_PTR(ret);
162}
163
17926a79
DH
164/*
165 * find a connection for a call
166 * - called in process context with IRQs enabled
167 */
999b69f8 168int rxrpc_connect_call(struct rxrpc_call *call,
19ffa01c 169 struct rxrpc_conn_parameters *cp,
17926a79 170 struct rxrpc_transport *trans,
999b69f8 171 struct sockaddr_rxrpc *srx,
17926a79
DH
172 gfp_t gfp)
173{
999b69f8
DH
174 struct rxrpc_connection *conn, *candidate = NULL;
175 struct rxrpc_local *local = cp->local;
176 struct rb_node *p, **pp, *parent;
177 long diff;
4a3388c8 178 int chan;
17926a79
DH
179
180 DECLARE_WAITQUEUE(myself, current);
181
999b69f8 182 _enter("{%d,%lx},", call->debug_id, call->user_call_ID);
17926a79 183
999b69f8
DH
184 cp->peer = trans->peer;
185 rxrpc_get_peer(cp->peer);
186
187 if (!cp->exclusive) {
188 /* Search for a existing client connection unless this is going
189 * to be a connection that's used exclusively for a single call.
190 */
191 _debug("search 1");
192 spin_lock(&local->client_conns_lock);
193 p = local->client_conns.rb_node;
194 while (p) {
195 conn = rb_entry(p, struct rxrpc_connection, client_node);
196
197#define cmp(X) ((long)conn->params.X - (long)cp->X)
198 diff = (cmp(peer) ?:
199 cmp(key) ?:
200 cmp(security_level));
201 if (diff < 0)
202 p = p->rb_left;
203 else if (diff > 0)
204 p = p->rb_right;
205 else
206 goto found_extant_conn;
17926a79 207 }
999b69f8
DH
208 spin_unlock(&local->client_conns_lock);
209 }
17926a79 210
999b69f8
DH
211 /* We didn't find a connection or we want an exclusive one. */
212 _debug("get new conn");
213 candidate = rxrpc_alloc_client_connection(cp, trans, gfp);
214 if (!candidate) {
215 _leave(" = -ENOMEM");
216 return -ENOMEM;
217 }
17926a79 218
999b69f8
DH
219 if (cp->exclusive) {
220 /* Assign the call on an exclusive connection to channel 0 and
221 * don't add the connection to the endpoint's shareable conn
222 * lookup tree.
223 */
224 _debug("exclusive chan 0");
225 conn = candidate;
226 atomic_set(&conn->avail_chans, RXRPC_MAXCALLS - 1);
227 spin_lock(&conn->channel_lock);
228 chan = 0;
229 goto found_channel;
230 }
17926a79 231
999b69f8
DH
232 /* We need to redo the search before attempting to add a new connection
233 * lest we race with someone else adding a conflicting instance.
234 */
235 _debug("search 2");
236 spin_lock(&local->client_conns_lock);
17926a79 237
999b69f8
DH
238 pp = &local->client_conns.rb_node;
239 parent = NULL;
240 while (*pp) {
241 parent = *pp;
242 conn = rb_entry(parent, struct rxrpc_connection, client_node);
17926a79 243
999b69f8
DH
244 diff = (cmp(peer) ?:
245 cmp(key) ?:
246 cmp(security_level));
247 if (diff < 0)
248 pp = &(*pp)->rb_left;
249 else if (diff > 0)
250 pp = &(*pp)->rb_right;
251 else
252 goto found_extant_conn;
253 }
17926a79 254
999b69f8
DH
255 /* The second search also failed; simply add the new connection with
256 * the new call in channel 0. Note that we need to take the channel
257 * lock before dropping the client conn lock.
258 */
259 _debug("new conn");
260 conn = candidate;
261 candidate = NULL;
17926a79 262
999b69f8
DH
263 rb_link_node(&conn->client_node, parent, pp);
264 rb_insert_color(&conn->client_node, &local->client_conns);
265
266 atomic_set(&conn->avail_chans, RXRPC_MAXCALLS - 1);
267 spin_lock(&conn->channel_lock);
268 spin_unlock(&local->client_conns_lock);
269 chan = 0;
270
271found_channel:
272 _debug("found chan");
273 call->conn = conn;
274 call->channel = chan;
275 call->epoch = conn->proto.epoch;
276 call->cid = conn->proto.cid | chan;
277 call->call_id = ++conn->call_counter;
278 rcu_assign_pointer(conn->channels[chan], call);
17926a79 279
999b69f8 280 _net("CONNECT call %d on conn %d", call->debug_id, conn->debug_id);
17926a79 281
999b69f8
DH
282 rxrpc_add_call_ID_to_conn(conn, call);
283 spin_unlock(&conn->channel_lock);
284 _leave(" = %p {u=%d}", conn, atomic_read(&conn->usage));
285 return 0;
286
287 /* We found a suitable connection already in existence. Discard any
288 * candidate we may have allocated, and try to get a channel on this
289 * one.
290 */
291found_extant_conn:
292 _debug("found conn");
293 rxrpc_get_connection(conn);
294 spin_unlock(&local->client_conns_lock);
17926a79 295
999b69f8 296 rxrpc_put_connection(candidate);
17926a79 297
999b69f8
DH
298 if (!atomic_add_unless(&conn->avail_chans, -1, 0)) {
299 if (!gfpflags_allow_blocking(gfp)) {
300 rxrpc_put_connection(conn);
301 _leave(" = -EAGAIN");
302 return -EAGAIN;
303 }
17926a79 304
999b69f8
DH
305 add_wait_queue(&conn->channel_wq, &myself);
306 for (;;) {
307 set_current_state(TASK_INTERRUPTIBLE);
308 if (atomic_add_unless(&conn->avail_chans, -1, 0))
309 break;
310 if (signal_pending(current))
311 goto interrupted;
312 schedule();
313 }
314 remove_wait_queue(&conn->channel_wq, &myself);
315 __set_current_state(TASK_RUNNING);
17926a79
DH
316 }
317
999b69f8
DH
318 /* The connection allegedly now has a free channel and we can now
319 * attach the call to it.
17926a79 320 */
999b69f8
DH
321 spin_lock(&conn->channel_lock);
322
17926a79
DH
323 for (chan = 0; chan < RXRPC_MAXCALLS; chan++)
324 if (!conn->channels[chan])
325 goto found_channel;
326 BUG();
327
17926a79 328interrupted:
999b69f8
DH
329 remove_wait_queue(&conn->channel_wq, &myself);
330 __set_current_state(TASK_RUNNING);
331 rxrpc_put_connection(conn);
17926a79
DH
332 _leave(" = -ERESTARTSYS");
333 return -ERESTARTSYS;
334}
335
336/*
337 * get a record of an incoming connection
338 */
999b69f8
DH
339struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_transport *trans,
340 struct sk_buff *skb)
17926a79
DH
341{
342 struct rxrpc_connection *conn, *candidate = NULL;
42886ffe 343 struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
17926a79
DH
344 struct rb_node *p, **pp;
345 const char *new = "old";
346 __be32 epoch;
0d12f8a4 347 u32 cid;
17926a79
DH
348
349 _enter("");
350
42886ffe 351 ASSERT(sp->hdr.flags & RXRPC_CLIENT_INITIATED);
17926a79 352
42886ffe
DH
353 epoch = sp->hdr.epoch;
354 cid = sp->hdr.cid & RXRPC_CIDMASK;
17926a79
DH
355
356 /* search the connection list first */
357 read_lock_bh(&trans->conn_lock);
358
359 p = trans->server_conns.rb_node;
360 while (p) {
999b69f8 361 conn = rb_entry(p, struct rxrpc_connection, service_node);
17926a79 362
19ffa01c 363 _debug("maybe %x", conn->proto.cid);
17926a79 364
19ffa01c 365 if (epoch < conn->proto.epoch)
17926a79 366 p = p->rb_left;
19ffa01c 367 else if (epoch > conn->proto.epoch)
17926a79 368 p = p->rb_right;
19ffa01c 369 else if (cid < conn->proto.cid)
17926a79 370 p = p->rb_left;
19ffa01c 371 else if (cid > conn->proto.cid)
17926a79
DH
372 p = p->rb_right;
373 else
374 goto found_extant_connection;
375 }
376 read_unlock_bh(&trans->conn_lock);
377
378 /* not yet present - create a candidate for a new record and then
379 * redo the search */
843099ca 380 candidate = rxrpc_alloc_connection(GFP_NOIO);
17926a79
DH
381 if (!candidate) {
382 _leave(" = -ENOMEM");
383 return ERR_PTR(-ENOMEM);
384 }
385
42886ffe
DH
386 candidate->trans = trans;
387 candidate->proto.local = trans->local;
388 candidate->proto.epoch = sp->hdr.epoch;
389 candidate->proto.cid = sp->hdr.cid & RXRPC_CIDMASK;
390 candidate->proto.in_clientflag = RXRPC_CLIENT_INITIATED;
391 candidate->params.local = trans->local;
392 candidate->params.peer = trans->peer;
393 candidate->params.service_id = sp->hdr.serviceId;
394 candidate->security_ix = sp->hdr.securityIndex;
395 candidate->out_clientflag = 0;
396 candidate->state = RXRPC_CONN_SERVER;
19ffa01c 397 if (candidate->params.service_id)
42886ffe 398 candidate->state = RXRPC_CONN_SERVER_UNSECURED;
17926a79
DH
399
400 write_lock_bh(&trans->conn_lock);
401
402 pp = &trans->server_conns.rb_node;
403 p = NULL;
404 while (*pp) {
405 p = *pp;
999b69f8 406 conn = rb_entry(p, struct rxrpc_connection, service_node);
17926a79 407
19ffa01c 408 if (epoch < conn->proto.epoch)
17926a79 409 pp = &(*pp)->rb_left;
19ffa01c 410 else if (epoch > conn->proto.epoch)
17926a79 411 pp = &(*pp)->rb_right;
19ffa01c 412 else if (cid < conn->proto.cid)
17926a79 413 pp = &(*pp)->rb_left;
19ffa01c 414 else if (cid > conn->proto.cid)
17926a79
DH
415 pp = &(*pp)->rb_right;
416 else
417 goto found_extant_second;
418 }
419
420 /* we can now add the new candidate to the list */
421 conn = candidate;
422 candidate = NULL;
999b69f8
DH
423 rb_link_node(&conn->service_node, p, pp);
424 rb_insert_color(&conn->service_node, &trans->server_conns);
17926a79
DH
425 atomic_inc(&conn->trans->usage);
426
427 write_unlock_bh(&trans->conn_lock);
428
b3f57504 429 write_lock(&rxrpc_connection_lock);
17926a79 430 list_add_tail(&conn->link, &rxrpc_connections);
b3f57504 431 write_unlock(&rxrpc_connection_lock);
17926a79
DH
432
433 new = "new";
434
435success:
19ffa01c 436 _net("CONNECTION %s %d {%x}", new, conn->debug_id, conn->proto.cid);
17926a79
DH
437
438 _leave(" = %p {u=%d}", conn, atomic_read(&conn->usage));
439 return conn;
440
441 /* we found the connection in the list immediately */
442found_extant_connection:
42886ffe 443 if (sp->hdr.securityIndex != conn->security_ix) {
17926a79
DH
444 read_unlock_bh(&trans->conn_lock);
445 goto security_mismatch;
446 }
5627cc8b 447 rxrpc_get_connection(conn);
17926a79
DH
448 read_unlock_bh(&trans->conn_lock);
449 goto success;
450
451 /* we found the connection on the second time through the list */
452found_extant_second:
42886ffe 453 if (sp->hdr.securityIndex != conn->security_ix) {
17926a79
DH
454 write_unlock_bh(&trans->conn_lock);
455 goto security_mismatch;
456 }
5627cc8b 457 rxrpc_get_connection(conn);
17926a79
DH
458 write_unlock_bh(&trans->conn_lock);
459 kfree(candidate);
460 goto success;
461
462security_mismatch:
463 kfree(candidate);
464 _leave(" = -EKEYREJECTED");
465 return ERR_PTR(-EKEYREJECTED);
466}
467
468/*
469 * find a connection based on transport and RxRPC connection ID for an incoming
470 * packet
471 */
472struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_transport *trans,
42886ffe 473 struct sk_buff *skb)
17926a79
DH
474{
475 struct rxrpc_connection *conn;
42886ffe 476 struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
17926a79 477 struct rb_node *p;
0d12f8a4 478 u32 epoch, cid;
17926a79 479
42886ffe 480 _enter(",{%x,%x}", sp->hdr.cid, sp->hdr.flags);
17926a79
DH
481
482 read_lock_bh(&trans->conn_lock);
483
42886ffe
DH
484 cid = sp->hdr.cid & RXRPC_CIDMASK;
485 epoch = sp->hdr.epoch;
17926a79 486
4a3388c8 487 if (sp->hdr.flags & RXRPC_CLIENT_INITIATED) {
17926a79 488 p = trans->server_conns.rb_node;
4a3388c8 489 while (p) {
999b69f8 490 conn = rb_entry(p, struct rxrpc_connection, service_node);
4a3388c8
DH
491
492 _debug("maybe %x", conn->proto.cid);
493
494 if (epoch < conn->proto.epoch)
495 p = p->rb_left;
496 else if (epoch > conn->proto.epoch)
497 p = p->rb_right;
498 else if (cid < conn->proto.cid)
499 p = p->rb_left;
500 else if (cid > conn->proto.cid)
501 p = p->rb_right;
502 else
503 goto found;
504 }
505 } else {
506 conn = idr_find(&rxrpc_client_conn_ids, cid >> RXRPC_CIDSHIFT);
507 if (conn && conn->proto.epoch == epoch)
17926a79
DH
508 goto found;
509 }
510
511 read_unlock_bh(&trans->conn_lock);
512 _leave(" = NULL");
513 return NULL;
514
515found:
5627cc8b 516 rxrpc_get_connection(conn);
17926a79
DH
517 read_unlock_bh(&trans->conn_lock);
518 _leave(" = %p", conn);
519 return conn;
520}
521
999b69f8
DH
522/*
523 * Disconnect a call and clear any channel it occupies when that call
524 * terminates.
525 */
526void rxrpc_disconnect_call(struct rxrpc_call *call)
527{
528 struct rxrpc_connection *conn = call->conn;
529 unsigned chan = call->channel;
530
531 _enter("%d,%d", conn->debug_id, call->channel);
532
533 if (conn->channels[chan] == call) {
534 rcu_assign_pointer(conn->channels[chan], NULL);
535 atomic_inc(&conn->avail_chans);
536 wake_up(&conn->channel_wq);
537 }
538}
539
17926a79
DH
540/*
541 * release a virtual connection
542 */
543void rxrpc_put_connection(struct rxrpc_connection *conn)
544{
999b69f8
DH
545 if (!conn)
546 return;
547
17926a79
DH
548 _enter("%p{u=%d,d=%d}",
549 conn, atomic_read(&conn->usage), conn->debug_id);
550
551 ASSERTCMP(atomic_read(&conn->usage), >, 0);
552
22a3f9a2 553 conn->put_time = ktime_get_seconds();
17926a79
DH
554 if (atomic_dec_and_test(&conn->usage)) {
555 _debug("zombie");
651350d1 556 rxrpc_queue_delayed_work(&rxrpc_connection_reap, 0);
17926a79
DH
557 }
558
559 _leave("");
560}
561
562/*
563 * destroy a virtual connection
564 */
565static void rxrpc_destroy_connection(struct rxrpc_connection *conn)
566{
567 _enter("%p{%d}", conn, atomic_read(&conn->usage));
568
569 ASSERTCMP(atomic_read(&conn->usage), ==, 0);
570
571 _net("DESTROY CONN %d", conn->debug_id);
572
17926a79
DH
573 ASSERT(RB_EMPTY_ROOT(&conn->calls));
574 rxrpc_purge_queue(&conn->rx_queue);
575
e0e4d82f 576 conn->security->clear(conn);
19ffa01c 577 key_put(conn->params.key);
e0e4d82f
DH
578 key_put(conn->server_key);
579
17926a79
DH
580 rxrpc_put_transport(conn->trans);
581 kfree(conn);
582 _leave("");
583}
584
585/*
586 * reap dead connections
587 */
5eaa65b2 588static void rxrpc_connection_reaper(struct work_struct *work)
17926a79
DH
589{
590 struct rxrpc_connection *conn, *_p;
591 unsigned long now, earliest, reap_time;
592
593 LIST_HEAD(graveyard);
594
595 _enter("");
596
22a3f9a2 597 now = ktime_get_seconds();
17926a79
DH
598 earliest = ULONG_MAX;
599
b3f57504 600 write_lock(&rxrpc_connection_lock);
17926a79
DH
601 list_for_each_entry_safe(conn, _p, &rxrpc_connections, link) {
602 _debug("reap CONN %d { u=%d,t=%ld }",
603 conn->debug_id, atomic_read(&conn->usage),
604 (long) now - (long) conn->put_time);
605
606 if (likely(atomic_read(&conn->usage) > 0))
607 continue;
608
999b69f8
DH
609 if (rxrpc_conn_is_client(conn)) {
610 struct rxrpc_local *local = conn->params.local;
611 spin_lock(&local->client_conns_lock);
612 reap_time = conn->put_time + rxrpc_connection_expiry;
17926a79 613
999b69f8
DH
614 if (atomic_read(&conn->usage) > 0) {
615 ;
616 } else if (reap_time <= now) {
617 list_move_tail(&conn->link, &graveyard);
4a3388c8 618 rxrpc_put_client_connection_id(conn);
999b69f8
DH
619 rb_erase(&conn->client_node,
620 &local->client_conns);
621 } else if (reap_time < earliest) {
622 earliest = reap_time;
623 }
624
625 spin_unlock(&local->client_conns_lock);
626 } else {
627 write_lock_bh(&conn->trans->conn_lock);
628 reap_time = conn->put_time + rxrpc_connection_expiry;
629
630 if (atomic_read(&conn->usage) > 0) {
631 ;
632 } else if (reap_time <= now) {
633 list_move_tail(&conn->link, &graveyard);
634 rb_erase(&conn->service_node,
17926a79 635 &conn->trans->server_conns);
999b69f8
DH
636 } else if (reap_time < earliest) {
637 earliest = reap_time;
17926a79
DH
638 }
639
999b69f8 640 write_unlock_bh(&conn->trans->conn_lock);
17926a79 641 }
17926a79 642 }
b3f57504 643 write_unlock(&rxrpc_connection_lock);
17926a79
DH
644
645 if (earliest != ULONG_MAX) {
646 _debug("reschedule reaper %ld", (long) earliest - now);
647 ASSERTCMP(earliest, >, now);
651350d1
DH
648 rxrpc_queue_delayed_work(&rxrpc_connection_reap,
649 (earliest - now) * HZ);
17926a79
DH
650 }
651
652 /* then destroy all those pulled out */
653 while (!list_empty(&graveyard)) {
654 conn = list_entry(graveyard.next, struct rxrpc_connection,
655 link);
656 list_del_init(&conn->link);
657
658 ASSERTCMP(atomic_read(&conn->usage), ==, 0);
659 rxrpc_destroy_connection(conn);
660 }
661
662 _leave("");
663}
664
665/*
666 * preemptively destroy all the connection records rather than waiting for them
667 * to time out
668 */
669void __exit rxrpc_destroy_all_connections(void)
670{
671 _enter("");
672
5873c083 673 rxrpc_connection_expiry = 0;
17926a79 674 cancel_delayed_work(&rxrpc_connection_reap);
651350d1 675 rxrpc_queue_delayed_work(&rxrpc_connection_reap, 0);
17926a79
DH
676
677 _leave("");
678}