rxrpc: Add a tracepoint to track rxrpc_peer refcounting
Add a tracepoint to track reference counting on the rxrpc_peer struct. Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
parent
31f5f9a169
commit
1159d4b496
|
@ -50,6 +50,14 @@ enum rxrpc_local_trace {
|
||||||
rxrpc_local_queued,
|
rxrpc_local_queued,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum rxrpc_peer_trace {
|
||||||
|
rxrpc_peer_got,
|
||||||
|
rxrpc_peer_new,
|
||||||
|
rxrpc_peer_processing,
|
||||||
|
rxrpc_peer_put,
|
||||||
|
rxrpc_peer_queued_error,
|
||||||
|
};
|
||||||
|
|
||||||
enum rxrpc_conn_trace {
|
enum rxrpc_conn_trace {
|
||||||
rxrpc_conn_got,
|
rxrpc_conn_got,
|
||||||
rxrpc_conn_new_client,
|
rxrpc_conn_new_client,
|
||||||
|
@ -230,6 +238,13 @@ enum rxrpc_congest_change {
|
||||||
EM(rxrpc_local_put, "PUT") \
|
EM(rxrpc_local_put, "PUT") \
|
||||||
E_(rxrpc_local_queued, "QUE")
|
E_(rxrpc_local_queued, "QUE")
|
||||||
|
|
||||||
|
#define rxrpc_peer_traces \
|
||||||
|
EM(rxrpc_peer_got, "GOT") \
|
||||||
|
EM(rxrpc_peer_new, "NEW") \
|
||||||
|
EM(rxrpc_peer_processing, "PRO") \
|
||||||
|
EM(rxrpc_peer_put, "PUT") \
|
||||||
|
E_(rxrpc_peer_queued_error, "QER")
|
||||||
|
|
||||||
#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") \
|
||||||
|
@ -482,6 +497,33 @@ TRACE_EVENT(rxrpc_local,
|
||||||
__entry->where)
|
__entry->where)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(rxrpc_peer,
|
||||||
|
TP_PROTO(struct rxrpc_peer *peer, enum rxrpc_peer_trace op,
|
||||||
|
int usage, const void *where),
|
||||||
|
|
||||||
|
TP_ARGS(peer, op, usage, where),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field(unsigned int, peer )
|
||||||
|
__field(int, op )
|
||||||
|
__field(int, usage )
|
||||||
|
__field(const void *, where )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->peer = peer->debug_id;
|
||||||
|
__entry->op = op;
|
||||||
|
__entry->usage = usage;
|
||||||
|
__entry->where = where;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("P=%08x %s u=%d sp=%pSR",
|
||||||
|
__entry->peer,
|
||||||
|
__print_symbolic(__entry->op, rxrpc_peer_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),
|
||||||
|
|
|
@ -1041,25 +1041,10 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_local *,
|
||||||
struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *, gfp_t);
|
struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *, gfp_t);
|
||||||
struct rxrpc_peer *rxrpc_lookup_incoming_peer(struct rxrpc_local *,
|
struct rxrpc_peer *rxrpc_lookup_incoming_peer(struct rxrpc_local *,
|
||||||
struct rxrpc_peer *);
|
struct rxrpc_peer *);
|
||||||
|
struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *);
|
||||||
static inline struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *peer)
|
struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *);
|
||||||
{
|
void rxrpc_put_peer(struct rxrpc_peer *);
|
||||||
atomic_inc(&peer->usage);
|
void __rxrpc_queue_peer_error(struct rxrpc_peer *);
|
||||||
return peer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline
|
|
||||||
struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *peer)
|
|
||||||
{
|
|
||||||
return atomic_inc_not_zero(&peer->usage) ? peer : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void __rxrpc_put_peer(struct rxrpc_peer *peer);
|
|
||||||
static inline void rxrpc_put_peer(struct rxrpc_peer *peer)
|
|
||||||
{
|
|
||||||
if (peer && atomic_dec_and_test(&peer->usage))
|
|
||||||
__rxrpc_put_peer(peer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* proc.c
|
* proc.c
|
||||||
|
|
|
@ -192,7 +192,7 @@ void rxrpc_error_report(struct sock *sk)
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
||||||
|
|
||||||
/* The ref we obtained is passed off to the work item */
|
/* The ref we obtained is passed off to the work item */
|
||||||
rxrpc_queue_work(&peer->error_distributor);
|
__rxrpc_queue_peer_error(peer);
|
||||||
_leave("");
|
_leave("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -386,9 +386,54 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_local *local,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Discard a ref on a remote peer record.
|
* Get a ref on a peer record.
|
||||||
*/
|
*/
|
||||||
void __rxrpc_put_peer(struct rxrpc_peer *peer)
|
struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *peer)
|
||||||
|
{
|
||||||
|
const void *here = __builtin_return_address(0);
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = atomic_inc_return(&peer->usage);
|
||||||
|
trace_rxrpc_peer(peer, rxrpc_peer_got, n, here);
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a ref on a peer record unless its usage has already reached 0.
|
||||||
|
*/
|
||||||
|
struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *peer)
|
||||||
|
{
|
||||||
|
const void *here = __builtin_return_address(0);
|
||||||
|
|
||||||
|
if (peer) {
|
||||||
|
int n = __atomic_add_unless(&peer->usage, 1, 0);
|
||||||
|
if (n > 0)
|
||||||
|
trace_rxrpc_peer(peer, rxrpc_peer_got, n + 1, here);
|
||||||
|
else
|
||||||
|
peer = NULL;
|
||||||
|
}
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Queue a peer record. This passes the caller's ref to the workqueue.
|
||||||
|
*/
|
||||||
|
void __rxrpc_queue_peer_error(struct rxrpc_peer *peer)
|
||||||
|
{
|
||||||
|
const void *here = __builtin_return_address(0);
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = atomic_read(&peer->usage);
|
||||||
|
if (rxrpc_queue_work(&peer->error_distributor))
|
||||||
|
trace_rxrpc_peer(peer, rxrpc_peer_queued_error, n, here);
|
||||||
|
else
|
||||||
|
rxrpc_put_peer(peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Discard a peer record.
|
||||||
|
*/
|
||||||
|
static void __rxrpc_put_peer(struct rxrpc_peer *peer)
|
||||||
{
|
{
|
||||||
struct rxrpc_net *rxnet = peer->local->rxnet;
|
struct rxrpc_net *rxnet = peer->local->rxnet;
|
||||||
|
|
||||||
|
@ -402,6 +447,22 @@ void __rxrpc_put_peer(struct rxrpc_peer *peer)
|
||||||
kfree_rcu(peer, rcu);
|
kfree_rcu(peer, rcu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Drop a ref on a peer record.
|
||||||
|
*/
|
||||||
|
void rxrpc_put_peer(struct rxrpc_peer *peer)
|
||||||
|
{
|
||||||
|
const void *here = __builtin_return_address(0);
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (peer) {
|
||||||
|
n = atomic_dec_return(&peer->usage);
|
||||||
|
trace_rxrpc_peer(peer, rxrpc_peer_put, n, here);
|
||||||
|
if (n == 0)
|
||||||
|
__rxrpc_put_peer(peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rxrpc_kernel_get_peer - Get the peer address of a call
|
* rxrpc_kernel_get_peer - Get the peer address of a call
|
||||||
* @sock: The socket on which the call is in progress.
|
* @sock: The socket on which the call is in progress.
|
||||||
|
|
Loading…
Reference in New Issue