RxRPC fixes

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEqG5UsNXhtOCrfGQP+7dXa6fLC2sFAl1T5QEACgkQ+7dXa6fL
 C2utGA//SeeXoU2E7ER2m66REbD/3+0/4Gwcy/NpNgou+GDLS9zo7ASbcQOmW1uN
 MkzEPsL4NuYyJFxJits02nDrqmIpsBKyg+tZCR1CfmmkYrvSHZ5UE8AWr3Ogu9nR
 3f6bJ2IhDmuSCQclThHJPaoSoPfLpvrqOMzvdngPzcvrIBX9YKQ91Pye8mEaZTbL
 yDWJ8MVN0OJV0X/uUVkaGd/5k/FImjBNV6+kH766Hna0lrCUO4NgwBylFHtyi06I
 ZG6zqDtnnZhytN5qkRgtYARqGRoAVubjoHUVywcLreenZ6XzXvo1+ch2aZ7ZFr0m
 10oSpjsgn5d2LniHhESxTZBVR+USjuTD/ySLyz5aPA0zE9Qo9qoQPURdZ0xtz4lC
 j15gjxXGZBw5c0W47IomGmH2tpUQzOVa8fUWVcZqBa2GS6ByxWzyVpOLd81EnUNQ
 MyXOZm44EeM6AE39/xRTYbNw8CGCzbV5gyENosTC0oXFIQjHBFXmHOMZgSIDUZiQ
 i09JiQGWafkuQfMM1TRaMICm83q4ObrCbuZTzf0c7vELAACCP10h6kF5KEJSUzuI
 Mf7VkVPjwgYx083zdUHzW8k1ZJyB6uOg3NFInZz75mxkHj9kyCfTZPd5qgsAqRY7
 MLLM/09PJsjNbHcstJLimJ0tAkHIHT6cx66QkYh4HhV3B7C5ACg=
 =zu2P
 -----END PGP SIGNATURE-----

Merge tag 'rxrpc-fixes-20190814' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs

David Howells says:

====================
rxrpc: Fix local endpoint handling

Here's a pair of patches that fix two issues in the handling of local
endpoints (rxrpc_local structs):

 (1) Use list_replace_init() rather than list_replace() if we're going to
     unconditionally delete the replaced item later, lest the list get
     corrupted.

 (2) Don't access the rxrpc_local object after passing our ref to the
     workqueue, not even to illuminate tracepoints, as the work function
     may cause the object to be freed.  We have to cache the information
     beforehand.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2019-08-15 16:33:22 -07:00
commit 480fd998bd
2 changed files with 14 additions and 13 deletions

View File

@ -498,10 +498,10 @@ rxrpc_tx_points;
#define E_(a, b) { a, b }
TRACE_EVENT(rxrpc_local,
TP_PROTO(struct rxrpc_local *local, enum rxrpc_local_trace op,
TP_PROTO(unsigned int local_debug_id, enum rxrpc_local_trace op,
int usage, const void *where),
TP_ARGS(local, op, usage, where),
TP_ARGS(local_debug_id, op, usage, where),
TP_STRUCT__entry(
__field(unsigned int, local )
@ -511,7 +511,7 @@ TRACE_EVENT(rxrpc_local,
),
TP_fast_assign(
__entry->local = local->debug_id;
__entry->local = local_debug_id;
__entry->op = op;
__entry->usage = usage;
__entry->where = where;

View File

@ -93,7 +93,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
local->debug_id = atomic_inc_return(&rxrpc_debug_id);
memcpy(&local->srx, srx, sizeof(*srx));
local->srx.srx_service = 0;
trace_rxrpc_local(local, rxrpc_local_new, 1, NULL);
trace_rxrpc_local(local->debug_id, rxrpc_local_new, 1, NULL);
}
_leave(" = %p", local);
@ -283,7 +283,7 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
goto sock_error;
if (cursor != &rxnet->local_endpoints)
list_replace(cursor, &local->link);
list_replace_init(cursor, &local->link);
else
list_add_tail(&local->link, cursor);
age = "new";
@ -321,7 +321,7 @@ struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *local)
int n;
n = atomic_inc_return(&local->usage);
trace_rxrpc_local(local, rxrpc_local_got, n, here);
trace_rxrpc_local(local->debug_id, rxrpc_local_got, n, here);
return local;
}
@ -335,7 +335,8 @@ struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local)
if (local) {
int n = atomic_fetch_add_unless(&local->usage, 1, 0);
if (n > 0)
trace_rxrpc_local(local, rxrpc_local_got, n + 1, here);
trace_rxrpc_local(local->debug_id, rxrpc_local_got,
n + 1, here);
else
local = NULL;
}
@ -343,16 +344,16 @@ struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local)
}
/*
* Queue a local endpoint unless it has become unreferenced and pass the
* caller's reference to the work item.
* Queue a local endpoint and pass the caller's reference to the work item.
*/
void rxrpc_queue_local(struct rxrpc_local *local)
{
const void *here = __builtin_return_address(0);
unsigned int debug_id = local->debug_id;
int n = atomic_read(&local->usage);
if (rxrpc_queue_work(&local->processor))
trace_rxrpc_local(local, rxrpc_local_queued,
atomic_read(&local->usage), here);
trace_rxrpc_local(debug_id, rxrpc_local_queued, n, here);
else
rxrpc_put_local(local);
}
@ -367,7 +368,7 @@ void rxrpc_put_local(struct rxrpc_local *local)
if (local) {
n = atomic_dec_return(&local->usage);
trace_rxrpc_local(local, rxrpc_local_put, n, here);
trace_rxrpc_local(local->debug_id, rxrpc_local_put, n, here);
if (n == 0)
call_rcu(&local->rcu, rxrpc_local_rcu);
@ -456,7 +457,7 @@ static void rxrpc_local_processor(struct work_struct *work)
container_of(work, struct rxrpc_local, processor);
bool again;
trace_rxrpc_local(local, rxrpc_local_processing,
trace_rxrpc_local(local->debug_id, rxrpc_local_processing,
atomic_read(&local->usage), NULL);
do {