diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-11 15:51:09 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-11 15:51:09 -0400 |
| commit | a2dd3793a1c3ac709f1d7b48ad7751563f4c654f (patch) | |
| tree | 81280559aad138fe997a3b4af205729093927b81 /net/rxrpc | |
| parent | d8725c86aebaf3516e220760aaf5fefc73825188 (diff) | |
| parent | 53d5864bc673288f03bb7892a3cffa41a173082b (diff) | |
Merge remote-tracking branch 'dh/afs' into for-davem
Diffstat (limited to 'net/rxrpc')
| -rw-r--r-- | net/rxrpc/ar-input.c | 23 | ||||
| -rw-r--r-- | net/rxrpc/ar-internal.h | 2 | ||||
| -rw-r--r-- | net/rxrpc/ar-local.c | 98 | ||||
| -rw-r--r-- | net/rxrpc/ar-output.c | 54 |
4 files changed, 148 insertions, 29 deletions
diff --git a/net/rxrpc/ar-input.c b/net/rxrpc/ar-input.c index 481f89f93789..4505a691d88c 100644 --- a/net/rxrpc/ar-input.c +++ b/net/rxrpc/ar-input.c | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | const char *rxrpc_pkts[] = { | 28 | const char *rxrpc_pkts[] = { |
| 29 | "?00", | 29 | "?00", |
| 30 | "DATA", "ACK", "BUSY", "ABORT", "ACKALL", "CHALL", "RESP", "DEBUG", | 30 | "DATA", "ACK", "BUSY", "ABORT", "ACKALL", "CHALL", "RESP", "DEBUG", |
| 31 | "?09", "?10", "?11", "?12", "?13", "?14", "?15" | 31 | "?09", "?10", "?11", "?12", "VERSION", "?14", "?15" |
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | /* | 34 | /* |
| @@ -593,6 +593,20 @@ static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn, | |||
| 593 | rxrpc_queue_conn(conn); | 593 | rxrpc_queue_conn(conn); |
| 594 | } | 594 | } |
| 595 | 595 | ||
| 596 | /* | ||
| 597 | * post endpoint-level events to the local endpoint | ||
| 598 | * - this includes debug and version messages | ||
| 599 | */ | ||
| 600 | static void rxrpc_post_packet_to_local(struct rxrpc_local *local, | ||
| 601 | struct sk_buff *skb) | ||
| 602 | { | ||
| 603 | _enter("%p,%p", local, skb); | ||
| 604 | |||
| 605 | atomic_inc(&local->usage); | ||
| 606 | skb_queue_tail(&local->event_queue, skb); | ||
| 607 | rxrpc_queue_work(&local->event_processor); | ||
| 608 | } | ||
| 609 | |||
| 596 | static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local, | 610 | static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local, |
| 597 | struct sk_buff *skb, | 611 | struct sk_buff *skb, |
| 598 | struct rxrpc_skb_priv *sp) | 612 | struct rxrpc_skb_priv *sp) |
| @@ -699,6 +713,11 @@ void rxrpc_data_ready(struct sock *sk) | |||
| 699 | goto bad_message; | 713 | goto bad_message; |
| 700 | } | 714 | } |
| 701 | 715 | ||
| 716 | if (sp->hdr.type == RXRPC_PACKET_TYPE_VERSION) { | ||
| 717 | rxrpc_post_packet_to_local(local, skb); | ||
| 718 | goto out; | ||
| 719 | } | ||
| 720 | |||
| 702 | if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA && | 721 | if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA && |
| 703 | (sp->hdr.callNumber == 0 || sp->hdr.seq == 0)) | 722 | (sp->hdr.callNumber == 0 || sp->hdr.seq == 0)) |
| 704 | goto bad_message; | 723 | goto bad_message; |
| @@ -731,6 +750,8 @@ void rxrpc_data_ready(struct sock *sk) | |||
| 731 | else | 750 | else |
| 732 | goto cant_route_call; | 751 | goto cant_route_call; |
| 733 | } | 752 | } |
| 753 | |||
| 754 | out: | ||
| 734 | rxrpc_put_local(local); | 755 | rxrpc_put_local(local); |
| 735 | return; | 756 | return; |
| 736 | 757 | ||
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 2fc1e659e5c9..aef1bd294e17 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h | |||
| @@ -152,11 +152,13 @@ struct rxrpc_local { | |||
| 152 | struct work_struct destroyer; /* endpoint destroyer */ | 152 | struct work_struct destroyer; /* endpoint destroyer */ |
| 153 | struct work_struct acceptor; /* incoming call processor */ | 153 | struct work_struct acceptor; /* incoming call processor */ |
| 154 | struct work_struct rejecter; /* packet reject writer */ | 154 | struct work_struct rejecter; /* packet reject writer */ |
| 155 | struct work_struct event_processor; /* endpoint event processor */ | ||
| 155 | struct list_head services; /* services listening on this endpoint */ | 156 | struct list_head services; /* services listening on this endpoint */ |
| 156 | struct list_head link; /* link in endpoint list */ | 157 | struct list_head link; /* link in endpoint list */ |
| 157 | struct rw_semaphore defrag_sem; /* control re-enablement of IP DF bit */ | 158 | struct rw_semaphore defrag_sem; /* control re-enablement of IP DF bit */ |
| 158 | struct sk_buff_head accept_queue; /* incoming calls awaiting acceptance */ | 159 | struct sk_buff_head accept_queue; /* incoming calls awaiting acceptance */ |
| 159 | struct sk_buff_head reject_queue; /* packets awaiting rejection */ | 160 | struct sk_buff_head reject_queue; /* packets awaiting rejection */ |
| 161 | struct sk_buff_head event_queue; /* endpoint event packets awaiting processing */ | ||
| 160 | spinlock_t lock; /* access lock */ | 162 | spinlock_t lock; /* access lock */ |
| 161 | rwlock_t services_lock; /* lock for services list */ | 163 | rwlock_t services_lock; /* lock for services list */ |
| 162 | atomic_t usage; | 164 | atomic_t usage; |
diff --git a/net/rxrpc/ar-local.c b/net/rxrpc/ar-local.c index 87f7135d238b..ca904ed5400a 100644 --- a/net/rxrpc/ar-local.c +++ b/net/rxrpc/ar-local.c | |||
| @@ -13,16 +13,22 @@ | |||
| 13 | #include <linux/net.h> | 13 | #include <linux/net.h> |
| 14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/udp.h> | ||
| 17 | #include <linux/ip.h> | ||
| 16 | #include <net/sock.h> | 18 | #include <net/sock.h> |
| 17 | #include <net/af_rxrpc.h> | 19 | #include <net/af_rxrpc.h> |
| 20 | #include <generated/utsrelease.h> | ||
| 18 | #include "ar-internal.h" | 21 | #include "ar-internal.h" |
| 19 | 22 | ||
| 23 | static const char rxrpc_version_string[65] = "linux-" UTS_RELEASE " AF_RXRPC"; | ||
| 24 | |||
| 20 | static LIST_HEAD(rxrpc_locals); | 25 | static LIST_HEAD(rxrpc_locals); |
| 21 | DEFINE_RWLOCK(rxrpc_local_lock); | 26 | DEFINE_RWLOCK(rxrpc_local_lock); |
| 22 | static DECLARE_RWSEM(rxrpc_local_sem); | 27 | static DECLARE_RWSEM(rxrpc_local_sem); |
| 23 | static DECLARE_WAIT_QUEUE_HEAD(rxrpc_local_wq); | 28 | static DECLARE_WAIT_QUEUE_HEAD(rxrpc_local_wq); |
| 24 | 29 | ||
| 25 | static void rxrpc_destroy_local(struct work_struct *work); | 30 | static void rxrpc_destroy_local(struct work_struct *work); |
| 31 | static void rxrpc_process_local_events(struct work_struct *work); | ||
| 26 | 32 | ||
| 27 | /* | 33 | /* |
| 28 | * allocate a new local | 34 | * allocate a new local |
| @@ -37,11 +43,13 @@ struct rxrpc_local *rxrpc_alloc_local(struct sockaddr_rxrpc *srx) | |||
| 37 | INIT_WORK(&local->destroyer, &rxrpc_destroy_local); | 43 | INIT_WORK(&local->destroyer, &rxrpc_destroy_local); |
| 38 | INIT_WORK(&local->acceptor, &rxrpc_accept_incoming_calls); | 44 | INIT_WORK(&local->acceptor, &rxrpc_accept_incoming_calls); |
| 39 | INIT_WORK(&local->rejecter, &rxrpc_reject_packets); | 45 | INIT_WORK(&local->rejecter, &rxrpc_reject_packets); |
| 46 | INIT_WORK(&local->event_processor, &rxrpc_process_local_events); | ||
| 40 | INIT_LIST_HEAD(&local->services); | 47 | INIT_LIST_HEAD(&local->services); |
| 41 | INIT_LIST_HEAD(&local->link); | 48 | INIT_LIST_HEAD(&local->link); |
| 42 | init_rwsem(&local->defrag_sem); | 49 | init_rwsem(&local->defrag_sem); |
| 43 | skb_queue_head_init(&local->accept_queue); | 50 | skb_queue_head_init(&local->accept_queue); |
| 44 | skb_queue_head_init(&local->reject_queue); | 51 | skb_queue_head_init(&local->reject_queue); |
| 52 | skb_queue_head_init(&local->event_queue); | ||
| 45 | spin_lock_init(&local->lock); | 53 | spin_lock_init(&local->lock); |
| 46 | rwlock_init(&local->services_lock); | 54 | rwlock_init(&local->services_lock); |
| 47 | atomic_set(&local->usage, 1); | 55 | atomic_set(&local->usage, 1); |
| @@ -264,10 +272,12 @@ static void rxrpc_destroy_local(struct work_struct *work) | |||
| 264 | ASSERT(list_empty(&local->services)); | 272 | ASSERT(list_empty(&local->services)); |
| 265 | ASSERT(!work_pending(&local->acceptor)); | 273 | ASSERT(!work_pending(&local->acceptor)); |
| 266 | ASSERT(!work_pending(&local->rejecter)); | 274 | ASSERT(!work_pending(&local->rejecter)); |
| 275 | ASSERT(!work_pending(&local->event_processor)); | ||
| 267 | 276 | ||
| 268 | /* finish cleaning up the local descriptor */ | 277 | /* finish cleaning up the local descriptor */ |
| 269 | rxrpc_purge_queue(&local->accept_queue); | 278 | rxrpc_purge_queue(&local->accept_queue); |
| 270 | rxrpc_purge_queue(&local->reject_queue); | 279 | rxrpc_purge_queue(&local->reject_queue); |
| 280 | rxrpc_purge_queue(&local->event_queue); | ||
| 271 | kernel_sock_shutdown(local->socket, SHUT_RDWR); | 281 | kernel_sock_shutdown(local->socket, SHUT_RDWR); |
| 272 | sock_release(local->socket); | 282 | sock_release(local->socket); |
| 273 | 283 | ||
| @@ -308,3 +318,91 @@ void __exit rxrpc_destroy_all_locals(void) | |||
| 308 | 318 | ||
| 309 | _leave(""); | 319 | _leave(""); |
| 310 | } | 320 | } |
| 321 | |||
| 322 | /* | ||
| 323 | * Reply to a version request | ||
| 324 | */ | ||
| 325 | static void rxrpc_send_version_request(struct rxrpc_local *local, | ||
| 326 | struct rxrpc_header *hdr, | ||
| 327 | struct sk_buff *skb) | ||
| 328 | { | ||
| 329 | struct sockaddr_in sin; | ||
| 330 | struct msghdr msg; | ||
| 331 | struct kvec iov[2]; | ||
| 332 | size_t len; | ||
| 333 | int ret; | ||
| 334 | |||
| 335 | _enter(""); | ||
| 336 | |||
| 337 | sin.sin_family = AF_INET; | ||
| 338 | sin.sin_port = udp_hdr(skb)->source; | ||
| 339 | sin.sin_addr.s_addr = ip_hdr(skb)->saddr; | ||
| 340 | |||
| 341 | msg.msg_name = &sin; | ||
| 342 | msg.msg_namelen = sizeof(sin); | ||
| 343 | msg.msg_control = NULL; | ||
| 344 | msg.msg_controllen = 0; | ||
| 345 | msg.msg_flags = 0; | ||
| 346 | |||
| 347 | hdr->seq = 0; | ||
| 348 | hdr->serial = 0; | ||
| 349 | hdr->type = RXRPC_PACKET_TYPE_VERSION; | ||
| 350 | hdr->flags = RXRPC_LAST_PACKET | (~hdr->flags & RXRPC_CLIENT_INITIATED); | ||
| 351 | hdr->userStatus = 0; | ||
| 352 | hdr->_rsvd = 0; | ||
| 353 | |||
| 354 | iov[0].iov_base = hdr; | ||
| 355 | iov[0].iov_len = sizeof(*hdr); | ||
| 356 | iov[1].iov_base = (char *)rxrpc_version_string; | ||
| 357 | iov[1].iov_len = sizeof(rxrpc_version_string); | ||
| 358 | |||
| 359 | len = iov[0].iov_len + iov[1].iov_len; | ||
| 360 | |||
| 361 | _proto("Tx VERSION (reply)"); | ||
| 362 | |||
| 363 | ret = kernel_sendmsg(local->socket, &msg, iov, 2, len); | ||
| 364 | if (ret < 0) | ||
| 365 | _debug("sendmsg failed: %d", ret); | ||
| 366 | |||
| 367 | _leave(""); | ||
| 368 | } | ||
| 369 | |||
| 370 | /* | ||
| 371 | * Process event packets targetted at a local endpoint. | ||
| 372 | */ | ||
| 373 | static void rxrpc_process_local_events(struct work_struct *work) | ||
| 374 | { | ||
| 375 | struct rxrpc_local *local = container_of(work, struct rxrpc_local, event_processor); | ||
| 376 | struct sk_buff *skb; | ||
| 377 | char v; | ||
| 378 | |||
| 379 | _enter(""); | ||
| 380 | |||
| 381 | atomic_inc(&local->usage); | ||
| 382 | |||
| 383 | while ((skb = skb_dequeue(&local->event_queue))) { | ||
| 384 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | ||
| 385 | |||
| 386 | kdebug("{%d},{%u}", local->debug_id, sp->hdr.type); | ||
| 387 | |||
| 388 | switch (sp->hdr.type) { | ||
| 389 | case RXRPC_PACKET_TYPE_VERSION: | ||
| 390 | if (skb_copy_bits(skb, 0, &v, 1) < 0) | ||
| 391 | return; | ||
| 392 | _proto("Rx VERSION { %02x }", v); | ||
| 393 | if (v == 0) | ||
| 394 | rxrpc_send_version_request(local, &sp->hdr, skb); | ||
| 395 | break; | ||
| 396 | |||
| 397 | default: | ||
| 398 | /* Just ignore anything we don't understand */ | ||
| 399 | break; | ||
| 400 | } | ||
| 401 | |||
| 402 | rxrpc_put_local(local); | ||
| 403 | rxrpc_free_skb(skb); | ||
| 404 | } | ||
| 405 | |||
| 406 | rxrpc_put_local(local); | ||
| 407 | _leave(""); | ||
| 408 | } | ||
diff --git a/net/rxrpc/ar-output.c b/net/rxrpc/ar-output.c index 09f584566e23..7a31a3958364 100644 --- a/net/rxrpc/ar-output.c +++ b/net/rxrpc/ar-output.c | |||
| @@ -542,11 +542,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
| 542 | call->tx_pending = NULL; | 542 | call->tx_pending = NULL; |
| 543 | 543 | ||
| 544 | copied = 0; | 544 | copied = 0; |
| 545 | if (len > iov_iter_count(&msg->msg_iter)) | 545 | do { |
| 546 | len = iov_iter_count(&msg->msg_iter); | ||
| 547 | while (len) { | ||
| 548 | int copy; | ||
| 549 | |||
| 550 | if (!skb) { | 546 | if (!skb) { |
| 551 | size_t size, chunk, max, space; | 547 | size_t size, chunk, max, space; |
| 552 | 548 | ||
| @@ -568,8 +564,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
| 568 | max &= ~(call->conn->size_align - 1UL); | 564 | max &= ~(call->conn->size_align - 1UL); |
| 569 | 565 | ||
| 570 | chunk = max; | 566 | chunk = max; |
| 571 | if (chunk > len && !more) | 567 | if (chunk > iov_iter_count(&msg->msg_iter) && !more) |
| 572 | chunk = len; | 568 | chunk = iov_iter_count(&msg->msg_iter); |
| 573 | 569 | ||
| 574 | space = chunk + call->conn->size_align; | 570 | space = chunk + call->conn->size_align; |
| 575 | space &= ~(call->conn->size_align - 1UL); | 571 | space &= ~(call->conn->size_align - 1UL); |
| @@ -612,23 +608,23 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
| 612 | sp = rxrpc_skb(skb); | 608 | sp = rxrpc_skb(skb); |
| 613 | 609 | ||
| 614 | /* append next segment of data to the current buffer */ | 610 | /* append next segment of data to the current buffer */ |
| 615 | copy = skb_tailroom(skb); | 611 | if (iov_iter_count(&msg->msg_iter) > 0) { |
| 616 | ASSERTCMP(copy, >, 0); | 612 | int copy = skb_tailroom(skb); |
| 617 | if (copy > len) | 613 | ASSERTCMP(copy, >, 0); |
| 618 | copy = len; | 614 | if (copy > iov_iter_count(&msg->msg_iter)) |
| 619 | if (copy > sp->remain) | 615 | copy = iov_iter_count(&msg->msg_iter); |
| 620 | copy = sp->remain; | 616 | if (copy > sp->remain) |
| 621 | 617 | copy = sp->remain; | |
| 622 | _debug("add"); | 618 | |
| 623 | ret = skb_add_data(skb, &msg->msg_iter, copy); | 619 | _debug("add"); |
| 624 | _debug("added"); | 620 | ret = skb_add_data(skb, &msg->msg_iter, copy); |
| 625 | if (ret < 0) | 621 | _debug("added"); |
| 626 | goto efault; | 622 | if (ret < 0) |
| 627 | sp->remain -= copy; | 623 | goto efault; |
| 628 | skb->mark += copy; | 624 | sp->remain -= copy; |
| 629 | copied += copy; | 625 | skb->mark += copy; |
| 630 | 626 | copied += copy; | |
| 631 | len -= copy; | 627 | } |
| 632 | 628 | ||
| 633 | /* check for the far side aborting the call or a network error | 629 | /* check for the far side aborting the call or a network error |
| 634 | * occurring */ | 630 | * occurring */ |
| @@ -636,7 +632,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
| 636 | goto call_aborted; | 632 | goto call_aborted; |
| 637 | 633 | ||
| 638 | /* add the packet to the send queue if it's now full */ | 634 | /* add the packet to the send queue if it's now full */ |
| 639 | if (sp->remain <= 0 || (!len && !more)) { | 635 | if (sp->remain <= 0 || |
| 636 | (iov_iter_count(&msg->msg_iter) == 0 && !more)) { | ||
| 640 | struct rxrpc_connection *conn = call->conn; | 637 | struct rxrpc_connection *conn = call->conn; |
| 641 | uint32_t seq; | 638 | uint32_t seq; |
| 642 | size_t pad; | 639 | size_t pad; |
| @@ -666,7 +663,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
| 666 | sp->hdr.serviceId = conn->service_id; | 663 | sp->hdr.serviceId = conn->service_id; |
| 667 | 664 | ||
| 668 | sp->hdr.flags = conn->out_clientflag; | 665 | sp->hdr.flags = conn->out_clientflag; |
| 669 | if (len == 0 && !more) | 666 | if (iov_iter_count(&msg->msg_iter) == 0 && !more) |
| 670 | sp->hdr.flags |= RXRPC_LAST_PACKET; | 667 | sp->hdr.flags |= RXRPC_LAST_PACKET; |
| 671 | else if (CIRC_SPACE(call->acks_head, call->acks_tail, | 668 | else if (CIRC_SPACE(call->acks_head, call->acks_tail, |
| 672 | call->acks_winsz) > 1) | 669 | call->acks_winsz) > 1) |
| @@ -682,10 +679,11 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
| 682 | 679 | ||
| 683 | memcpy(skb->head, &sp->hdr, | 680 | memcpy(skb->head, &sp->hdr, |
| 684 | sizeof(struct rxrpc_header)); | 681 | sizeof(struct rxrpc_header)); |
| 685 | rxrpc_queue_packet(call, skb, !iov_iter_count(&msg->msg_iter) && !more); | 682 | rxrpc_queue_packet(call, skb, |
| 683 | iov_iter_count(&msg->msg_iter) == 0 && !more); | ||
| 686 | skb = NULL; | 684 | skb = NULL; |
| 687 | } | 685 | } |
| 688 | } | 686 | } while (iov_iter_count(&msg->msg_iter) > 0); |
| 689 | 687 | ||
| 690 | success: | 688 | success: |
| 691 | ret = copied; | 689 | ret = copied; |
