Commit 48c9e0ec authored by David Howells's avatar David Howells

rxrpc: Fix trace-after-put looking at the put call record

rxrpc_put_call() calls trace_rxrpc_call() after it has done the decrement
of the refcount - which looks at the debug_id in the call 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: e34d4234 ("rxrpc: Trace rxrpc_call usage")
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 4c1295dc
...@@ -606,10 +606,10 @@ TRACE_EVENT(rxrpc_client, ...@@ -606,10 +606,10 @@ TRACE_EVENT(rxrpc_client,
); );
TRACE_EVENT(rxrpc_call, TRACE_EVENT(rxrpc_call,
TP_PROTO(struct rxrpc_call *call, enum rxrpc_call_trace op, TP_PROTO(unsigned int call_debug_id, enum rxrpc_call_trace op,
int usage, const void *where, const void *aux), int usage, const void *where, const void *aux),
TP_ARGS(call, op, usage, where, aux), TP_ARGS(call_debug_id, op, usage, where, aux),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(unsigned int, call ) __field(unsigned int, call )
...@@ -620,7 +620,7 @@ TRACE_EVENT(rxrpc_call, ...@@ -620,7 +620,7 @@ TRACE_EVENT(rxrpc_call,
), ),
TP_fast_assign( TP_fast_assign(
__entry->call = call->debug_id; __entry->call = call_debug_id;
__entry->op = op; __entry->op = op;
__entry->usage = usage; __entry->usage = usage;
__entry->where = where; __entry->where = where;
......
...@@ -97,7 +97,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx, ...@@ -97,7 +97,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
call->flags |= (1 << RXRPC_CALL_IS_SERVICE); call->flags |= (1 << RXRPC_CALL_IS_SERVICE);
call->state = RXRPC_CALL_SERVER_PREALLOC; call->state = RXRPC_CALL_SERVER_PREALLOC;
trace_rxrpc_call(call, rxrpc_call_new_service, trace_rxrpc_call(call->debug_id, rxrpc_call_new_service,
atomic_read(&call->usage), atomic_read(&call->usage),
here, (const void *)user_call_ID); here, (const void *)user_call_ID);
......
...@@ -240,7 +240,8 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, ...@@ -240,7 +240,8 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
if (p->intr) if (p->intr)
__set_bit(RXRPC_CALL_IS_INTR, &call->flags); __set_bit(RXRPC_CALL_IS_INTR, &call->flags);
call->tx_total_len = p->tx_total_len; call->tx_total_len = p->tx_total_len;
trace_rxrpc_call(call, rxrpc_call_new_client, atomic_read(&call->usage), trace_rxrpc_call(call->debug_id, rxrpc_call_new_client,
atomic_read(&call->usage),
here, (const void *)p->user_call_ID); here, (const void *)p->user_call_ID);
/* We need to protect a partially set up call against the user as we /* We need to protect a partially set up call against the user as we
...@@ -290,8 +291,8 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, ...@@ -290,8 +291,8 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
if (ret < 0) if (ret < 0)
goto error; goto error;
trace_rxrpc_call(call, rxrpc_call_connected, atomic_read(&call->usage), trace_rxrpc_call(call->debug_id, rxrpc_call_connected,
here, NULL); atomic_read(&call->usage), here, NULL);
rxrpc_start_call_timer(call); rxrpc_start_call_timer(call);
...@@ -313,8 +314,8 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, ...@@ -313,8 +314,8 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
error: error:
__rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, __rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR,
RX_CALL_DEAD, ret); RX_CALL_DEAD, ret);
trace_rxrpc_call(call, rxrpc_call_error, atomic_read(&call->usage), trace_rxrpc_call(call->debug_id, rxrpc_call_error,
here, ERR_PTR(ret)); atomic_read(&call->usage), here, ERR_PTR(ret));
rxrpc_release_call(rx, call); rxrpc_release_call(rx, call);
mutex_unlock(&call->user_mutex); mutex_unlock(&call->user_mutex);
rxrpc_put_call(call, rxrpc_call_put); rxrpc_put_call(call, rxrpc_call_put);
...@@ -376,7 +377,8 @@ bool rxrpc_queue_call(struct rxrpc_call *call) ...@@ -376,7 +377,8 @@ bool rxrpc_queue_call(struct rxrpc_call *call)
if (n == 0) if (n == 0)
return false; return false;
if (rxrpc_queue_work(&call->processor)) if (rxrpc_queue_work(&call->processor))
trace_rxrpc_call(call, rxrpc_call_queued, n + 1, here, NULL); trace_rxrpc_call(call->debug_id, rxrpc_call_queued, n + 1,
here, NULL);
else else
rxrpc_put_call(call, rxrpc_call_put_noqueue); rxrpc_put_call(call, rxrpc_call_put_noqueue);
return true; return true;
...@@ -391,7 +393,8 @@ bool __rxrpc_queue_call(struct rxrpc_call *call) ...@@ -391,7 +393,8 @@ bool __rxrpc_queue_call(struct rxrpc_call *call)
int n = atomic_read(&call->usage); int n = atomic_read(&call->usage);
ASSERTCMP(n, >=, 1); ASSERTCMP(n, >=, 1);
if (rxrpc_queue_work(&call->processor)) if (rxrpc_queue_work(&call->processor))
trace_rxrpc_call(call, rxrpc_call_queued_ref, n, here, NULL); trace_rxrpc_call(call->debug_id, rxrpc_call_queued_ref, n,
here, NULL);
else else
rxrpc_put_call(call, rxrpc_call_put_noqueue); rxrpc_put_call(call, rxrpc_call_put_noqueue);
return true; return true;
...@@ -406,7 +409,8 @@ void rxrpc_see_call(struct rxrpc_call *call) ...@@ -406,7 +409,8 @@ void rxrpc_see_call(struct rxrpc_call *call)
if (call) { if (call) {
int n = atomic_read(&call->usage); int n = atomic_read(&call->usage);
trace_rxrpc_call(call, rxrpc_call_seen, n, here, NULL); trace_rxrpc_call(call->debug_id, rxrpc_call_seen, n,
here, NULL);
} }
} }
...@@ -418,7 +422,7 @@ void rxrpc_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op) ...@@ -418,7 +422,7 @@ void rxrpc_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op)
const void *here = __builtin_return_address(0); const void *here = __builtin_return_address(0);
int n = atomic_inc_return(&call->usage); int n = atomic_inc_return(&call->usage);
trace_rxrpc_call(call, op, n, here, NULL); trace_rxrpc_call(call->debug_id, op, n, here, NULL);
} }
/* /*
...@@ -445,7 +449,8 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) ...@@ -445,7 +449,8 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
_enter("{%d,%d}", call->debug_id, atomic_read(&call->usage)); _enter("{%d,%d}", call->debug_id, atomic_read(&call->usage));
trace_rxrpc_call(call, rxrpc_call_release, atomic_read(&call->usage), trace_rxrpc_call(call->debug_id, rxrpc_call_release,
atomic_read(&call->usage),
here, (const void *)call->flags); here, (const void *)call->flags);
ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE);
...@@ -534,12 +539,13 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace op) ...@@ -534,12 +539,13 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace op)
{ {
struct rxrpc_net *rxnet = call->rxnet; struct rxrpc_net *rxnet = call->rxnet;
const void *here = __builtin_return_address(0); const void *here = __builtin_return_address(0);
unsigned int debug_id = call->debug_id;
int n; int n;
ASSERT(call != NULL); ASSERT(call != NULL);
n = atomic_dec_return(&call->usage); n = atomic_dec_return(&call->usage);
trace_rxrpc_call(call, op, n, here, NULL); trace_rxrpc_call(debug_id, op, n, here, NULL);
ASSERTCMP(n, >=, 0); ASSERTCMP(n, >=, 0);
if (n == 0) { if (n == 0) {
_debug("call %d dead", call->debug_id); _debug("call %d dead", call->debug_id);
......
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