rxrpc: Add a tracepoint to track rxrpc_local refcounting
authorDavid Howells <dhowells@redhat.com>
Fri, 30 Mar 2018 20:05:28 +0000 (21:05 +0100)
committerDavid Howells <dhowells@redhat.com>
Fri, 30 Mar 2018 20:05:28 +0000 (21:05 +0100)
Add a tracepoint to track reference counting on the rxrpc_local struct.

Signed-off-by: David Howells <dhowells@redhat.com>
include/trace/events/rxrpc.h
net/rxrpc/ar-internal.h
net/rxrpc/call_accept.c
net/rxrpc/local_object.c

index 2ea788f6f95d091bc53691f17acc682f522089c3..0410dfeb79c66e3d7f656bf8594c8509c2141386 100644 (file)
@@ -42,6 +42,14 @@ enum rxrpc_skb_trace {
        rxrpc_skb_tx_seen,
 };
 
+enum rxrpc_local_trace {
+       rxrpc_local_got,
+       rxrpc_local_new,
+       rxrpc_local_processing,
+       rxrpc_local_put,
+       rxrpc_local_queued,
+};
+
 enum rxrpc_conn_trace {
        rxrpc_conn_got,
        rxrpc_conn_new_client,
@@ -215,6 +223,13 @@ enum rxrpc_congest_change {
        EM(rxrpc_skb_tx_rotated,                "Tx ROT") \
        E_(rxrpc_skb_tx_seen,                   "Tx SEE")
 
+#define rxrpc_local_traces \
+       EM(rxrpc_local_got,                     "GOT") \
+       EM(rxrpc_local_new,                     "NEW") \
+       EM(rxrpc_local_processing,              "PRO") \
+       EM(rxrpc_local_put,                     "PUT") \
+       E_(rxrpc_local_queued,                  "QUE")
+
 #define rxrpc_conn_traces \
        EM(rxrpc_conn_got,                      "GOT") \
        EM(rxrpc_conn_new_client,               "NWc") \
@@ -416,6 +431,7 @@ enum rxrpc_congest_change {
 #define E_(a, b) TRACE_DEFINE_ENUM(a);
 
 rxrpc_skb_traces;
+rxrpc_local_traces;
 rxrpc_conn_traces;
 rxrpc_client_traces;
 rxrpc_call_traces;
@@ -439,6 +455,33 @@ rxrpc_congest_changes;
 #define EM(a, b)       { a, b },
 #define E_(a, b)       { a, b }
 
+TRACE_EVENT(rxrpc_local,
+           TP_PROTO(struct rxrpc_local *local, enum rxrpc_local_trace op,
+                    int usage, const void *where),
+
+           TP_ARGS(local, op, usage, where),
+
+           TP_STRUCT__entry(
+                   __field(unsigned int,       local           )
+                   __field(int,                op              )
+                   __field(int,                usage           )
+                   __field(const void *,       where           )
+                            ),
+
+           TP_fast_assign(
+                   __entry->local = local->debug_id;
+                   __entry->op = op;
+                   __entry->usage = usage;
+                   __entry->where = where;
+                          ),
+
+           TP_printk("L=%08x %s u=%d sp=%pSR",
+                     __entry->local,
+                     __print_symbolic(__entry->op, rxrpc_local_traces),
+                     __entry->usage,
+                     __entry->where)
+           );
+
 TRACE_EVENT(rxrpc_conn,
            TP_PROTO(struct rxrpc_connection *conn, enum rxrpc_conn_trace op,
                     int usage, const void *where),
index 2a2b0fdfb15792098548157328ca6fb7de1bc79c..cc51d3eb0548cd4b43cbb9f9f5fd7d0d84dfc537 100644 (file)
@@ -981,31 +981,12 @@ extern void rxrpc_process_local_events(struct rxrpc_local *);
  * local_object.c
  */
 struct rxrpc_local *rxrpc_lookup_local(struct net *, const struct sockaddr_rxrpc *);
-void __rxrpc_put_local(struct rxrpc_local *);
+struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *);
+struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *);
+void rxrpc_put_local(struct rxrpc_local *);
+void rxrpc_queue_local(struct rxrpc_local *);
 void rxrpc_destroy_all_locals(struct rxrpc_net *);
 
-static inline void rxrpc_get_local(struct rxrpc_local *local)
-{
-       atomic_inc(&local->usage);
-}
-
-static inline
-struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local)
-{
-       return atomic_inc_not_zero(&local->usage) ? local : NULL;
-}
-
-static inline void rxrpc_put_local(struct rxrpc_local *local)
-{
-       if (local && atomic_dec_and_test(&local->usage))
-               __rxrpc_put_local(local);
-}
-
-static inline void rxrpc_queue_local(struct rxrpc_local *local)
-{
-       rxrpc_queue_work(&local->processor);
-}
-
 /*
  * misc.c
  */
index 493545033e42bde05f8a26d7ff3854c3624ab1b9..5a9b1d91612462cf6f0bb8470897db305f7130ac 100644 (file)
@@ -296,8 +296,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
                b->conn_backlog[conn_tail] = NULL;
                smp_store_release(&b->conn_backlog_tail,
                                  (conn_tail + 1) & (RXRPC_BACKLOG_MAX - 1));
-               rxrpc_get_local(local);
-               conn->params.local = local;
+               conn->params.local = rxrpc_get_local(local);
                conn->params.peer = peer;
                rxrpc_see_connection(conn);
                rxrpc_new_incoming_connection(rx, conn, skb);
index 38b99db30e541e789b838e10600944f11b4124e0..8b54e9531d52b63c0afd0989b1fbb641d147e6f3 100644 (file)
@@ -95,6 +95,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
                local->debug_id = atomic_inc_return(&rxrpc_debug_id);
                memcpy(&local->srx, srx, sizeof(*srx));
                local->srx.srx_service = 0;
+               trace_rxrpc_local(local, rxrpc_local_new, 1, NULL);
        }
 
        _leave(" = %p", local);
@@ -256,15 +257,74 @@ addr_in_use:
        return ERR_PTR(-EADDRINUSE);
 }
 
+/*
+ * Get a ref on a local endpoint.
+ */
+struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *local)
+{
+       const void *here = __builtin_return_address(0);
+       int n;
+
+       n = atomic_inc_return(&local->usage);
+       trace_rxrpc_local(local, rxrpc_local_got, n, here);
+       return local;
+}
+
+/*
+ * Get a ref on a local endpoint unless its usage has already reached 0.
+ */
+struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local)
+{
+       const void *here = __builtin_return_address(0);
+
+       if (local) {
+               int n = __atomic_add_unless(&local->usage, 1, 0);
+               if (n > 0)
+                       trace_rxrpc_local(local, rxrpc_local_got, n + 1, here);
+               else
+                       local = NULL;
+       }
+       return local;
+}
+
+/*
+ * Queue a local endpoint.
+ */
+void rxrpc_queue_local(struct rxrpc_local *local)
+{
+       const void *here = __builtin_return_address(0);
+
+       if (rxrpc_queue_work(&local->processor))
+               trace_rxrpc_local(local, rxrpc_local_queued,
+                                 atomic_read(&local->usage), here);
+}
+
 /*
  * A local endpoint reached its end of life.
  */
-void __rxrpc_put_local(struct rxrpc_local *local)
+static void __rxrpc_put_local(struct rxrpc_local *local)
 {
        _enter("%d", local->debug_id);
        rxrpc_queue_work(&local->processor);
 }
 
+/*
+ * Drop a ref on a local endpoint.
+ */
+void rxrpc_put_local(struct rxrpc_local *local)
+{
+       const void *here = __builtin_return_address(0);
+       int n;
+
+       if (local) {
+               n = atomic_dec_return(&local->usage);
+               trace_rxrpc_local(local, rxrpc_local_put, n, here);
+
+               if (n == 0)
+                       __rxrpc_put_local(local);
+       }
+}
+
 /*
  * Destroy a local endpoint's socket and then hand the record to RCU to dispose
  * of.
@@ -322,7 +382,8 @@ static void rxrpc_local_processor(struct work_struct *work)
                container_of(work, struct rxrpc_local, processor);
        bool again;
 
-       _enter("%d", local->debug_id);
+       trace_rxrpc_local(local, rxrpc_local_processing,
+                         atomic_read(&local->usage), NULL);
 
        do {
                again = false;