forked from mirrors/linux
		
	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 @@ 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)
 | 
				
			||||||
		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