Skip to content

Commit

Permalink
rxrpc: Fix trace-after-put looking at the put connection record
Browse files Browse the repository at this point in the history
rxrpc_put_*conn() calls trace_rxrpc_conn() after they have done the
decrement of the refcount - which looks at the debug_id in the connection
record.  But unless the refcount was reduced to zero, we no longer have the
right to look in the record and, indeed, it may be deleted by some other
thread.

Fix this by getting the debug_id out before decrementing the refcount and
then passing that into the tracepoint.

Fixes: 363deea ("rxrpc: Add connection tracepoint and client conn state tracepoint")
Signed-off-by: David Howells <[email protected]>
  • Loading branch information
dhowells committed Oct 7, 2019
1 parent 55f6c98 commit 4c1295d
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 13 deletions.
6 changes: 3 additions & 3 deletions include/trace/events/rxrpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -546,10 +546,10 @@ TRACE_EVENT(rxrpc_peer,
);

TRACE_EVENT(rxrpc_conn,
TP_PROTO(struct rxrpc_connection *conn, enum rxrpc_conn_trace op,
TP_PROTO(unsigned int conn_debug_id, enum rxrpc_conn_trace op,
int usage, const void *where),

TP_ARGS(conn, op, usage, where),
TP_ARGS(conn_debug_id, op, usage, where),

TP_STRUCT__entry(
__field(unsigned int, conn )
Expand All @@ -559,7 +559,7 @@ TRACE_EVENT(rxrpc_conn,
),

TP_fast_assign(
__entry->conn = conn->debug_id;
__entry->conn = conn_debug_id;
__entry->op = op;
__entry->usage = usage;
__entry->where = where;
Expand Down
2 changes: 1 addition & 1 deletion net/rxrpc/call_accept.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
smp_store_release(&b->conn_backlog_head,
(head + 1) & (size - 1));

trace_rxrpc_conn(conn, rxrpc_conn_new_service,
trace_rxrpc_conn(conn->debug_id, rxrpc_conn_new_service,
atomic_read(&conn->usage), here);
}

Expand Down
6 changes: 4 additions & 2 deletions net/rxrpc/conn_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ rxrpc_alloc_client_connection(struct rxrpc_conn_parameters *cp, gfp_t gfp)
rxrpc_get_local(conn->params.local);
key_get(conn->params.key);

trace_rxrpc_conn(conn, rxrpc_conn_new_client, atomic_read(&conn->usage),
trace_rxrpc_conn(conn->debug_id, rxrpc_conn_new_client,
atomic_read(&conn->usage),
__builtin_return_address(0));
trace_rxrpc_client(conn, -1, rxrpc_client_alloc);
_leave(" = %p", conn);
Expand Down Expand Up @@ -985,11 +986,12 @@ rxrpc_put_one_client_conn(struct rxrpc_connection *conn)
void rxrpc_put_client_conn(struct rxrpc_connection *conn)
{
const void *here = __builtin_return_address(0);
unsigned int debug_id = conn->debug_id;
int n;

do {
n = atomic_dec_return(&conn->usage);
trace_rxrpc_conn(conn, rxrpc_conn_put_client, n, here);
trace_rxrpc_conn(debug_id, rxrpc_conn_put_client, n, here);
if (n > 0)
return;
ASSERTCMP(n, >=, 0);
Expand Down
13 changes: 7 additions & 6 deletions net/rxrpc/conn_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ bool rxrpc_queue_conn(struct rxrpc_connection *conn)
if (n == 0)
return false;
if (rxrpc_queue_work(&conn->processor))
trace_rxrpc_conn(conn, rxrpc_conn_queued, n + 1, here);
trace_rxrpc_conn(conn->debug_id, rxrpc_conn_queued, n + 1, here);
else
rxrpc_put_connection(conn);
return true;
Expand All @@ -284,7 +284,7 @@ void rxrpc_see_connection(struct rxrpc_connection *conn)
if (conn) {
int n = atomic_read(&conn->usage);

trace_rxrpc_conn(conn, rxrpc_conn_seen, n, here);
trace_rxrpc_conn(conn->debug_id, rxrpc_conn_seen, n, here);
}
}

Expand All @@ -296,7 +296,7 @@ void rxrpc_get_connection(struct rxrpc_connection *conn)
const void *here = __builtin_return_address(0);
int n = atomic_inc_return(&conn->usage);

trace_rxrpc_conn(conn, rxrpc_conn_got, n, here);
trace_rxrpc_conn(conn->debug_id, rxrpc_conn_got, n, here);
}

/*
Expand All @@ -310,7 +310,7 @@ rxrpc_get_connection_maybe(struct rxrpc_connection *conn)
if (conn) {
int n = atomic_fetch_add_unless(&conn->usage, 1, 0);
if (n > 0)
trace_rxrpc_conn(conn, rxrpc_conn_got, n + 1, here);
trace_rxrpc_conn(conn->debug_id, rxrpc_conn_got, n + 1, here);
else
conn = NULL;
}
Expand All @@ -333,10 +333,11 @@ static void rxrpc_set_service_reap_timer(struct rxrpc_net *rxnet,
void rxrpc_put_service_conn(struct rxrpc_connection *conn)
{
const void *here = __builtin_return_address(0);
unsigned int debug_id = conn->debug_id;
int n;

n = atomic_dec_return(&conn->usage);
trace_rxrpc_conn(conn, rxrpc_conn_put_service, n, here);
trace_rxrpc_conn(debug_id, rxrpc_conn_put_service, n, here);
ASSERTCMP(n, >=, 0);
if (n == 1)
rxrpc_set_service_reap_timer(conn->params.local->rxnet,
Expand Down Expand Up @@ -420,7 +421,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
*/
if (atomic_cmpxchg(&conn->usage, 1, 0) != 1)
continue;
trace_rxrpc_conn(conn, rxrpc_conn_reap_service, 0, NULL);
trace_rxrpc_conn(conn->debug_id, rxrpc_conn_reap_service, 0, NULL);

if (rxrpc_conn_is_client(conn))
BUG();
Expand Down
2 changes: 1 addition & 1 deletion net/rxrpc/conn_service.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *rxn
list_add_tail(&conn->proc_link, &rxnet->conn_proc_list);
write_unlock(&rxnet->conn_lock);

trace_rxrpc_conn(conn, rxrpc_conn_new_service,
trace_rxrpc_conn(conn->debug_id, rxrpc_conn_new_service,
atomic_read(&conn->usage),
__builtin_return_address(0));
}
Expand Down

0 comments on commit 4c1295d

Please sign in to comment.