Blame view
net/rxrpc/conn_object.c
11.6 KB
45025bcee rxrpc: Improve ma... |
1 |
/* RxRPC virtual connection handler, common bits. |
17926a793 [AF_RXRPC]: Provi... |
2 |
* |
45025bcee rxrpc: Improve ma... |
3 |
* Copyright (C) 2007, 2016 Red Hat, Inc. All Rights Reserved. |
17926a793 [AF_RXRPC]: Provi... |
4 5 6 7 8 9 10 |
* Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ |
9b6d53985 rxrpc: Use pr_<le... |
11 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
17926a793 [AF_RXRPC]: Provi... |
12 |
#include <linux/module.h> |
5a0e3ad6a include cleanup: ... |
13 |
#include <linux/slab.h> |
17926a793 [AF_RXRPC]: Provi... |
14 15 |
#include <linux/net.h> #include <linux/skbuff.h> |
17926a793 [AF_RXRPC]: Provi... |
16 |
#include "ar-internal.h" |
5873c0834 af_rxrpc: Add sys... |
17 18 19 |
/* * Time till a connection expires after last use (in seconds). */ |
1392633ba rxrpc: Fix servic... |
20 21 |
unsigned int __read_mostly rxrpc_connection_expiry = 10 * 60; unsigned int __read_mostly rxrpc_closed_conn_expiry = 10; |
5873c0834 af_rxrpc: Add sys... |
22 |
|
45025bcee rxrpc: Improve ma... |
23 |
static void rxrpc_destroy_connection(struct rcu_head *); |
17926a793 [AF_RXRPC]: Provi... |
24 |
/* |
17926a793 [AF_RXRPC]: Provi... |
25 26 |
* allocate a new connection */ |
c6d2b8d76 rxrpc: Split clie... |
27 |
struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp) |
17926a793 [AF_RXRPC]: Provi... |
28 29 30 31 32 33 34 |
{ struct rxrpc_connection *conn; _enter(""); conn = kzalloc(sizeof(struct rxrpc_connection), gfp); if (conn) { |
45025bcee rxrpc: Improve ma... |
35 |
INIT_LIST_HEAD(&conn->cache_link); |
999b69f89 rxrpc: Kill the c... |
36 |
spin_lock_init(&conn->channel_lock); |
45025bcee rxrpc: Improve ma... |
37 |
INIT_LIST_HEAD(&conn->waiting_calls); |
17926a793 [AF_RXRPC]: Provi... |
38 |
INIT_WORK(&conn->processor, &rxrpc_process_connection); |
4d028b2c8 rxrpc: Dup the ma... |
39 |
INIT_LIST_HEAD(&conn->proc_link); |
999b69f89 rxrpc: Kill the c... |
40 |
INIT_LIST_HEAD(&conn->link); |
17926a793 [AF_RXRPC]: Provi... |
41 |
skb_queue_head_init(&conn->rx_queue); |
e0e4d82f3 rxrpc: Create a n... |
42 |
conn->security = &rxrpc_no_security; |
17926a793 [AF_RXRPC]: Provi... |
43 |
spin_lock_init(&conn->state_lock); |
17926a793 [AF_RXRPC]: Provi... |
44 |
conn->debug_id = atomic_inc_return(&rxrpc_debug_id); |
17926a793 [AF_RXRPC]: Provi... |
45 |
conn->size_align = 4; |
f51b44800 rxrpc: Set connec... |
46 |
conn->idle_timestamp = jiffies; |
17926a793 [AF_RXRPC]: Provi... |
47 |
} |
16c61add5 [RXRPC] net/rxrpc... |
48 |
_leave(" = %p{%d}", conn, conn ? conn->debug_id : 0); |
17926a793 [AF_RXRPC]: Provi... |
49 50 51 52 |
return conn; } /* |
8496af50e rxrpc: Use RCU to... |
53 54 55 56 57 58 |
* Look up a connection in the cache by protocol parameters. * * If successful, a pointer to the connection is returned, but no ref is taken. * NULL is returned if there is no match. * * The caller must be holding the RCU read lock. |
17926a793 [AF_RXRPC]: Provi... |
59 |
*/ |
8496af50e rxrpc: Use RCU to... |
60 61 |
struct rxrpc_connection *rxrpc_find_connection_rcu(struct rxrpc_local *local, struct sk_buff *skb) |
17926a793 [AF_RXRPC]: Provi... |
62 63 |
{ struct rxrpc_connection *conn; |
1291e9d10 rxrpc: Move data_... |
64 |
struct rxrpc_conn_proto k; |
42886ffe7 rxrpc: Pass sk_bu... |
65 |
struct rxrpc_skb_priv *sp = rxrpc_skb(skb); |
1291e9d10 rxrpc: Move data_... |
66 67 |
struct sockaddr_rxrpc srx; struct rxrpc_peer *peer; |
17926a793 [AF_RXRPC]: Provi... |
68 |
|
8496af50e rxrpc: Use RCU to... |
69 |
_enter(",%x", sp->hdr.cid & RXRPC_CIDMASK); |
17926a793 [AF_RXRPC]: Provi... |
70 |
|
7b674e390 rxrpc: Fix IPv6 s... |
71 |
if (rxrpc_extract_addr_from_skb(local, &srx, skb) < 0) |
1291e9d10 rxrpc: Move data_... |
72 |
goto not_found; |
17926a793 [AF_RXRPC]: Provi... |
73 |
|
8496af50e rxrpc: Use RCU to... |
74 75 |
k.epoch = sp->hdr.epoch; k.cid = sp->hdr.cid & RXRPC_CIDMASK; |
1291e9d10 rxrpc: Move data_... |
76 77 78 79 80 81 82 83 84 85 86 |
/* We may have to handle mixing IPv4 and IPv6 */ if (srx.transport.family != local->srx.transport.family) { pr_warn_ratelimited("AF_RXRPC: Protocol mismatch %u not %u ", srx.transport.family, local->srx.transport.family); goto not_found; } k.epoch = sp->hdr.epoch; k.cid = sp->hdr.cid & RXRPC_CIDMASK; |
17926a793 [AF_RXRPC]: Provi... |
87 |
|
4a3388c80 rxrpc: Use IDR to... |
88 |
if (sp->hdr.flags & RXRPC_CLIENT_INITIATED) { |
1291e9d10 rxrpc: Move data_... |
89 90 91 92 93 94 95 |
/* We need to look up service connections by the full protocol * parameter set. We look up the peer first as an intermediate * step and then the connection from the peer's tree. */ peer = rxrpc_lookup_peer_rcu(local, &srx); if (!peer) goto not_found; |
8496af50e rxrpc: Use RCU to... |
96 97 98 99 100 |
conn = rxrpc_find_service_conn_rcu(peer, skb); if (!conn || atomic_read(&conn->usage) == 0) goto not_found; _leave(" = %p", conn); return conn; |
4a3388c80 rxrpc: Use IDR to... |
101 |
} else { |
8496af50e rxrpc: Use RCU to... |
102 103 104 |
/* Look up client connections by connection ID alone as their * IDs are unique for this machine. */ |
1291e9d10 rxrpc: Move data_... |
105 |
conn = idr_find(&rxrpc_client_conn_ids, |
8496af50e rxrpc: Use RCU to... |
106 107 108 109 110 111 112 |
sp->hdr.cid >> RXRPC_CIDSHIFT); if (!conn || atomic_read(&conn->usage) == 0) { _debug("no conn"); goto not_found; } if (conn->proto.epoch != k.epoch || |
1291e9d10 rxrpc: Move data_... |
113 114 115 116 117 118 119 120 121 122 123 124 |
conn->params.local != local) goto not_found; peer = conn->params.peer; switch (srx.transport.family) { case AF_INET: if (peer->srx.transport.sin.sin_port != srx.transport.sin.sin_port || peer->srx.transport.sin.sin_addr.s_addr != srx.transport.sin.sin_addr.s_addr) goto not_found; break; |
d19127473 rxrpc: Make IPv6 ... |
125 |
#ifdef CONFIG_AF_RXRPC_IPV6 |
75b54cb57 rxrpc: Add IPv6 s... |
126 127 128 129 130 131 132 133 |
case AF_INET6: if (peer->srx.transport.sin6.sin6_port != srx.transport.sin6.sin6_port || memcmp(&peer->srx.transport.sin6.sin6_addr, &srx.transport.sin6.sin6_addr, sizeof(struct in6_addr)) != 0) goto not_found; break; |
d19127473 rxrpc: Make IPv6 ... |
134 |
#endif |
1291e9d10 rxrpc: Move data_... |
135 136 137 |
default: BUG(); } |
1291e9d10 rxrpc: Move data_... |
138 139 |
_leave(" = %p", conn); return conn; |
17926a793 [AF_RXRPC]: Provi... |
140 |
} |
1291e9d10 rxrpc: Move data_... |
141 |
not_found: |
17926a793 [AF_RXRPC]: Provi... |
142 143 |
_leave(" = NULL"); return NULL; |
17926a793 [AF_RXRPC]: Provi... |
144 145 146 |
} /* |
999b69f89 rxrpc: Kill the c... |
147 |
* Disconnect a call and clear any channel it occupies when that call |
a1399f8bb rxrpc: Call chann... |
148 149 |
* terminates. The caller must hold the channel_lock and must release the * call's ref on the connection. |
999b69f89 rxrpc: Kill the c... |
150 |
*/ |
45025bcee rxrpc: Improve ma... |
151 152 |
void __rxrpc_disconnect_call(struct rxrpc_connection *conn, struct rxrpc_call *call) |
999b69f89 rxrpc: Kill the c... |
153 |
{ |
01a90a459 rxrpc: Drop chann... |
154 155 |
struct rxrpc_channel *chan = &conn->channels[call->cid & RXRPC_CHANNELMASK]; |
999b69f89 rxrpc: Kill the c... |
156 |
|
01a90a459 rxrpc: Drop chann... |
157 |
_enter("%d,%x", conn->debug_id, call->cid); |
999b69f89 rxrpc: Kill the c... |
158 |
|
a1399f8bb rxrpc: Call chann... |
159 160 161 162 |
if (rcu_access_pointer(chan->call) == call) { /* Save the result of the call so that we can repeat it if necessary * through the channel, whilst disposing of the actual call record. */ |
b1d9f7fde rxrpc: Add some m... |
163 |
trace_rxrpc_disconnect_call(call); |
f5c17aaeb rxrpc: Calls shou... |
164 165 |
if (call->abort_code) { chan->last_abort = call->abort_code; |
18bfeba50 rxrpc: Perform te... |
166 167 |
chan->last_type = RXRPC_PACKET_TYPE_ABORT; } else { |
248f219cb rxrpc: Rewrite th... |
168 |
chan->last_seq = call->rx_hard_ack; |
18bfeba50 rxrpc: Perform te... |
169 170 171 |
chan->last_type = RXRPC_PACKET_TYPE_ACK; } /* Sync with rxrpc_conn_retransmit(). */ |
a1399f8bb rxrpc: Call chann... |
172 173 174 |
smp_wmb(); chan->last_call = chan->call_id; chan->call_id = chan->call_counter; |
e653cfe49 rxrpc: Release a ... |
175 |
|
a1399f8bb rxrpc: Call chann... |
176 |
rcu_assign_pointer(chan->call, NULL); |
999b69f89 rxrpc: Kill the c... |
177 |
} |
e653cfe49 rxrpc: Release a ... |
178 |
|
a1399f8bb rxrpc: Call chann... |
179 180 181 182 183 184 185 186 187 188 |
_leave(""); } /* * Disconnect a call and clear any channel it occupies when that call * terminates. */ void rxrpc_disconnect_call(struct rxrpc_call *call) { struct rxrpc_connection *conn = call->conn; |
f7aec129a rxrpc: Cache the ... |
189 |
call->peer->cong_cwnd = call->cong_cwnd; |
248f219cb rxrpc: Rewrite th... |
190 191 192 |
spin_lock_bh(&conn->params.peer->lock); hlist_del_init(&call->error_link); spin_unlock_bh(&conn->params.peer->lock); |
45025bcee rxrpc: Improve ma... |
193 194 |
if (rxrpc_is_client_call(call)) return rxrpc_disconnect_client_call(call); |
a1399f8bb rxrpc: Call chann... |
195 |
spin_lock(&conn->channel_lock); |
45025bcee rxrpc: Improve ma... |
196 |
__rxrpc_disconnect_call(conn, call); |
e653cfe49 rxrpc: Release a ... |
197 198 199 |
spin_unlock(&conn->channel_lock); call->conn = NULL; |
f51b44800 rxrpc: Set connec... |
200 |
conn->idle_timestamp = jiffies; |
e653cfe49 rxrpc: Release a ... |
201 |
rxrpc_put_connection(conn); |
999b69f89 rxrpc: Kill the c... |
202 203 204 |
} /* |
45025bcee rxrpc: Improve ma... |
205 206 207 208 |
* Kill off a connection. */ void rxrpc_kill_connection(struct rxrpc_connection *conn) { |
2baec2c3f rxrpc: Support ne... |
209 |
struct rxrpc_net *rxnet = conn->params.local->rxnet; |
45025bcee rxrpc: Improve ma... |
210 211 212 213 214 |
ASSERT(!rcu_access_pointer(conn->channels[0].call) && !rcu_access_pointer(conn->channels[1].call) && !rcu_access_pointer(conn->channels[2].call) && !rcu_access_pointer(conn->channels[3].call)); ASSERT(list_empty(&conn->cache_link)); |
2baec2c3f rxrpc: Support ne... |
215 |
write_lock(&rxnet->conn_lock); |
45025bcee rxrpc: Improve ma... |
216 |
list_del_init(&conn->proc_link); |
2baec2c3f rxrpc: Support ne... |
217 |
write_unlock(&rxnet->conn_lock); |
45025bcee rxrpc: Improve ma... |
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
/* Drain the Rx queue. Note that even though we've unpublished, an * incoming packet could still be being added to our Rx queue, so we * will need to drain it again in the RCU cleanup handler. */ rxrpc_purge_queue(&conn->rx_queue); /* Leave final destruction to RCU. The connection processor work item * must carry a ref on the connection to prevent us getting here whilst * it is queued or running. */ call_rcu(&conn->rcu, rxrpc_destroy_connection); } /* |
363deeab6 rxrpc: Add connec... |
233 234 |
* Queue a connection's work processor, getting a ref to pass to the work * queue. |
17926a793 [AF_RXRPC]: Provi... |
235 |
*/ |
363deeab6 rxrpc: Add connec... |
236 |
bool rxrpc_queue_conn(struct rxrpc_connection *conn) |
17926a793 [AF_RXRPC]: Provi... |
237 |
{ |
363deeab6 rxrpc: Add connec... |
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
const void *here = __builtin_return_address(0); int n = __atomic_add_unless(&conn->usage, 1, 0); if (n == 0) return false; if (rxrpc_queue_work(&conn->processor)) trace_rxrpc_conn(conn, rxrpc_conn_queued, n + 1, here); else rxrpc_put_connection(conn); return true; } /* * Note the re-emergence of a connection. */ void rxrpc_see_connection(struct rxrpc_connection *conn) { const void *here = __builtin_return_address(0); if (conn) { int n = atomic_read(&conn->usage); trace_rxrpc_conn(conn, rxrpc_conn_seen, n, here); } } /* * Get a ref on a connection. */ void rxrpc_get_connection(struct rxrpc_connection *conn) { const void *here = __builtin_return_address(0); int n = atomic_inc_return(&conn->usage); trace_rxrpc_conn(conn, rxrpc_conn_got, n, here); } /* * Try to get a ref on a connection. */ struct rxrpc_connection * rxrpc_get_connection_maybe(struct rxrpc_connection *conn) { const void *here = __builtin_return_address(0); if (conn) { int n = __atomic_add_unless(&conn->usage, 1, 0); if (n > 0) trace_rxrpc_conn(conn, rxrpc_conn_got, n + 1, here); else conn = NULL; } return conn; } /* * Release a service connection */ void rxrpc_put_service_conn(struct rxrpc_connection *conn) { |
2baec2c3f rxrpc: Support ne... |
296 |
struct rxrpc_net *rxnet; |
363deeab6 rxrpc: Add connec... |
297 298 299 300 301 302 |
const void *here = __builtin_return_address(0); int n; n = atomic_dec_return(&conn->usage); trace_rxrpc_conn(conn, rxrpc_conn_put_service, n, here); ASSERTCMP(n, >=, 0); |
1392633ba rxrpc: Fix servic... |
303 |
if (n == 1) { |
2baec2c3f rxrpc: Support ne... |
304 305 306 |
rxnet = conn->params.local->rxnet; rxrpc_queue_delayed_work(&rxnet->service_conn_reaper, 0); } |
17926a793 [AF_RXRPC]: Provi... |
307 308 309 310 311 |
} /* * destroy a virtual connection */ |
dee46364c rxrpc: Add RCU de... |
312 |
static void rxrpc_destroy_connection(struct rcu_head *rcu) |
17926a793 [AF_RXRPC]: Provi... |
313 |
{ |
dee46364c rxrpc: Add RCU de... |
314 315 316 317 |
struct rxrpc_connection *conn = container_of(rcu, struct rxrpc_connection, rcu); _enter("{%d,u=%d}", conn->debug_id, atomic_read(&conn->usage)); |
17926a793 [AF_RXRPC]: Provi... |
318 319 320 321 |
ASSERTCMP(atomic_read(&conn->usage), ==, 0); _net("DESTROY CONN %d", conn->debug_id); |
17926a793 [AF_RXRPC]: Provi... |
322 |
rxrpc_purge_queue(&conn->rx_queue); |
e0e4d82f3 rxrpc: Create a n... |
323 |
conn->security->clear(conn); |
19ffa01c9 rxrpc: Use struct... |
324 |
key_put(conn->params.key); |
e0e4d82f3 rxrpc: Create a n... |
325 |
key_put(conn->server_key); |
aa390bbe2 rxrpc: Kill off t... |
326 327 |
rxrpc_put_peer(conn->params.peer); rxrpc_put_local(conn->params.local); |
e0e4d82f3 rxrpc: Create a n... |
328 |
|
17926a793 [AF_RXRPC]: Provi... |
329 330 331 332 333 |
kfree(conn); _leave(""); } /* |
45025bcee rxrpc: Improve ma... |
334 |
* reap dead service connections |
17926a793 [AF_RXRPC]: Provi... |
335 |
*/ |
2baec2c3f rxrpc: Support ne... |
336 |
void rxrpc_service_connection_reaper(struct work_struct *work) |
17926a793 [AF_RXRPC]: Provi... |
337 338 |
{ struct rxrpc_connection *conn, *_p; |
2baec2c3f rxrpc: Support ne... |
339 340 341 |
struct rxrpc_net *rxnet = container_of(to_delayed_work(work), struct rxrpc_net, service_conn_reaper); |
1392633ba rxrpc: Fix servic... |
342 |
unsigned long expire_at, earliest, idle_timestamp, now; |
17926a793 [AF_RXRPC]: Provi... |
343 344 345 346 |
LIST_HEAD(graveyard); _enter(""); |
f51b44800 rxrpc: Set connec... |
347 |
now = jiffies; |
1392633ba rxrpc: Fix servic... |
348 |
earliest = now + MAX_JIFFY_OFFSET; |
17926a793 [AF_RXRPC]: Provi... |
349 |
|
2baec2c3f rxrpc: Support ne... |
350 351 |
write_lock(&rxnet->conn_lock); list_for_each_entry_safe(conn, _p, &rxnet->service_conns, link) { |
001c11224 rxrpc: Maintain a... |
352 353 |
ASSERTCMP(atomic_read(&conn->usage), >, 0); if (likely(atomic_read(&conn->usage) > 1)) |
17926a793 [AF_RXRPC]: Provi... |
354 |
continue; |
00e907127 rxrpc: Preallocat... |
355 356 |
if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) continue; |
17926a793 [AF_RXRPC]: Provi... |
357 |
|
1392633ba rxrpc: Fix servic... |
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
if (rxnet->live) { idle_timestamp = READ_ONCE(conn->idle_timestamp); expire_at = idle_timestamp + rxrpc_connection_expiry * HZ; if (conn->params.local->service_closed) expire_at = idle_timestamp + rxrpc_closed_conn_expiry * HZ; _debug("reap CONN %d { u=%d,t=%ld }", conn->debug_id, atomic_read(&conn->usage), (long)expire_at - (long)now); if (time_before(now, expire_at)) { if (time_before(expire_at, earliest)) earliest = expire_at; continue; } |
17926a793 [AF_RXRPC]: Provi... |
373 |
} |
001c11224 rxrpc: Maintain a... |
374 375 376 377 378 379 |
/* The usage count sits at 1 whilst the object is unused on the * list; we reduce that to 0 to make the object unavailable. */ if (atomic_cmpxchg(&conn->usage, 1, 0) != 1) continue; |
1392633ba rxrpc: Fix servic... |
380 |
trace_rxrpc_conn(conn, rxrpc_conn_reap_service, 0, 0); |
001c11224 rxrpc: Maintain a... |
381 382 |
if (rxrpc_conn_is_client(conn)) |
45025bcee rxrpc: Improve ma... |
383 |
BUG(); |
001c11224 rxrpc: Maintain a... |
384 385 386 387 |
else rxrpc_unpublish_service_conn(conn); list_move_tail(&conn->link, &graveyard); |
17926a793 [AF_RXRPC]: Provi... |
388 |
} |
2baec2c3f rxrpc: Support ne... |
389 |
write_unlock(&rxnet->conn_lock); |
17926a793 [AF_RXRPC]: Provi... |
390 |
|
1392633ba rxrpc: Fix servic... |
391 392 |
if (earliest != now + MAX_JIFFY_OFFSET) { _debug("reschedule reaper %ld", (long)earliest - (long)now); |
f51b44800 rxrpc: Set connec... |
393 |
ASSERT(time_after(earliest, now)); |
1392633ba rxrpc: Fix servic... |
394 |
rxrpc_queue_delayed_work(&rxnet->service_conn_reaper, |
f51b44800 rxrpc: Set connec... |
395 |
earliest - now); |
17926a793 [AF_RXRPC]: Provi... |
396 |
} |
17926a793 [AF_RXRPC]: Provi... |
397 398 399 400 401 402 |
while (!list_empty(&graveyard)) { conn = list_entry(graveyard.next, struct rxrpc_connection, link); list_del_init(&conn->link); ASSERTCMP(atomic_read(&conn->usage), ==, 0); |
45025bcee rxrpc: Improve ma... |
403 |
rxrpc_kill_connection(conn); |
17926a793 [AF_RXRPC]: Provi... |
404 405 406 407 408 409 |
} _leave(""); } /* |
45025bcee rxrpc: Improve ma... |
410 411 |
* preemptively destroy all the service connection records rather than * waiting for them to time out |
17926a793 [AF_RXRPC]: Provi... |
412 |
*/ |
2baec2c3f rxrpc: Support ne... |
413 |
void rxrpc_destroy_all_connections(struct rxrpc_net *rxnet) |
17926a793 [AF_RXRPC]: Provi... |
414 |
{ |
dee46364c rxrpc: Add RCU de... |
415 416 |
struct rxrpc_connection *conn, *_p; bool leak = false; |
17926a793 [AF_RXRPC]: Provi... |
417 |
_enter(""); |
2baec2c3f rxrpc: Support ne... |
418 |
rxrpc_destroy_all_client_connections(rxnet); |
45025bcee rxrpc: Improve ma... |
419 |
|
2baec2c3f rxrpc: Support ne... |
420 421 |
cancel_delayed_work(&rxnet->client_conn_reaper); rxrpc_queue_delayed_work(&rxnet->client_conn_reaper, 0); |
dee46364c rxrpc: Add RCU de... |
422 |
flush_workqueue(rxrpc_workqueue); |
2baec2c3f rxrpc: Support ne... |
423 424 |
write_lock(&rxnet->conn_lock); list_for_each_entry_safe(conn, _p, &rxnet->service_conns, link) { |
dee46364c rxrpc: Add RCU de... |
425 426 427 428 429 |
pr_err("AF_RXRPC: Leaked conn %p {%d} ", conn, atomic_read(&conn->usage)); leak = true; } |
2baec2c3f rxrpc: Support ne... |
430 |
write_unlock(&rxnet->conn_lock); |
dee46364c rxrpc: Add RCU de... |
431 |
BUG_ON(leak); |
2baec2c3f rxrpc: Support ne... |
432 |
ASSERT(list_empty(&rxnet->conn_proc_list)); |
17926a793 [AF_RXRPC]: Provi... |
433 434 435 |
_leave(""); } |