| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* RxRPC individual remote procedure call handling |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. |
|---|
| 4 | 5 | * 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 | 6 | */ |
|---|
| 11 | 7 | |
|---|
| 12 | 8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 27 | 23 | [RXRPC_CALL_CLIENT_RECV_REPLY] = "ClRcvRpl", |
|---|
| 28 | 24 | [RXRPC_CALL_SERVER_PREALLOC] = "SvPrealc", |
|---|
| 29 | 25 | [RXRPC_CALL_SERVER_SECURING] = "SvSecure", |
|---|
| 30 | | - [RXRPC_CALL_SERVER_ACCEPTING] = "SvAccept", |
|---|
| 31 | 26 | [RXRPC_CALL_SERVER_RECV_REQUEST] = "SvRcvReq", |
|---|
| 32 | 27 | [RXRPC_CALL_SERVER_ACK_REQUEST] = "SvAckReq", |
|---|
| 33 | 28 | [RXRPC_CALL_SERVER_SEND_REPLY] = "SvSndRpl", |
|---|
| .. | .. |
|---|
| 45 | 40 | |
|---|
| 46 | 41 | struct kmem_cache *rxrpc_call_jar; |
|---|
| 47 | 42 | |
|---|
| 43 | +static struct semaphore rxrpc_call_limiter = |
|---|
| 44 | + __SEMAPHORE_INITIALIZER(rxrpc_call_limiter, 1000); |
|---|
| 45 | +static struct semaphore rxrpc_kernel_call_limiter = |
|---|
| 46 | + __SEMAPHORE_INITIALIZER(rxrpc_kernel_call_limiter, 1000); |
|---|
| 47 | + |
|---|
| 48 | 48 | static void rxrpc_call_timer_expired(struct timer_list *t) |
|---|
| 49 | 49 | { |
|---|
| 50 | 50 | struct rxrpc_call *call = from_timer(call, t, timer); |
|---|
| .. | .. |
|---|
| 53 | 53 | |
|---|
| 54 | 54 | if (call->state < RXRPC_CALL_COMPLETE) { |
|---|
| 55 | 55 | trace_rxrpc_timer(call, rxrpc_timer_expired, jiffies); |
|---|
| 56 | | - rxrpc_queue_call(call); |
|---|
| 56 | + __rxrpc_queue_call(call); |
|---|
| 57 | + } else { |
|---|
| 58 | + rxrpc_put_call(call, rxrpc_call_put); |
|---|
| 57 | 59 | } |
|---|
| 60 | +} |
|---|
| 61 | + |
|---|
| 62 | +void rxrpc_reduce_call_timer(struct rxrpc_call *call, |
|---|
| 63 | + unsigned long expire_at, |
|---|
| 64 | + unsigned long now, |
|---|
| 65 | + enum rxrpc_timer_trace why) |
|---|
| 66 | +{ |
|---|
| 67 | + if (rxrpc_try_get_call(call, rxrpc_call_got_timer)) { |
|---|
| 68 | + trace_rxrpc_timer(call, why, now); |
|---|
| 69 | + if (timer_reduce(&call->timer, expire_at)) |
|---|
| 70 | + rxrpc_put_call(call, rxrpc_call_put_notimer); |
|---|
| 71 | + } |
|---|
| 72 | +} |
|---|
| 73 | + |
|---|
| 74 | +void rxrpc_delete_call_timer(struct rxrpc_call *call) |
|---|
| 75 | +{ |
|---|
| 76 | + if (del_timer_sync(&call->timer)) |
|---|
| 77 | + rxrpc_put_call(call, rxrpc_call_put_timer); |
|---|
| 58 | 78 | } |
|---|
| 59 | 79 | |
|---|
| 60 | 80 | static struct lock_class_key rxrpc_call_user_mutex_lock_class_key; |
|---|
| .. | .. |
|---|
| 92 | 112 | found_extant_call: |
|---|
| 93 | 113 | rxrpc_get_call(call, rxrpc_call_got); |
|---|
| 94 | 114 | read_unlock(&rx->call_lock); |
|---|
| 95 | | - _leave(" = %p [%d]", call, atomic_read(&call->usage)); |
|---|
| 115 | + _leave(" = %p [%d]", call, refcount_read(&call->ref)); |
|---|
| 96 | 116 | return call; |
|---|
| 97 | 117 | } |
|---|
| 98 | 118 | |
|---|
| .. | .. |
|---|
| 140 | 160 | spin_lock_init(&call->notify_lock); |
|---|
| 141 | 161 | spin_lock_init(&call->input_lock); |
|---|
| 142 | 162 | rwlock_init(&call->state_lock); |
|---|
| 143 | | - atomic_set(&call->usage, 1); |
|---|
| 163 | + refcount_set(&call->ref, 1); |
|---|
| 144 | 164 | call->debug_id = debug_id; |
|---|
| 145 | 165 | call->tx_total_len = -1; |
|---|
| 146 | 166 | call->next_rx_timo = 20 * HZ; |
|---|
| .. | .. |
|---|
| 157 | 177 | call->cong_ssthresh = RXRPC_RXTX_BUFF_SIZE - 1; |
|---|
| 158 | 178 | |
|---|
| 159 | 179 | call->rxnet = rxnet; |
|---|
| 180 | + call->rtt_avail = RXRPC_CALL_RTT_AVAIL_MASK; |
|---|
| 160 | 181 | atomic_inc(&rxnet->nr_calls); |
|---|
| 161 | 182 | return call; |
|---|
| 162 | 183 | |
|---|
| .. | .. |
|---|
| 213 | 234 | } |
|---|
| 214 | 235 | |
|---|
| 215 | 236 | /* |
|---|
| 237 | + * Wait for a call slot to become available. |
|---|
| 238 | + */ |
|---|
| 239 | +static struct semaphore *rxrpc_get_call_slot(struct rxrpc_call_params *p, gfp_t gfp) |
|---|
| 240 | +{ |
|---|
| 241 | + struct semaphore *limiter = &rxrpc_call_limiter; |
|---|
| 242 | + |
|---|
| 243 | + if (p->kernel) |
|---|
| 244 | + limiter = &rxrpc_kernel_call_limiter; |
|---|
| 245 | + if (p->interruptibility == RXRPC_UNINTERRUPTIBLE) { |
|---|
| 246 | + down(limiter); |
|---|
| 247 | + return limiter; |
|---|
| 248 | + } |
|---|
| 249 | + return down_interruptible(limiter) < 0 ? NULL : limiter; |
|---|
| 250 | +} |
|---|
| 251 | + |
|---|
| 252 | +/* |
|---|
| 253 | + * Release a call slot. |
|---|
| 254 | + */ |
|---|
| 255 | +static void rxrpc_put_call_slot(struct rxrpc_call *call) |
|---|
| 256 | +{ |
|---|
| 257 | + struct semaphore *limiter = &rxrpc_call_limiter; |
|---|
| 258 | + |
|---|
| 259 | + if (test_bit(RXRPC_CALL_KERNEL, &call->flags)) |
|---|
| 260 | + limiter = &rxrpc_kernel_call_limiter; |
|---|
| 261 | + up(limiter); |
|---|
| 262 | +} |
|---|
| 263 | + |
|---|
| 264 | +/* |
|---|
| 216 | 265 | * Set up a call for the given parameters. |
|---|
| 217 | 266 | * - Called with the socket lock held, which it must release. |
|---|
| 218 | 267 | * - If it returns a call, the call's lock will need releasing by the caller. |
|---|
| .. | .. |
|---|
| 228 | 277 | { |
|---|
| 229 | 278 | struct rxrpc_call *call, *xcall; |
|---|
| 230 | 279 | struct rxrpc_net *rxnet; |
|---|
| 280 | + struct semaphore *limiter; |
|---|
| 231 | 281 | struct rb_node *parent, **pp; |
|---|
| 232 | 282 | const void *here = __builtin_return_address(0); |
|---|
| 233 | 283 | int ret; |
|---|
| 234 | 284 | |
|---|
| 235 | 285 | _enter("%p,%lx", rx, p->user_call_ID); |
|---|
| 236 | 286 | |
|---|
| 287 | + limiter = rxrpc_get_call_slot(p, gfp); |
|---|
| 288 | + if (!limiter) { |
|---|
| 289 | + release_sock(&rx->sk); |
|---|
| 290 | + return ERR_PTR(-ERESTARTSYS); |
|---|
| 291 | + } |
|---|
| 292 | + |
|---|
| 237 | 293 | call = rxrpc_alloc_client_call(rx, srx, gfp, debug_id); |
|---|
| 238 | 294 | if (IS_ERR(call)) { |
|---|
| 239 | 295 | release_sock(&rx->sk); |
|---|
| 296 | + up(limiter); |
|---|
| 240 | 297 | _leave(" = %ld", PTR_ERR(call)); |
|---|
| 241 | 298 | return call; |
|---|
| 242 | 299 | } |
|---|
| 243 | 300 | |
|---|
| 301 | + call->interruptibility = p->interruptibility; |
|---|
| 244 | 302 | call->tx_total_len = p->tx_total_len; |
|---|
| 245 | | - trace_rxrpc_call(call, rxrpc_call_new_client, atomic_read(&call->usage), |
|---|
| 303 | + trace_rxrpc_call(call->debug_id, rxrpc_call_new_client, |
|---|
| 304 | + refcount_read(&call->ref), |
|---|
| 246 | 305 | here, (const void *)p->user_call_ID); |
|---|
| 306 | + if (p->kernel) |
|---|
| 307 | + __set_bit(RXRPC_CALL_KERNEL, &call->flags); |
|---|
| 247 | 308 | |
|---|
| 248 | 309 | /* We need to protect a partially set up call against the user as we |
|---|
| 249 | 310 | * will be acting outside the socket lock. |
|---|
| .. | .. |
|---|
| 292 | 353 | if (ret < 0) |
|---|
| 293 | 354 | goto error_attached_to_socket; |
|---|
| 294 | 355 | |
|---|
| 295 | | - trace_rxrpc_call(call, rxrpc_call_connected, atomic_read(&call->usage), |
|---|
| 296 | | - here, NULL); |
|---|
| 356 | + trace_rxrpc_call(call->debug_id, rxrpc_call_connected, |
|---|
| 357 | + refcount_read(&call->ref), here, NULL); |
|---|
| 297 | 358 | |
|---|
| 298 | 359 | rxrpc_start_call_timer(call); |
|---|
| 299 | 360 | |
|---|
| .. | .. |
|---|
| 312 | 373 | release_sock(&rx->sk); |
|---|
| 313 | 374 | __rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, |
|---|
| 314 | 375 | RX_CALL_DEAD, -EEXIST); |
|---|
| 315 | | - trace_rxrpc_call(call, rxrpc_call_error, atomic_read(&call->usage), |
|---|
| 316 | | - here, ERR_PTR(-EEXIST)); |
|---|
| 376 | + trace_rxrpc_call(call->debug_id, rxrpc_call_error, |
|---|
| 377 | + refcount_read(&call->ref), here, ERR_PTR(-EEXIST)); |
|---|
| 317 | 378 | rxrpc_release_call(rx, call); |
|---|
| 318 | 379 | mutex_unlock(&call->user_mutex); |
|---|
| 319 | 380 | rxrpc_put_call(call, rxrpc_call_put); |
|---|
| .. | .. |
|---|
| 326 | 387 | * leave the error to recvmsg() to deal with. |
|---|
| 327 | 388 | */ |
|---|
| 328 | 389 | error_attached_to_socket: |
|---|
| 329 | | - trace_rxrpc_call(call, rxrpc_call_error, atomic_read(&call->usage), |
|---|
| 330 | | - here, ERR_PTR(ret)); |
|---|
| 390 | + trace_rxrpc_call(call->debug_id, rxrpc_call_error, |
|---|
| 391 | + refcount_read(&call->ref), here, ERR_PTR(ret)); |
|---|
| 331 | 392 | set_bit(RXRPC_CALL_DISCONNECTED, &call->flags); |
|---|
| 332 | 393 | __rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, |
|---|
| 333 | 394 | RX_CALL_DEAD, ret); |
|---|
| 334 | 395 | _leave(" = c=%08x [err]", call->debug_id); |
|---|
| 335 | 396 | return call; |
|---|
| 336 | | -} |
|---|
| 337 | | - |
|---|
| 338 | | -/* |
|---|
| 339 | | - * Retry a call to a new address. It is expected that the Tx queue of the call |
|---|
| 340 | | - * will contain data previously packaged for an old call. |
|---|
| 341 | | - */ |
|---|
| 342 | | -int rxrpc_retry_client_call(struct rxrpc_sock *rx, |
|---|
| 343 | | - struct rxrpc_call *call, |
|---|
| 344 | | - struct rxrpc_conn_parameters *cp, |
|---|
| 345 | | - struct sockaddr_rxrpc *srx, |
|---|
| 346 | | - gfp_t gfp) |
|---|
| 347 | | -{ |
|---|
| 348 | | - const void *here = __builtin_return_address(0); |
|---|
| 349 | | - int ret; |
|---|
| 350 | | - |
|---|
| 351 | | - /* Set up or get a connection record and set the protocol parameters, |
|---|
| 352 | | - * including channel number and call ID. |
|---|
| 353 | | - */ |
|---|
| 354 | | - ret = rxrpc_connect_call(rx, call, cp, srx, gfp); |
|---|
| 355 | | - if (ret < 0) |
|---|
| 356 | | - goto error; |
|---|
| 357 | | - |
|---|
| 358 | | - trace_rxrpc_call(call, rxrpc_call_connected, atomic_read(&call->usage), |
|---|
| 359 | | - here, NULL); |
|---|
| 360 | | - |
|---|
| 361 | | - rxrpc_start_call_timer(call); |
|---|
| 362 | | - |
|---|
| 363 | | - _net("CALL new %d on CONN %d", call->debug_id, call->conn->debug_id); |
|---|
| 364 | | - |
|---|
| 365 | | - if (!test_and_set_bit(RXRPC_CALL_EV_RESEND, &call->events)) |
|---|
| 366 | | - rxrpc_queue_call(call); |
|---|
| 367 | | - |
|---|
| 368 | | - _leave(" = 0"); |
|---|
| 369 | | - return 0; |
|---|
| 370 | | - |
|---|
| 371 | | -error: |
|---|
| 372 | | - rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, |
|---|
| 373 | | - RX_CALL_DEAD, ret); |
|---|
| 374 | | - trace_rxrpc_call(call, rxrpc_call_error, atomic_read(&call->usage), |
|---|
| 375 | | - here, ERR_PTR(ret)); |
|---|
| 376 | | - _leave(" = %d", ret); |
|---|
| 377 | | - return ret; |
|---|
| 378 | 397 | } |
|---|
| 379 | 398 | |
|---|
| 380 | 399 | /* |
|---|
| .. | .. |
|---|
| 395 | 414 | call->call_id = sp->hdr.callNumber; |
|---|
| 396 | 415 | call->service_id = sp->hdr.serviceId; |
|---|
| 397 | 416 | call->cid = sp->hdr.cid; |
|---|
| 398 | | - call->state = RXRPC_CALL_SERVER_ACCEPTING; |
|---|
| 399 | | - if (sp->hdr.securityIndex > 0) |
|---|
| 400 | | - call->state = RXRPC_CALL_SERVER_SECURING; |
|---|
| 417 | + call->state = RXRPC_CALL_SERVER_SECURING; |
|---|
| 401 | 418 | call->cong_tstamp = skb->tstamp; |
|---|
| 402 | 419 | |
|---|
| 403 | 420 | /* Set the channel for this call. We don't get channel_lock as we're |
|---|
| .. | .. |
|---|
| 427 | 444 | bool rxrpc_queue_call(struct rxrpc_call *call) |
|---|
| 428 | 445 | { |
|---|
| 429 | 446 | const void *here = __builtin_return_address(0); |
|---|
| 430 | | - int n = atomic_fetch_add_unless(&call->usage, 1, 0); |
|---|
| 431 | | - if (n == 0) |
|---|
| 447 | + int n; |
|---|
| 448 | + |
|---|
| 449 | + if (!__refcount_inc_not_zero(&call->ref, &n)) |
|---|
| 432 | 450 | return false; |
|---|
| 433 | 451 | if (rxrpc_queue_work(&call->processor)) |
|---|
| 434 | | - trace_rxrpc_call(call, rxrpc_call_queued, n + 1, here, NULL); |
|---|
| 452 | + trace_rxrpc_call(call->debug_id, rxrpc_call_queued, n + 1, |
|---|
| 453 | + here, NULL); |
|---|
| 435 | 454 | else |
|---|
| 436 | 455 | rxrpc_put_call(call, rxrpc_call_put_noqueue); |
|---|
| 437 | 456 | return true; |
|---|
| .. | .. |
|---|
| 443 | 462 | bool __rxrpc_queue_call(struct rxrpc_call *call) |
|---|
| 444 | 463 | { |
|---|
| 445 | 464 | const void *here = __builtin_return_address(0); |
|---|
| 446 | | - int n = atomic_read(&call->usage); |
|---|
| 465 | + int n = refcount_read(&call->ref); |
|---|
| 447 | 466 | ASSERTCMP(n, >=, 1); |
|---|
| 448 | 467 | if (rxrpc_queue_work(&call->processor)) |
|---|
| 449 | | - trace_rxrpc_call(call, rxrpc_call_queued_ref, n, here, NULL); |
|---|
| 468 | + trace_rxrpc_call(call->debug_id, rxrpc_call_queued_ref, n, |
|---|
| 469 | + here, NULL); |
|---|
| 450 | 470 | else |
|---|
| 451 | 471 | rxrpc_put_call(call, rxrpc_call_put_noqueue); |
|---|
| 452 | 472 | return true; |
|---|
| .. | .. |
|---|
| 459 | 479 | { |
|---|
| 460 | 480 | const void *here = __builtin_return_address(0); |
|---|
| 461 | 481 | if (call) { |
|---|
| 462 | | - int n = atomic_read(&call->usage); |
|---|
| 482 | + int n = refcount_read(&call->ref); |
|---|
| 463 | 483 | |
|---|
| 464 | | - trace_rxrpc_call(call, rxrpc_call_seen, n, here, NULL); |
|---|
| 484 | + trace_rxrpc_call(call->debug_id, rxrpc_call_seen, n, |
|---|
| 485 | + here, NULL); |
|---|
| 465 | 486 | } |
|---|
| 487 | +} |
|---|
| 488 | + |
|---|
| 489 | +bool rxrpc_try_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op) |
|---|
| 490 | +{ |
|---|
| 491 | + const void *here = __builtin_return_address(0); |
|---|
| 492 | + int n; |
|---|
| 493 | + |
|---|
| 494 | + if (!__refcount_inc_not_zero(&call->ref, &n)) |
|---|
| 495 | + return false; |
|---|
| 496 | + trace_rxrpc_call(call->debug_id, op, n + 1, here, NULL); |
|---|
| 497 | + return true; |
|---|
| 466 | 498 | } |
|---|
| 467 | 499 | |
|---|
| 468 | 500 | /* |
|---|
| .. | .. |
|---|
| 471 | 503 | void rxrpc_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op) |
|---|
| 472 | 504 | { |
|---|
| 473 | 505 | const void *here = __builtin_return_address(0); |
|---|
| 474 | | - int n = atomic_inc_return(&call->usage); |
|---|
| 506 | + int n; |
|---|
| 475 | 507 | |
|---|
| 476 | | - trace_rxrpc_call(call, op, n, here, NULL); |
|---|
| 508 | + __refcount_inc(&call->ref, &n); |
|---|
| 509 | + trace_rxrpc_call(call->debug_id, op, n + 1, here, NULL); |
|---|
| 510 | +} |
|---|
| 511 | + |
|---|
| 512 | +/* |
|---|
| 513 | + * Clean up the RxTx skb ring. |
|---|
| 514 | + */ |
|---|
| 515 | +static void rxrpc_cleanup_ring(struct rxrpc_call *call) |
|---|
| 516 | +{ |
|---|
| 517 | + int i; |
|---|
| 518 | + |
|---|
| 519 | + for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) { |
|---|
| 520 | + rxrpc_free_skb(call->rxtx_buffer[i], rxrpc_skb_cleaned); |
|---|
| 521 | + call->rxtx_buffer[i] = NULL; |
|---|
| 522 | + } |
|---|
| 477 | 523 | } |
|---|
| 478 | 524 | |
|---|
| 479 | 525 | /* |
|---|
| .. | .. |
|---|
| 484 | 530 | const void *here = __builtin_return_address(0); |
|---|
| 485 | 531 | struct rxrpc_connection *conn = call->conn; |
|---|
| 486 | 532 | bool put = false; |
|---|
| 487 | | - int i; |
|---|
| 488 | 533 | |
|---|
| 489 | | - _enter("{%d,%d}", call->debug_id, atomic_read(&call->usage)); |
|---|
| 534 | + _enter("{%d,%d}", call->debug_id, refcount_read(&call->ref)); |
|---|
| 490 | 535 | |
|---|
| 491 | | - trace_rxrpc_call(call, rxrpc_call_release, atomic_read(&call->usage), |
|---|
| 536 | + trace_rxrpc_call(call->debug_id, rxrpc_call_release, |
|---|
| 537 | + refcount_read(&call->ref), |
|---|
| 492 | 538 | here, (const void *)call->flags); |
|---|
| 493 | 539 | |
|---|
| 494 | 540 | ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); |
|---|
| .. | .. |
|---|
| 498 | 544 | BUG(); |
|---|
| 499 | 545 | spin_unlock_bh(&call->lock); |
|---|
| 500 | 546 | |
|---|
| 501 | | - del_timer_sync(&call->timer); |
|---|
| 547 | + rxrpc_put_call_slot(call); |
|---|
| 548 | + rxrpc_delete_call_timer(call); |
|---|
| 502 | 549 | |
|---|
| 503 | 550 | /* Make sure we don't get any more notifications */ |
|---|
| 504 | 551 | write_lock_bh(&rx->recvmsg_lock); |
|---|
| .. | .. |
|---|
| 533 | 580 | |
|---|
| 534 | 581 | if (conn && !test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) |
|---|
| 535 | 582 | rxrpc_disconnect_call(call); |
|---|
| 536 | | - |
|---|
| 537 | | - for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) { |
|---|
| 538 | | - rxrpc_free_skb(call->rxtx_buffer[i], |
|---|
| 539 | | - (call->tx_phase ? rxrpc_skb_tx_cleaned : |
|---|
| 540 | | - rxrpc_skb_rx_cleaned)); |
|---|
| 541 | | - call->rxtx_buffer[i] = NULL; |
|---|
| 542 | | - } |
|---|
| 543 | | - |
|---|
| 583 | + if (call->security) |
|---|
| 584 | + call->security->free_call_crypto(call); |
|---|
| 544 | 585 | _leave(""); |
|---|
| 545 | | -} |
|---|
| 546 | | - |
|---|
| 547 | | -/* |
|---|
| 548 | | - * Prepare a kernel service call for retry. |
|---|
| 549 | | - */ |
|---|
| 550 | | -int rxrpc_prepare_call_for_retry(struct rxrpc_sock *rx, struct rxrpc_call *call) |
|---|
| 551 | | -{ |
|---|
| 552 | | - const void *here = __builtin_return_address(0); |
|---|
| 553 | | - int i; |
|---|
| 554 | | - u8 last = 0; |
|---|
| 555 | | - |
|---|
| 556 | | - _enter("{%d,%d}", call->debug_id, atomic_read(&call->usage)); |
|---|
| 557 | | - |
|---|
| 558 | | - trace_rxrpc_call(call, rxrpc_call_release, atomic_read(&call->usage), |
|---|
| 559 | | - here, (const void *)call->flags); |
|---|
| 560 | | - |
|---|
| 561 | | - ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); |
|---|
| 562 | | - ASSERTCMP(call->completion, !=, RXRPC_CALL_REMOTELY_ABORTED); |
|---|
| 563 | | - ASSERTCMP(call->completion, !=, RXRPC_CALL_LOCALLY_ABORTED); |
|---|
| 564 | | - ASSERT(list_empty(&call->recvmsg_link)); |
|---|
| 565 | | - |
|---|
| 566 | | - del_timer_sync(&call->timer); |
|---|
| 567 | | - |
|---|
| 568 | | - _debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, call->conn); |
|---|
| 569 | | - |
|---|
| 570 | | - if (call->conn) |
|---|
| 571 | | - rxrpc_disconnect_call(call); |
|---|
| 572 | | - |
|---|
| 573 | | - if (rxrpc_is_service_call(call) || |
|---|
| 574 | | - !call->tx_phase || |
|---|
| 575 | | - call->tx_hard_ack != 0 || |
|---|
| 576 | | - call->rx_hard_ack != 0 || |
|---|
| 577 | | - call->rx_top != 0) |
|---|
| 578 | | - return -EINVAL; |
|---|
| 579 | | - |
|---|
| 580 | | - call->state = RXRPC_CALL_UNINITIALISED; |
|---|
| 581 | | - call->completion = RXRPC_CALL_SUCCEEDED; |
|---|
| 582 | | - call->call_id = 0; |
|---|
| 583 | | - call->cid = 0; |
|---|
| 584 | | - call->cong_cwnd = 0; |
|---|
| 585 | | - call->cong_extra = 0; |
|---|
| 586 | | - call->cong_ssthresh = 0; |
|---|
| 587 | | - call->cong_mode = 0; |
|---|
| 588 | | - call->cong_dup_acks = 0; |
|---|
| 589 | | - call->cong_cumul_acks = 0; |
|---|
| 590 | | - call->acks_lowest_nak = 0; |
|---|
| 591 | | - |
|---|
| 592 | | - for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) { |
|---|
| 593 | | - last |= call->rxtx_annotations[i]; |
|---|
| 594 | | - call->rxtx_annotations[i] &= RXRPC_TX_ANNO_LAST; |
|---|
| 595 | | - call->rxtx_annotations[i] |= RXRPC_TX_ANNO_RETRANS; |
|---|
| 596 | | - } |
|---|
| 597 | | - |
|---|
| 598 | | - _leave(" = 0"); |
|---|
| 599 | | - return 0; |
|---|
| 600 | 586 | } |
|---|
| 601 | 587 | |
|---|
| 602 | 588 | /* |
|---|
| .. | .. |
|---|
| 636 | 622 | { |
|---|
| 637 | 623 | struct rxrpc_net *rxnet = call->rxnet; |
|---|
| 638 | 624 | const void *here = __builtin_return_address(0); |
|---|
| 625 | + unsigned int debug_id = call->debug_id; |
|---|
| 626 | + bool dead; |
|---|
| 639 | 627 | int n; |
|---|
| 640 | 628 | |
|---|
| 641 | 629 | ASSERT(call != NULL); |
|---|
| 642 | 630 | |
|---|
| 643 | | - n = atomic_dec_return(&call->usage); |
|---|
| 644 | | - trace_rxrpc_call(call, op, n, here, NULL); |
|---|
| 645 | | - ASSERTCMP(n, >=, 0); |
|---|
| 646 | | - if (n == 0) { |
|---|
| 631 | + dead = __refcount_dec_and_test(&call->ref, &n); |
|---|
| 632 | + trace_rxrpc_call(debug_id, op, n, here, NULL); |
|---|
| 633 | + if (dead) { |
|---|
| 647 | 634 | _debug("call %d dead", call->debug_id); |
|---|
| 648 | 635 | ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); |
|---|
| 649 | 636 | |
|---|
| .. | .. |
|---|
| 664 | 651 | { |
|---|
| 665 | 652 | struct rxrpc_call *call = container_of(work, struct rxrpc_call, processor); |
|---|
| 666 | 653 | struct rxrpc_net *rxnet = call->rxnet; |
|---|
| 654 | + |
|---|
| 655 | + rxrpc_delete_call_timer(call); |
|---|
| 667 | 656 | |
|---|
| 668 | 657 | rxrpc_put_connection(call->conn); |
|---|
| 669 | 658 | rxrpc_put_peer(call->peer); |
|---|
| .. | .. |
|---|
| 695 | 684 | */ |
|---|
| 696 | 685 | void rxrpc_cleanup_call(struct rxrpc_call *call) |
|---|
| 697 | 686 | { |
|---|
| 698 | | - int i; |
|---|
| 699 | | - |
|---|
| 700 | 687 | _net("DESTROY CALL %d", call->debug_id); |
|---|
| 701 | 688 | |
|---|
| 702 | 689 | memset(&call->sock_node, 0xcd, sizeof(call->sock_node)); |
|---|
| 703 | 690 | |
|---|
| 704 | | - del_timer_sync(&call->timer); |
|---|
| 705 | | - |
|---|
| 706 | 691 | ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); |
|---|
| 707 | 692 | ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags)); |
|---|
| 708 | 693 | |
|---|
| 709 | | - /* Clean up the Rx/Tx buffer */ |
|---|
| 710 | | - for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) |
|---|
| 711 | | - rxrpc_free_skb(call->rxtx_buffer[i], |
|---|
| 712 | | - (call->tx_phase ? rxrpc_skb_tx_cleaned : |
|---|
| 713 | | - rxrpc_skb_rx_cleaned)); |
|---|
| 714 | | - |
|---|
| 715 | | - rxrpc_free_skb(call->tx_pending, rxrpc_skb_tx_cleaned); |
|---|
| 694 | + rxrpc_cleanup_ring(call); |
|---|
| 695 | + rxrpc_free_skb(call->tx_pending, rxrpc_skb_cleaned); |
|---|
| 716 | 696 | |
|---|
| 717 | 697 | call_rcu(&call->rcu, rxrpc_rcu_destroy_call); |
|---|
| 718 | 698 | } |
|---|
| .. | .. |
|---|
| 740 | 720 | list_del_init(&call->link); |
|---|
| 741 | 721 | |
|---|
| 742 | 722 | pr_err("Call %p still in use (%d,%s,%lx,%lx)!\n", |
|---|
| 743 | | - call, atomic_read(&call->usage), |
|---|
| 723 | + call, refcount_read(&call->ref), |
|---|
| 744 | 724 | rxrpc_call_states[call->state], |
|---|
| 745 | 725 | call->flags, call->events); |
|---|
| 746 | 726 | |
|---|