Blame view
net/rxrpc/call_object.c
18.5 KB
17926a793 [AF_RXRPC]: Provi... |
1 2 3 4 5 6 7 8 9 10 |
/* RxRPC individual remote procedure call handling * * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. * 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 |
5a0e3ad6a include cleanup: ... |
12 |
#include <linux/slab.h> |
17926a793 [AF_RXRPC]: Provi... |
13 14 |
#include <linux/module.h> #include <linux/circ_buf.h> |
7727640cc af_rxrpc: Keep rx... |
15 |
#include <linux/spinlock_types.h> |
17926a793 [AF_RXRPC]: Provi... |
16 17 18 |
#include <net/sock.h> #include <net/af_rxrpc.h> #include "ar-internal.h" |
5b8848d14 rxrpc: Convert ca... |
19 |
const char *const rxrpc_call_states[NR__RXRPC_CALL_STATES] = { |
f5c17aaeb rxrpc: Calls shou... |
20 |
[RXRPC_CALL_UNINITIALISED] = "Uninit ", |
999b69f89 rxrpc: Kill the c... |
21 |
[RXRPC_CALL_CLIENT_AWAIT_CONN] = "ClWtConn", |
1f8481d19 [AF_RXRPC]: Make ... |
22 23 24 |
[RXRPC_CALL_CLIENT_SEND_REQUEST] = "ClSndReq", [RXRPC_CALL_CLIENT_AWAIT_REPLY] = "ClAwtRpl", [RXRPC_CALL_CLIENT_RECV_REPLY] = "ClRcvRpl", |
00e907127 rxrpc: Preallocat... |
25 |
[RXRPC_CALL_SERVER_PREALLOC] = "SvPrealc", |
1f8481d19 [AF_RXRPC]: Make ... |
26 27 28 29 30 31 32 |
[RXRPC_CALL_SERVER_SECURING] = "SvSecure", [RXRPC_CALL_SERVER_ACCEPTING] = "SvAccept", [RXRPC_CALL_SERVER_RECV_REQUEST] = "SvRcvReq", [RXRPC_CALL_SERVER_ACK_REQUEST] = "SvAckReq", [RXRPC_CALL_SERVER_SEND_REPLY] = "SvSndRpl", [RXRPC_CALL_SERVER_AWAIT_ACK] = "SvAwtACK", [RXRPC_CALL_COMPLETE] = "Complete", |
f5c17aaeb rxrpc: Calls shou... |
33 34 35 36 |
}; const char *const rxrpc_call_completions[NR__RXRPC_CALL_COMPLETIONS] = { [RXRPC_CALL_SUCCEEDED] = "Complete", |
1f8481d19 [AF_RXRPC]: Make ... |
37 38 |
[RXRPC_CALL_REMOTELY_ABORTED] = "RmtAbort", [RXRPC_CALL_LOCALLY_ABORTED] = "LocAbort", |
f5c17aaeb rxrpc: Calls shou... |
39 |
[RXRPC_CALL_LOCAL_ERROR] = "LocError", |
1f8481d19 [AF_RXRPC]: Make ... |
40 |
[RXRPC_CALL_NETWORK_ERROR] = "NetError", |
1f8481d19 [AF_RXRPC]: Make ... |
41 |
}; |
17926a793 [AF_RXRPC]: Provi... |
42 |
struct kmem_cache *rxrpc_call_jar; |
17926a793 [AF_RXRPC]: Provi... |
43 |
|
248f219cb rxrpc: Rewrite th... |
44 45 46 47 48 |
static void rxrpc_call_timer_expired(unsigned long _call) { struct rxrpc_call *call = (struct rxrpc_call *)_call; _enter("%d", call->debug_id); |
405dea1de rxrpc: Fix the ca... |
49 50 |
if (call->state < RXRPC_CALL_COMPLETE) rxrpc_set_timer(call, rxrpc_timer_expired, ktime_get_real()); |
248f219cb rxrpc: Rewrite th... |
51 |
} |
17926a793 [AF_RXRPC]: Provi... |
52 |
|
b89372f23 rxrpc: Provide a ... |
53 |
static struct lock_class_key rxrpc_call_user_mutex_lock_class_key; |
17926a793 [AF_RXRPC]: Provi... |
54 |
/* |
2341e0775 rxrpc: Simplify c... |
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
* find an extant server call * - called in process context with IRQs enabled */ struct rxrpc_call *rxrpc_find_call_by_user_ID(struct rxrpc_sock *rx, unsigned long user_call_ID) { struct rxrpc_call *call; struct rb_node *p; _enter("%p,%lx", rx, user_call_ID); read_lock(&rx->call_lock); p = rx->calls.rb_node; while (p) { call = rb_entry(p, struct rxrpc_call, sock_node); if (user_call_ID < call->user_call_ID) p = p->rb_left; else if (user_call_ID > call->user_call_ID) p = p->rb_right; else goto found_extant_call; } read_unlock(&rx->call_lock); _leave(" = NULL"); return NULL; found_extant_call: |
fff72429c rxrpc: Improve th... |
85 |
rxrpc_get_call(call, rxrpc_call_got); |
2341e0775 rxrpc: Simplify c... |
86 87 88 89 90 91 |
read_unlock(&rx->call_lock); _leave(" = %p [%d]", call, atomic_read(&call->usage)); return call; } /* |
17926a793 [AF_RXRPC]: Provi... |
92 93 |
* allocate a new call */ |
b89372f23 rxrpc: Provide a ... |
94 |
struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *rx, gfp_t gfp) |
17926a793 [AF_RXRPC]: Provi... |
95 96 97 98 99 100 |
{ struct rxrpc_call *call; call = kmem_cache_zalloc(rxrpc_call_jar, gfp); if (!call) return NULL; |
248f219cb rxrpc: Rewrite th... |
101 102 |
call->rxtx_buffer = kcalloc(RXRPC_RXTX_BUFF_SIZE, sizeof(struct sk_buff *), |
17926a793 [AF_RXRPC]: Provi... |
103 |
gfp); |
248f219cb rxrpc: Rewrite th... |
104 105 |
if (!call->rxtx_buffer) goto nomem; |
17926a793 [AF_RXRPC]: Provi... |
106 |
|
248f219cb rxrpc: Rewrite th... |
107 108 109 |
call->rxtx_annotations = kcalloc(RXRPC_RXTX_BUFF_SIZE, sizeof(u8), gfp); if (!call->rxtx_annotations) goto nomem_2; |
540b1c48c rxrpc: Fix deadlo... |
110 |
mutex_init(&call->user_mutex); |
b89372f23 rxrpc: Provide a ... |
111 112 113 114 115 116 117 |
/* Prevent lockdep reporting a deadlock false positive between the afs * filesystem and sys_sendmsg() via the mmap sem. */ if (rx->sk.sk_kern_sock) lockdep_set_class(&call->user_mutex, &rxrpc_call_user_mutex_lock_class_key); |
248f219cb rxrpc: Rewrite th... |
118 119 |
setup_timer(&call->timer, rxrpc_call_timer_expired, (unsigned long)call); |
17926a793 [AF_RXRPC]: Provi... |
120 |
INIT_WORK(&call->processor, &rxrpc_process_call); |
999b69f89 rxrpc: Kill the c... |
121 |
INIT_LIST_HEAD(&call->link); |
45025bcee rxrpc: Improve ma... |
122 |
INIT_LIST_HEAD(&call->chan_wait_link); |
17926a793 [AF_RXRPC]: Provi... |
123 |
INIT_LIST_HEAD(&call->accept_link); |
248f219cb rxrpc: Rewrite th... |
124 125 |
INIT_LIST_HEAD(&call->recvmsg_link); INIT_LIST_HEAD(&call->sock_link); |
45025bcee rxrpc: Improve ma... |
126 |
init_waitqueue_head(&call->waitq); |
17926a793 [AF_RXRPC]: Provi... |
127 128 129 130 |
spin_lock_init(&call->lock); rwlock_init(&call->state_lock); atomic_set(&call->usage, 1); call->debug_id = atomic_inc_return(&rxrpc_debug_id); |
e754eba68 rxrpc: Provide a ... |
131 |
call->tx_total_len = -1; |
17926a793 [AF_RXRPC]: Provi... |
132 133 |
memset(&call->sock_node, 0xed, sizeof(call->sock_node)); |
248f219cb rxrpc: Rewrite th... |
134 |
/* Leave space in the ring to handle a maxed-out jumbo packet */ |
75e421263 rxrpc: Correctly ... |
135 |
call->rx_winsize = rxrpc_rx_window_size; |
248f219cb rxrpc: Rewrite th... |
136 137 |
call->tx_winsize = 16; call->rx_expect_next = 1; |
57494343c rxrpc: Implement ... |
138 |
|
f7aec129a rxrpc: Cache the ... |
139 |
call->cong_cwnd = 2; |
57494343c rxrpc: Implement ... |
140 |
call->cong_ssthresh = RXRPC_RXTX_BUFF_SIZE - 1; |
17926a793 [AF_RXRPC]: Provi... |
141 |
return call; |
248f219cb rxrpc: Rewrite th... |
142 143 144 145 146 147 |
nomem_2: kfree(call->rxtx_buffer); nomem: kmem_cache_free(rxrpc_call_jar, call); return NULL; |
17926a793 [AF_RXRPC]: Provi... |
148 149 150 |
} /* |
999b69f89 rxrpc: Kill the c... |
151 |
* Allocate a new client call. |
17926a793 [AF_RXRPC]: Provi... |
152 |
*/ |
b89372f23 rxrpc: Provide a ... |
153 154 |
static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx, struct sockaddr_rxrpc *srx, |
aa390bbe2 rxrpc: Kill off t... |
155 |
gfp_t gfp) |
17926a793 [AF_RXRPC]: Provi... |
156 157 |
{ struct rxrpc_call *call; |
57494343c rxrpc: Implement ... |
158 |
ktime_t now; |
17926a793 [AF_RXRPC]: Provi... |
159 160 |
_enter(""); |
b89372f23 rxrpc: Provide a ... |
161 |
call = rxrpc_alloc_call(rx, gfp); |
17926a793 [AF_RXRPC]: Provi... |
162 163 |
if (!call) return ERR_PTR(-ENOMEM); |
999b69f89 rxrpc: Kill the c... |
164 |
call->state = RXRPC_CALL_CLIENT_AWAIT_CONN; |
999b69f89 rxrpc: Kill the c... |
165 |
call->service_id = srx->srx_service; |
71f3ca408 rxrpc: Improve sk... |
166 |
call->tx_phase = true; |
57494343c rxrpc: Implement ... |
167 168 169 |
now = ktime_get_real(); call->acks_latest_ts = now; call->cong_tstamp = now; |
999b69f89 rxrpc: Kill the c... |
170 171 172 173 174 175 |
_leave(" = %p", call); return call; } /* |
248f219cb rxrpc: Rewrite th... |
176 |
* Initiate the call ack/resend/expiry timer. |
999b69f89 rxrpc: Kill the c... |
177 |
*/ |
248f219cb rxrpc: Rewrite th... |
178 |
static void rxrpc_start_call_timer(struct rxrpc_call *call) |
999b69f89 rxrpc: Kill the c... |
179 |
{ |
df0adc788 rxrpc: Keep the c... |
180 |
ktime_t now = ktime_get_real(), expire_at; |
248f219cb rxrpc: Rewrite th... |
181 |
|
df0adc788 rxrpc: Keep the c... |
182 |
expire_at = ktime_add_ms(now, rxrpc_max_call_lifetime); |
248f219cb rxrpc: Rewrite th... |
183 184 |
call->expire_at = expire_at; call->ack_at = expire_at; |
a5af7e1fc rxrpc: Fix loss o... |
185 |
call->ping_at = expire_at; |
248f219cb rxrpc: Rewrite th... |
186 |
call->resend_at = expire_at; |
df0adc788 rxrpc: Keep the c... |
187 188 |
call->timer.expires = jiffies + LONG_MAX / 2; rxrpc_set_timer(call, rxrpc_timer_begin, now); |
17926a793 [AF_RXRPC]: Provi... |
189 190 191 |
} /* |
540b1c48c rxrpc: Fix deadlo... |
192 193 194 |
* Set up a call for the given parameters. * - Called with the socket lock held, which it must release. * - If it returns a call, the call's lock will need releasing by the caller. |
17926a793 [AF_RXRPC]: Provi... |
195 |
*/ |
2341e0775 rxrpc: Simplify c... |
196 |
struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, |
19ffa01c9 rxrpc: Use struct... |
197 |
struct rxrpc_conn_parameters *cp, |
999b69f89 rxrpc: Kill the c... |
198 |
struct sockaddr_rxrpc *srx, |
17926a793 [AF_RXRPC]: Provi... |
199 |
unsigned long user_call_ID, |
e754eba68 rxrpc: Provide a ... |
200 |
s64 tx_total_len, |
17926a793 [AF_RXRPC]: Provi... |
201 |
gfp_t gfp) |
540b1c48c rxrpc: Fix deadlo... |
202 |
__releases(&rx->sk.sk_lock.slock) |
17926a793 [AF_RXRPC]: Provi... |
203 |
{ |
2341e0775 rxrpc: Simplify c... |
204 |
struct rxrpc_call *call, *xcall; |
2baec2c3f rxrpc: Support ne... |
205 |
struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk)); |
2341e0775 rxrpc: Simplify c... |
206 |
struct rb_node *parent, **pp; |
e34d4234b rxrpc: Trace rxrp... |
207 |
const void *here = __builtin_return_address(0); |
999b69f89 rxrpc: Kill the c... |
208 |
int ret; |
17926a793 [AF_RXRPC]: Provi... |
209 |
|
999b69f89 rxrpc: Kill the c... |
210 |
_enter("%p,%lx", rx, user_call_ID); |
17926a793 [AF_RXRPC]: Provi... |
211 |
|
b89372f23 rxrpc: Provide a ... |
212 |
call = rxrpc_alloc_client_call(rx, srx, gfp); |
2341e0775 rxrpc: Simplify c... |
213 |
if (IS_ERR(call)) { |
540b1c48c rxrpc: Fix deadlo... |
214 |
release_sock(&rx->sk); |
2341e0775 rxrpc: Simplify c... |
215 216 |
_leave(" = %ld", PTR_ERR(call)); return call; |
17926a793 [AF_RXRPC]: Provi... |
217 |
} |
e754eba68 rxrpc: Provide a ... |
218 |
call->tx_total_len = tx_total_len; |
a84a46d73 rxrpc: Add some a... |
219 220 |
trace_rxrpc_call(call, rxrpc_call_new_client, atomic_read(&call->usage), here, (const void *)user_call_ID); |
e34d4234b rxrpc: Trace rxrp... |
221 |
|
540b1c48c rxrpc: Fix deadlo... |
222 223 224 225 |
/* We need to protect a partially set up call against the user as we * will be acting outside the socket lock. */ mutex_lock(&call->user_mutex); |
999b69f89 rxrpc: Kill the c... |
226 |
/* Publish the call, even though it is incompletely set up as yet */ |
17926a793 [AF_RXRPC]: Provi... |
227 228 229 230 231 232 |
write_lock(&rx->call_lock); pp = &rx->calls.rb_node; parent = NULL; while (*pp) { parent = *pp; |
2341e0775 rxrpc: Simplify c... |
233 |
xcall = rb_entry(parent, struct rxrpc_call, sock_node); |
17926a793 [AF_RXRPC]: Provi... |
234 |
|
2341e0775 rxrpc: Simplify c... |
235 |
if (user_call_ID < xcall->user_call_ID) |
17926a793 [AF_RXRPC]: Provi... |
236 |
pp = &(*pp)->rb_left; |
2341e0775 rxrpc: Simplify c... |
237 |
else if (user_call_ID > xcall->user_call_ID) |
17926a793 [AF_RXRPC]: Provi... |
238 239 |
pp = &(*pp)->rb_right; else |
357f5ef64 rxrpc: Call rxrpc... |
240 |
goto error_dup_user_ID; |
17926a793 [AF_RXRPC]: Provi... |
241 |
} |
248f219cb rxrpc: Rewrite th... |
242 |
rcu_assign_pointer(call->socket, rx); |
357f5ef64 rxrpc: Call rxrpc... |
243 244 |
call->user_call_ID = user_call_ID; __set_bit(RXRPC_CALL_HAS_USERID, &call->flags); |
fff72429c rxrpc: Improve th... |
245 |
rxrpc_get_call(call, rxrpc_call_got_userid); |
17926a793 [AF_RXRPC]: Provi... |
246 247 |
rb_link_node(&call->sock_node, parent, pp); rb_insert_color(&call->sock_node, &rx->calls); |
248f219cb rxrpc: Rewrite th... |
248 |
list_add(&call->sock_link, &rx->sock_calls); |
17926a793 [AF_RXRPC]: Provi... |
249 |
write_unlock(&rx->call_lock); |
2baec2c3f rxrpc: Support ne... |
250 251 252 |
write_lock(&rxnet->call_lock); list_add_tail(&call->link, &rxnet->calls); write_unlock(&rxnet->call_lock); |
17926a793 [AF_RXRPC]: Provi... |
253 |
|
540b1c48c rxrpc: Fix deadlo... |
254 255 |
/* From this point on, the call is protected by its own lock. */ release_sock(&rx->sk); |
248f219cb rxrpc: Rewrite th... |
256 257 258 259 |
/* Set up or get a connection record and set the protocol parameters, * including channel number and call ID. */ ret = rxrpc_connect_call(call, cp, srx, gfp); |
999b69f89 rxrpc: Kill the c... |
260 261 |
if (ret < 0) goto error; |
a84a46d73 rxrpc: Add some a... |
262 |
trace_rxrpc_call(call, rxrpc_call_connected, atomic_read(&call->usage), |
54fde4234 rxrpc: Fix checke... |
263 |
here, NULL); |
a84a46d73 rxrpc: Add some a... |
264 |
|
248f219cb rxrpc: Rewrite th... |
265 |
rxrpc_start_call_timer(call); |
17926a793 [AF_RXRPC]: Provi... |
266 267 268 269 |
_net("CALL new %d on CONN %d", call->debug_id, call->conn->debug_id); _leave(" = %p [new]", call); return call; |
2341e0775 rxrpc: Simplify c... |
270 271 272 273 274 |
/* We unexpectedly found the user ID in the list after taking * the call_lock. This shouldn't happen unless the user races * with itself and tries to add the same user ID twice at the * same time in different threads. */ |
357f5ef64 rxrpc: Call rxrpc... |
275 |
error_dup_user_ID: |
17926a793 [AF_RXRPC]: Provi... |
276 |
write_unlock(&rx->call_lock); |
540b1c48c rxrpc: Fix deadlo... |
277 |
release_sock(&rx->sk); |
8d94aa381 rxrpc: Calls shou... |
278 |
ret = -EEXIST; |
357f5ef64 rxrpc: Call rxrpc... |
279 280 281 282 |
error: __rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, RX_CALL_DEAD, ret); |
a84a46d73 rxrpc: Add some a... |
283 284 |
trace_rxrpc_call(call, rxrpc_call_error, atomic_read(&call->usage), here, ERR_PTR(ret)); |
357f5ef64 rxrpc: Call rxrpc... |
285 |
rxrpc_release_call(rx, call); |
540b1c48c rxrpc: Fix deadlo... |
286 |
mutex_unlock(&call->user_mutex); |
357f5ef64 rxrpc: Call rxrpc... |
287 288 289 |
rxrpc_put_call(call, rxrpc_call_put); _leave(" = %d", ret); return ERR_PTR(ret); |
17926a793 [AF_RXRPC]: Provi... |
290 291 292 |
} /* |
c038a58cc rxrpc: Allow fail... |
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
* Retry a call to a new address. It is expected that the Tx queue of the call * will contain data previously packaged for an old call. */ int rxrpc_retry_client_call(struct rxrpc_sock *rx, struct rxrpc_call *call, struct rxrpc_conn_parameters *cp, struct sockaddr_rxrpc *srx, gfp_t gfp) { const void *here = __builtin_return_address(0); int ret; /* Set up or get a connection record and set the protocol parameters, * including channel number and call ID. */ ret = rxrpc_connect_call(call, cp, srx, gfp); if (ret < 0) goto error; trace_rxrpc_call(call, rxrpc_call_connected, atomic_read(&call->usage), here, NULL); rxrpc_start_call_timer(call); _net("CALL new %d on CONN %d", call->debug_id, call->conn->debug_id); if (!test_and_set_bit(RXRPC_CALL_EV_RESEND, &call->events)) rxrpc_queue_call(call); _leave(" = 0"); return 0; error: rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, RX_CALL_DEAD, ret); trace_rxrpc_call(call, rxrpc_call_error, atomic_read(&call->usage), here, ERR_PTR(ret)); _leave(" = %d", ret); return ret; } /* |
248f219cb rxrpc: Rewrite th... |
335 336 |
* Set up an incoming call. call->conn points to the connection. * This is called in BH context and isn't allowed to fail. |
17926a793 [AF_RXRPC]: Provi... |
337 |
*/ |
248f219cb rxrpc: Rewrite th... |
338 339 340 |
void rxrpc_incoming_call(struct rxrpc_sock *rx, struct rxrpc_call *call, struct sk_buff *skb) |
17926a793 [AF_RXRPC]: Provi... |
341 |
{ |
248f219cb rxrpc: Rewrite th... |
342 |
struct rxrpc_connection *conn = call->conn; |
42886ffe7 rxrpc: Pass sk_bu... |
343 |
struct rxrpc_skb_priv *sp = rxrpc_skb(skb); |
248f219cb rxrpc: Rewrite th... |
344 |
u32 chan; |
17926a793 [AF_RXRPC]: Provi... |
345 |
|
248f219cb rxrpc: Rewrite th... |
346 |
_enter(",%d", call->conn->debug_id); |
e34d4234b rxrpc: Trace rxrp... |
347 |
|
248f219cb rxrpc: Rewrite th... |
348 349 350 351 352 353 354 |
rcu_assign_pointer(call->socket, rx); call->call_id = sp->hdr.callNumber; call->service_id = sp->hdr.serviceId; call->cid = sp->hdr.cid; call->state = RXRPC_CALL_SERVER_ACCEPTING; if (sp->hdr.securityIndex > 0) call->state = RXRPC_CALL_SERVER_SECURING; |
57494343c rxrpc: Implement ... |
355 |
call->cong_tstamp = skb->tstamp; |
248f219cb rxrpc: Rewrite th... |
356 357 358 359 360 361 |
/* Set the channel for this call. We don't get channel_lock as we're * only defending against the data_ready handler (which we're called * from) and the RESPONSE packet parser (which is only really * interested in call_counter and can cope with a disagreement with the * call pointer). |
a1399f8bb rxrpc: Call chann... |
362 |
*/ |
248f219cb rxrpc: Rewrite th... |
363 364 365 |
chan = sp->hdr.cid & RXRPC_CHANNELMASK; conn->channels[chan].call_counter = call->call_id; conn->channels[chan].call_id = call->call_id; |
a1399f8bb rxrpc: Call chann... |
366 |
rcu_assign_pointer(conn->channels[chan].call, call); |
17926a793 [AF_RXRPC]: Provi... |
367 |
|
85f32278b rxrpc: Replace co... |
368 369 370 |
spin_lock(&conn->params.peer->lock); hlist_add_head(&call->error_link, &conn->params.peer->error_targets); spin_unlock(&conn->params.peer->lock); |
17926a793 [AF_RXRPC]: Provi... |
371 |
|
17926a793 [AF_RXRPC]: Provi... |
372 |
_net("CALL incoming %d on CONN %d", call->debug_id, call->conn->debug_id); |
248f219cb rxrpc: Rewrite th... |
373 374 |
rxrpc_start_call_timer(call); _leave(""); |
17926a793 [AF_RXRPC]: Provi... |
375 376 377 |
} /* |
8d94aa381 rxrpc: Calls shou... |
378 379 380 381 382 383 |
* Queue a call's work processor, getting a ref to pass to the work queue. */ bool rxrpc_queue_call(struct rxrpc_call *call) { const void *here = __builtin_return_address(0); int n = __atomic_add_unless(&call->usage, 1, 0); |
8d94aa381 rxrpc: Calls shou... |
384 385 386 |
if (n == 0) return false; if (rxrpc_queue_work(&call->processor)) |
2ab27215e rxrpc: Remove skb... |
387 |
trace_rxrpc_call(call, rxrpc_call_queued, n + 1, here, NULL); |
8d94aa381 rxrpc: Calls shou... |
388 389 390 391 392 393 394 395 396 397 398 399 |
else rxrpc_put_call(call, rxrpc_call_put_noqueue); return true; } /* * Queue a call's work processor, passing the callers ref to the work queue. */ bool __rxrpc_queue_call(struct rxrpc_call *call) { const void *here = __builtin_return_address(0); int n = atomic_read(&call->usage); |
8d94aa381 rxrpc: Calls shou... |
400 401 |
ASSERTCMP(n, >=, 1); if (rxrpc_queue_work(&call->processor)) |
2ab27215e rxrpc: Remove skb... |
402 |
trace_rxrpc_call(call, rxrpc_call_queued_ref, n, here, NULL); |
8d94aa381 rxrpc: Calls shou... |
403 404 405 406 407 408 |
else rxrpc_put_call(call, rxrpc_call_put_noqueue); return true; } /* |
e34d4234b rxrpc: Trace rxrp... |
409 410 411 412 413 414 415 |
* Note the re-emergence of a call. */ void rxrpc_see_call(struct rxrpc_call *call) { const void *here = __builtin_return_address(0); if (call) { int n = atomic_read(&call->usage); |
e34d4234b rxrpc: Trace rxrp... |
416 |
|
2ab27215e rxrpc: Remove skb... |
417 |
trace_rxrpc_call(call, rxrpc_call_seen, n, here, NULL); |
e34d4234b rxrpc: Trace rxrp... |
418 419 420 421 422 423 |
} } /* * Note the addition of a ref on a call. */ |
fff72429c rxrpc: Improve th... |
424 |
void rxrpc_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op) |
e34d4234b rxrpc: Trace rxrp... |
425 426 427 |
{ const void *here = __builtin_return_address(0); int n = atomic_inc_return(&call->usage); |
e34d4234b rxrpc: Trace rxrp... |
428 |
|
2ab27215e rxrpc: Remove skb... |
429 |
trace_rxrpc_call(call, op, n, here, NULL); |
e34d4234b rxrpc: Trace rxrp... |
430 431 432 |
} /* |
248f219cb rxrpc: Rewrite th... |
433 |
* Detach a call from its owning socket. |
e34d4234b rxrpc: Trace rxrp... |
434 |
*/ |
248f219cb rxrpc: Rewrite th... |
435 |
void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) |
e34d4234b rxrpc: Trace rxrp... |
436 |
{ |
a84a46d73 rxrpc: Add some a... |
437 |
const void *here = __builtin_return_address(0); |
248f219cb rxrpc: Rewrite th... |
438 439 440 |
struct rxrpc_connection *conn = call->conn; bool put = false; int i; |
e34d4234b rxrpc: Trace rxrp... |
441 |
|
248f219cb rxrpc: Rewrite th... |
442 |
_enter("{%d,%d}", call->debug_id, atomic_read(&call->usage)); |
e34d4234b rxrpc: Trace rxrp... |
443 |
|
a84a46d73 rxrpc: Add some a... |
444 445 |
trace_rxrpc_call(call, rxrpc_call_release, atomic_read(&call->usage), here, (const void *)call->flags); |
17926a793 [AF_RXRPC]: Provi... |
446 |
|
a84a46d73 rxrpc: Add some a... |
447 |
ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); |
e34d4234b rxrpc: Trace rxrp... |
448 |
|
17926a793 [AF_RXRPC]: Provi... |
449 450 451 452 |
spin_lock_bh(&call->lock); if (test_and_set_bit(RXRPC_CALL_RELEASED, &call->flags)) BUG(); spin_unlock_bh(&call->lock); |
248f219cb rxrpc: Rewrite th... |
453 |
del_timer_sync(&call->timer); |
17926a793 [AF_RXRPC]: Provi... |
454 |
|
248f219cb rxrpc: Rewrite th... |
455 456 |
/* Make sure we don't get any more notifications */ write_lock_bh(&rx->recvmsg_lock); |
e653cfe49 rxrpc: Release a ... |
457 |
|
248f219cb rxrpc: Rewrite th... |
458 |
if (!list_empty(&call->recvmsg_link)) { |
17926a793 [AF_RXRPC]: Provi... |
459 460 |
_debug("unlinking once-pending call %p { e=%lx f=%lx }", call, call->events, call->flags); |
248f219cb rxrpc: Rewrite th... |
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 |
list_del(&call->recvmsg_link); put = true; } /* list_empty() must return false in rxrpc_notify_socket() */ call->recvmsg_link.next = NULL; call->recvmsg_link.prev = NULL; write_unlock_bh(&rx->recvmsg_lock); if (put) rxrpc_put_call(call, rxrpc_call_put); write_lock(&rx->call_lock); if (test_and_clear_bit(RXRPC_CALL_HAS_USERID, &call->flags)) { |
17926a793 [AF_RXRPC]: Provi... |
476 477 |
rb_erase(&call->sock_node, &rx->calls); memset(&call->sock_node, 0xdd, sizeof(call->sock_node)); |
8d94aa381 rxrpc: Calls shou... |
478 |
rxrpc_put_call(call, rxrpc_call_put_userid); |
17926a793 [AF_RXRPC]: Provi... |
479 |
} |
17926a793 [AF_RXRPC]: Provi... |
480 |
|
248f219cb rxrpc: Rewrite th... |
481 482 483 484 485 486 |
list_del(&call->sock_link); write_unlock(&rx->call_lock); _debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, conn); if (conn) |
8d94aa381 rxrpc: Calls shou... |
487 |
rxrpc_disconnect_call(call); |
e653cfe49 rxrpc: Release a ... |
488 |
|
248f219cb rxrpc: Rewrite th... |
489 |
for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) { |
71f3ca408 rxrpc: Improve sk... |
490 491 492 |
rxrpc_free_skb(call->rxtx_buffer[i], (call->tx_phase ? rxrpc_skb_tx_cleaned : rxrpc_skb_rx_cleaned)); |
248f219cb rxrpc: Rewrite th... |
493 |
call->rxtx_buffer[i] = NULL; |
17926a793 [AF_RXRPC]: Provi... |
494 |
} |
17926a793 [AF_RXRPC]: Provi... |
495 496 497 498 499 |
_leave(""); } /* |
c038a58cc rxrpc: Allow fail... |
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 |
* Prepare a kernel service call for retry. */ int rxrpc_prepare_call_for_retry(struct rxrpc_sock *rx, struct rxrpc_call *call) { const void *here = __builtin_return_address(0); int i; u8 last = 0; _enter("{%d,%d}", call->debug_id, atomic_read(&call->usage)); trace_rxrpc_call(call, rxrpc_call_release, atomic_read(&call->usage), here, (const void *)call->flags); ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); ASSERTCMP(call->completion, !=, RXRPC_CALL_REMOTELY_ABORTED); ASSERTCMP(call->completion, !=, RXRPC_CALL_LOCALLY_ABORTED); ASSERT(list_empty(&call->recvmsg_link)); del_timer_sync(&call->timer); _debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, call->conn); if (call->conn) rxrpc_disconnect_call(call); if (rxrpc_is_service_call(call) || !call->tx_phase || call->tx_hard_ack != 0 || call->rx_hard_ack != 0 || call->rx_top != 0) return -EINVAL; call->state = RXRPC_CALL_UNINITIALISED; call->completion = RXRPC_CALL_SUCCEEDED; call->call_id = 0; call->cid = 0; call->cong_cwnd = 0; call->cong_extra = 0; call->cong_ssthresh = 0; call->cong_mode = 0; call->cong_dup_acks = 0; call->cong_cumul_acks = 0; call->acks_lowest_nak = 0; for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) { last |= call->rxtx_annotations[i]; call->rxtx_annotations[i] &= RXRPC_TX_ANNO_LAST; call->rxtx_annotations[i] |= RXRPC_TX_ANNO_RETRANS; } _leave(" = 0"); return 0; } /* |
17926a793 [AF_RXRPC]: Provi... |
555 556 557 558 559 |
* release all the calls associated with a socket */ void rxrpc_release_calls_on_socket(struct rxrpc_sock *rx) { struct rxrpc_call *call; |
17926a793 [AF_RXRPC]: Provi... |
560 561 |
_enter("%p", rx); |
0360da6db rxrpc: Purge the ... |
562 563 564 565 |
while (!list_empty(&rx->to_be_accepted)) { call = list_entry(rx->to_be_accepted.next, struct rxrpc_call, accept_link); list_del(&call->accept_link); |
3a92789af rxrpc: Use negati... |
566 |
rxrpc_abort_call("SKR", call, 0, RX_CALL_DEAD, -ECONNRESET); |
0360da6db rxrpc: Purge the ... |
567 568 |
rxrpc_put_call(call, rxrpc_call_put); } |
248f219cb rxrpc: Rewrite th... |
569 570 571 572 |
while (!list_empty(&rx->sock_calls)) { call = list_entry(rx->sock_calls.next, struct rxrpc_call, sock_link); rxrpc_get_call(call, rxrpc_call_got); |
3a92789af rxrpc: Use negati... |
573 |
rxrpc_abort_call("SKT", call, 0, RX_CALL_DEAD, -ECONNRESET); |
26cb02aa6 rxrpc: Fix warnin... |
574 |
rxrpc_send_abort_packet(call); |
8d94aa381 rxrpc: Calls shou... |
575 |
rxrpc_release_call(rx, call); |
248f219cb rxrpc: Rewrite th... |
576 |
rxrpc_put_call(call, rxrpc_call_put); |
f36b5e444 rxrpc: When clear... |
577 |
} |
17926a793 [AF_RXRPC]: Provi... |
578 579 580 581 582 583 |
_leave(""); } /* * release a call */ |
fff72429c rxrpc: Improve th... |
584 |
void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace op) |
17926a793 [AF_RXRPC]: Provi... |
585 |
{ |
2baec2c3f rxrpc: Support ne... |
586 |
struct rxrpc_net *rxnet; |
e34d4234b rxrpc: Trace rxrp... |
587 |
const void *here = __builtin_return_address(0); |
2ab27215e rxrpc: Remove skb... |
588 |
int n; |
17926a793 [AF_RXRPC]: Provi... |
589 |
|
e34d4234b rxrpc: Trace rxrp... |
590 |
ASSERT(call != NULL); |
17926a793 [AF_RXRPC]: Provi... |
591 |
|
e34d4234b rxrpc: Trace rxrp... |
592 |
n = atomic_dec_return(&call->usage); |
2ab27215e rxrpc: Remove skb... |
593 |
trace_rxrpc_call(call, op, n, here, NULL); |
e34d4234b rxrpc: Trace rxrp... |
594 595 596 |
ASSERTCMP(n, >=, 0); if (n == 0) { _debug("call %d dead", call->debug_id); |
248f219cb rxrpc: Rewrite th... |
597 |
ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); |
17926a793 [AF_RXRPC]: Provi... |
598 |
|
2baec2c3f rxrpc: Support ne... |
599 600 601 602 603 604 |
if (!list_empty(&call->link)) { rxnet = rxrpc_net(sock_net(&call->socket->sk)); write_lock(&rxnet->call_lock); list_del_init(&call->link); write_unlock(&rxnet->call_lock); } |
e34d4234b rxrpc: Trace rxrp... |
605 |
|
8d94aa381 rxrpc: Calls shou... |
606 |
rxrpc_cleanup_call(call); |
17926a793 [AF_RXRPC]: Provi... |
607 |
} |
17926a793 [AF_RXRPC]: Provi... |
608 609 610 |
} /* |
dee46364c rxrpc: Add RCU de... |
611 612 613 614 615 |
* Final call destruction under RCU. */ static void rxrpc_rcu_destroy_call(struct rcu_head *rcu) { struct rxrpc_call *call = container_of(rcu, struct rxrpc_call, rcu); |
df5d8bf70 rxrpc: Make /proc... |
616 |
rxrpc_put_peer(call->peer); |
248f219cb rxrpc: Rewrite th... |
617 618 |
kfree(call->rxtx_buffer); kfree(call->rxtx_annotations); |
dee46364c rxrpc: Add RCU de... |
619 620 621 622 |
kmem_cache_free(rxrpc_call_jar, call); } /* |
17926a793 [AF_RXRPC]: Provi... |
623 624 |
* clean up a call */ |
00e907127 rxrpc: Preallocat... |
625 |
void rxrpc_cleanup_call(struct rxrpc_call *call) |
17926a793 [AF_RXRPC]: Provi... |
626 |
{ |
248f219cb rxrpc: Rewrite th... |
627 |
int i; |
17926a793 [AF_RXRPC]: Provi... |
628 |
|
248f219cb rxrpc: Rewrite th... |
629 |
_net("DESTROY CALL %d", call->debug_id); |
17926a793 [AF_RXRPC]: Provi... |
630 631 |
memset(&call->sock_node, 0xcd, sizeof(call->sock_node)); |
248f219cb rxrpc: Rewrite th... |
632 |
del_timer_sync(&call->timer); |
17926a793 [AF_RXRPC]: Provi... |
633 |
|
8d94aa381 rxrpc: Calls shou... |
634 |
ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); |
17926a793 [AF_RXRPC]: Provi... |
635 |
ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags)); |
e653cfe49 rxrpc: Release a ... |
636 |
ASSERTCMP(call->conn, ==, NULL); |
17926a793 [AF_RXRPC]: Provi... |
637 |
|
248f219cb rxrpc: Rewrite th... |
638 639 |
/* Clean up the Rx/Tx buffer */ for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) |
71f3ca408 rxrpc: Improve sk... |
640 641 642 |
rxrpc_free_skb(call->rxtx_buffer[i], (call->tx_phase ? rxrpc_skb_tx_cleaned : rxrpc_skb_rx_cleaned)); |
17926a793 [AF_RXRPC]: Provi... |
643 |
|
71f3ca408 rxrpc: Improve sk... |
644 |
rxrpc_free_skb(call->tx_pending, rxrpc_skb_tx_cleaned); |
17926a793 [AF_RXRPC]: Provi... |
645 |
|
dee46364c rxrpc: Add RCU de... |
646 |
call_rcu(&call->rcu, rxrpc_rcu_destroy_call); |
17926a793 [AF_RXRPC]: Provi... |
647 648 649 |
} /* |
2baec2c3f rxrpc: Support ne... |
650 651 652 |
* Make sure that all calls are gone from a network namespace. To reach this * point, any open UDP sockets in that namespace must have been closed, so any * outstanding calls cannot be doing I/O. |
17926a793 [AF_RXRPC]: Provi... |
653 |
*/ |
2baec2c3f rxrpc: Support ne... |
654 |
void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet) |
17926a793 [AF_RXRPC]: Provi... |
655 656 657 658 |
{ struct rxrpc_call *call; _enter(""); |
8d94aa381 rxrpc: Calls shou... |
659 |
|
2baec2c3f rxrpc: Support ne... |
660 |
if (list_empty(&rxnet->calls)) |
8d94aa381 rxrpc: Calls shou... |
661 |
return; |
248f219cb rxrpc: Rewrite th... |
662 |
|
2baec2c3f rxrpc: Support ne... |
663 |
write_lock(&rxnet->call_lock); |
17926a793 [AF_RXRPC]: Provi... |
664 |
|
2baec2c3f rxrpc: Support ne... |
665 666 |
while (!list_empty(&rxnet->calls)) { call = list_entry(rxnet->calls.next, struct rxrpc_call, link); |
17926a793 [AF_RXRPC]: Provi... |
667 |
_debug("Zapping call %p", call); |
e34d4234b rxrpc: Trace rxrp... |
668 |
rxrpc_see_call(call); |
17926a793 [AF_RXRPC]: Provi... |
669 |
list_del_init(&call->link); |
248f219cb rxrpc: Rewrite th... |
670 671 |
pr_err("Call %p still in use (%d,%s,%lx,%lx)! ", |
8d94aa381 rxrpc: Calls shou... |
672 |
call, atomic_read(&call->usage), |
8d94aa381 rxrpc: Calls shou... |
673 674 |
rxrpc_call_states[call->state], call->flags, call->events); |
17926a793 [AF_RXRPC]: Provi... |
675 |
|
2baec2c3f rxrpc: Support ne... |
676 |
write_unlock(&rxnet->call_lock); |
17926a793 [AF_RXRPC]: Provi... |
677 |
cond_resched(); |
2baec2c3f rxrpc: Support ne... |
678 |
write_lock(&rxnet->call_lock); |
17926a793 [AF_RXRPC]: Provi... |
679 |
} |
2baec2c3f rxrpc: Support ne... |
680 |
write_unlock(&rxnet->call_lock); |
17926a793 [AF_RXRPC]: Provi... |
681 |
} |