diff options
Diffstat (limited to 'net/rxrpc/sendmsg.c')
| -rw-r--r-- | net/rxrpc/sendmsg.c | 126 |
1 files changed, 78 insertions, 48 deletions
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index 7d2595582c09..09f2a3e05221 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c | |||
| @@ -21,22 +21,6 @@ | |||
| 21 | #include <net/af_rxrpc.h> | 21 | #include <net/af_rxrpc.h> |
| 22 | #include "ar-internal.h" | 22 | #include "ar-internal.h" |
| 23 | 23 | ||
| 24 | enum rxrpc_command { | ||
| 25 | RXRPC_CMD_SEND_DATA, /* send data message */ | ||
| 26 | RXRPC_CMD_SEND_ABORT, /* request abort generation */ | ||
| 27 | RXRPC_CMD_ACCEPT, /* [server] accept incoming call */ | ||
| 28 | RXRPC_CMD_REJECT_BUSY, /* [server] reject a call as busy */ | ||
| 29 | }; | ||
| 30 | |||
| 31 | struct rxrpc_send_params { | ||
| 32 | s64 tx_total_len; /* Total Tx data length (if send data) */ | ||
| 33 | unsigned long user_call_ID; /* User's call ID */ | ||
| 34 | u32 abort_code; /* Abort code to Tx (if abort) */ | ||
| 35 | enum rxrpc_command command : 8; /* The command to implement */ | ||
| 36 | bool exclusive; /* Shared or exclusive call */ | ||
| 37 | bool upgrade; /* If the connection is upgradeable */ | ||
| 38 | }; | ||
| 39 | |||
| 40 | /* | 24 | /* |
| 41 | * Wait for space to appear in the Tx queue or a signal to occur. | 25 | * Wait for space to appear in the Tx queue or a signal to occur. |
| 42 | */ | 26 | */ |
| @@ -174,6 +158,7 @@ static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call, | |||
| 174 | rxrpc_notify_end_tx_t notify_end_tx) | 158 | rxrpc_notify_end_tx_t notify_end_tx) |
| 175 | { | 159 | { |
| 176 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | 160 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); |
| 161 | unsigned long now; | ||
| 177 | rxrpc_seq_t seq = sp->hdr.seq; | 162 | rxrpc_seq_t seq = sp->hdr.seq; |
| 178 | int ret, ix; | 163 | int ret, ix; |
| 179 | u8 annotation = RXRPC_TX_ANNO_UNACK; | 164 | u8 annotation = RXRPC_TX_ANNO_UNACK; |
| @@ -213,11 +198,11 @@ static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call, | |||
| 213 | break; | 198 | break; |
| 214 | case RXRPC_CALL_SERVER_ACK_REQUEST: | 199 | case RXRPC_CALL_SERVER_ACK_REQUEST: |
| 215 | call->state = RXRPC_CALL_SERVER_SEND_REPLY; | 200 | call->state = RXRPC_CALL_SERVER_SEND_REPLY; |
| 216 | call->ack_at = call->expire_at; | 201 | now = jiffies; |
| 202 | WRITE_ONCE(call->ack_at, now + MAX_JIFFY_OFFSET); | ||
| 217 | if (call->ackr_reason == RXRPC_ACK_DELAY) | 203 | if (call->ackr_reason == RXRPC_ACK_DELAY) |
| 218 | call->ackr_reason = 0; | 204 | call->ackr_reason = 0; |
| 219 | __rxrpc_set_timer(call, rxrpc_timer_init_for_send_reply, | 205 | trace_rxrpc_timer(call, rxrpc_timer_init_for_send_reply, now); |
| 220 | ktime_get_real()); | ||
| 221 | if (!last) | 206 | if (!last) |
| 222 | break; | 207 | break; |
| 223 | /* Fall through */ | 208 | /* Fall through */ |
| @@ -239,14 +224,19 @@ static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call, | |||
| 239 | _debug("need instant resend %d", ret); | 224 | _debug("need instant resend %d", ret); |
| 240 | rxrpc_instant_resend(call, ix); | 225 | rxrpc_instant_resend(call, ix); |
| 241 | } else { | 226 | } else { |
| 242 | ktime_t now = ktime_get_real(), resend_at; | 227 | unsigned long now = jiffies, resend_at; |
| 243 | 228 | ||
| 244 | resend_at = ktime_add_ms(now, rxrpc_resend_timeout); | 229 | if (call->peer->rtt_usage > 1) |
| 245 | 230 | resend_at = nsecs_to_jiffies(call->peer->rtt * 3 / 2); | |
| 246 | if (ktime_before(resend_at, call->resend_at)) { | 231 | else |
| 247 | call->resend_at = resend_at; | 232 | resend_at = rxrpc_resend_timeout; |
| 248 | rxrpc_set_timer(call, rxrpc_timer_set_for_send, now); | 233 | if (resend_at < 1) |
| 249 | } | 234 | resend_at = 1; |
| 235 | |||
| 236 | resend_at += now; | ||
| 237 | WRITE_ONCE(call->resend_at, resend_at); | ||
| 238 | rxrpc_reduce_call_timer(call, resend_at, now, | ||
| 239 | rxrpc_timer_set_for_send); | ||
| 250 | } | 240 | } |
| 251 | 241 | ||
| 252 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); | 242 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); |
| @@ -295,7 +285,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
| 295 | do { | 285 | do { |
| 296 | /* Check to see if there's a ping ACK to reply to. */ | 286 | /* Check to see if there's a ping ACK to reply to. */ |
| 297 | if (call->ackr_reason == RXRPC_ACK_PING_RESPONSE) | 287 | if (call->ackr_reason == RXRPC_ACK_PING_RESPONSE) |
| 298 | rxrpc_send_ack_packet(call, false); | 288 | rxrpc_send_ack_packet(call, false, NULL); |
| 299 | 289 | ||
| 300 | if (!skb) { | 290 | if (!skb) { |
| 301 | size_t size, chunk, max, space; | 291 | size_t size, chunk, max, space; |
| @@ -480,11 +470,11 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg, struct rxrpc_send_params *p) | |||
| 480 | if (msg->msg_flags & MSG_CMSG_COMPAT) { | 470 | if (msg->msg_flags & MSG_CMSG_COMPAT) { |
| 481 | if (len != sizeof(u32)) | 471 | if (len != sizeof(u32)) |
| 482 | return -EINVAL; | 472 | return -EINVAL; |
| 483 | p->user_call_ID = *(u32 *)CMSG_DATA(cmsg); | 473 | p->call.user_call_ID = *(u32 *)CMSG_DATA(cmsg); |
| 484 | } else { | 474 | } else { |
| 485 | if (len != sizeof(unsigned long)) | 475 | if (len != sizeof(unsigned long)) |
| 486 | return -EINVAL; | 476 | return -EINVAL; |
| 487 | p->user_call_ID = *(unsigned long *) | 477 | p->call.user_call_ID = *(unsigned long *) |
| 488 | CMSG_DATA(cmsg); | 478 | CMSG_DATA(cmsg); |
| 489 | } | 479 | } |
| 490 | got_user_ID = true; | 480 | got_user_ID = true; |
| @@ -522,11 +512,24 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg, struct rxrpc_send_params *p) | |||
| 522 | break; | 512 | break; |
| 523 | 513 | ||
| 524 | case RXRPC_TX_LENGTH: | 514 | case RXRPC_TX_LENGTH: |
| 525 | if (p->tx_total_len != -1 || len != sizeof(__s64)) | 515 | if (p->call.tx_total_len != -1 || len != sizeof(__s64)) |
| 516 | return -EINVAL; | ||
| 517 | p->call.tx_total_len = *(__s64 *)CMSG_DATA(cmsg); | ||
| 518 | if (p->call.tx_total_len < 0) | ||
| 526 | return -EINVAL; | 519 | return -EINVAL; |
| 527 | p->tx_total_len = *(__s64 *)CMSG_DATA(cmsg); | 520 | break; |
| 528 | if (p->tx_total_len < 0) | 521 | |
| 522 | case RXRPC_SET_CALL_TIMEOUT: | ||
| 523 | if (len & 3 || len < 4 || len > 12) | ||
| 529 | return -EINVAL; | 524 | return -EINVAL; |
| 525 | memcpy(&p->call.timeouts, CMSG_DATA(cmsg), len); | ||
| 526 | p->call.nr_timeouts = len / 4; | ||
| 527 | if (p->call.timeouts.hard > INT_MAX / HZ) | ||
| 528 | return -ERANGE; | ||
| 529 | if (p->call.nr_timeouts >= 2 && p->call.timeouts.idle > 60 * 60 * 1000) | ||
| 530 | return -ERANGE; | ||
| 531 | if (p->call.nr_timeouts >= 3 && p->call.timeouts.normal > 60 * 60 * 1000) | ||
| 532 | return -ERANGE; | ||
| 530 | break; | 533 | break; |
| 531 | 534 | ||
| 532 | default: | 535 | default: |
| @@ -536,7 +539,7 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg, struct rxrpc_send_params *p) | |||
| 536 | 539 | ||
| 537 | if (!got_user_ID) | 540 | if (!got_user_ID) |
| 538 | return -EINVAL; | 541 | return -EINVAL; |
| 539 | if (p->tx_total_len != -1 && p->command != RXRPC_CMD_SEND_DATA) | 542 | if (p->call.tx_total_len != -1 && p->command != RXRPC_CMD_SEND_DATA) |
| 540 | return -EINVAL; | 543 | return -EINVAL; |
| 541 | _leave(" = 0"); | 544 | _leave(" = 0"); |
| 542 | return 0; | 545 | return 0; |
| @@ -576,8 +579,7 @@ rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, | |||
| 576 | cp.exclusive = rx->exclusive | p->exclusive; | 579 | cp.exclusive = rx->exclusive | p->exclusive; |
| 577 | cp.upgrade = p->upgrade; | 580 | cp.upgrade = p->upgrade; |
| 578 | cp.service_id = srx->srx_service; | 581 | cp.service_id = srx->srx_service; |
| 579 | call = rxrpc_new_client_call(rx, &cp, srx, p->user_call_ID, | 582 | call = rxrpc_new_client_call(rx, &cp, srx, &p->call, GFP_KERNEL); |
| 580 | p->tx_total_len, GFP_KERNEL); | ||
| 581 | /* The socket is now unlocked */ | 583 | /* The socket is now unlocked */ |
| 582 | 584 | ||
| 583 | _leave(" = %p\n", call); | 585 | _leave(" = %p\n", call); |
| @@ -594,15 +596,17 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) | |||
| 594 | { | 596 | { |
| 595 | enum rxrpc_call_state state; | 597 | enum rxrpc_call_state state; |
| 596 | struct rxrpc_call *call; | 598 | struct rxrpc_call *call; |
| 599 | unsigned long now, j; | ||
| 597 | int ret; | 600 | int ret; |
| 598 | 601 | ||
| 599 | struct rxrpc_send_params p = { | 602 | struct rxrpc_send_params p = { |
| 600 | .tx_total_len = -1, | 603 | .call.tx_total_len = -1, |
| 601 | .user_call_ID = 0, | 604 | .call.user_call_ID = 0, |
| 602 | .abort_code = 0, | 605 | .call.nr_timeouts = 0, |
| 603 | .command = RXRPC_CMD_SEND_DATA, | 606 | .abort_code = 0, |
| 604 | .exclusive = false, | 607 | .command = RXRPC_CMD_SEND_DATA, |
| 605 | .upgrade = true, | 608 | .exclusive = false, |
| 609 | .upgrade = false, | ||
| 606 | }; | 610 | }; |
| 607 | 611 | ||
| 608 | _enter(""); | 612 | _enter(""); |
| @@ -615,15 +619,15 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) | |||
| 615 | ret = -EINVAL; | 619 | ret = -EINVAL; |
| 616 | if (rx->sk.sk_state != RXRPC_SERVER_LISTENING) | 620 | if (rx->sk.sk_state != RXRPC_SERVER_LISTENING) |
| 617 | goto error_release_sock; | 621 | goto error_release_sock; |
| 618 | call = rxrpc_accept_call(rx, p.user_call_ID, NULL); | 622 | call = rxrpc_accept_call(rx, p.call.user_call_ID, NULL); |
| 619 | /* The socket is now unlocked. */ | 623 | /* The socket is now unlocked. */ |
| 620 | if (IS_ERR(call)) | 624 | if (IS_ERR(call)) |
| 621 | return PTR_ERR(call); | 625 | return PTR_ERR(call); |
| 622 | rxrpc_put_call(call, rxrpc_call_put); | 626 | ret = 0; |
| 623 | return 0; | 627 | goto out_put_unlock; |
| 624 | } | 628 | } |
| 625 | 629 | ||
| 626 | call = rxrpc_find_call_by_user_ID(rx, p.user_call_ID); | 630 | call = rxrpc_find_call_by_user_ID(rx, p.call.user_call_ID); |
| 627 | if (!call) { | 631 | if (!call) { |
| 628 | ret = -EBADSLT; | 632 | ret = -EBADSLT; |
| 629 | if (p.command != RXRPC_CMD_SEND_DATA) | 633 | if (p.command != RXRPC_CMD_SEND_DATA) |
| @@ -653,14 +657,39 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) | |||
| 653 | goto error_put; | 657 | goto error_put; |
| 654 | } | 658 | } |
| 655 | 659 | ||
| 656 | if (p.tx_total_len != -1) { | 660 | if (p.call.tx_total_len != -1) { |
| 657 | ret = -EINVAL; | 661 | ret = -EINVAL; |
| 658 | if (call->tx_total_len != -1 || | 662 | if (call->tx_total_len != -1 || |
| 659 | call->tx_pending || | 663 | call->tx_pending || |
| 660 | call->tx_top != 0) | 664 | call->tx_top != 0) |
| 661 | goto error_put; | 665 | goto error_put; |
| 662 | call->tx_total_len = p.tx_total_len; | 666 | call->tx_total_len = p.call.tx_total_len; |
| 667 | } | ||
| 668 | } | ||
| 669 | |||
| 670 | switch (p.call.nr_timeouts) { | ||
| 671 | case 3: | ||
| 672 | j = msecs_to_jiffies(p.call.timeouts.normal); | ||
| 673 | if (p.call.timeouts.normal > 0 && j == 0) | ||
| 674 | j = 1; | ||
| 675 | WRITE_ONCE(call->next_rx_timo, j); | ||
| 676 | /* Fall through */ | ||
| 677 | case 2: | ||
| 678 | j = msecs_to_jiffies(p.call.timeouts.idle); | ||
| 679 | if (p.call.timeouts.idle > 0 && j == 0) | ||
| 680 | j = 1; | ||
| 681 | WRITE_ONCE(call->next_req_timo, j); | ||
| 682 | /* Fall through */ | ||
| 683 | case 1: | ||
| 684 | if (p.call.timeouts.hard > 0) { | ||
| 685 | j = msecs_to_jiffies(p.call.timeouts.hard); | ||
| 686 | now = jiffies; | ||
| 687 | j += now; | ||
| 688 | WRITE_ONCE(call->expect_term_by, j); | ||
| 689 | rxrpc_reduce_call_timer(call, j, now, | ||
| 690 | rxrpc_timer_set_for_hard); | ||
| 663 | } | 691 | } |
| 692 | break; | ||
| 664 | } | 693 | } |
| 665 | 694 | ||
| 666 | state = READ_ONCE(call->state); | 695 | state = READ_ONCE(call->state); |
| @@ -689,6 +718,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) | |||
| 689 | ret = rxrpc_send_data(rx, call, msg, len, NULL); | 718 | ret = rxrpc_send_data(rx, call, msg, len, NULL); |
| 690 | } | 719 | } |
| 691 | 720 | ||
| 721 | out_put_unlock: | ||
| 692 | mutex_unlock(&call->user_mutex); | 722 | mutex_unlock(&call->user_mutex); |
| 693 | error_put: | 723 | error_put: |
| 694 | rxrpc_put_call(call, rxrpc_call_put); | 724 | rxrpc_put_call(call, rxrpc_call_put); |
