Commit 09d2bf59 authored by David Howells's avatar David Howells

rxrpc: Add a tracepoint to track rxrpc_local refcounting

Add a tracepoint to track reference counting on the rxrpc_local struct.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent d3be4d24
...@@ -42,6 +42,14 @@ enum rxrpc_skb_trace { ...@@ -42,6 +42,14 @@ enum rxrpc_skb_trace {
rxrpc_skb_tx_seen, 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 { enum rxrpc_conn_trace {
rxrpc_conn_got, rxrpc_conn_got,
rxrpc_conn_new_client, rxrpc_conn_new_client,
...@@ -215,6 +223,13 @@ enum rxrpc_congest_change { ...@@ -215,6 +223,13 @@ enum rxrpc_congest_change {
EM(rxrpc_skb_tx_rotated, "Tx ROT") \ EM(rxrpc_skb_tx_rotated, "Tx ROT") \
E_(rxrpc_skb_tx_seen, "Tx SEE") 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 \ #define rxrpc_conn_traces \
EM(rxrpc_conn_got, "GOT") \ EM(rxrpc_conn_got, "GOT") \
EM(rxrpc_conn_new_client, "NWc") \ EM(rxrpc_conn_new_client, "NWc") \
...@@ -416,6 +431,7 @@ enum rxrpc_congest_change { ...@@ -416,6 +431,7 @@ enum rxrpc_congest_change {
#define E_(a, b) TRACE_DEFINE_ENUM(a); #define E_(a, b) TRACE_DEFINE_ENUM(a);
rxrpc_skb_traces; rxrpc_skb_traces;
rxrpc_local_traces;
rxrpc_conn_traces; rxrpc_conn_traces;
rxrpc_client_traces; rxrpc_client_traces;
rxrpc_call_traces; rxrpc_call_traces;
...@@ -439,6 +455,33 @@ rxrpc_congest_changes; ...@@ -439,6 +455,33 @@ rxrpc_congest_changes;
#define EM(a, b) { a, b }, #define EM(a, b) { a, b },
#define E_(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, TRACE_EVENT(rxrpc_conn,
TP_PROTO(struct rxrpc_connection *conn, enum rxrpc_conn_trace op, TP_PROTO(struct rxrpc_connection *conn, enum rxrpc_conn_trace op,
int usage, const void *where), int usage, const void *where),
......
...@@ -981,31 +981,12 @@ extern void rxrpc_process_local_events(struct rxrpc_local *); ...@@ -981,31 +981,12 @@ extern void rxrpc_process_local_events(struct rxrpc_local *);
* local_object.c * local_object.c
*/ */
struct rxrpc_local *rxrpc_lookup_local(struct net *, const struct sockaddr_rxrpc *); 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 *); 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 * misc.c
*/ */
......
...@@ -296,8 +296,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx, ...@@ -296,8 +296,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
b->conn_backlog[conn_tail] = NULL; b->conn_backlog[conn_tail] = NULL;
smp_store_release(&b->conn_backlog_tail, smp_store_release(&b->conn_backlog_tail,
(conn_tail + 1) & (RXRPC_BACKLOG_MAX - 1)); (conn_tail + 1) & (RXRPC_BACKLOG_MAX - 1));
rxrpc_get_local(local); conn->params.local = rxrpc_get_local(local);
conn->params.local = local;
conn->params.peer = peer; conn->params.peer = peer;
rxrpc_see_connection(conn); rxrpc_see_connection(conn);
rxrpc_new_incoming_connection(rx, conn, skb); rxrpc_new_incoming_connection(rx, conn, skb);
......
...@@ -95,6 +95,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet, ...@@ -95,6 +95,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
local->debug_id = atomic_inc_return(&rxrpc_debug_id); local->debug_id = atomic_inc_return(&rxrpc_debug_id);
memcpy(&local->srx, srx, sizeof(*srx)); memcpy(&local->srx, srx, sizeof(*srx));
local->srx.srx_service = 0; local->srx.srx_service = 0;
trace_rxrpc_local(local, rxrpc_local_new, 1, NULL);
} }
_leave(" = %p", local); _leave(" = %p", local);
...@@ -256,15 +257,74 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net, ...@@ -256,15 +257,74 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
return ERR_PTR(-EADDRINUSE); 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. * 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); _enter("%d", local->debug_id);
rxrpc_queue_work(&local->processor); 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 * Destroy a local endpoint's socket and then hand the record to RCU to dispose
* of. * of.
...@@ -322,7 +382,8 @@ static void rxrpc_local_processor(struct work_struct *work) ...@@ -322,7 +382,8 @@ static void rxrpc_local_processor(struct work_struct *work)
container_of(work, struct rxrpc_local, processor); container_of(work, struct rxrpc_local, processor);
bool again; bool again;
_enter("%d", local->debug_id); trace_rxrpc_local(local, rxrpc_local_processing,
atomic_read(&local->usage), NULL);
do { do {
again = false; again = false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment