diff options
author | David Howells <dhowells@redhat.com> | 2016-09-17 05:49:14 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2016-09-17 06:24:04 -0400 |
commit | 71f3ca408fd43b586c02480768a503af075b247e (patch) | |
tree | 9fcca5ef4f931aa9836e5f92b78abfb5c2d68a55 | |
parent | ba39f3a0ed756ccd882adf4a77916ec863db3ce4 (diff) |
rxrpc: Improve skb tracing
Improve sk_buff tracing within AF_RXRPC by the following means:
(1) Use an enum to note the event type rather than plain integers and use
an array of event names rather than a big multi ?: list.
(2) Distinguish Rx from Tx packets and account them separately. This
requires the call phase to be tracked so that we know what we might
find in rxtx_buffer[].
(3) Add a parameter to rxrpc_{new,see,get,free}_skb() to indicate the
event type.
(4) A pair of 'rotate' events are added to indicate packets that are about
to be rotated out of the Rx and Tx windows.
(5) A pair of 'lost' events are added, along with rxrpc_lose_skb() for
packet loss injection recording.
Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r-- | include/trace/events/rxrpc.h | 12 | ||||
-rw-r--r-- | net/rxrpc/af_rxrpc.c | 5 | ||||
-rw-r--r-- | net/rxrpc/ar-internal.h | 33 | ||||
-rw-r--r-- | net/rxrpc/call_event.c | 8 | ||||
-rw-r--r-- | net/rxrpc/call_object.c | 11 | ||||
-rw-r--r-- | net/rxrpc/conn_event.c | 6 | ||||
-rw-r--r-- | net/rxrpc/input.c | 13 | ||||
-rw-r--r-- | net/rxrpc/local_event.c | 4 | ||||
-rw-r--r-- | net/rxrpc/misc.c | 18 | ||||
-rw-r--r-- | net/rxrpc/output.c | 4 | ||||
-rw-r--r-- | net/rxrpc/peer_event.c | 10 | ||||
-rw-r--r-- | net/rxrpc/recvmsg.c | 7 | ||||
-rw-r--r-- | net/rxrpc/sendmsg.c | 10 | ||||
-rw-r--r-- | net/rxrpc/skbuff.c | 53 |
14 files changed, 131 insertions, 63 deletions
diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h index 58732202e9f0..75a5d8bf50e1 100644 --- a/include/trace/events/rxrpc.h +++ b/include/trace/events/rxrpc.h | |||
@@ -107,14 +107,14 @@ TRACE_EVENT(rxrpc_call, | |||
107 | ); | 107 | ); |
108 | 108 | ||
109 | TRACE_EVENT(rxrpc_skb, | 109 | TRACE_EVENT(rxrpc_skb, |
110 | TP_PROTO(struct sk_buff *skb, int op, int usage, int mod_count, | 110 | TP_PROTO(struct sk_buff *skb, enum rxrpc_skb_trace op, |
111 | const void *where), | 111 | int usage, int mod_count, const void *where), |
112 | 112 | ||
113 | TP_ARGS(skb, op, usage, mod_count, where), | 113 | TP_ARGS(skb, op, usage, mod_count, where), |
114 | 114 | ||
115 | TP_STRUCT__entry( | 115 | TP_STRUCT__entry( |
116 | __field(struct sk_buff *, skb ) | 116 | __field(struct sk_buff *, skb ) |
117 | __field(int, op ) | 117 | __field(enum rxrpc_skb_trace, op ) |
118 | __field(int, usage ) | 118 | __field(int, usage ) |
119 | __field(int, mod_count ) | 119 | __field(int, mod_count ) |
120 | __field(const void *, where ) | 120 | __field(const void *, where ) |
@@ -130,11 +130,7 @@ TRACE_EVENT(rxrpc_skb, | |||
130 | 130 | ||
131 | TP_printk("s=%p %s u=%d m=%d p=%pSR", | 131 | TP_printk("s=%p %s u=%d m=%d p=%pSR", |
132 | __entry->skb, | 132 | __entry->skb, |
133 | (__entry->op == 0 ? "NEW" : | 133 | rxrpc_skb_traces[__entry->op], |
134 | __entry->op == 1 ? "SEE" : | ||
135 | __entry->op == 2 ? "GET" : | ||
136 | __entry->op == 3 ? "FRE" : | ||
137 | "PUR"), | ||
138 | __entry->usage, | 134 | __entry->usage, |
139 | __entry->mod_count, | 135 | __entry->mod_count, |
140 | __entry->where) | 136 | __entry->where) |
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 09f81befc705..8dbf7bed2cc4 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
@@ -45,7 +45,7 @@ u32 rxrpc_epoch; | |||
45 | atomic_t rxrpc_debug_id; | 45 | atomic_t rxrpc_debug_id; |
46 | 46 | ||
47 | /* count of skbs currently in use */ | 47 | /* count of skbs currently in use */ |
48 | atomic_t rxrpc_n_skbs; | 48 | atomic_t rxrpc_n_tx_skbs, rxrpc_n_rx_skbs; |
49 | 49 | ||
50 | struct workqueue_struct *rxrpc_workqueue; | 50 | struct workqueue_struct *rxrpc_workqueue; |
51 | 51 | ||
@@ -867,7 +867,8 @@ static void __exit af_rxrpc_exit(void) | |||
867 | proto_unregister(&rxrpc_proto); | 867 | proto_unregister(&rxrpc_proto); |
868 | rxrpc_destroy_all_calls(); | 868 | rxrpc_destroy_all_calls(); |
869 | rxrpc_destroy_all_connections(); | 869 | rxrpc_destroy_all_connections(); |
870 | ASSERTCMP(atomic_read(&rxrpc_n_skbs), ==, 0); | 870 | ASSERTCMP(atomic_read(&rxrpc_n_tx_skbs), ==, 0); |
871 | ASSERTCMP(atomic_read(&rxrpc_n_rx_skbs), ==, 0); | ||
871 | rxrpc_destroy_all_locals(); | 872 | rxrpc_destroy_all_locals(); |
872 | 873 | ||
873 | remove_proc_entry("rxrpc_conns", init_net.proc_net); | 874 | remove_proc_entry("rxrpc_conns", init_net.proc_net); |
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index a17341d2df3d..034f525f2235 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h | |||
@@ -520,6 +520,7 @@ struct rxrpc_call { | |||
520 | rxrpc_seq_t rx_expect_next; /* Expected next packet sequence number */ | 520 | rxrpc_seq_t rx_expect_next; /* Expected next packet sequence number */ |
521 | u8 rx_winsize; /* Size of Rx window */ | 521 | u8 rx_winsize; /* Size of Rx window */ |
522 | u8 tx_winsize; /* Maximum size of Tx window */ | 522 | u8 tx_winsize; /* Maximum size of Tx window */ |
523 | bool tx_phase; /* T if transmission phase, F if receive phase */ | ||
523 | u8 nr_jumbo_bad; /* Number of jumbo dups/exceeds-windows */ | 524 | u8 nr_jumbo_bad; /* Number of jumbo dups/exceeds-windows */ |
524 | 525 | ||
525 | /* receive-phase ACK management */ | 526 | /* receive-phase ACK management */ |
@@ -534,6 +535,27 @@ struct rxrpc_call { | |||
534 | rxrpc_serial_t acks_latest; /* serial number of latest ACK received */ | 535 | rxrpc_serial_t acks_latest; /* serial number of latest ACK received */ |
535 | }; | 536 | }; |
536 | 537 | ||
538 | enum rxrpc_skb_trace { | ||
539 | rxrpc_skb_rx_cleaned, | ||
540 | rxrpc_skb_rx_freed, | ||
541 | rxrpc_skb_rx_got, | ||
542 | rxrpc_skb_rx_lost, | ||
543 | rxrpc_skb_rx_received, | ||
544 | rxrpc_skb_rx_rotated, | ||
545 | rxrpc_skb_rx_purged, | ||
546 | rxrpc_skb_rx_seen, | ||
547 | rxrpc_skb_tx_cleaned, | ||
548 | rxrpc_skb_tx_freed, | ||
549 | rxrpc_skb_tx_got, | ||
550 | rxrpc_skb_tx_lost, | ||
551 | rxrpc_skb_tx_new, | ||
552 | rxrpc_skb_tx_rotated, | ||
553 | rxrpc_skb_tx_seen, | ||
554 | rxrpc_skb__nr_trace | ||
555 | }; | ||
556 | |||
557 | extern const char rxrpc_skb_traces[rxrpc_skb__nr_trace][7]; | ||
558 | |||
537 | enum rxrpc_conn_trace { | 559 | enum rxrpc_conn_trace { |
538 | rxrpc_conn_new_client, | 560 | rxrpc_conn_new_client, |
539 | rxrpc_conn_new_service, | 561 | rxrpc_conn_new_service, |
@@ -642,7 +664,7 @@ extern const char *rxrpc_acks(u8 reason); | |||
642 | /* | 664 | /* |
643 | * af_rxrpc.c | 665 | * af_rxrpc.c |
644 | */ | 666 | */ |
645 | extern atomic_t rxrpc_n_skbs; | 667 | extern atomic_t rxrpc_n_tx_skbs, rxrpc_n_rx_skbs; |
646 | extern u32 rxrpc_epoch; | 668 | extern u32 rxrpc_epoch; |
647 | extern atomic_t rxrpc_debug_id; | 669 | extern atomic_t rxrpc_debug_id; |
648 | extern struct workqueue_struct *rxrpc_workqueue; | 670 | extern struct workqueue_struct *rxrpc_workqueue; |
@@ -1000,10 +1022,11 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *, struct msghdr *, size_t); | |||
1000 | */ | 1022 | */ |
1001 | void rxrpc_kernel_data_consumed(struct rxrpc_call *, struct sk_buff *); | 1023 | void rxrpc_kernel_data_consumed(struct rxrpc_call *, struct sk_buff *); |
1002 | void rxrpc_packet_destructor(struct sk_buff *); | 1024 | void rxrpc_packet_destructor(struct sk_buff *); |
1003 | void rxrpc_new_skb(struct sk_buff *); | 1025 | void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace); |
1004 | void rxrpc_see_skb(struct sk_buff *); | 1026 | void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace); |
1005 | void rxrpc_get_skb(struct sk_buff *); | 1027 | void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace); |
1006 | void rxrpc_free_skb(struct sk_buff *); | 1028 | void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace); |
1029 | void rxrpc_lose_skb(struct sk_buff *, enum rxrpc_skb_trace); | ||
1007 | void rxrpc_purge_queue(struct sk_buff_head *); | 1030 | void rxrpc_purge_queue(struct sk_buff_head *); |
1008 | 1031 | ||
1009 | /* | 1032 | /* |
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c index f0cabc48a1b7..7d1b99824ed9 100644 --- a/net/rxrpc/call_event.c +++ b/net/rxrpc/call_event.c | |||
@@ -170,7 +170,7 @@ static void rxrpc_resend(struct rxrpc_call *call) | |||
170 | continue; | 170 | continue; |
171 | 171 | ||
172 | skb = call->rxtx_buffer[ix]; | 172 | skb = call->rxtx_buffer[ix]; |
173 | rxrpc_see_skb(skb); | 173 | rxrpc_see_skb(skb, rxrpc_skb_tx_seen); |
174 | sp = rxrpc_skb(skb); | 174 | sp = rxrpc_skb(skb); |
175 | 175 | ||
176 | if (annotation == RXRPC_TX_ANNO_UNACK) { | 176 | if (annotation == RXRPC_TX_ANNO_UNACK) { |
@@ -199,7 +199,7 @@ static void rxrpc_resend(struct rxrpc_call *call) | |||
199 | continue; | 199 | continue; |
200 | 200 | ||
201 | skb = call->rxtx_buffer[ix]; | 201 | skb = call->rxtx_buffer[ix]; |
202 | rxrpc_get_skb(skb); | 202 | rxrpc_get_skb(skb, rxrpc_skb_tx_got); |
203 | spin_unlock_bh(&call->lock); | 203 | spin_unlock_bh(&call->lock); |
204 | sp = rxrpc_skb(skb); | 204 | sp = rxrpc_skb(skb); |
205 | 205 | ||
@@ -211,7 +211,7 @@ static void rxrpc_resend(struct rxrpc_call *call) | |||
211 | 211 | ||
212 | if (rxrpc_send_data_packet(call->conn, skb) < 0) { | 212 | if (rxrpc_send_data_packet(call->conn, skb) < 0) { |
213 | call->resend_at = now + 2; | 213 | call->resend_at = now + 2; |
214 | rxrpc_free_skb(skb); | 214 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); |
215 | return; | 215 | return; |
216 | } | 216 | } |
217 | 217 | ||
@@ -219,7 +219,7 @@ static void rxrpc_resend(struct rxrpc_call *call) | |||
219 | rxrpc_expose_client_call(call); | 219 | rxrpc_expose_client_call(call); |
220 | sp->resend_at = now + rxrpc_resend_timeout; | 220 | sp->resend_at = now + rxrpc_resend_timeout; |
221 | 221 | ||
222 | rxrpc_free_skb(skb); | 222 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); |
223 | spin_lock_bh(&call->lock); | 223 | spin_lock_bh(&call->lock); |
224 | 224 | ||
225 | /* We need to clear the retransmit state, but there are two | 225 | /* We need to clear the retransmit state, but there are two |
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index 54f30482a7fd..f50a6094e198 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c | |||
@@ -182,6 +182,7 @@ static struct rxrpc_call *rxrpc_alloc_client_call(struct sockaddr_rxrpc *srx, | |||
182 | return ERR_PTR(-ENOMEM); | 182 | return ERR_PTR(-ENOMEM); |
183 | call->state = RXRPC_CALL_CLIENT_AWAIT_CONN; | 183 | call->state = RXRPC_CALL_CLIENT_AWAIT_CONN; |
184 | call->service_id = srx->srx_service; | 184 | call->service_id = srx->srx_service; |
185 | call->tx_phase = true; | ||
185 | 186 | ||
186 | _leave(" = %p", call); | 187 | _leave(" = %p", call); |
187 | return call; | 188 | return call; |
@@ -458,7 +459,9 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) | |||
458 | rxrpc_disconnect_call(call); | 459 | rxrpc_disconnect_call(call); |
459 | 460 | ||
460 | for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) { | 461 | for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) { |
461 | rxrpc_free_skb(call->rxtx_buffer[i]); | 462 | rxrpc_free_skb(call->rxtx_buffer[i], |
463 | (call->tx_phase ? rxrpc_skb_tx_cleaned : | ||
464 | rxrpc_skb_rx_cleaned)); | ||
462 | call->rxtx_buffer[i] = NULL; | 465 | call->rxtx_buffer[i] = NULL; |
463 | } | 466 | } |
464 | 467 | ||
@@ -552,9 +555,11 @@ void rxrpc_cleanup_call(struct rxrpc_call *call) | |||
552 | 555 | ||
553 | /* Clean up the Rx/Tx buffer */ | 556 | /* Clean up the Rx/Tx buffer */ |
554 | for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) | 557 | for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) |
555 | rxrpc_free_skb(call->rxtx_buffer[i]); | 558 | rxrpc_free_skb(call->rxtx_buffer[i], |
559 | (call->tx_phase ? rxrpc_skb_tx_cleaned : | ||
560 | rxrpc_skb_rx_cleaned)); | ||
556 | 561 | ||
557 | rxrpc_free_skb(call->tx_pending); | 562 | rxrpc_free_skb(call->tx_pending, rxrpc_skb_tx_cleaned); |
558 | 563 | ||
559 | call_rcu(&call->rcu, rxrpc_rcu_destroy_call); | 564 | call_rcu(&call->rcu, rxrpc_rcu_destroy_call); |
560 | } | 565 | } |
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c index 9b19c51831aa..75a15a4c74c3 100644 --- a/net/rxrpc/conn_event.c +++ b/net/rxrpc/conn_event.c | |||
@@ -388,7 +388,7 @@ void rxrpc_process_connection(struct work_struct *work) | |||
388 | /* go through the conn-level event packets, releasing the ref on this | 388 | /* go through the conn-level event packets, releasing the ref on this |
389 | * connection that each one has when we've finished with it */ | 389 | * connection that each one has when we've finished with it */ |
390 | while ((skb = skb_dequeue(&conn->rx_queue))) { | 390 | while ((skb = skb_dequeue(&conn->rx_queue))) { |
391 | rxrpc_see_skb(skb); | 391 | rxrpc_see_skb(skb, rxrpc_skb_rx_seen); |
392 | ret = rxrpc_process_event(conn, skb, &abort_code); | 392 | ret = rxrpc_process_event(conn, skb, &abort_code); |
393 | switch (ret) { | 393 | switch (ret) { |
394 | case -EPROTO: | 394 | case -EPROTO: |
@@ -399,7 +399,7 @@ void rxrpc_process_connection(struct work_struct *work) | |||
399 | goto requeue_and_leave; | 399 | goto requeue_and_leave; |
400 | case -ECONNABORTED: | 400 | case -ECONNABORTED: |
401 | default: | 401 | default: |
402 | rxrpc_free_skb(skb); | 402 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); |
403 | break; | 403 | break; |
404 | } | 404 | } |
405 | } | 405 | } |
@@ -416,7 +416,7 @@ requeue_and_leave: | |||
416 | protocol_error: | 416 | protocol_error: |
417 | if (rxrpc_abort_connection(conn, -ret, abort_code) < 0) | 417 | if (rxrpc_abort_connection(conn, -ret, abort_code) < 0) |
418 | goto requeue_and_leave; | 418 | goto requeue_and_leave; |
419 | rxrpc_free_skb(skb); | 419 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); |
420 | _leave(" [EPROTO]"); | 420 | _leave(" [EPROTO]"); |
421 | goto out; | 421 | goto out; |
422 | } | 422 | } |
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index b690220533c6..84bb16d47b85 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c | |||
@@ -50,7 +50,7 @@ static void rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to) | |||
50 | call->tx_hard_ack++; | 50 | call->tx_hard_ack++; |
51 | ix = call->tx_hard_ack & RXRPC_RXTX_BUFF_MASK; | 51 | ix = call->tx_hard_ack & RXRPC_RXTX_BUFF_MASK; |
52 | skb = call->rxtx_buffer[ix]; | 52 | skb = call->rxtx_buffer[ix]; |
53 | rxrpc_see_skb(skb); | 53 | rxrpc_see_skb(skb, rxrpc_skb_tx_rotated); |
54 | call->rxtx_buffer[ix] = NULL; | 54 | call->rxtx_buffer[ix] = NULL; |
55 | call->rxtx_annotations[ix] = 0; | 55 | call->rxtx_annotations[ix] = 0; |
56 | skb->next = list; | 56 | skb->next = list; |
@@ -66,7 +66,7 @@ static void rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to) | |||
66 | skb = list; | 66 | skb = list; |
67 | list = skb->next; | 67 | list = skb->next; |
68 | skb->next = NULL; | 68 | skb->next = NULL; |
69 | rxrpc_free_skb(skb); | 69 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); |
70 | } | 70 | } |
71 | } | 71 | } |
72 | 72 | ||
@@ -99,6 +99,7 @@ static bool rxrpc_end_tx_phase(struct rxrpc_call *call, const char *abort_why) | |||
99 | default: | 99 | default: |
100 | break; | 100 | break; |
101 | case RXRPC_CALL_CLIENT_AWAIT_REPLY: | 101 | case RXRPC_CALL_CLIENT_AWAIT_REPLY: |
102 | call->tx_phase = false; | ||
102 | call->state = RXRPC_CALL_CLIENT_RECV_REPLY; | 103 | call->state = RXRPC_CALL_CLIENT_RECV_REPLY; |
103 | break; | 104 | break; |
104 | case RXRPC_CALL_SERVER_AWAIT_ACK: | 105 | case RXRPC_CALL_SERVER_AWAIT_ACK: |
@@ -278,7 +279,7 @@ next_subpacket: | |||
278 | * Barriers against rxrpc_recvmsg_data() and rxrpc_rotate_rx_window() | 279 | * Barriers against rxrpc_recvmsg_data() and rxrpc_rotate_rx_window() |
279 | * and also rxrpc_fill_out_ack(). | 280 | * and also rxrpc_fill_out_ack(). |
280 | */ | 281 | */ |
281 | rxrpc_get_skb(skb); | 282 | rxrpc_get_skb(skb, rxrpc_skb_rx_got); |
282 | call->rxtx_annotations[ix] = annotation; | 283 | call->rxtx_annotations[ix] = annotation; |
283 | smp_wmb(); | 284 | smp_wmb(); |
284 | call->rxtx_buffer[ix] = skb; | 285 | call->rxtx_buffer[ix] = skb; |
@@ -691,13 +692,13 @@ void rxrpc_data_ready(struct sock *udp_sk) | |||
691 | return; | 692 | return; |
692 | } | 693 | } |
693 | 694 | ||
694 | rxrpc_new_skb(skb); | 695 | rxrpc_new_skb(skb, rxrpc_skb_rx_received); |
695 | 696 | ||
696 | _net("recv skb %p", skb); | 697 | _net("recv skb %p", skb); |
697 | 698 | ||
698 | /* we'll probably need to checksum it (didn't call sock_recvmsg) */ | 699 | /* we'll probably need to checksum it (didn't call sock_recvmsg) */ |
699 | if (skb_checksum_complete(skb)) { | 700 | if (skb_checksum_complete(skb)) { |
700 | rxrpc_free_skb(skb); | 701 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); |
701 | __UDP_INC_STATS(&init_net, UDP_MIB_INERRORS, 0); | 702 | __UDP_INC_STATS(&init_net, UDP_MIB_INERRORS, 0); |
702 | _leave(" [CSUM failed]"); | 703 | _leave(" [CSUM failed]"); |
703 | return; | 704 | return; |
@@ -821,7 +822,7 @@ void rxrpc_data_ready(struct sock *udp_sk) | |||
821 | discard_unlock: | 822 | discard_unlock: |
822 | rcu_read_unlock(); | 823 | rcu_read_unlock(); |
823 | discard: | 824 | discard: |
824 | rxrpc_free_skb(skb); | 825 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); |
825 | out: | 826 | out: |
826 | trace_rxrpc_rx_done(0, 0); | 827 | trace_rxrpc_rx_done(0, 0); |
827 | return; | 828 | return; |
diff --git a/net/rxrpc/local_event.c b/net/rxrpc/local_event.c index f073e932500e..190f68bd9e27 100644 --- a/net/rxrpc/local_event.c +++ b/net/rxrpc/local_event.c | |||
@@ -90,7 +90,7 @@ void rxrpc_process_local_events(struct rxrpc_local *local) | |||
90 | if (skb) { | 90 | if (skb) { |
91 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | 91 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); |
92 | 92 | ||
93 | rxrpc_see_skb(skb); | 93 | rxrpc_see_skb(skb, rxrpc_skb_rx_seen); |
94 | _debug("{%d},{%u}", local->debug_id, sp->hdr.type); | 94 | _debug("{%d},{%u}", local->debug_id, sp->hdr.type); |
95 | 95 | ||
96 | switch (sp->hdr.type) { | 96 | switch (sp->hdr.type) { |
@@ -107,7 +107,7 @@ void rxrpc_process_local_events(struct rxrpc_local *local) | |||
107 | break; | 107 | break; |
108 | } | 108 | } |
109 | 109 | ||
110 | rxrpc_free_skb(skb); | 110 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); |
111 | } | 111 | } |
112 | 112 | ||
113 | _leave(""); | 113 | _leave(""); |
diff --git a/net/rxrpc/misc.c b/net/rxrpc/misc.c index c7065d893d1e..026e1f2e83ff 100644 --- a/net/rxrpc/misc.c +++ b/net/rxrpc/misc.c | |||
@@ -102,6 +102,24 @@ const char *rxrpc_acks(u8 reason) | |||
102 | return str[reason]; | 102 | return str[reason]; |
103 | } | 103 | } |
104 | 104 | ||
105 | const char rxrpc_skb_traces[rxrpc_skb__nr_trace][7] = { | ||
106 | [rxrpc_skb_rx_cleaned] = "Rx CLN", | ||
107 | [rxrpc_skb_rx_freed] = "Rx FRE", | ||
108 | [rxrpc_skb_rx_got] = "Rx GOT", | ||
109 | [rxrpc_skb_rx_lost] = "Rx *L*", | ||
110 | [rxrpc_skb_rx_received] = "Rx RCV", | ||
111 | [rxrpc_skb_rx_purged] = "Rx PUR", | ||
112 | [rxrpc_skb_rx_rotated] = "Rx ROT", | ||
113 | [rxrpc_skb_rx_seen] = "Rx SEE", | ||
114 | [rxrpc_skb_tx_cleaned] = "Tx CLN", | ||
115 | [rxrpc_skb_tx_freed] = "Tx FRE", | ||
116 | [rxrpc_skb_tx_got] = "Tx GOT", | ||
117 | [rxrpc_skb_tx_lost] = "Tx *L*", | ||
118 | [rxrpc_skb_tx_new] = "Tx NEW", | ||
119 | [rxrpc_skb_tx_rotated] = "Tx ROT", | ||
120 | [rxrpc_skb_tx_seen] = "Tx SEE", | ||
121 | }; | ||
122 | |||
105 | const char rxrpc_conn_traces[rxrpc_conn__nr_trace][4] = { | 123 | const char rxrpc_conn_traces[rxrpc_conn__nr_trace][4] = { |
106 | [rxrpc_conn_new_client] = "NWc", | 124 | [rxrpc_conn_new_client] = "NWc", |
107 | [rxrpc_conn_new_service] = "NWs", | 125 | [rxrpc_conn_new_service] = "NWs", |
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c index 2c9daeadce87..a2cad5ce7416 100644 --- a/net/rxrpc/output.c +++ b/net/rxrpc/output.c | |||
@@ -324,7 +324,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local) | |||
324 | whdr.type = RXRPC_PACKET_TYPE_ABORT; | 324 | whdr.type = RXRPC_PACKET_TYPE_ABORT; |
325 | 325 | ||
326 | while ((skb = skb_dequeue(&local->reject_queue))) { | 326 | while ((skb = skb_dequeue(&local->reject_queue))) { |
327 | rxrpc_see_skb(skb); | 327 | rxrpc_see_skb(skb, rxrpc_skb_rx_seen); |
328 | sp = rxrpc_skb(skb); | 328 | sp = rxrpc_skb(skb); |
329 | 329 | ||
330 | if (rxrpc_extract_addr_from_skb(&srx, skb) == 0) { | 330 | if (rxrpc_extract_addr_from_skb(&srx, skb) == 0) { |
@@ -343,7 +343,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local) | |||
343 | kernel_sendmsg(local->socket, &msg, iov, 2, size); | 343 | kernel_sendmsg(local->socket, &msg, iov, 2, size); |
344 | } | 344 | } |
345 | 345 | ||
346 | rxrpc_free_skb(skb); | 346 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); |
347 | } | 347 | } |
348 | 348 | ||
349 | _leave(""); | 349 | _leave(""); |
diff --git a/net/rxrpc/peer_event.c b/net/rxrpc/peer_event.c index 9e0725f5652b..18276e7cb9e0 100644 --- a/net/rxrpc/peer_event.c +++ b/net/rxrpc/peer_event.c | |||
@@ -155,11 +155,11 @@ void rxrpc_error_report(struct sock *sk) | |||
155 | _leave("UDP socket errqueue empty"); | 155 | _leave("UDP socket errqueue empty"); |
156 | return; | 156 | return; |
157 | } | 157 | } |
158 | rxrpc_new_skb(skb); | 158 | rxrpc_new_skb(skb, rxrpc_skb_rx_received); |
159 | serr = SKB_EXT_ERR(skb); | 159 | serr = SKB_EXT_ERR(skb); |
160 | if (!skb->len && serr->ee.ee_origin == SO_EE_ORIGIN_TIMESTAMPING) { | 160 | if (!skb->len && serr->ee.ee_origin == SO_EE_ORIGIN_TIMESTAMPING) { |
161 | _leave("UDP empty message"); | 161 | _leave("UDP empty message"); |
162 | rxrpc_free_skb(skb); | 162 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); |
163 | return; | 163 | return; |
164 | } | 164 | } |
165 | 165 | ||
@@ -169,7 +169,7 @@ void rxrpc_error_report(struct sock *sk) | |||
169 | peer = NULL; | 169 | peer = NULL; |
170 | if (!peer) { | 170 | if (!peer) { |
171 | rcu_read_unlock(); | 171 | rcu_read_unlock(); |
172 | rxrpc_free_skb(skb); | 172 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); |
173 | _leave(" [no peer]"); | 173 | _leave(" [no peer]"); |
174 | return; | 174 | return; |
175 | } | 175 | } |
@@ -179,7 +179,7 @@ void rxrpc_error_report(struct sock *sk) | |||
179 | serr->ee.ee_code == ICMP_FRAG_NEEDED)) { | 179 | serr->ee.ee_code == ICMP_FRAG_NEEDED)) { |
180 | rxrpc_adjust_mtu(peer, serr); | 180 | rxrpc_adjust_mtu(peer, serr); |
181 | rcu_read_unlock(); | 181 | rcu_read_unlock(); |
182 | rxrpc_free_skb(skb); | 182 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); |
183 | rxrpc_put_peer(peer); | 183 | rxrpc_put_peer(peer); |
184 | _leave(" [MTU update]"); | 184 | _leave(" [MTU update]"); |
185 | return; | 185 | return; |
@@ -187,7 +187,7 @@ void rxrpc_error_report(struct sock *sk) | |||
187 | 187 | ||
188 | rxrpc_store_error(peer, serr); | 188 | rxrpc_store_error(peer, serr); |
189 | rcu_read_unlock(); | 189 | rcu_read_unlock(); |
190 | rxrpc_free_skb(skb); | 190 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); |
191 | 191 | ||
192 | /* The ref we obtained is passed off to the work item */ | 192 | /* The ref we obtained is passed off to the work item */ |
193 | rxrpc_queue_work(&peer->error_distributor); | 193 | rxrpc_queue_work(&peer->error_distributor); |
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c index 79e65668bc58..6ba4af5a8d95 100644 --- a/net/rxrpc/recvmsg.c +++ b/net/rxrpc/recvmsg.c | |||
@@ -155,6 +155,7 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call) | |||
155 | break; | 155 | break; |
156 | 156 | ||
157 | case RXRPC_CALL_SERVER_RECV_REQUEST: | 157 | case RXRPC_CALL_SERVER_RECV_REQUEST: |
158 | call->tx_phase = true; | ||
158 | call->state = RXRPC_CALL_SERVER_ACK_REQUEST; | 159 | call->state = RXRPC_CALL_SERVER_ACK_REQUEST; |
159 | break; | 160 | break; |
160 | default: | 161 | default: |
@@ -185,7 +186,7 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call) | |||
185 | hard_ack++; | 186 | hard_ack++; |
186 | ix = hard_ack & RXRPC_RXTX_BUFF_MASK; | 187 | ix = hard_ack & RXRPC_RXTX_BUFF_MASK; |
187 | skb = call->rxtx_buffer[ix]; | 188 | skb = call->rxtx_buffer[ix]; |
188 | rxrpc_see_skb(skb); | 189 | rxrpc_see_skb(skb, rxrpc_skb_rx_rotated); |
189 | sp = rxrpc_skb(skb); | 190 | sp = rxrpc_skb(skb); |
190 | flags = sp->hdr.flags; | 191 | flags = sp->hdr.flags; |
191 | serial = sp->hdr.serial; | 192 | serial = sp->hdr.serial; |
@@ -197,7 +198,7 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call) | |||
197 | /* Barrier against rxrpc_input_data(). */ | 198 | /* Barrier against rxrpc_input_data(). */ |
198 | smp_store_release(&call->rx_hard_ack, hard_ack); | 199 | smp_store_release(&call->rx_hard_ack, hard_ack); |
199 | 200 | ||
200 | rxrpc_free_skb(skb); | 201 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); |
201 | 202 | ||
202 | _debug("%u,%u,%02x", hard_ack, top, flags); | 203 | _debug("%u,%u,%02x", hard_ack, top, flags); |
203 | trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack); | 204 | trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack); |
@@ -317,7 +318,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call, | |||
317 | break; | 318 | break; |
318 | } | 319 | } |
319 | smp_rmb(); | 320 | smp_rmb(); |
320 | rxrpc_see_skb(skb); | 321 | rxrpc_see_skb(skb, rxrpc_skb_rx_seen); |
321 | sp = rxrpc_skb(skb); | 322 | sp = rxrpc_skb(skb); |
322 | 323 | ||
323 | if (!(flags & MSG_PEEK)) | 324 | if (!(flags & MSG_PEEK)) |
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index 28d8f73cf11d..6a39ee97a0b7 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c | |||
@@ -100,7 +100,7 @@ static void rxrpc_queue_packet(struct rxrpc_call *call, struct sk_buff *skb, | |||
100 | ASSERTCMP(seq, ==, call->tx_top + 1); | 100 | ASSERTCMP(seq, ==, call->tx_top + 1); |
101 | 101 | ||
102 | ix = seq & RXRPC_RXTX_BUFF_MASK; | 102 | ix = seq & RXRPC_RXTX_BUFF_MASK; |
103 | rxrpc_get_skb(skb); | 103 | rxrpc_get_skb(skb, rxrpc_skb_tx_got); |
104 | call->rxtx_annotations[ix] = RXRPC_TX_ANNO_UNACK; | 104 | call->rxtx_annotations[ix] = RXRPC_TX_ANNO_UNACK; |
105 | smp_wmb(); | 105 | smp_wmb(); |
106 | call->rxtx_buffer[ix] = skb; | 106 | call->rxtx_buffer[ix] = skb; |
@@ -146,7 +146,7 @@ static void rxrpc_queue_packet(struct rxrpc_call *call, struct sk_buff *skb, | |||
146 | rxrpc_instant_resend(call, ix); | 146 | rxrpc_instant_resend(call, ix); |
147 | } | 147 | } |
148 | 148 | ||
149 | rxrpc_free_skb(skb); | 149 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); |
150 | _leave(""); | 150 | _leave(""); |
151 | } | 151 | } |
152 | 152 | ||
@@ -201,7 +201,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
201 | 201 | ||
202 | skb = call->tx_pending; | 202 | skb = call->tx_pending; |
203 | call->tx_pending = NULL; | 203 | call->tx_pending = NULL; |
204 | rxrpc_see_skb(skb); | 204 | rxrpc_see_skb(skb, rxrpc_skb_tx_seen); |
205 | 205 | ||
206 | copied = 0; | 206 | copied = 0; |
207 | do { | 207 | do { |
@@ -242,7 +242,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
242 | if (!skb) | 242 | if (!skb) |
243 | goto maybe_error; | 243 | goto maybe_error; |
244 | 244 | ||
245 | rxrpc_new_skb(skb); | 245 | rxrpc_new_skb(skb, rxrpc_skb_tx_new); |
246 | 246 | ||
247 | _debug("ALLOC SEND %p", skb); | 247 | _debug("ALLOC SEND %p", skb); |
248 | 248 | ||
@@ -352,7 +352,7 @@ out: | |||
352 | return ret; | 352 | return ret; |
353 | 353 | ||
354 | call_terminated: | 354 | call_terminated: |
355 | rxrpc_free_skb(skb); | 355 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); |
356 | _leave(" = %d", -call->error); | 356 | _leave(" = %d", -call->error); |
357 | return -call->error; | 357 | return -call->error; |
358 | 358 | ||
diff --git a/net/rxrpc/skbuff.c b/net/rxrpc/skbuff.c index 620d9ccaf3c1..5154cbf7e540 100644 --- a/net/rxrpc/skbuff.c +++ b/net/rxrpc/skbuff.c | |||
@@ -18,55 +18,77 @@ | |||
18 | #include <net/af_rxrpc.h> | 18 | #include <net/af_rxrpc.h> |
19 | #include "ar-internal.h" | 19 | #include "ar-internal.h" |
20 | 20 | ||
21 | #define select_skb_count(op) (op >= rxrpc_skb_tx_cleaned ? &rxrpc_n_tx_skbs : &rxrpc_n_rx_skbs) | ||
22 | |||
21 | /* | 23 | /* |
22 | * Note the existence of a new-to-us socket buffer (allocated or dequeued). | 24 | * Note the allocation or reception of a socket buffer. |
23 | */ | 25 | */ |
24 | void rxrpc_new_skb(struct sk_buff *skb) | 26 | void rxrpc_new_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) |
25 | { | 27 | { |
26 | const void *here = __builtin_return_address(0); | 28 | const void *here = __builtin_return_address(0); |
27 | int n = atomic_inc_return(&rxrpc_n_skbs); | 29 | int n = atomic_inc_return(select_skb_count(op)); |
28 | trace_rxrpc_skb(skb, 0, atomic_read(&skb->users), n, here); | 30 | trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here); |
29 | } | 31 | } |
30 | 32 | ||
31 | /* | 33 | /* |
32 | * Note the re-emergence of a socket buffer from a queue or buffer. | 34 | * Note the re-emergence of a socket buffer from a queue or buffer. |
33 | */ | 35 | */ |
34 | void rxrpc_see_skb(struct sk_buff *skb) | 36 | void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) |
35 | { | 37 | { |
36 | const void *here = __builtin_return_address(0); | 38 | const void *here = __builtin_return_address(0); |
37 | if (skb) { | 39 | if (skb) { |
38 | int n = atomic_read(&rxrpc_n_skbs); | 40 | int n = atomic_read(select_skb_count(op)); |
39 | trace_rxrpc_skb(skb, 1, atomic_read(&skb->users), n, here); | 41 | trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here); |
40 | } | 42 | } |
41 | } | 43 | } |
42 | 44 | ||
43 | /* | 45 | /* |
44 | * Note the addition of a ref on a socket buffer. | 46 | * Note the addition of a ref on a socket buffer. |
45 | */ | 47 | */ |
46 | void rxrpc_get_skb(struct sk_buff *skb) | 48 | void rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) |
47 | { | 49 | { |
48 | const void *here = __builtin_return_address(0); | 50 | const void *here = __builtin_return_address(0); |
49 | int n = atomic_inc_return(&rxrpc_n_skbs); | 51 | int n = atomic_inc_return(select_skb_count(op)); |
50 | trace_rxrpc_skb(skb, 2, atomic_read(&skb->users), n, here); | 52 | trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here); |
51 | skb_get(skb); | 53 | skb_get(skb); |
52 | } | 54 | } |
53 | 55 | ||
54 | /* | 56 | /* |
55 | * Note the destruction of a socket buffer. | 57 | * Note the destruction of a socket buffer. |
56 | */ | 58 | */ |
57 | void rxrpc_free_skb(struct sk_buff *skb) | 59 | void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) |
58 | { | 60 | { |
59 | const void *here = __builtin_return_address(0); | 61 | const void *here = __builtin_return_address(0); |
60 | if (skb) { | 62 | if (skb) { |
61 | int n; | 63 | int n; |
62 | CHECK_SLAB_OKAY(&skb->users); | 64 | CHECK_SLAB_OKAY(&skb->users); |
63 | n = atomic_dec_return(&rxrpc_n_skbs); | 65 | n = atomic_dec_return(select_skb_count(op)); |
64 | trace_rxrpc_skb(skb, 3, atomic_read(&skb->users), n, here); | 66 | trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here); |
65 | kfree_skb(skb); | 67 | kfree_skb(skb); |
66 | } | 68 | } |
67 | } | 69 | } |
68 | 70 | ||
69 | /* | 71 | /* |
72 | * Note the injected loss of a socket buffer. | ||
73 | */ | ||
74 | void rxrpc_lose_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) | ||
75 | { | ||
76 | const void *here = __builtin_return_address(0); | ||
77 | if (skb) { | ||
78 | int n; | ||
79 | CHECK_SLAB_OKAY(&skb->users); | ||
80 | if (op == rxrpc_skb_tx_lost) { | ||
81 | n = atomic_read(select_skb_count(op)); | ||
82 | trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here); | ||
83 | } else { | ||
84 | n = atomic_dec_return(select_skb_count(op)); | ||
85 | trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here); | ||
86 | kfree_skb(skb); | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | |||
91 | /* | ||
70 | * Clear a queue of socket buffers. | 92 | * Clear a queue of socket buffers. |
71 | */ | 93 | */ |
72 | void rxrpc_purge_queue(struct sk_buff_head *list) | 94 | void rxrpc_purge_queue(struct sk_buff_head *list) |
@@ -74,8 +96,9 @@ void rxrpc_purge_queue(struct sk_buff_head *list) | |||
74 | const void *here = __builtin_return_address(0); | 96 | const void *here = __builtin_return_address(0); |
75 | struct sk_buff *skb; | 97 | struct sk_buff *skb; |
76 | while ((skb = skb_dequeue((list))) != NULL) { | 98 | while ((skb = skb_dequeue((list))) != NULL) { |
77 | int n = atomic_dec_return(&rxrpc_n_skbs); | 99 | int n = atomic_dec_return(select_skb_count(rxrpc_skb_rx_purged)); |
78 | trace_rxrpc_skb(skb, 4, atomic_read(&skb->users), n, here); | 100 | trace_rxrpc_skb(skb, rxrpc_skb_rx_purged, |
101 | atomic_read(&skb->users), n, here); | ||
79 | kfree_skb(skb); | 102 | kfree_skb(skb); |
80 | } | 103 | } |
81 | } | 104 | } |