summaryrefslogtreecommitdiffstats
path: root/net/rxrpc/skbuff.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-08-23 16:27:24 +0200
committerDavid Howells <dhowells@redhat.com>2016-08-23 16:27:24 +0200
commitdf844fd46b98c2efde8f4ac2d50d59bc90c4c679 (patch)
tree0a067071fa1bf6fe2fc41de100d822e9585289a0 /net/rxrpc/skbuff.c
parentrxrpc: Drop channel number field from rxrpc_call struct (diff)
downloadlinux-df844fd46b98c2efde8f4ac2d50d59bc90c4c679.tar.xz
linux-df844fd46b98c2efde8f4ac2d50d59bc90c4c679.zip
rxrpc: Use a tracepoint for skb accounting debugging
Use a tracepoint to log various skb accounting points to help in debugging refcounting errors. Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/rxrpc/skbuff.c')
-rw-r--r--net/rxrpc/skbuff.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/net/rxrpc/skbuff.c b/net/rxrpc/skbuff.c
index 06c51d4b622d..d28058a97bc1 100644
--- a/net/rxrpc/skbuff.c
+++ b/net/rxrpc/skbuff.c
@@ -163,3 +163,65 @@ void rxrpc_kernel_free_skb(struct sk_buff *skb)
rxrpc_free_skb(skb);
}
EXPORT_SYMBOL(rxrpc_kernel_free_skb);
+
+/*
+ * Note the existence of a new-to-us socket buffer (allocated or dequeued).
+ */
+void rxrpc_new_skb(struct sk_buff *skb)
+{
+ const void *here = __builtin_return_address(0);
+ int n = atomic_inc_return(&rxrpc_n_skbs);
+ trace_rxrpc_skb(skb, 0, atomic_read(&skb->users), n, here);
+}
+
+/*
+ * Note the re-emergence of a socket buffer from a queue or buffer.
+ */
+void rxrpc_see_skb(struct sk_buff *skb)
+{
+ const void *here = __builtin_return_address(0);
+ if (skb) {
+ int n = atomic_read(&rxrpc_n_skbs);
+ trace_rxrpc_skb(skb, 1, atomic_read(&skb->users), n, here);
+ }
+}
+
+/*
+ * Note the addition of a ref on a socket buffer.
+ */
+void rxrpc_get_skb(struct sk_buff *skb)
+{
+ const void *here = __builtin_return_address(0);
+ int n = atomic_inc_return(&rxrpc_n_skbs);
+ trace_rxrpc_skb(skb, 2, atomic_read(&skb->users), n, here);
+ skb_get(skb);
+}
+
+/*
+ * Note the destruction of a socket buffer.
+ */
+void rxrpc_free_skb(struct sk_buff *skb)
+{
+ const void *here = __builtin_return_address(0);
+ if (skb) {
+ int n;
+ CHECK_SLAB_OKAY(&skb->users);
+ n = atomic_dec_return(&rxrpc_n_skbs);
+ trace_rxrpc_skb(skb, 3, atomic_read(&skb->users), n, here);
+ kfree_skb(skb);
+ }
+}
+
+/*
+ * Clear a queue of socket buffers.
+ */
+void rxrpc_purge_queue(struct sk_buff_head *list)
+{
+ const void *here = __builtin_return_address(0);
+ struct sk_buff *skb;
+ while ((skb = skb_dequeue((list))) != NULL) {
+ int n = atomic_dec_return(&rxrpc_n_skbs);
+ trace_rxrpc_skb(skb, 4, atomic_read(&skb->users), n, here);
+ kfree_skb(skb);
+ }
+}