diff options
-rw-r--r-- | Documentation/networking/rxrpc.txt | 45 | ||||
-rw-r--r-- | include/net/af_rxrpc.h | 16 | ||||
-rw-r--r-- | net/rxrpc/af_rxrpc.c | 70 | ||||
-rw-r--r-- | net/rxrpc/ar-internal.h | 19 | ||||
-rw-r--r-- | net/rxrpc/call_object.c | 97 | ||||
-rw-r--r-- | net/rxrpc/conn_client.c | 5 | ||||
-rw-r--r-- | net/rxrpc/sendmsg.c | 24 |
7 files changed, 24 insertions, 252 deletions
diff --git a/Documentation/networking/rxrpc.txt b/Documentation/networking/rxrpc.txt index c9d052e0cf51..2df5894353d6 100644 --- a/Documentation/networking/rxrpc.txt +++ b/Documentation/networking/rxrpc.txt | |||
@@ -1000,51 +1000,6 @@ The kernel interface functions are as follows: | |||
1000 | size should be set when the call is begun. tx_total_len may not be less | 1000 | size should be set when the call is begun. tx_total_len may not be less |
1001 | than zero. | 1001 | than zero. |
1002 | 1002 | ||
1003 | (*) Check to see the completion state of a call so that the caller can assess | ||
1004 | whether it needs to be retried. | ||
1005 | |||
1006 | enum rxrpc_call_completion { | ||
1007 | RXRPC_CALL_SUCCEEDED, | ||
1008 | RXRPC_CALL_REMOTELY_ABORTED, | ||
1009 | RXRPC_CALL_LOCALLY_ABORTED, | ||
1010 | RXRPC_CALL_LOCAL_ERROR, | ||
1011 | RXRPC_CALL_NETWORK_ERROR, | ||
1012 | }; | ||
1013 | |||
1014 | int rxrpc_kernel_check_call(struct socket *sock, struct rxrpc_call *call, | ||
1015 | enum rxrpc_call_completion *_compl, | ||
1016 | u32 *_abort_code); | ||
1017 | |||
1018 | On return, -EINPROGRESS will be returned if the call is still ongoing; if | ||
1019 | it is finished, *_compl will be set to indicate the manner of completion, | ||
1020 | *_abort_code will be set to any abort code that occurred. 0 will be | ||
1021 | returned on a successful completion, -ECONNABORTED will be returned if the | ||
1022 | client failed due to a remote abort and anything else will return an | ||
1023 | appropriate error code. | ||
1024 | |||
1025 | The caller should look at this information to decide if it's worth | ||
1026 | retrying the call. | ||
1027 | |||
1028 | (*) Retry a client call. | ||
1029 | |||
1030 | int rxrpc_kernel_retry_call(struct socket *sock, | ||
1031 | struct rxrpc_call *call, | ||
1032 | struct sockaddr_rxrpc *srx, | ||
1033 | struct key *key); | ||
1034 | |||
1035 | This attempts to partially reinitialise a call and submit it again while | ||
1036 | reusing the original call's Tx queue to avoid the need to repackage and | ||
1037 | re-encrypt the data to be sent. call indicates the call to retry, srx the | ||
1038 | new address to send it to and key the encryption key to use for signing or | ||
1039 | encrypting the packets. | ||
1040 | |||
1041 | For this to work, the first Tx data packet must still be in the transmit | ||
1042 | queue, and currently this is only permitted for local and network errors | ||
1043 | and the call must not have been aborted. Any partially constructed Tx | ||
1044 | packet is left as is and can continue being filled afterwards. | ||
1045 | |||
1046 | It returns 0 if the call was requeued and an error otherwise. | ||
1047 | |||
1048 | (*) Get call RTT. | 1003 | (*) Get call RTT. |
1049 | 1004 | ||
1050 | u64 rxrpc_kernel_get_rtt(struct socket *sock, struct rxrpc_call *call); | 1005 | u64 rxrpc_kernel_get_rtt(struct socket *sock, struct rxrpc_call *call); |
diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h index 1adefe42c0a6..2bfb87eb98ce 100644 --- a/include/net/af_rxrpc.h +++ b/include/net/af_rxrpc.h | |||
@@ -21,18 +21,6 @@ struct socket; | |||
21 | struct rxrpc_call; | 21 | struct rxrpc_call; |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * Call completion condition (state == RXRPC_CALL_COMPLETE). | ||
25 | */ | ||
26 | enum rxrpc_call_completion { | ||
27 | RXRPC_CALL_SUCCEEDED, /* - Normal termination */ | ||
28 | RXRPC_CALL_REMOTELY_ABORTED, /* - call aborted by peer */ | ||
29 | RXRPC_CALL_LOCALLY_ABORTED, /* - call aborted locally on error or close */ | ||
30 | RXRPC_CALL_LOCAL_ERROR, /* - call failed due to local error */ | ||
31 | RXRPC_CALL_NETWORK_ERROR, /* - call terminated by network error */ | ||
32 | NR__RXRPC_CALL_COMPLETIONS | ||
33 | }; | ||
34 | |||
35 | /* | ||
36 | * Debug ID counter for tracing. | 24 | * Debug ID counter for tracing. |
37 | */ | 25 | */ |
38 | extern atomic_t rxrpc_debug_id; | 26 | extern atomic_t rxrpc_debug_id; |
@@ -73,10 +61,6 @@ int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t, | |||
73 | rxrpc_user_attach_call_t, unsigned long, gfp_t, | 61 | rxrpc_user_attach_call_t, unsigned long, gfp_t, |
74 | unsigned int); | 62 | unsigned int); |
75 | void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64); | 63 | void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64); |
76 | int rxrpc_kernel_retry_call(struct socket *, struct rxrpc_call *, | ||
77 | struct sockaddr_rxrpc *, struct key *); | ||
78 | int rxrpc_kernel_check_call(struct socket *, struct rxrpc_call *, | ||
79 | enum rxrpc_call_completion *, u32 *); | ||
80 | u32 rxrpc_kernel_check_life(const struct socket *, const struct rxrpc_call *); | 64 | u32 rxrpc_kernel_check_life(const struct socket *, const struct rxrpc_call *); |
81 | void rxrpc_kernel_probe_life(struct socket *, struct rxrpc_call *); | 65 | void rxrpc_kernel_probe_life(struct socket *, struct rxrpc_call *); |
82 | u32 rxrpc_kernel_get_epoch(struct socket *, struct rxrpc_call *); | 66 | u32 rxrpc_kernel_get_epoch(struct socket *, struct rxrpc_call *); |
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index a2522f9d71e2..96f2952bbdfd 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
@@ -419,76 +419,6 @@ u32 rxrpc_kernel_get_epoch(struct socket *sock, struct rxrpc_call *call) | |||
419 | EXPORT_SYMBOL(rxrpc_kernel_get_epoch); | 419 | EXPORT_SYMBOL(rxrpc_kernel_get_epoch); |
420 | 420 | ||
421 | /** | 421 | /** |
422 | * rxrpc_kernel_check_call - Check a call's state | ||
423 | * @sock: The socket the call is on | ||
424 | * @call: The call to check | ||
425 | * @_compl: Where to store the completion state | ||
426 | * @_abort_code: Where to store any abort code | ||
427 | * | ||
428 | * Allow a kernel service to query the state of a call and find out the manner | ||
429 | * of its termination if it has completed. Returns -EINPROGRESS if the call is | ||
430 | * still going, 0 if the call finished successfully, -ECONNABORTED if the call | ||
431 | * was aborted and an appropriate error if the call failed in some other way. | ||
432 | */ | ||
433 | int rxrpc_kernel_check_call(struct socket *sock, struct rxrpc_call *call, | ||
434 | enum rxrpc_call_completion *_compl, u32 *_abort_code) | ||
435 | { | ||
436 | if (call->state != RXRPC_CALL_COMPLETE) | ||
437 | return -EINPROGRESS; | ||
438 | smp_rmb(); | ||
439 | *_compl = call->completion; | ||
440 | *_abort_code = call->abort_code; | ||
441 | return call->error; | ||
442 | } | ||
443 | EXPORT_SYMBOL(rxrpc_kernel_check_call); | ||
444 | |||
445 | /** | ||
446 | * rxrpc_kernel_retry_call - Allow a kernel service to retry a call | ||
447 | * @sock: The socket the call is on | ||
448 | * @call: The call to retry | ||
449 | * @srx: The address of the peer to contact | ||
450 | * @key: The security context to use (defaults to socket setting) | ||
451 | * | ||
452 | * Allow a kernel service to try resending a client call that failed due to a | ||
453 | * network error to a new address. The Tx queue is maintained intact, thereby | ||
454 | * relieving the need to re-encrypt any request data that has already been | ||
455 | * buffered. | ||
456 | */ | ||
457 | int rxrpc_kernel_retry_call(struct socket *sock, struct rxrpc_call *call, | ||
458 | struct sockaddr_rxrpc *srx, struct key *key) | ||
459 | { | ||
460 | struct rxrpc_conn_parameters cp; | ||
461 | struct rxrpc_sock *rx = rxrpc_sk(sock->sk); | ||
462 | int ret; | ||
463 | |||
464 | _enter("%d{%d}", call->debug_id, atomic_read(&call->usage)); | ||
465 | |||
466 | if (!key) | ||
467 | key = rx->key; | ||
468 | if (key && !key->payload.data[0]) | ||
469 | key = NULL; /* a no-security key */ | ||
470 | |||
471 | memset(&cp, 0, sizeof(cp)); | ||
472 | cp.local = rx->local; | ||
473 | cp.key = key; | ||
474 | cp.security_level = 0; | ||
475 | cp.exclusive = false; | ||
476 | cp.service_id = srx->srx_service; | ||
477 | |||
478 | mutex_lock(&call->user_mutex); | ||
479 | |||
480 | ret = rxrpc_prepare_call_for_retry(rx, call); | ||
481 | if (ret == 0) | ||
482 | ret = rxrpc_retry_client_call(rx, call, &cp, srx, GFP_KERNEL); | ||
483 | |||
484 | mutex_unlock(&call->user_mutex); | ||
485 | rxrpc_put_peer(cp.peer); | ||
486 | _leave(" = %d", ret); | ||
487 | return ret; | ||
488 | } | ||
489 | EXPORT_SYMBOL(rxrpc_kernel_retry_call); | ||
490 | |||
491 | /** | ||
492 | * rxrpc_kernel_new_call_notification - Get notifications of new calls | 422 | * rxrpc_kernel_new_call_notification - Get notifications of new calls |
493 | * @sock: The socket to intercept received messages on | 423 | * @sock: The socket to intercept received messages on |
494 | * @notify_new_call: Function to be called when new calls appear | 424 | * @notify_new_call: Function to be called when new calls appear |
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index bc628acf4f4f..4b1a534d290a 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h | |||
@@ -476,7 +476,6 @@ enum rxrpc_call_flag { | |||
476 | RXRPC_CALL_EXPOSED, /* The call was exposed to the world */ | 476 | RXRPC_CALL_EXPOSED, /* The call was exposed to the world */ |
477 | RXRPC_CALL_RX_LAST, /* Received the last packet (at rxtx_top) */ | 477 | RXRPC_CALL_RX_LAST, /* Received the last packet (at rxtx_top) */ |
478 | RXRPC_CALL_TX_LAST, /* Last packet in Tx buffer (at rxtx_top) */ | 478 | RXRPC_CALL_TX_LAST, /* Last packet in Tx buffer (at rxtx_top) */ |
479 | RXRPC_CALL_TX_LASTQ, /* Last packet has been queued */ | ||
480 | RXRPC_CALL_SEND_PING, /* A ping will need to be sent */ | 479 | RXRPC_CALL_SEND_PING, /* A ping will need to be sent */ |
481 | RXRPC_CALL_PINGING, /* Ping in process */ | 480 | RXRPC_CALL_PINGING, /* Ping in process */ |
482 | RXRPC_CALL_RETRANS_TIMEOUT, /* Retransmission due to timeout occurred */ | 481 | RXRPC_CALL_RETRANS_TIMEOUT, /* Retransmission due to timeout occurred */ |
@@ -518,6 +517,18 @@ enum rxrpc_call_state { | |||
518 | }; | 517 | }; |
519 | 518 | ||
520 | /* | 519 | /* |
520 | * Call completion condition (state == RXRPC_CALL_COMPLETE). | ||
521 | */ | ||
522 | enum rxrpc_call_completion { | ||
523 | RXRPC_CALL_SUCCEEDED, /* - Normal termination */ | ||
524 | RXRPC_CALL_REMOTELY_ABORTED, /* - call aborted by peer */ | ||
525 | RXRPC_CALL_LOCALLY_ABORTED, /* - call aborted locally on error or close */ | ||
526 | RXRPC_CALL_LOCAL_ERROR, /* - call failed due to local error */ | ||
527 | RXRPC_CALL_NETWORK_ERROR, /* - call terminated by network error */ | ||
528 | NR__RXRPC_CALL_COMPLETIONS | ||
529 | }; | ||
530 | |||
531 | /* | ||
521 | * Call Tx congestion management modes. | 532 | * Call Tx congestion management modes. |
522 | */ | 533 | */ |
523 | enum rxrpc_congest_mode { | 534 | enum rxrpc_congest_mode { |
@@ -761,15 +772,9 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *, | |||
761 | struct sockaddr_rxrpc *, | 772 | struct sockaddr_rxrpc *, |
762 | struct rxrpc_call_params *, gfp_t, | 773 | struct rxrpc_call_params *, gfp_t, |
763 | unsigned int); | 774 | unsigned int); |
764 | int rxrpc_retry_client_call(struct rxrpc_sock *, | ||
765 | struct rxrpc_call *, | ||
766 | struct rxrpc_conn_parameters *, | ||
767 | struct sockaddr_rxrpc *, | ||
768 | gfp_t); | ||
769 | void rxrpc_incoming_call(struct rxrpc_sock *, struct rxrpc_call *, | 775 | void rxrpc_incoming_call(struct rxrpc_sock *, struct rxrpc_call *, |
770 | struct sk_buff *); | 776 | struct sk_buff *); |
771 | void rxrpc_release_call(struct rxrpc_sock *, struct rxrpc_call *); | 777 | void rxrpc_release_call(struct rxrpc_sock *, struct rxrpc_call *); |
772 | int rxrpc_prepare_call_for_retry(struct rxrpc_sock *, struct rxrpc_call *); | ||
773 | void rxrpc_release_calls_on_socket(struct rxrpc_sock *); | 778 | void rxrpc_release_calls_on_socket(struct rxrpc_sock *); |
774 | bool __rxrpc_queue_call(struct rxrpc_call *); | 779 | bool __rxrpc_queue_call(struct rxrpc_call *); |
775 | bool rxrpc_queue_call(struct rxrpc_call *); | 780 | bool rxrpc_queue_call(struct rxrpc_call *); |
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index 8f1a8f85b1f9..8aa2937b069f 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c | |||
@@ -325,48 +325,6 @@ error: | |||
325 | } | 325 | } |
326 | 326 | ||
327 | /* | 327 | /* |
328 | * Retry a call to a new address. It is expected that the Tx queue of the call | ||
329 | * will contain data previously packaged for an old call. | ||
330 | */ | ||
331 | int rxrpc_retry_client_call(struct rxrpc_sock *rx, | ||
332 | struct rxrpc_call *call, | ||
333 | struct rxrpc_conn_parameters *cp, | ||
334 | struct sockaddr_rxrpc *srx, | ||
335 | gfp_t gfp) | ||
336 | { | ||
337 | const void *here = __builtin_return_address(0); | ||
338 | int ret; | ||
339 | |||
340 | /* Set up or get a connection record and set the protocol parameters, | ||
341 | * including channel number and call ID. | ||
342 | */ | ||
343 | ret = rxrpc_connect_call(rx, call, cp, srx, gfp); | ||
344 | if (ret < 0) | ||
345 | goto error; | ||
346 | |||
347 | trace_rxrpc_call(call, rxrpc_call_connected, atomic_read(&call->usage), | ||
348 | here, NULL); | ||
349 | |||
350 | rxrpc_start_call_timer(call); | ||
351 | |||
352 | _net("CALL new %d on CONN %d", call->debug_id, call->conn->debug_id); | ||
353 | |||
354 | if (!test_and_set_bit(RXRPC_CALL_EV_RESEND, &call->events)) | ||
355 | rxrpc_queue_call(call); | ||
356 | |||
357 | _leave(" = 0"); | ||
358 | return 0; | ||
359 | |||
360 | error: | ||
361 | rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, | ||
362 | RX_CALL_DEAD, ret); | ||
363 | trace_rxrpc_call(call, rxrpc_call_error, atomic_read(&call->usage), | ||
364 | here, ERR_PTR(ret)); | ||
365 | _leave(" = %d", ret); | ||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | /* | ||
370 | * Set up an incoming call. call->conn points to the connection. | 328 | * Set up an incoming call. call->conn points to the connection. |
371 | * This is called in BH context and isn't allowed to fail. | 329 | * This is called in BH context and isn't allowed to fail. |
372 | */ | 330 | */ |
@@ -534,61 +492,6 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) | |||
534 | } | 492 | } |
535 | 493 | ||
536 | /* | 494 | /* |
537 | * Prepare a kernel service call for retry. | ||
538 | */ | ||
539 | int rxrpc_prepare_call_for_retry(struct rxrpc_sock *rx, struct rxrpc_call *call) | ||
540 | { | ||
541 | const void *here = __builtin_return_address(0); | ||
542 | int i; | ||
543 | u8 last = 0; | ||
544 | |||
545 | _enter("{%d,%d}", call->debug_id, atomic_read(&call->usage)); | ||
546 | |||
547 | trace_rxrpc_call(call, rxrpc_call_release, atomic_read(&call->usage), | ||
548 | here, (const void *)call->flags); | ||
549 | |||
550 | ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); | ||
551 | ASSERTCMP(call->completion, !=, RXRPC_CALL_REMOTELY_ABORTED); | ||
552 | ASSERTCMP(call->completion, !=, RXRPC_CALL_LOCALLY_ABORTED); | ||
553 | ASSERT(list_empty(&call->recvmsg_link)); | ||
554 | |||
555 | del_timer_sync(&call->timer); | ||
556 | |||
557 | _debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, call->conn); | ||
558 | |||
559 | if (call->conn) | ||
560 | rxrpc_disconnect_call(call); | ||
561 | |||
562 | if (rxrpc_is_service_call(call) || | ||
563 | !call->tx_phase || | ||
564 | call->tx_hard_ack != 0 || | ||
565 | call->rx_hard_ack != 0 || | ||
566 | call->rx_top != 0) | ||
567 | return -EINVAL; | ||
568 | |||
569 | call->state = RXRPC_CALL_UNINITIALISED; | ||
570 | call->completion = RXRPC_CALL_SUCCEEDED; | ||
571 | call->call_id = 0; | ||
572 | call->cid = 0; | ||
573 | call->cong_cwnd = 0; | ||
574 | call->cong_extra = 0; | ||
575 | call->cong_ssthresh = 0; | ||
576 | call->cong_mode = 0; | ||
577 | call->cong_dup_acks = 0; | ||
578 | call->cong_cumul_acks = 0; | ||
579 | call->acks_lowest_nak = 0; | ||
580 | |||
581 | for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) { | ||
582 | last |= call->rxtx_annotations[i]; | ||
583 | call->rxtx_annotations[i] &= RXRPC_TX_ANNO_LAST; | ||
584 | call->rxtx_annotations[i] |= RXRPC_TX_ANNO_RETRANS; | ||
585 | } | ||
586 | |||
587 | _leave(" = 0"); | ||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | /* | ||
592 | * release all the calls associated with a socket | 495 | * release all the calls associated with a socket |
593 | */ | 496 | */ |
594 | void rxrpc_release_calls_on_socket(struct rxrpc_sock *rx) | 497 | void rxrpc_release_calls_on_socket(struct rxrpc_sock *rx) |
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c index 521189f4b666..b2adfa825363 100644 --- a/net/rxrpc/conn_client.c +++ b/net/rxrpc/conn_client.c | |||
@@ -562,10 +562,7 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn, | |||
562 | clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags); | 562 | clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags); |
563 | 563 | ||
564 | write_lock_bh(&call->state_lock); | 564 | write_lock_bh(&call->state_lock); |
565 | if (!test_bit(RXRPC_CALL_TX_LASTQ, &call->flags)) | 565 | call->state = RXRPC_CALL_CLIENT_SEND_REQUEST; |
566 | call->state = RXRPC_CALL_CLIENT_SEND_REQUEST; | ||
567 | else | ||
568 | call->state = RXRPC_CALL_CLIENT_AWAIT_REPLY; | ||
569 | write_unlock_bh(&call->state_lock); | 566 | write_unlock_bh(&call->state_lock); |
570 | 567 | ||
571 | rxrpc_see_call(call); | 568 | rxrpc_see_call(call); |
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index be01f9c5d963..46c9312085b1 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c | |||
@@ -169,10 +169,8 @@ static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call, | |||
169 | 169 | ||
170 | ASSERTCMP(seq, ==, call->tx_top + 1); | 170 | ASSERTCMP(seq, ==, call->tx_top + 1); |
171 | 171 | ||
172 | if (last) { | 172 | if (last) |
173 | annotation |= RXRPC_TX_ANNO_LAST; | 173 | annotation |= RXRPC_TX_ANNO_LAST; |
174 | set_bit(RXRPC_CALL_TX_LASTQ, &call->flags); | ||
175 | } | ||
176 | 174 | ||
177 | /* We have to set the timestamp before queueing as the retransmit | 175 | /* We have to set the timestamp before queueing as the retransmit |
178 | * algorithm can see the packet as soon as we queue it. | 176 | * algorithm can see the packet as soon as we queue it. |
@@ -386,6 +384,11 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
386 | call->tx_total_len -= copy; | 384 | call->tx_total_len -= copy; |
387 | } | 385 | } |
388 | 386 | ||
387 | /* check for the far side aborting the call or a network error | ||
388 | * occurring */ | ||
389 | if (call->state == RXRPC_CALL_COMPLETE) | ||
390 | goto call_terminated; | ||
391 | |||
389 | /* add the packet to the send queue if it's now full */ | 392 | /* add the packet to the send queue if it's now full */ |
390 | if (sp->remain <= 0 || | 393 | if (sp->remain <= 0 || |
391 | (msg_data_left(msg) == 0 && !more)) { | 394 | (msg_data_left(msg) == 0 && !more)) { |
@@ -425,16 +428,6 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
425 | notify_end_tx); | 428 | notify_end_tx); |
426 | skb = NULL; | 429 | skb = NULL; |
427 | } | 430 | } |
428 | |||
429 | /* Check for the far side aborting the call or a network error | ||
430 | * occurring. If this happens, save any packet that was under | ||
431 | * construction so that in the case of a network error, the | ||
432 | * call can be retried or redirected. | ||
433 | */ | ||
434 | if (call->state == RXRPC_CALL_COMPLETE) { | ||
435 | ret = call->error; | ||
436 | goto out; | ||
437 | } | ||
438 | } while (msg_data_left(msg) > 0); | 431 | } while (msg_data_left(msg) > 0); |
439 | 432 | ||
440 | success: | 433 | success: |
@@ -444,6 +437,11 @@ out: | |||
444 | _leave(" = %d", ret); | 437 | _leave(" = %d", ret); |
445 | return ret; | 438 | return ret; |
446 | 439 | ||
440 | call_terminated: | ||
441 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); | ||
442 | _leave(" = %d", call->error); | ||
443 | return call->error; | ||
444 | |||
447 | maybe_error: | 445 | maybe_error: |
448 | if (copied) | 446 | if (copied) |
449 | goto success; | 447 | goto success; |