rxrpc: Add a tracepoint to track rxrpc_local refcounting
Add a tracepoint to track reference counting on the rxrpc_local struct. Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
parent
d3be4d2443
commit
09d2bf595d
4 changed files with 111 additions and 27 deletions
|
@ -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 {
|
||||||
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 {
|
||||||
#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;
|
||||||
#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 *);
|
||||||
* 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,
|
||||||
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,
|
||||||
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 @@ addr_in_use:
|
||||||
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)
|
||||||
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;
|
||||||
|
|
Loading…
Reference in a new issue