Blame view

net/rxrpc/conn_object.c 11.6 KB
45025bcee   David Howells   rxrpc: Improve ma...
1
  /* RxRPC virtual connection handler, common bits.
17926a793   David Howells   [AF_RXRPC]: Provi...
2
   *
45025bcee   David Howells   rxrpc: Improve ma...
3
   * Copyright (C) 2007, 2016 Red Hat, Inc. All Rights Reserved.
17926a793   David Howells   [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   Joe Perches   rxrpc: Use pr_<le...
11
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17926a793   David Howells   [AF_RXRPC]: Provi...
12
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
13
  #include <linux/slab.h>
17926a793   David Howells   [AF_RXRPC]: Provi...
14
15
  #include <linux/net.h>
  #include <linux/skbuff.h>
17926a793   David Howells   [AF_RXRPC]: Provi...
16
  #include "ar-internal.h"
5873c0834   David Howells   af_rxrpc: Add sys...
17
18
19
  /*
   * Time till a connection expires after last use (in seconds).
   */
1392633ba   David Howells   rxrpc: Fix servic...
20
21
  unsigned int __read_mostly rxrpc_connection_expiry = 10 * 60;
  unsigned int __read_mostly rxrpc_closed_conn_expiry = 10;
5873c0834   David Howells   af_rxrpc: Add sys...
22

45025bcee   David Howells   rxrpc: Improve ma...
23
  static void rxrpc_destroy_connection(struct rcu_head *);
17926a793   David Howells   [AF_RXRPC]: Provi...
24
  /*
17926a793   David Howells   [AF_RXRPC]: Provi...
25
26
   * allocate a new connection
   */
c6d2b8d76   David Howells   rxrpc: Split clie...
27
  struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
17926a793   David Howells   [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   David Howells   rxrpc: Improve ma...
35
  		INIT_LIST_HEAD(&conn->cache_link);
999b69f89   David Howells   rxrpc: Kill the c...
36
  		spin_lock_init(&conn->channel_lock);
45025bcee   David Howells   rxrpc: Improve ma...
37
  		INIT_LIST_HEAD(&conn->waiting_calls);
17926a793   David Howells   [AF_RXRPC]: Provi...
38
  		INIT_WORK(&conn->processor, &rxrpc_process_connection);
4d028b2c8   David Howells   rxrpc: Dup the ma...
39
  		INIT_LIST_HEAD(&conn->proc_link);
999b69f89   David Howells   rxrpc: Kill the c...
40
  		INIT_LIST_HEAD(&conn->link);
17926a793   David Howells   [AF_RXRPC]: Provi...
41
  		skb_queue_head_init(&conn->rx_queue);
e0e4d82f3   David Howells   rxrpc: Create a n...
42
  		conn->security = &rxrpc_no_security;
17926a793   David Howells   [AF_RXRPC]: Provi...
43
  		spin_lock_init(&conn->state_lock);
17926a793   David Howells   [AF_RXRPC]: Provi...
44
  		conn->debug_id = atomic_inc_return(&rxrpc_debug_id);
17926a793   David Howells   [AF_RXRPC]: Provi...
45
  		conn->size_align = 4;
f51b44800   David Howells   rxrpc: Set connec...
46
  		conn->idle_timestamp = jiffies;
17926a793   David Howells   [AF_RXRPC]: Provi...
47
  	}
16c61add5   Adrian Bunk   [RXRPC] net/rxrpc...
48
  	_leave(" = %p{%d}", conn, conn ? conn->debug_id : 0);
17926a793   David Howells   [AF_RXRPC]: Provi...
49
50
51
52
  	return conn;
  }
  
  /*
8496af50e   David Howells   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   David Howells   [AF_RXRPC]: Provi...
59
   */
8496af50e   David Howells   rxrpc: Use RCU to...
60
61
  struct rxrpc_connection *rxrpc_find_connection_rcu(struct rxrpc_local *local,
  						   struct sk_buff *skb)
17926a793   David Howells   [AF_RXRPC]: Provi...
62
63
  {
  	struct rxrpc_connection *conn;
1291e9d10   David Howells   rxrpc: Move data_...
64
  	struct rxrpc_conn_proto k;
42886ffe7   David Howells   rxrpc: Pass sk_bu...
65
  	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
1291e9d10   David Howells   rxrpc: Move data_...
66
67
  	struct sockaddr_rxrpc srx;
  	struct rxrpc_peer *peer;
17926a793   David Howells   [AF_RXRPC]: Provi...
68

8496af50e   David Howells   rxrpc: Use RCU to...
69
  	_enter(",%x", sp->hdr.cid & RXRPC_CIDMASK);
17926a793   David Howells   [AF_RXRPC]: Provi...
70

7b674e390   David Howells   rxrpc: Fix IPv6 s...
71
  	if (rxrpc_extract_addr_from_skb(local, &srx, skb) < 0)
1291e9d10   David Howells   rxrpc: Move data_...
72
  		goto not_found;
17926a793   David Howells   [AF_RXRPC]: Provi...
73

8496af50e   David Howells   rxrpc: Use RCU to...
74
75
  	k.epoch	= sp->hdr.epoch;
  	k.cid	= sp->hdr.cid & RXRPC_CIDMASK;
1291e9d10   David Howells   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   David Howells   [AF_RXRPC]: Provi...
87

4a3388c80   David Howells   rxrpc: Use IDR to...
88
  	if (sp->hdr.flags & RXRPC_CLIENT_INITIATED) {
1291e9d10   David Howells   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   David Howells   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   David Howells   rxrpc: Use IDR to...
101
  	} else {
8496af50e   David Howells   rxrpc: Use RCU to...
102
103
104
  		/* Look up client connections by connection ID alone as their
  		 * IDs are unique for this machine.
  		 */
1291e9d10   David Howells   rxrpc: Move data_...
105
  		conn = idr_find(&rxrpc_client_conn_ids,
8496af50e   David Howells   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   David Howells   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   David Howells   rxrpc: Make IPv6 ...
125
  #ifdef CONFIG_AF_RXRPC_IPV6
75b54cb57   David Howells   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   David Howells   rxrpc: Make IPv6 ...
134
  #endif
1291e9d10   David Howells   rxrpc: Move data_...
135
136
137
  		default:
  			BUG();
  		}
1291e9d10   David Howells   rxrpc: Move data_...
138
139
  		_leave(" = %p", conn);
  		return conn;
17926a793   David Howells   [AF_RXRPC]: Provi...
140
  	}
1291e9d10   David Howells   rxrpc: Move data_...
141
  not_found:
17926a793   David Howells   [AF_RXRPC]: Provi...
142
143
  	_leave(" = NULL");
  	return NULL;
17926a793   David Howells   [AF_RXRPC]: Provi...
144
145
146
  }
  
  /*
999b69f89   David Howells   rxrpc: Kill the c...
147
   * Disconnect a call and clear any channel it occupies when that call
a1399f8bb   David Howells   rxrpc: Call chann...
148
149
   * terminates.  The caller must hold the channel_lock and must release the
   * call's ref on the connection.
999b69f89   David Howells   rxrpc: Kill the c...
150
   */
45025bcee   David Howells   rxrpc: Improve ma...
151
152
  void __rxrpc_disconnect_call(struct rxrpc_connection *conn,
  			     struct rxrpc_call *call)
999b69f89   David Howells   rxrpc: Kill the c...
153
  {
01a90a459   David Howells   rxrpc: Drop chann...
154
155
  	struct rxrpc_channel *chan =
  		&conn->channels[call->cid & RXRPC_CHANNELMASK];
999b69f89   David Howells   rxrpc: Kill the c...
156

01a90a459   David Howells   rxrpc: Drop chann...
157
  	_enter("%d,%x", conn->debug_id, call->cid);
999b69f89   David Howells   rxrpc: Kill the c...
158

a1399f8bb   David Howells   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   David Howells   rxrpc: Add some m...
163
  		trace_rxrpc_disconnect_call(call);
f5c17aaeb   David Howells   rxrpc: Calls shou...
164
165
  		if (call->abort_code) {
  			chan->last_abort = call->abort_code;
18bfeba50   David Howells   rxrpc: Perform te...
166
167
  			chan->last_type = RXRPC_PACKET_TYPE_ABORT;
  		} else {
248f219cb   David Howells   rxrpc: Rewrite th...
168
  			chan->last_seq = call->rx_hard_ack;
18bfeba50   David Howells   rxrpc: Perform te...
169
170
171
  			chan->last_type = RXRPC_PACKET_TYPE_ACK;
  		}
  		/* Sync with rxrpc_conn_retransmit(). */
a1399f8bb   David Howells   rxrpc: Call chann...
172
173
174
  		smp_wmb();
  		chan->last_call = chan->call_id;
  		chan->call_id = chan->call_counter;
e653cfe49   David Howells   rxrpc: Release a ...
175

a1399f8bb   David Howells   rxrpc: Call chann...
176
  		rcu_assign_pointer(chan->call, NULL);
999b69f89   David Howells   rxrpc: Kill the c...
177
  	}
e653cfe49   David Howells   rxrpc: Release a ...
178

a1399f8bb   David Howells   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   David Howells   rxrpc: Cache the ...
189
  	call->peer->cong_cwnd = call->cong_cwnd;
248f219cb   David Howells   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   David Howells   rxrpc: Improve ma...
193
194
  	if (rxrpc_is_client_call(call))
  		return rxrpc_disconnect_client_call(call);
a1399f8bb   David Howells   rxrpc: Call chann...
195
  	spin_lock(&conn->channel_lock);
45025bcee   David Howells   rxrpc: Improve ma...
196
  	__rxrpc_disconnect_call(conn, call);
e653cfe49   David Howells   rxrpc: Release a ...
197
198
199
  	spin_unlock(&conn->channel_lock);
  
  	call->conn = NULL;
f51b44800   David Howells   rxrpc: Set connec...
200
  	conn->idle_timestamp = jiffies;
e653cfe49   David Howells   rxrpc: Release a ...
201
  	rxrpc_put_connection(conn);
999b69f89   David Howells   rxrpc: Kill the c...
202
203
204
  }
  
  /*
45025bcee   David Howells   rxrpc: Improve ma...
205
206
207
208
   * Kill off a connection.
   */
  void rxrpc_kill_connection(struct rxrpc_connection *conn)
  {
2baec2c3f   David Howells   rxrpc: Support ne...
209
  	struct rxrpc_net *rxnet = conn->params.local->rxnet;
45025bcee   David Howells   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   David Howells   rxrpc: Support ne...
215
  	write_lock(&rxnet->conn_lock);
45025bcee   David Howells   rxrpc: Improve ma...
216
  	list_del_init(&conn->proc_link);
2baec2c3f   David Howells   rxrpc: Support ne...
217
  	write_unlock(&rxnet->conn_lock);
45025bcee   David Howells   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   David Howells   rxrpc: Add connec...
233
234
   * Queue a connection's work processor, getting a ref to pass to the work
   * queue.
17926a793   David Howells   [AF_RXRPC]: Provi...
235
   */
363deeab6   David Howells   rxrpc: Add connec...
236
  bool rxrpc_queue_conn(struct rxrpc_connection *conn)
17926a793   David Howells   [AF_RXRPC]: Provi...
237
  {
363deeab6   David Howells   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   David Howells   rxrpc: Support ne...
296
  	struct rxrpc_net *rxnet;
363deeab6   David Howells   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   David Howells   rxrpc: Fix servic...
303
  	if (n == 1) {
2baec2c3f   David Howells   rxrpc: Support ne...
304
305
306
  		rxnet = conn->params.local->rxnet;
  		rxrpc_queue_delayed_work(&rxnet->service_conn_reaper, 0);
  	}
17926a793   David Howells   [AF_RXRPC]: Provi...
307
308
309
310
311
  }
  
  /*
   * destroy a virtual connection
   */
dee46364c   David Howells   rxrpc: Add RCU de...
312
  static void rxrpc_destroy_connection(struct rcu_head *rcu)
17926a793   David Howells   [AF_RXRPC]: Provi...
313
  {
dee46364c   David Howells   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   David Howells   [AF_RXRPC]: Provi...
318
319
320
321
  
  	ASSERTCMP(atomic_read(&conn->usage), ==, 0);
  
  	_net("DESTROY CONN %d", conn->debug_id);
17926a793   David Howells   [AF_RXRPC]: Provi...
322
  	rxrpc_purge_queue(&conn->rx_queue);
e0e4d82f3   David Howells   rxrpc: Create a n...
323
  	conn->security->clear(conn);
19ffa01c9   David Howells   rxrpc: Use struct...
324
  	key_put(conn->params.key);
e0e4d82f3   David Howells   rxrpc: Create a n...
325
  	key_put(conn->server_key);
aa390bbe2   David Howells   rxrpc: Kill off t...
326
327
  	rxrpc_put_peer(conn->params.peer);
  	rxrpc_put_local(conn->params.local);
e0e4d82f3   David Howells   rxrpc: Create a n...
328

17926a793   David Howells   [AF_RXRPC]: Provi...
329
330
331
332
333
  	kfree(conn);
  	_leave("");
  }
  
  /*
45025bcee   David Howells   rxrpc: Improve ma...
334
   * reap dead service connections
17926a793   David Howells   [AF_RXRPC]: Provi...
335
   */
2baec2c3f   David Howells   rxrpc: Support ne...
336
  void rxrpc_service_connection_reaper(struct work_struct *work)
17926a793   David Howells   [AF_RXRPC]: Provi...
337
338
  {
  	struct rxrpc_connection *conn, *_p;
2baec2c3f   David Howells   rxrpc: Support ne...
339
340
341
  	struct rxrpc_net *rxnet =
  		container_of(to_delayed_work(work),
  			     struct rxrpc_net, service_conn_reaper);
1392633ba   David Howells   rxrpc: Fix servic...
342
  	unsigned long expire_at, earliest, idle_timestamp, now;
17926a793   David Howells   [AF_RXRPC]: Provi...
343
344
345
346
  
  	LIST_HEAD(graveyard);
  
  	_enter("");
f51b44800   David Howells   rxrpc: Set connec...
347
  	now = jiffies;
1392633ba   David Howells   rxrpc: Fix servic...
348
  	earliest = now + MAX_JIFFY_OFFSET;
17926a793   David Howells   [AF_RXRPC]: Provi...
349

2baec2c3f   David Howells   rxrpc: Support ne...
350
351
  	write_lock(&rxnet->conn_lock);
  	list_for_each_entry_safe(conn, _p, &rxnet->service_conns, link) {
001c11224   David Howells   rxrpc: Maintain a...
352
353
  		ASSERTCMP(atomic_read(&conn->usage), >, 0);
  		if (likely(atomic_read(&conn->usage) > 1))
17926a793   David Howells   [AF_RXRPC]: Provi...
354
  			continue;
00e907127   David Howells   rxrpc: Preallocat...
355
356
  		if (conn->state == RXRPC_CONN_SERVICE_PREALLOC)
  			continue;
17926a793   David Howells   [AF_RXRPC]: Provi...
357

1392633ba   David Howells   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   David Howells   [AF_RXRPC]: Provi...
373
  		}
001c11224   David Howells   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   David Howells   rxrpc: Fix servic...
380
  		trace_rxrpc_conn(conn, rxrpc_conn_reap_service, 0, 0);
001c11224   David Howells   rxrpc: Maintain a...
381
382
  
  		if (rxrpc_conn_is_client(conn))
45025bcee   David Howells   rxrpc: Improve ma...
383
  			BUG();
001c11224   David Howells   rxrpc: Maintain a...
384
385
386
387
  		else
  			rxrpc_unpublish_service_conn(conn);
  
  		list_move_tail(&conn->link, &graveyard);
17926a793   David Howells   [AF_RXRPC]: Provi...
388
  	}
2baec2c3f   David Howells   rxrpc: Support ne...
389
  	write_unlock(&rxnet->conn_lock);
17926a793   David Howells   [AF_RXRPC]: Provi...
390

1392633ba   David Howells   rxrpc: Fix servic...
391
392
  	if (earliest != now + MAX_JIFFY_OFFSET) {
  		_debug("reschedule reaper %ld", (long)earliest - (long)now);
f51b44800   David Howells   rxrpc: Set connec...
393
  		ASSERT(time_after(earliest, now));
1392633ba   David Howells   rxrpc: Fix servic...
394
  		rxrpc_queue_delayed_work(&rxnet->service_conn_reaper,
f51b44800   David Howells   rxrpc: Set connec...
395
  					 earliest - now);
17926a793   David Howells   [AF_RXRPC]: Provi...
396
  	}
17926a793   David Howells   [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   David Howells   rxrpc: Improve ma...
403
  		rxrpc_kill_connection(conn);
17926a793   David Howells   [AF_RXRPC]: Provi...
404
405
406
407
408
409
  	}
  
  	_leave("");
  }
  
  /*
45025bcee   David Howells   rxrpc: Improve ma...
410
411
   * preemptively destroy all the service connection records rather than
   * waiting for them to time out
17926a793   David Howells   [AF_RXRPC]: Provi...
412
   */
2baec2c3f   David Howells   rxrpc: Support ne...
413
  void rxrpc_destroy_all_connections(struct rxrpc_net *rxnet)
17926a793   David Howells   [AF_RXRPC]: Provi...
414
  {
dee46364c   David Howells   rxrpc: Add RCU de...
415
416
  	struct rxrpc_connection *conn, *_p;
  	bool leak = false;
17926a793   David Howells   [AF_RXRPC]: Provi...
417
  	_enter("");
2baec2c3f   David Howells   rxrpc: Support ne...
418
  	rxrpc_destroy_all_client_connections(rxnet);
45025bcee   David Howells   rxrpc: Improve ma...
419

2baec2c3f   David Howells   rxrpc: Support ne...
420
421
  	cancel_delayed_work(&rxnet->client_conn_reaper);
  	rxrpc_queue_delayed_work(&rxnet->client_conn_reaper, 0);
dee46364c   David Howells   rxrpc: Add RCU de...
422
  	flush_workqueue(rxrpc_workqueue);
2baec2c3f   David Howells   rxrpc: Support ne...
423
424
  	write_lock(&rxnet->conn_lock);
  	list_for_each_entry_safe(conn, _p, &rxnet->service_conns, link) {
dee46364c   David Howells   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   David Howells   rxrpc: Support ne...
430
  	write_unlock(&rxnet->conn_lock);
dee46364c   David Howells   rxrpc: Add RCU de...
431
  	BUG_ON(leak);
2baec2c3f   David Howells   rxrpc: Support ne...
432
  	ASSERT(list_empty(&rxnet->conn_proc_list));
17926a793   David Howells   [AF_RXRPC]: Provi...
433
434
435
  
  	_leave("");
  }