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